4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc.
27 #include <arpa/inet.h>
31 #include <inet/iptun.h>
32 #include <inet/tunables.h>
34 #include <libdliptun.h>
35 #include <libdllink.h>
36 #include <libinetutil.h>
40 #include <netinet/in.h>
49 #include <sys/types.h>
52 #define STR_UNKNOWN_VAL "?"
53 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
56 typedef void cmdfunc_t(int, char **, const char *);
57 static cmdfunc_t do_create_if
, do_delete_if
, do_enable_if
, do_disable_if
;
58 static cmdfunc_t do_show_if
;
59 static cmdfunc_t do_set_prop
, do_show_prop
, do_set_ifprop
;
60 static cmdfunc_t do_show_ifprop
, do_reset_ifprop
, do_reset_prop
;
61 static cmdfunc_t do_show_addrprop
, do_set_addrprop
, do_reset_addrprop
;
62 static cmdfunc_t do_create_addr
, do_delete_addr
, do_show_addr
;
63 static cmdfunc_t do_enable_addr
, do_disable_addr
;
64 static cmdfunc_t do_up_addr
, do_down_addr
, do_refresh_addr
;
72 static cmd_t cmds
[] = {
73 /* interface management related sub-commands */
74 { "create-if", do_create_if
, "\tcreate-if\t[-t] <interface>" },
75 { "disable-if", do_disable_if
, "\tdisable-if\t-t <interface>" },
76 { "enable-if", do_enable_if
, "\tenable-if\t-t <interface>" },
77 { "delete-if", do_delete_if
, "\tdelete-if\t<interface>" },
78 { "show-if", do_show_if
,
79 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
80 { "set-ifprop", do_set_ifprop
,
81 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
83 { "reset-ifprop", do_reset_ifprop
,
84 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
85 { "show-ifprop", do_show_ifprop
,
86 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
87 "\t\t\t[-m <protocol>] [interface]\n" },
89 /* address management related sub-commands */
90 { "create-addr", do_create_addr
,
91 "\tcreate-addr\t[-t] -T static [-d] "
92 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
93 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"
94 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
95 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
96 { "down-addr", do_down_addr
, "\tdown-addr\t[-t] <addrobj>" },
97 { "up-addr", do_up_addr
, "\tup-addr\t\t[-t] <addrobj>" },
98 { "disable-addr", do_disable_addr
, "\tdisable-addr\t-t <addrobj>" },
99 { "enable-addr", do_enable_addr
, "\tenable-addr\t-t <addrobj>" },
100 { "refresh-addr", do_refresh_addr
, "\trefresh-addr\t[-i] <addrobj>" },
101 { "delete-addr", do_delete_addr
, "\tdelete-addr\t[-r] <addrobj>" },
102 { "show-addr", do_show_addr
,
103 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
104 { "set-addrprop", do_set_addrprop
,
105 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
106 { "reset-addrprop", do_reset_addrprop
,
107 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
108 { "show-addrprop", do_show_addrprop
,
109 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
112 /* protocol properties related sub-commands */
113 { "set-prop", do_set_prop
,
114 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
115 { "reset-prop", do_reset_prop
,
116 "\treset-prop\t[-t] -p <prop> <protocol>" },
117 { "show-prop", do_show_prop
,
118 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
122 static const struct option if_longopts
[] = {
123 {"temporary", no_argument
, 0, 't' },
127 static const struct option show_prop_longopts
[] = {
128 {"parsable", no_argument
, 0, 'c' },
129 {"prop", required_argument
, 0, 'p' },
130 {"output", required_argument
, 0, 'o' },
134 static const struct option show_ifprop_longopts
[] = {
135 {"module", required_argument
, 0, 'm' },
136 {"parsable", no_argument
, 0, 'c' },
137 {"prop", required_argument
, 0, 'p' },
138 {"output", required_argument
, 0, 'o' },
142 static const struct option set_prop_longopts
[] = {
143 {"prop", required_argument
, 0, 'p' },
144 {"temporary", no_argument
, 0, 't' },
148 static const struct option set_ifprop_longopts
[] = {
149 {"module", required_argument
, 0, 'm' },
150 {"prop", required_argument
, 0, 'p' },
151 {"temporary", no_argument
, 0, 't' },
155 static const struct option addr_misc_longopts
[] = {
156 {"inform", no_argument
, 0, 'i' },
157 {"release", no_argument
, 0, 'r' },
158 {"temporary", no_argument
, 0, 't' },
162 static const struct option addr_longopts
[] = {
163 {"address", required_argument
, 0, 'a' },
164 {"down", no_argument
, 0, 'd' },
165 {"interface-id", required_argument
, 0, 'i' },
166 {"prop", required_argument
, 0, 'p' },
167 {"temporary", no_argument
, 0, 't' },
168 {"type", required_argument
, 0, 'T' },
169 {"wait", required_argument
, 0, 'w' },
173 static const struct option show_addr_longopts
[] = {
174 {"parsable", no_argument
, 0, 'p' },
175 {"output", required_argument
, 0, 'o' },
179 static const struct option show_if_longopts
[] = {
180 {"parsable", no_argument
, 0, 'p' },
181 {"output", required_argument
, 0, 'o' },
185 /* callback functions to print show-* subcommands output */
186 static ofmt_cb_t print_prop_cb
;
187 static ofmt_cb_t print_sa_cb
;
188 static ofmt_cb_t print_si_cb
;
190 /* structures for 'ipadm show-*' subcommands */
192 IPADM_PROPFIELD_IFNAME
,
193 IPADM_PROPFIELD_PROTO
,
194 IPADM_PROPFIELD_ADDROBJ
,
195 IPADM_PROPFIELD_PROPERTY
,
196 IPADM_PROPFIELD_PERM
,
197 IPADM_PROPFIELD_CURRENT
,
198 IPADM_PROPFIELD_PERSISTENT
,
199 IPADM_PROPFIELD_DEFAULT
,
200 IPADM_PROPFIELD_POSSIBLE
201 } ipadm_propfield_index_t
;
203 static ofmt_field_t intfprop_fields
[] = {
204 /* name, field width, index, callback */
205 { "IFNAME", 12, IPADM_PROPFIELD_IFNAME
, print_prop_cb
},
206 { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
207 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
208 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
209 { "CURRENT", 11, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
210 { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
211 { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
212 { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
217 static ofmt_field_t modprop_fields
[] = {
218 /* name, field width, index, callback */
219 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
220 { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
221 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
222 { "CURRENT", 13, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
223 { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
224 { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
225 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
229 static ofmt_field_t addrprop_fields
[] = {
230 /* name, field width, index, callback */
231 { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ
, print_prop_cb
},
232 { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
233 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
234 { "CURRENT", 16, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
235 { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
236 { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
237 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
241 typedef struct show_prop_state
{
242 char sps_ifname
[LIFNAMSIZ
];
243 char sps_aobjname
[IPADM_AOBJSIZ
];
244 const char *sps_pname
;
247 nvlist_t
*sps_proplist
;
248 boolean_t sps_parsable
;
249 boolean_t sps_addrprop
;
250 boolean_t sps_ifprop
;
251 boolean_t sps_modprop
;
252 ipadm_status_t sps_status
;
253 ipadm_status_t sps_retstatus
;
254 ofmt_handle_t sps_ofmt
;
257 typedef struct show_addr_state
{
258 boolean_t sa_parsable
;
259 boolean_t sa_persist
;
260 ofmt_handle_t sa_ofmt
;
263 typedef struct show_if_state
{
264 boolean_t si_parsable
;
265 ofmt_handle_t si_ofmt
;
268 typedef struct show_addr_args_s
{
269 show_addr_state_t
*sa_state
;
270 ipadm_addr_info_t
*sa_info
;
273 typedef struct show_if_args_s
{
274 show_if_state_t
*si_state
;
275 ipadm_if_info_t
*si_info
;
294 static ofmt_field_t show_addr_fields
[] = {
295 /* name, field width, id, callback */
296 { "ADDROBJ", 18, SA_ADDROBJ
, print_sa_cb
},
297 { "TYPE", 9, SA_TYPE
, print_sa_cb
},
298 { "STATE", 13, SA_STATE
, print_sa_cb
},
299 { "CURRENT", 8, SA_CURRENT
, print_sa_cb
},
300 { "PERSISTENT", 11, SA_PERSISTENT
, print_sa_cb
},
301 { "ADDR", 46, SA_ADDR
, print_sa_cb
},
305 static ofmt_field_t show_if_fields
[] = {
306 /* name, field width, id, callback */
307 { "IFNAME", 11, SI_IFNAME
, print_si_cb
},
308 { "STATE", 9, SI_STATE
, print_si_cb
},
309 { "CURRENT", 13, SI_CURRENT
, print_si_cb
},
310 { "PERSISTENT", 11, SI_PERSISTENT
, print_si_cb
},
314 #define IPADM_ALL_BITS ((uint_t)-1)
315 typedef struct intf_mask
{
322 * Handle to libipadm. Opened in main() before the sub-command specific
323 * function is called and is closed before the program exits.
325 ipadm_handle_t iph
= NULL
;
328 * Opaque ipadm address object. Used by all the address management subcommands.
330 ipadm_addrobj_t ipaddr
= NULL
;
332 static char *progname
;
334 static void die(const char *, ...);
335 static void die_opterr(int, int, const char *);
336 static void warn_ipadmerr(ipadm_status_t
, const char *, ...);
337 static void ipadm_ofmt_check(ofmt_status_t
, boolean_t
, ofmt_handle_t
);
338 static void ipadm_check_propstr(const char *, boolean_t
, const char *);
339 static void process_misc_addrargs(int, char **, const char *, int *,
348 (void) fprintf(stderr
,
349 gettext("usage: ipadm <subcommand> <args> ...\n"));
350 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
352 if (cmdp
->c_usage
!= NULL
)
353 (void) fprintf(stderr
, "%s\n", gettext(cmdp
->c_usage
));
356 ipadm_destroy_addrobj(ipaddr
);
362 main(int argc
, char *argv
[])
366 ipadm_status_t status
;
368 (void) setlocale(LC_ALL
, "");
369 (void) textdomain(TEXT_DOMAIN
);
371 if ((progname
= strrchr(argv
[0], '/')) == NULL
)
376 status
= ipadm_open(&iph
, 0);
377 if (status
!= IPADM_SUCCESS
) {
378 die("Could not open handle to library - %s",
379 ipadm_status2str(status
));
383 char *args
= "show-addr";
384 do_show_addr(1, &args
, args
);
389 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
391 if (strcmp(argv
[1], cmdp
->c_name
) == 0) {
392 cmdp
->c_fn(argc
- 1, &argv
[1], gettext(cmdp
->c_usage
));
393 ipadm_destroy_addrobj(ipaddr
);
399 (void) fprintf(stderr
, gettext("%s: unknown subcommand '%s'\n"),
407 * Create an IP interface for which no saved configuration exists in the
411 do_create_if(int argc
, char *argv
[], const char *use
)
413 ipadm_status_t status
;
415 uint32_t flags
= IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
;
418 while ((option
= getopt_long(argc
, argv
, ":t", if_longopts
,
423 * "ifconfig" mode - plumb interface, but do not
424 * restore settings that may exist in db.
426 flags
&= ~IPADM_OPT_PERSIST
;
429 die_opterr(optopt
, option
, use
);
432 if (optind
!= (argc
- 1))
433 die("Usage: %s", use
);
434 status
= ipadm_create_if(iph
, argv
[optind
], AF_UNSPEC
, flags
);
435 if (status
!= IPADM_SUCCESS
) {
436 die("Could not create %s : %s",
437 argv
[optind
], ipadm_status2str(status
));
442 * Enable an IP interface based on the persistent configuration for
446 do_enable_if(int argc
, char *argv
[], const char *use
)
448 ipadm_status_t status
;
450 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
452 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
453 if (flags
& IPADM_OPT_PERSIST
)
454 die("persistent operation not supported for enable-if");
455 status
= ipadm_enable_if(iph
, argv
[index
], flags
);
456 if (status
== IPADM_ALL_ADDRS_NOT_ENABLED
) {
457 warn_ipadmerr(status
, "");
458 } else if (status
!= IPADM_SUCCESS
) {
459 die("Could not enable %s : %s",
460 argv
[optind
], ipadm_status2str(status
));
465 * Remove an IP interface from both active and persistent configuration.
468 do_delete_if(int argc
, char *argv
[], const char *use
)
470 ipadm_status_t status
;
471 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
474 die("Usage: %s", use
);
476 status
= ipadm_delete_if(iph
, argv
[1], AF_UNSPEC
, flags
);
477 if (status
!= IPADM_SUCCESS
) {
478 die("Could not delete %s: %s",
479 argv
[optind
], ipadm_status2str(status
));
484 * Disable an IP interface by removing it from active configuration.
487 do_disable_if(int argc
, char *argv
[], const char *use
)
489 ipadm_status_t status
;
491 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
493 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
494 if (flags
& IPADM_OPT_PERSIST
)
495 die("persistent operation not supported for disable-if");
496 status
= ipadm_disable_if(iph
, argv
[index
], flags
);
497 if (status
!= IPADM_SUCCESS
) {
498 die("Could not disable %s: %s",
499 argv
[optind
], ipadm_status2str(status
));
504 * Print individual columns for the show-*prop subcommands.
507 print_prop(show_prop_state_t
*statep
, uint_t flags
, char *buf
, size_t bufsize
)
509 const char *prop_name
= statep
->sps_pname
;
510 char *ifname
= statep
->sps_ifname
;
511 char *propval
= statep
->sps_propval
;
512 uint_t proto
= statep
->sps_proto
;
513 size_t propsize
= MAXPROPVALLEN
;
515 ipadm_status_t status
;
517 if (statep
->sps_ifprop
) {
518 status
= ipadm_get_ifprop(iph
, ifname
, prop_name
, propval
,
519 &propsize
, proto
, flags
);
521 } else if (statep
->sps_modprop
) {
522 status
= ipadm_get_prop(iph
, prop_name
, propval
, &propsize
,
524 object
= ipadm_proto2str(proto
);
526 status
= ipadm_get_addrprop(iph
, prop_name
, propval
, &propsize
,
527 statep
->sps_aobjname
, flags
);
528 object
= statep
->sps_aobjname
;
531 if (status
!= IPADM_SUCCESS
) {
532 if ((status
== IPADM_NOTFOUND
&& (flags
& IPADM_OPT_PERSIST
)) ||
533 status
== IPADM_ENXIO
) {
537 statep
->sps_status
= status
;
538 statep
->sps_retstatus
= status
;
542 statep
->sps_status
= IPADM_SUCCESS
;
543 (void) snprintf(buf
, bufsize
, "%s", propval
);
547 * Callback function for show-*prop subcommands.
550 print_prop_cb(ofmt_arg_t
*ofarg
, char *buf
, size_t bufsize
)
552 show_prop_state_t
*statep
= ofarg
->ofmt_cbarg
;
553 const char *propname
= statep
->sps_pname
;
554 uint_t proto
= statep
->sps_proto
;
555 boolean_t cont
= _B_TRUE
;
558 * Fail retrieving remaining fields, if you fail
559 * to retrieve a field.
561 if (statep
->sps_status
!= IPADM_SUCCESS
)
564 switch (ofarg
->ofmt_id
) {
565 case IPADM_PROPFIELD_IFNAME
:
566 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_ifname
);
568 case IPADM_PROPFIELD_PROTO
:
569 (void) snprintf(buf
, bufsize
, "%s", ipadm_proto2str(proto
));
571 case IPADM_PROPFIELD_ADDROBJ
:
572 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_aobjname
);
574 case IPADM_PROPFIELD_PROPERTY
:
575 (void) snprintf(buf
, bufsize
, "%s", propname
);
577 case IPADM_PROPFIELD_PERM
:
578 print_prop(statep
, IPADM_OPT_PERM
, buf
, bufsize
);
580 case IPADM_PROPFIELD_CURRENT
:
581 print_prop(statep
, IPADM_OPT_ACTIVE
, buf
, bufsize
);
583 case IPADM_PROPFIELD_PERSISTENT
:
584 print_prop(statep
, IPADM_OPT_PERSIST
, buf
, bufsize
);
586 case IPADM_PROPFIELD_DEFAULT
:
587 print_prop(statep
, IPADM_OPT_DEFAULT
, buf
, bufsize
);
589 case IPADM_PROPFIELD_POSSIBLE
:
590 print_prop(statep
, IPADM_OPT_POSSIBLE
, buf
, bufsize
);
593 if (statep
->sps_status
!= IPADM_SUCCESS
)
599 * Callback function called by the property walker (ipadm_walk_prop() or
600 * ipadm_walk_proptbl()), for every matched property. This function in turn
601 * calls ofmt_print() to print property information.
604 show_property(void *arg
, const char *pname
, uint_t proto
)
606 show_prop_state_t
*statep
= arg
;
608 statep
->sps_pname
= pname
;
609 statep
->sps_proto
= proto
;
610 statep
->sps_status
= IPADM_SUCCESS
;
611 ofmt_print(statep
->sps_ofmt
, arg
);
614 * if an object is not found or operation is not supported then
617 if (statep
->sps_status
== IPADM_NOTFOUND
||
618 statep
->sps_status
== IPADM_NOTSUP
)
624 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
625 * for all the properties for the specified object, relavant information, will
626 * be displayed. Otherwise, for the selected property set, display relevant
630 show_properties(void *arg
, int prop_class
)
632 show_prop_state_t
*statep
= arg
;
633 nvlist_t
*nvl
= statep
->sps_proplist
;
634 uint_t proto
= statep
->sps_proto
;
637 ipadm_status_t status
;
639 /* allocate sufficient buffer to hold a property value */
640 if ((buf
= malloc(MAXPROPVALLEN
)) == NULL
)
641 die("insufficient memory");
642 statep
->sps_propval
= buf
;
644 /* if no properties were specified, display all the properties */
646 (void) ipadm_walk_proptbl(proto
, prop_class
, show_property
,
649 for (curr_nvp
= nvlist_next_nvpair(nvl
, NULL
); curr_nvp
;
650 curr_nvp
= nvlist_next_nvpair(nvl
, curr_nvp
)) {
651 name
= nvpair_name(curr_nvp
);
652 status
= ipadm_walk_prop(name
, proto
, prop_class
,
653 show_property
, statep
);
654 if (status
== IPADM_PROP_UNKNOWN
)
655 (void) show_property(statep
, name
, proto
);
663 * Display information for all or specific interface properties, either for a
664 * given interface or for all the interfaces in the system.
667 do_show_ifprop(int argc
, char **argv
, const char *use
)
670 nvlist_t
*proplist
= NULL
;
671 char *fields_str
= NULL
;
675 uint_t ofmtflags
= 0;
677 boolean_t m_arg
= _B_FALSE
;
679 ipadm_if_info_t
*ifinfo
, *ifp
;
680 ipadm_status_t status
;
681 show_prop_state_t state
;
684 bzero(&state
, sizeof (state
));
685 state
.sps_propval
= NULL
;
686 state
.sps_parsable
= _B_FALSE
;
687 state
.sps_ifprop
= _B_TRUE
;
688 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
689 while ((option
= getopt_long(argc
, argv
, ":p:m:co:",
690 show_ifprop_longopts
, NULL
)) != -1) {
693 if (ipadm_str2nvlist(optarg
, &proplist
,
695 die("invalid interface properties specified");
698 state
.sps_parsable
= _B_TRUE
;
705 die("cannot specify more than one -m");
710 die_opterr(optopt
, option
, use
);
715 if (optind
== argc
- 1)
716 ifname
= argv
[optind
];
717 else if (optind
!= argc
)
718 die("Usage: %s", use
);
724 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
725 die("invalid protocol '%s' specified", protostr
);
727 state
.sps_proto
= proto
;
728 state
.sps_proplist
= proplist
;
730 if (state
.sps_parsable
)
731 ofmtflags
|= OFMT_PARSABLE
;
732 oferr
= ofmt_open(fields_str
, intfprop_fields
, ofmtflags
, 0, &ofmt
);
733 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
734 state
.sps_ofmt
= ofmt
;
736 /* retrieve interface(s) and print the properties */
737 status
= ipadm_if_info(iph
, ifname
, &ifinfo
, 0, LIFC_DEFAULT
);
738 if (ifname
!= NULL
&& status
== IPADM_ENXIO
)
739 die("no such object '%s': %s", ifname
,
740 ipadm_status2str(status
));
741 if (status
!= IPADM_SUCCESS
)
742 die("Error retrieving interface(s): %s",
743 ipadm_status2str(status
));
744 for (ifp
= ifinfo
; ifp
; ifp
= ifp
->ifi_next
) {
745 (void) strlcpy(state
.sps_ifname
, ifp
->ifi_name
, LIFNAMSIZ
);
746 state
.sps_proto
= proto
;
747 show_properties(&state
, IPADMPROP_CLASS_IF
);
750 ipadm_free_if_info(ifinfo
);
752 nvlist_free(proplist
);
755 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
762 * set/reset the interface property for a given interface.
765 set_ifprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
768 ipadm_status_t status
= IPADM_SUCCESS
;
769 boolean_t p_arg
= _B_FALSE
;
770 boolean_t m_arg
= _B_FALSE
;
771 char *ifname
, *nv
, *protostr
;
772 char *prop_name
, *prop_val
;
773 uint_t flags
= IPADM_OPT_PERSIST
;
777 while ((option
= getopt_long(argc
, argv
, ":m:p:t",
778 set_ifprop_longopts
, NULL
)) != -1) {
782 die("-p must be specified once only");
785 ipadm_check_propstr(optarg
, reset
, use
);
790 die("-m must be specified once only");
795 flags
&= ~IPADM_OPT_PERSIST
;
798 die_opterr(optopt
, option
, use
);
802 if (!m_arg
|| !p_arg
|| optind
!= argc
- 1)
803 die("Usage: %s", use
);
805 ifname
= argv
[optind
];
808 prop_val
= strchr(nv
, '=');
809 if (prop_val
!= NULL
)
812 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
813 die("invalid protocol '%s' specified", protostr
);
816 flags
|= IPADM_OPT_DEFAULT
;
818 flags
|= IPADM_OPT_ACTIVE
;
819 status
= ipadm_set_ifprop(iph
, ifname
, prop_name
, prop_val
, proto
,
823 if (status
!= IPADM_SUCCESS
) {
825 die("reset-ifprop: %s: %s",
826 prop_name
, ipadm_status2str(status
));
828 die("set-ifprop: %s: %s",
829 prop_name
, ipadm_status2str(status
));
834 do_set_ifprop(int argc
, char **argv
, const char *use
)
836 set_ifprop(argc
, argv
, _B_FALSE
, use
);
840 do_reset_ifprop(int argc
, char **argv
, const char *use
)
842 set_ifprop(argc
, argv
, _B_TRUE
, use
);
846 * Display information for all or specific protocol properties, either for a
847 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
850 do_show_prop(int argc
, char **argv
, const char *use
)
853 nvlist_t
*proplist
= NULL
;
854 char *fields_str
= NULL
;
856 show_prop_state_t state
;
859 uint_t ofmtflags
= 0;
861 boolean_t p_arg
= _B_FALSE
;
864 bzero(&state
, sizeof (state
));
865 state
.sps_propval
= NULL
;
866 state
.sps_parsable
= _B_FALSE
;
867 state
.sps_modprop
= _B_TRUE
;
868 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
869 while ((option
= getopt_long(argc
, argv
, ":p:co:", show_prop_longopts
,
874 die("-p must be specified once only");
876 if (ipadm_str2nvlist(optarg
, &proplist
,
878 die("invalid protocol properties specified");
881 state
.sps_parsable
= _B_TRUE
;
887 die_opterr(optopt
, option
, use
);
891 if (optind
== argc
- 1) {
892 protostr
= argv
[optind
];
893 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
894 die("invalid protocol '%s' specified", protostr
);
895 state
.sps_proto
= proto
;
896 } else if (optind
!= argc
) {
897 die("Usage: %s", use
);
900 die("protocol must be specified when "
901 "property name is used");
902 state
.sps_proto
= MOD_PROTO_NONE
;
905 state
.sps_proplist
= proplist
;
907 if (state
.sps_parsable
)
908 ofmtflags
|= OFMT_PARSABLE
;
910 ofmtflags
|= OFMT_WRAP
;
911 oferr
= ofmt_open(fields_str
, modprop_fields
, ofmtflags
, 0, &ofmt
);
912 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
913 state
.sps_ofmt
= ofmt
;
915 /* handles all the errors */
916 show_properties(&state
, IPADMPROP_CLASS_MODULE
);
918 nvlist_free(proplist
);
921 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
928 * Checks to see if there are any modifiers, + or -. If there are modifiers
929 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
932 parse_modifiers(const char *pstr
, uint_t
*flags
, const char *use
)
936 if ((p
= strchr(pstr
, '=')) == NULL
)
940 die("Invalid prop=val specified\n%s", use
);
944 *flags
|= IPADM_OPT_APPEND
;
946 *flags
|= IPADM_OPT_REMOVE
;
950 * set/reset the protocol property for a given protocol.
953 set_prop(int argc
, char **argv
, boolean_t reset
, const char *use
)
956 ipadm_status_t status
= IPADM_SUCCESS
;
957 char *protostr
, *nv
, *prop_name
, *prop_val
;
958 boolean_t p_arg
= _B_FALSE
;
960 uint_t flags
= IPADM_OPT_PERSIST
;
963 while ((option
= getopt_long(argc
, argv
, ":p:t", set_prop_longopts
,
968 die("-p must be specified once only");
971 ipadm_check_propstr(optarg
, reset
, use
);
975 flags
&= ~IPADM_OPT_PERSIST
;
978 die_opterr(optopt
, option
, use
);
982 if (!p_arg
|| optind
!= argc
- 1)
983 die("Usage: %s", use
);
985 parse_modifiers(nv
, &flags
, use
);
987 prop_val
= strchr(nv
, '=');
988 if (prop_val
!= NULL
) {
989 if (flags
& (IPADM_OPT_APPEND
|IPADM_OPT_REMOVE
))
990 *(prop_val
- 1) = '\0';
993 protostr
= argv
[optind
];
994 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
995 die("invalid protocol '%s' specified", protostr
);
998 flags
|= IPADM_OPT_DEFAULT
;
1000 flags
|= IPADM_OPT_ACTIVE
;
1001 status
= ipadm_set_prop(iph
, prop_name
, prop_val
, proto
, flags
);
1003 if (status
!= IPADM_SUCCESS
) {
1005 die("reset-prop: %s: %s",
1006 prop_name
, ipadm_status2str(status
));
1008 die("set-prop: %s: %s",
1009 prop_name
, ipadm_status2str(status
));
1014 do_set_prop(int argc
, char **argv
, const char *use
)
1016 set_prop(argc
, argv
, _B_FALSE
, use
);
1020 do_reset_prop(int argc
, char **argv
, const char *use
)
1022 set_prop(argc
, argv
, _B_TRUE
, use
);
1027 warn(const char *format
, ...)
1031 format
= gettext(format
);
1032 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1034 va_start(alist
, format
);
1035 (void) vfprintf(stderr
, format
, alist
);
1038 (void) fprintf(stderr
, "\n");
1043 die(const char *format
, ...)
1047 format
= gettext(format
);
1048 (void) fprintf(stderr
, "%s: ", progname
);
1050 va_start(alist
, format
);
1051 (void) vfprintf(stderr
, format
, alist
);
1054 (void) putchar('\n');
1056 ipadm_destroy_addrobj(ipaddr
);
1062 die_opterr(int opt
, int opterr
, const char *usage
)
1066 die("option '-%c' requires a value\nusage: %s", opt
,
1071 die("unrecognized option '-%c'\nusage: %s", opt
,
1079 warn_ipadmerr(ipadm_status_t err
, const char *format
, ...)
1083 format
= gettext(format
);
1084 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1086 va_start(alist
, format
);
1087 (void) vfprintf(stderr
, format
, alist
);
1090 (void) fprintf(stderr
, "%s\n", ipadm_status2str(err
));
1094 process_static_addrargs(const char *use
, char *addrarg
, const char *aobjname
)
1100 char *save_input_arg
= addrarg
;
1101 boolean_t found_mismatch
= _B_FALSE
;
1102 ipadm_status_t status
;
1103 enum { A_LOCAL
, A_REMOTE
};
1104 static char *addr_optstr
[] = {
1110 while (*addrarg
!= '\0') {
1111 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1115 die("Multiple local addresses provided");
1120 die("Multiple remote addresses provided");
1125 die("Invalid address provided\nusage: %s", use
);
1126 found_mismatch
= _B_TRUE
;
1130 if (raddr
!= NULL
&& laddr
== NULL
)
1131 die("Missing local address\nusage: %s", use
);
1133 /* If only one address is provided, it is assumed a local address. */
1134 if (laddr
== NULL
) {
1136 laddr
= save_input_arg
;
1138 die("Missing local address\nusage: %s", use
);
1141 /* Initialize the addrobj for static addresses. */
1142 status
= ipadm_create_addrobj(IPADM_ADDR_STATIC
, aobjname
, &ipaddr
);
1143 if (status
!= IPADM_SUCCESS
) {
1144 die("Error in creating address object: %s",
1145 ipadm_status2str(status
));
1148 /* Set the local and remote addresses */
1149 status
= ipadm_set_addr(ipaddr
, laddr
, AF_UNSPEC
);
1150 if (status
!= IPADM_SUCCESS
) {
1151 die("Error in setting local address: %s",
1152 ipadm_status2str(status
));
1154 if (raddr
!= NULL
) {
1155 status
= ipadm_set_dst_addr(ipaddr
, raddr
, AF_UNSPEC
);
1156 if (status
!= IPADM_SUCCESS
) {
1157 die("Error in setting remote address: %s",
1158 ipadm_status2str(status
));
1164 process_addrconf_addrargs(const char *use
, char *addrarg
)
1168 enum { P_STATELESS
, P_STATEFUL
};
1169 static char *addr_optstr
[] = {
1174 boolean_t stateless
;
1175 boolean_t stateless_arg
= _B_FALSE
;
1177 boolean_t stateful_arg
= _B_FALSE
;
1178 ipadm_status_t status
;
1180 while (*addrarg
!= '\0') {
1181 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1185 die("Duplicate option");
1187 die("Invalid argument");
1188 if (strcmp(val
, "yes") == 0)
1189 stateless
= _B_TRUE
;
1190 else if (strcmp(val
, "no") == 0)
1191 stateless
= _B_FALSE
;
1193 die("Invalid argument");
1194 stateless_arg
= _B_TRUE
;
1198 die("Duplicate option");
1200 die("Invalid argument");
1201 if (strcmp(val
, "yes") == 0)
1203 else if (strcmp(val
, "no") == 0)
1204 stateful
= _B_FALSE
;
1206 die("Invalid argument");
1207 stateful_arg
= _B_TRUE
;
1210 die_opterr(optopt
, option
, use
);
1214 if (!stateless_arg
&& !stateful_arg
)
1215 die("Invalid arguments for option -p");
1217 /* Set the addrobj fields for addrconf */
1218 if (stateless_arg
) {
1219 status
= ipadm_set_stateless(ipaddr
, stateless
);
1220 if (status
!= IPADM_SUCCESS
) {
1221 die("Error in setting stateless option: %s",
1222 ipadm_status2str(status
));
1226 status
= ipadm_set_stateful(ipaddr
, stateful
);
1227 if (status
!= IPADM_SUCCESS
) {
1228 die("Error in setting stateful option: %s",
1229 ipadm_status2str(status
));
1235 * Creates static, dhcp or addrconf addresses and associates the created
1236 * addresses with the specified address object name.
1239 do_create_addr(int argc
, char *argv
[], const char *use
)
1241 ipadm_status_t status
;
1244 IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
|IPADM_OPT_UP
|IPADM_OPT_V46
;
1247 char *static_arg
= NULL
;
1248 char *addrconf_arg
= NULL
;
1249 char *interface_id
= NULL
;
1251 boolean_t s_opt
= _B_FALSE
; /* static addr options */
1252 boolean_t auto_opt
= _B_FALSE
; /* Addrconf options */
1253 boolean_t dhcp_opt
= _B_FALSE
; /* dhcp options */
1256 while ((option
= getopt_long(argc
, argv
, ":T:a:di:p:w:t",
1257 addr_longopts
, NULL
)) != -1) {
1263 static_arg
= optarg
;
1267 flags
&= ~IPADM_OPT_UP
;
1271 interface_id
= optarg
;
1275 addrconf_arg
= optarg
;
1283 flags
&= ~IPADM_OPT_PERSIST
;
1286 die_opterr(optopt
, option
, use
);
1289 if (atype
== NULL
|| optind
!= (argc
- 1)) {
1290 die("Invalid arguments\nusage: %s", use
);
1291 } else if ((cp
= strchr(argv
[optind
], '/')) == NULL
||
1292 strlen(++cp
) == 0) {
1293 die("invalid address object name: %s\nusage: %s",
1298 * Allocate and initialize the addrobj based on the address type.
1300 if (strcmp(atype
, "static") == 0) {
1301 if (static_arg
== NULL
|| auto_opt
|| dhcp_opt
) {
1302 die("Invalid arguments for type %s\nusage: %s",
1305 process_static_addrargs(use
, static_arg
, argv
[optind
]);
1306 } else if (strcmp(atype
, "dhcp") == 0) {
1307 if (auto_opt
|| s_opt
) {
1308 die("Invalid arguments for type %s\nusage: %s",
1312 /* Initialize the addrobj for dhcp addresses. */
1313 status
= ipadm_create_addrobj(IPADM_ADDR_DHCP
, argv
[optind
],
1315 if (status
!= IPADM_SUCCESS
) {
1316 die("Error in creating address object: %s",
1317 ipadm_status2str(status
));
1322 if (strcmp(wait
, "forever") == 0) {
1323 ipadm_wait
= IPADM_DHCP_WAIT_FOREVER
;
1326 long timeout
= strtol(wait
, &end
, 10);
1328 if (*end
!= '\0' || timeout
< 0)
1329 die("Invalid argument");
1330 ipadm_wait
= (int32_t)timeout
;
1332 status
= ipadm_set_wait_time(ipaddr
, ipadm_wait
);
1333 if (status
!= IPADM_SUCCESS
) {
1334 die("Error in setting wait time: %s",
1335 ipadm_status2str(status
));
1338 } else if (strcmp(atype
, "addrconf") == 0) {
1339 if (dhcp_opt
|| s_opt
) {
1340 die("Invalid arguments for type %s\nusage: %s",
1344 /* Initialize the addrobj for dhcp addresses. */
1345 status
= ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF
,
1346 argv
[optind
], &ipaddr
);
1347 if (status
!= IPADM_SUCCESS
) {
1348 die("Error in creating address object: %s",
1349 ipadm_status2str(status
));
1351 if (interface_id
!= NULL
) {
1352 status
= ipadm_set_interface_id(ipaddr
, interface_id
);
1353 if (status
!= IPADM_SUCCESS
) {
1354 die("Error in setting interface ID: %s",
1355 ipadm_status2str(status
));
1359 process_addrconf_addrargs(use
, addrconf_arg
);
1361 die("Invalid address type %s", atype
);
1364 status
= ipadm_create_addr(iph
, ipaddr
, flags
);
1365 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1366 warn_ipadmerr(status
, "");
1367 else if (status
!= IPADM_SUCCESS
)
1368 die("Could not create address: %s", ipadm_status2str(status
));
1372 * Used by some address management functions to parse the command line
1373 * arguments and create `ipaddr' address object.
1376 process_misc_addrargs(int argc
, char *argv
[], const char *use
, int *index
,
1382 while ((option
= getopt_long(argc
, argv
, ":t", addr_misc_longopts
,
1386 *flags
&= ~IPADM_OPT_PERSIST
;
1389 die_opterr(optopt
, option
, use
);
1392 if (optind
!= (argc
- 1))
1393 die("Usage: %s", use
);
1399 * Remove an addrobj from both active and persistent configuration.
1402 do_delete_addr(int argc
, char *argv
[], const char *use
)
1404 ipadm_status_t status
;
1405 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1409 while ((option
= getopt_long(argc
, argv
, ":r", addr_misc_longopts
,
1413 flags
|= IPADM_OPT_RELEASE
;
1416 die_opterr(optopt
, option
, use
);
1419 if (optind
!= (argc
- 1))
1420 die("Usage: %s", use
);
1422 status
= ipadm_delete_addr(iph
, argv
[optind
], flags
);
1423 if (status
!= IPADM_SUCCESS
) {
1424 die("could not delete address: %s",
1425 ipadm_status2str(status
));
1430 * Enable an IP address based on the persistent configuration for that
1434 do_enable_addr(int argc
, char *argv
[], const char *use
)
1436 ipadm_status_t status
;
1438 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1440 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1441 if (flags
& IPADM_OPT_PERSIST
)
1442 die("persistent operation not supported for enable-addr");
1444 status
= ipadm_enable_addr(iph
, argv
[index
], flags
);
1445 if (status
!= IPADM_SUCCESS
)
1446 die("could not enable address: %s", ipadm_status2str(status
));
1450 * Mark the address identified by addrobj 'up'
1453 do_up_addr(int argc
, char *argv
[], const char *use
)
1455 ipadm_status_t status
;
1457 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1459 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1460 status
= ipadm_up_addr(iph
, argv
[index
], flags
);
1461 if (status
!= IPADM_SUCCESS
) {
1462 die("Could not mark the address up: %s",
1463 ipadm_status2str(status
));
1468 * Disable the specified addrobj by removing it from active cofiguration
1471 do_disable_addr(int argc
, char *argv
[], const char *use
)
1473 ipadm_status_t status
;
1475 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1477 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1478 if (flags
& IPADM_OPT_PERSIST
)
1479 die("persistent operation not supported for disable-addr");
1481 status
= ipadm_disable_addr(iph
, argv
[index
], flags
);
1482 if (status
!= IPADM_SUCCESS
) {
1483 die("could not disable address: %s",
1484 ipadm_status2str(status
));
1489 * Mark the address identified by addrobj 'down'
1492 do_down_addr(int argc
, char *argv
[], const char *use
)
1494 ipadm_status_t status
;
1496 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1498 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1499 status
= ipadm_down_addr(iph
, argv
[index
], flags
);
1500 if (status
!= IPADM_SUCCESS
)
1501 die("Could not mark the address down: %s",
1502 ipadm_status2str(status
));
1506 * Restart DAD for static address. Extend lease duration for DHCP addresses
1509 do_refresh_addr(int argc
, char *argv
[], const char *use
)
1511 ipadm_status_t status
;
1516 while ((option
= getopt_long(argc
, argv
, ":i", addr_misc_longopts
,
1520 flags
|= IPADM_OPT_INFORM
;
1523 die_opterr(optopt
, option
, use
);
1526 if (optind
!= (argc
- 1))
1527 die("Usage: %s", use
);
1529 status
= ipadm_refresh_addr(iph
, argv
[optind
], flags
);
1530 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1531 warn_ipadmerr(status
, "");
1532 else if (status
!= IPADM_SUCCESS
)
1533 die("could not refresh address %s", ipadm_status2str(status
));
1537 sockaddr2str(const struct sockaddr_storage
*ssp
, char *buf
, uint_t bufsize
)
1540 struct sockaddr
*sp
= (struct sockaddr
*)ssp
;
1542 switch (ssp
->ss_family
) {
1544 socklen
= sizeof (struct sockaddr_in
);
1547 socklen
= sizeof (struct sockaddr_in6
);
1550 (void) strlcpy(buf
, STR_UNKNOWN_VAL
, bufsize
);
1554 (void) getnameinfo(sp
, socklen
, buf
, bufsize
, NULL
, 0,
1555 (NI_NOFQDN
| NI_NUMERICHOST
));
1559 flags2str(uint64_t flags
, fmask_t
*tbl
, boolean_t is_bits
,
1560 char *buf
, uint_t bufsize
)
1563 boolean_t first
= _B_TRUE
;
1566 for (i
= 0; tbl
[i
].name
; i
++) {
1567 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
)
1568 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1570 (void) strlcat(buf
, "-", bufsize
);
1573 for (i
= 0; tbl
[i
].name
; i
++) {
1574 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
) {
1576 (void) strlcat(buf
, ",", bufsize
);
1577 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1585 * return true if the address for lifname comes to us from the global zone
1586 * with 'allowed-ips' constraints.
1589 is_from_gz(const char *lifname
)
1591 ipadm_if_info_t
*if_info
;
1592 char phyname
[LIFNAMSIZ
], *cp
;
1593 boolean_t ret
= _B_FALSE
;
1594 ipadm_status_t status
;
1598 if ((zoneid
= getzoneid()) == GLOBAL_ZONEID
)
1599 return (_B_FALSE
); /* from-gz only makes sense in a NGZ */
1601 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &zflags
, sizeof (zflags
)) < 0)
1604 if (!(zflags
& ZF_NET_EXCL
))
1605 return (_B_TRUE
); /* everything is from the GZ for shared-ip */
1607 (void) strncpy(phyname
, lifname
, sizeof (phyname
));
1608 if ((cp
= strchr(phyname
, ':')) != NULL
)
1610 status
= ipadm_if_info(iph
, phyname
, &if_info
, 0, LIFC_DEFAULT
);
1611 if (status
!= IPADM_SUCCESS
)
1614 if (if_info
->ifi_cflags
& IFIF_L3PROTECT
)
1617 ipadm_free_if_info(if_info
);
1622 print_sa_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1624 show_addr_args_t
*arg
= ofarg
->ofmt_cbarg
;
1625 ipadm_addr_info_t
*ainfo
= arg
->sa_info
;
1626 char interface
[LIFNAMSIZ
];
1627 char addrbuf
[MAXPROPVALLEN
];
1628 char dstbuf
[MAXPROPVALLEN
];
1629 char prefixlenstr
[MAXPROPVALLEN
];
1631 struct sockaddr_in
*sin
;
1632 struct sockaddr_in6
*sin6
;
1634 char *phyname
= NULL
;
1635 struct ifaddrs
*ifa
= &ainfo
->ia_ifa
;
1636 fmask_t cflags_mask
[] = {
1637 { "U", IA_UP
, IA_UP
},
1638 { "u", IA_UNNUMBERED
, IA_UNNUMBERED
},
1639 { "p", IA_PRIVATE
, IA_PRIVATE
},
1640 { "t", IA_TEMPORARY
, IA_TEMPORARY
},
1641 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1644 fmask_t pflags_mask
[] = {
1645 { "U", IA_UP
, IA_UP
},
1646 { "p", IA_PRIVATE
, IA_PRIVATE
},
1647 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1651 { "static", IPADM_ADDR_STATIC
, IPADM_ALL_BITS
},
1652 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF
, IPADM_ALL_BITS
},
1653 { "dhcp", IPADM_ADDR_DHCP
, IPADM_ALL_BITS
},
1656 fmask_t addr_state
[] = {
1657 { "disabled", IFA_DISABLED
, IPADM_ALL_BITS
},
1658 { "duplicate", IFA_DUPLICATE
, IPADM_ALL_BITS
},
1659 { "down", IFA_DOWN
, IPADM_ALL_BITS
},
1660 { "tentative", IFA_TENTATIVE
, IPADM_ALL_BITS
},
1661 { "ok", IFA_OK
, IPADM_ALL_BITS
},
1662 { "inaccessible", IFA_INACCESSIBLE
, IPADM_ALL_BITS
},
1667 switch (ofarg
->ofmt_id
) {
1669 if (ainfo
->ia_aobjname
[0] == '\0') {
1670 (void) strncpy(interface
, ifa
->ifa_name
, LIFNAMSIZ
);
1671 phyname
= strrchr(interface
, ':');
1674 (void) snprintf(buf
, bufsize
, "%s/%s", interface
,
1677 (void) snprintf(buf
, bufsize
, "%s", ainfo
->ia_aobjname
);
1681 flags2str(ainfo
->ia_state
, addr_state
, _B_FALSE
,
1685 if (is_from_gz(ifa
->ifa_name
))
1686 (void) snprintf(buf
, bufsize
, "from-gz");
1688 flags2str(ainfo
->ia_atype
, type
, _B_FALSE
, buf
,
1692 flags2str(ainfo
->ia_cflags
, cflags_mask
, _B_TRUE
, buf
, bufsize
);
1695 flags2str(ainfo
->ia_pflags
, pflags_mask
, _B_TRUE
, buf
, bufsize
);
1698 af
= ifa
->ifa_addr
->sa_family
;
1700 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1701 * print STR_UNKNOWN_VAL.
1703 if (ainfo
->ia_atype
== IPADM_ADDR_DHCP
) {
1704 sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1705 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1706 if ((af
== AF_INET
&&
1707 sin
->sin_addr
.s_addr
== INADDR_ANY
) ||
1709 IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
))) {
1710 (void) snprintf(buf
, bufsize
, STR_UNKNOWN_VAL
);
1714 if (ifa
->ifa_netmask
== NULL
)
1717 prefixlen
= mask2plen(ifa
->ifa_netmask
);
1718 bzero(prefixlenstr
, sizeof (prefixlenstr
));
1719 if (prefixlen
> 0) {
1720 (void) snprintf(prefixlenstr
, sizeof (prefixlenstr
),
1723 bzero(addrbuf
, sizeof (addrbuf
));
1724 bzero(dstbuf
, sizeof (dstbuf
));
1725 if (ainfo
->ia_atype
== IPADM_ADDR_STATIC
) {
1727 * Print the hostname fields if the address is not
1728 * in active configuration.
1730 if (ainfo
->ia_state
== IFA_DISABLED
) {
1731 (void) snprintf(buf
, bufsize
, "%s",
1733 if (ainfo
->ia_dname
[0] != '\0') {
1734 (void) snprintf(dstbuf
, sizeof (dstbuf
),
1735 "->%s", ainfo
->ia_dname
);
1736 (void) strlcat(buf
, dstbuf
, bufsize
);
1738 (void) strlcat(buf
, prefixlenstr
,
1745 * For the non-persistent case, we need to show the
1746 * currently configured addresses for source and
1749 sockaddr2str((struct sockaddr_storage
*)ifa
->ifa_addr
,
1750 addrbuf
, sizeof (addrbuf
));
1751 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
1753 (struct sockaddr_storage
*)ifa
->ifa_dstaddr
,
1754 dstbuf
, sizeof (dstbuf
));
1755 (void) snprintf(buf
, bufsize
, "%s->%s", addrbuf
,
1758 (void) snprintf(buf
, bufsize
, "%s%s", addrbuf
,
1763 die("invalid input");
1771 * Display address information, either for the given address or
1772 * for all the addresses managed by ipadm.
1775 do_show_addr(int argc
, char *argv
[], const char *use
)
1777 ipadm_status_t status
;
1778 show_addr_state_t state
;
1779 char *def_fields_str
= "addrobj,type,state,addr";
1780 char *fields_str
= NULL
;
1781 ipadm_addr_info_t
*ainfo
;
1782 ipadm_addr_info_t
*ptr
;
1783 show_addr_args_t sargs
;
1786 ofmt_status_t oferr
;
1787 uint_t ofmtflags
= 0;
1789 char *ifname
= NULL
;
1791 boolean_t found
= _B_FALSE
;
1794 state
.sa_parsable
= _B_FALSE
;
1795 state
.sa_persist
= _B_FALSE
;
1796 while ((option
= getopt_long(argc
, argv
, "po:", show_addr_longopts
,
1800 state
.sa_parsable
= _B_TRUE
;
1803 fields_str
= optarg
;
1806 die_opterr(optopt
, option
, use
);
1810 if (state
.sa_parsable
&& fields_str
== NULL
)
1811 die("-p requires -o");
1813 if (optind
== argc
- 1) {
1814 aname
= argv
[optind
];
1815 if ((cp
= strchr(aname
, '/')) == NULL
)
1816 die("Invalid address object name provided");
1817 if (*(cp
+ 1) == '\0') {
1822 } else if (optind
== argc
) {
1825 die("Usage: %s", use
);
1828 if (state
.sa_parsable
)
1829 ofmtflags
|= OFMT_PARSABLE
;
1830 if (fields_str
== NULL
)
1831 fields_str
= def_fields_str
;
1832 oferr
= ofmt_open(fields_str
, show_addr_fields
, ofmtflags
, 0, &ofmt
);
1834 ipadm_ofmt_check(oferr
, state
.sa_parsable
, ofmt
);
1835 state
.sa_ofmt
= ofmt
;
1837 status
= ipadm_addr_info(iph
, ifname
, &ainfo
, 0, LIFC_DEFAULT
);
1839 * Return without printing any error, if no addresses were found,
1840 * for the case where all addresses are requested.
1842 if (status
!= IPADM_SUCCESS
)
1843 die("Could not get address: %s", ipadm_status2str(status
));
1844 if (ainfo
== NULL
) {
1849 bzero(&sargs
, sizeof (sargs
));
1850 sargs
.sa_state
= &state
;
1851 for (ptr
= ainfo
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
1852 sargs
.sa_info
= ptr
;
1853 if (aname
!= NULL
) {
1854 if (strcmp(sargs
.sa_info
->ia_aobjname
, aname
) != 0)
1858 ofmt_print(state
.sa_ofmt
, &sargs
);
1861 ipadm_free_addr_info(ainfo
);
1862 if (aname
!= NULL
&& !found
)
1863 die("Address object not found");
1867 print_si_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1869 show_if_args_t
*arg
= ofarg
->ofmt_cbarg
;
1870 ipadm_if_info_t
*ifinfo
= arg
->si_info
;
1871 char *ifname
= ifinfo
->ifi_name
;
1872 fmask_t intf_state
[] = {
1873 { "ok", IFIS_OK
, IPADM_ALL_BITS
},
1874 { "down", IFIS_DOWN
, IPADM_ALL_BITS
},
1875 { "disabled", IFIS_DISABLED
, IPADM_ALL_BITS
},
1876 { "failed", IFIS_FAILED
, IPADM_ALL_BITS
},
1877 { "offline", IFIS_OFFLINE
, IPADM_ALL_BITS
},
1880 fmask_t intf_pflags
[] = {
1881 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1882 { "4", IFIF_IPV4
, IFIF_IPV4
},
1883 { "6", IFIF_IPV6
, IFIF_IPV6
},
1886 fmask_t intf_cflags
[] = {
1887 { "b", IFIF_BROADCAST
, IFIF_BROADCAST
},
1888 { "m", IFIF_MULTICAST
, IFIF_MULTICAST
},
1889 { "p", IFIF_POINTOPOINT
, IFIF_POINTOPOINT
},
1890 { "v", IFIF_VIRTUAL
, IFIF_VIRTUAL
},
1891 { "I", IFIF_IPMP
, IFIF_IPMP
},
1892 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1893 { "i", IFIF_INACTIVE
, IFIF_INACTIVE
},
1894 { "V", IFIF_VRRP
, IFIF_VRRP
},
1895 { "a", IFIF_NOACCEPT
, IFIF_NOACCEPT
},
1896 { "Z", IFIF_L3PROTECT
, IFIF_L3PROTECT
},
1897 { "4", IFIF_IPV4
, IFIF_IPV4
},
1898 { "6", IFIF_IPV6
, IFIF_IPV6
},
1903 switch (ofarg
->ofmt_id
) {
1905 (void) snprintf(buf
, bufsize
, "%s", ifname
);
1908 flags2str(ifinfo
->ifi_state
, intf_state
, _B_FALSE
,
1912 flags2str(ifinfo
->ifi_cflags
, intf_cflags
, _B_TRUE
,
1916 flags2str(ifinfo
->ifi_pflags
, intf_pflags
, _B_TRUE
,
1920 die("invalid input");
1928 * Display interface information, either for the given interface or
1929 * for all the interfaces in the system.
1932 do_show_if(int argc
, char *argv
[], const char *use
)
1934 ipadm_status_t status
;
1935 show_if_state_t state
;
1936 char *fields_str
= NULL
;
1937 ipadm_if_info_t
*if_info
, *ptr
;
1938 show_if_args_t sargs
;
1941 ofmt_status_t oferr
;
1942 uint_t ofmtflags
= 0;
1943 char *ifname
= NULL
;
1946 state
.si_parsable
= _B_FALSE
;
1948 while ((option
= getopt_long(argc
, argv
, "po:", show_if_longopts
,
1952 state
.si_parsable
= _B_TRUE
;
1955 fields_str
= optarg
;
1958 die_opterr(optopt
, option
, use
);
1962 if (optind
== argc
- 1)
1963 ifname
= argv
[optind
];
1964 else if (optind
!= argc
)
1965 die("Usage: %s", use
);
1966 if (state
.si_parsable
)
1967 ofmtflags
|= OFMT_PARSABLE
;
1968 oferr
= ofmt_open(fields_str
, show_if_fields
, ofmtflags
, 0, &ofmt
);
1969 ipadm_ofmt_check(oferr
, state
.si_parsable
, ofmt
);
1970 state
.si_ofmt
= ofmt
;
1971 bzero(&sargs
, sizeof (sargs
));
1972 sargs
.si_state
= &state
;
1973 status
= ipadm_if_info(iph
, ifname
, &if_info
, 0, LIFC_DEFAULT
);
1975 * Return without printing any error, if no addresses were found.
1977 if (status
!= IPADM_SUCCESS
) {
1978 die("Could not get interface(s): %s",
1979 ipadm_status2str(status
));
1982 for (ptr
= if_info
; ptr
; ptr
= ptr
->ifi_next
) {
1983 sargs
.si_info
= ptr
;
1984 ofmt_print(state
.si_ofmt
, &sargs
);
1987 ipadm_free_if_info(if_info
);
1991 * set/reset the address property for a given address
1994 set_addrprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
1997 ipadm_status_t status
= IPADM_SUCCESS
;
1998 boolean_t p_arg
= _B_FALSE
;
1999 char *nv
, *aobjname
;
2000 char *prop_name
, *prop_val
;
2001 uint_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
2004 while ((option
= getopt_long(argc
, argv
, ":i:p:t", set_ifprop_longopts
,
2009 die("-p must be specified once only");
2012 ipadm_check_propstr(optarg
, reset
, use
);
2016 flags
&= ~IPADM_OPT_PERSIST
;
2019 die_opterr(optopt
, option
, use
);
2023 if (!p_arg
|| optind
!= (argc
- 1))
2024 die("Usage: %s", use
);
2027 prop_val
= strchr(nv
, '=');
2028 if (prop_val
!= NULL
)
2030 aobjname
= argv
[optind
];
2032 flags
|= IPADM_OPT_DEFAULT
;
2033 status
= ipadm_set_addrprop(iph
, prop_name
, prop_val
, aobjname
, flags
);
2034 if (status
!= IPADM_SUCCESS
) {
2036 die("reset-addrprop: %s: %s", prop_name
,
2037 ipadm_status2str(status
));
2039 die("set-addrprop: %s: %s", prop_name
,
2040 ipadm_status2str(status
));
2045 * Sets a property on an address object.
2048 do_set_addrprop(int argc
, char **argv
, const char *use
)
2050 set_addrprop(argc
, argv
, _B_FALSE
, use
);
2054 * Resets a property to its default value on an address object.
2057 do_reset_addrprop(int argc
, char **argv
, const char *use
)
2059 set_addrprop(argc
, argv
, _B_TRUE
, use
);
2063 * Display information for all or specific address properties, either for a
2064 * given address or for all the addresses in the system.
2067 do_show_addrprop(int argc
, char *argv
[], const char *use
)
2070 nvlist_t
*proplist
= NULL
;
2071 char *fields_str
= NULL
;
2072 show_prop_state_t state
;
2074 ofmt_status_t oferr
;
2075 uint_t ofmtflags
= 0;
2076 char *aobjname
= NULL
;
2077 char *ifname
= NULL
;
2079 ipadm_addr_info_t
*ainfop
= NULL
;
2080 ipadm_addr_info_t
*ptr
;
2081 ipadm_status_t status
;
2082 boolean_t found
= _B_FALSE
;
2085 bzero(&state
, sizeof (state
));
2086 state
.sps_propval
= NULL
;
2087 state
.sps_parsable
= _B_FALSE
;
2088 state
.sps_addrprop
= _B_TRUE
;
2089 state
.sps_proto
= MOD_PROTO_NONE
;
2090 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
2091 while ((option
= getopt_long(argc
, argv
, ":p:i:cPo:",
2092 show_prop_longopts
, NULL
)) != -1) {
2095 if (ipadm_str2nvlist(optarg
, &proplist
,
2097 die("invalid addrobj properties specified");
2100 state
.sps_parsable
= _B_TRUE
;
2103 fields_str
= optarg
;
2106 die_opterr(optopt
, option
, use
);
2110 if (optind
== argc
- 1) {
2111 aobjname
= argv
[optind
];
2112 cp
= strchr(aobjname
, '/');
2114 die("invalid addrobj name provided");
2115 if (*(cp
+ 1) == '\0') {
2120 } else if (optind
!= argc
) {
2121 die("Usage: %s", use
);
2123 state
.sps_proplist
= proplist
;
2124 if (state
.sps_parsable
)
2125 ofmtflags
|= OFMT_PARSABLE
;
2126 oferr
= ofmt_open(fields_str
, addrprop_fields
, ofmtflags
, 0, &ofmt
);
2127 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
2128 state
.sps_ofmt
= ofmt
;
2130 status
= ipadm_addr_info(iph
, ifname
, &ainfop
, 0, LIFC_DEFAULT
);
2131 /* Return without printing any error, if no addresses were found */
2132 if (status
== IPADM_NOTFOUND
)
2134 if (status
!= IPADM_SUCCESS
)
2135 die("error retrieving address: %s", ipadm_status2str(status
));
2137 for (ptr
= ainfop
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
2138 char *taobjname
= ptr
->ia_aobjname
;
2140 if (taobjname
[0] == '\0')
2142 if (aobjname
!= NULL
) {
2143 if (strcmp(aobjname
, taobjname
) == 0)
2148 if (ptr
->ia_atype
== IPADM_ADDR_IPV6_ADDRCONF
) {
2154 (void) strlcpy(state
.sps_aobjname
, taobjname
,
2155 sizeof (state
.sps_aobjname
));
2156 show_properties(&state
, IPADMPROP_CLASS_ADDR
);
2160 ipadm_free_addr_info(ainfop
);
2162 if (aobjname
!= NULL
&& !found
)
2163 die("addrobj not found: %s", aobjname
);
2165 nvlist_free(proplist
);
2167 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
2174 ipadm_ofmt_check(ofmt_status_t oferr
, boolean_t parsable
,
2177 char buf
[OFMT_BUFSIZE
];
2179 if (oferr
== OFMT_SUCCESS
)
2181 (void) ofmt_strerror(ofmt
, oferr
, buf
, sizeof (buf
));
2183 * All errors are considered fatal in parsable mode.
2184 * NOMEM errors are always fatal, regardless of mode.
2185 * For other errors, we print diagnostics in human-readable
2186 * mode and processs what we can.
2188 if (parsable
|| oferr
== OFMT_ENOFIELDS
) {
2197 * check if the `pstr' adheres to following syntax
2198 * - prop=<value[,...]> (for set)
2199 * - prop (for reset)
2202 ipadm_check_propstr(const char *pstr
, boolean_t reset
, const char *use
)
2206 nv
= strchr(pstr
, '=');
2209 die("incorrect syntax used for -p.\n%s", use
);
2211 if (nv
== NULL
|| *++nv
== '\0')
2212 die("please specify the value to be set.\n%s", use
);
2213 nv
= strchr(nv
, '=');
2214 /* cannot have multiple 'prop=val' for single -p */
2216 die("cannot specify more than one prop=val at "
2217 "a time.\n%s", use
);