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
)
379 status
= ipadm_open(&iph
, 0);
380 if (status
!= IPADM_SUCCESS
) {
381 die("Could not open handle to library - %s",
382 ipadm_status2str(status
));
385 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
387 if (strcmp(argv
[1], cmdp
->c_name
) == 0) {
388 cmdp
->c_fn(argc
- 1, &argv
[1], gettext(cmdp
->c_usage
));
389 ipadm_destroy_addrobj(ipaddr
);
395 (void) fprintf(stderr
, gettext("%s: unknown subcommand '%s'\n"),
403 * Create an IP interface for which no saved configuration exists in the
407 do_create_if(int argc
, char *argv
[], const char *use
)
409 ipadm_status_t status
;
411 uint32_t flags
= IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
;
414 while ((option
= getopt_long(argc
, argv
, ":t", if_longopts
,
419 * "ifconfig" mode - plumb interface, but do not
420 * restore settings that may exist in db.
422 flags
&= ~IPADM_OPT_PERSIST
;
425 die_opterr(optopt
, option
, use
);
428 if (optind
!= (argc
- 1))
429 die("Usage: %s", use
);
430 status
= ipadm_create_if(iph
, argv
[optind
], AF_UNSPEC
, flags
);
431 if (status
!= IPADM_SUCCESS
) {
432 die("Could not create %s : %s",
433 argv
[optind
], ipadm_status2str(status
));
438 * Enable an IP interface based on the persistent configuration for
442 do_enable_if(int argc
, char *argv
[], const char *use
)
444 ipadm_status_t status
;
446 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
448 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
449 if (flags
& IPADM_OPT_PERSIST
)
450 die("persistent operation not supported for enable-if");
451 status
= ipadm_enable_if(iph
, argv
[index
], flags
);
452 if (status
== IPADM_ALL_ADDRS_NOT_ENABLED
) {
453 warn_ipadmerr(status
, "");
454 } else if (status
!= IPADM_SUCCESS
) {
455 die("Could not enable %s : %s",
456 argv
[optind
], ipadm_status2str(status
));
461 * Remove an IP interface from both active and persistent configuration.
464 do_delete_if(int argc
, char *argv
[], const char *use
)
466 ipadm_status_t status
;
467 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
470 die("Usage: %s", use
);
472 status
= ipadm_delete_if(iph
, argv
[1], AF_UNSPEC
, flags
);
473 if (status
!= IPADM_SUCCESS
) {
474 die("Could not delete %s: %s",
475 argv
[optind
], ipadm_status2str(status
));
480 * Disable an IP interface by removing it from active configuration.
483 do_disable_if(int argc
, char *argv
[], const char *use
)
485 ipadm_status_t status
;
487 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
489 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
490 if (flags
& IPADM_OPT_PERSIST
)
491 die("persistent operation not supported for disable-if");
492 status
= ipadm_disable_if(iph
, argv
[index
], flags
);
493 if (status
!= IPADM_SUCCESS
) {
494 die("Could not disable %s: %s",
495 argv
[optind
], ipadm_status2str(status
));
500 * Print individual columns for the show-*prop subcommands.
503 print_prop(show_prop_state_t
*statep
, uint_t flags
, char *buf
, size_t bufsize
)
505 const char *prop_name
= statep
->sps_pname
;
506 char *ifname
= statep
->sps_ifname
;
507 char *propval
= statep
->sps_propval
;
508 uint_t proto
= statep
->sps_proto
;
509 size_t propsize
= MAXPROPVALLEN
;
511 ipadm_status_t status
;
513 if (statep
->sps_ifprop
) {
514 status
= ipadm_get_ifprop(iph
, ifname
, prop_name
, propval
,
515 &propsize
, proto
, flags
);
517 } else if (statep
->sps_modprop
) {
518 status
= ipadm_get_prop(iph
, prop_name
, propval
, &propsize
,
520 object
= ipadm_proto2str(proto
);
522 status
= ipadm_get_addrprop(iph
, prop_name
, propval
, &propsize
,
523 statep
->sps_aobjname
, flags
);
524 object
= statep
->sps_aobjname
;
527 if (status
!= IPADM_SUCCESS
) {
528 if ((status
== IPADM_NOTFOUND
&& (flags
& IPADM_OPT_PERSIST
)) ||
529 status
== IPADM_ENXIO
) {
533 statep
->sps_status
= status
;
534 statep
->sps_retstatus
= status
;
538 statep
->sps_status
= IPADM_SUCCESS
;
539 (void) snprintf(buf
, bufsize
, "%s", propval
);
543 * Callback function for show-*prop subcommands.
546 print_prop_cb(ofmt_arg_t
*ofarg
, char *buf
, size_t bufsize
)
548 show_prop_state_t
*statep
= ofarg
->ofmt_cbarg
;
549 const char *propname
= statep
->sps_pname
;
550 uint_t proto
= statep
->sps_proto
;
551 boolean_t cont
= _B_TRUE
;
554 * Fail retrieving remaining fields, if you fail
555 * to retrieve a field.
557 if (statep
->sps_status
!= IPADM_SUCCESS
)
560 switch (ofarg
->ofmt_id
) {
561 case IPADM_PROPFIELD_IFNAME
:
562 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_ifname
);
564 case IPADM_PROPFIELD_PROTO
:
565 (void) snprintf(buf
, bufsize
, "%s", ipadm_proto2str(proto
));
567 case IPADM_PROPFIELD_ADDROBJ
:
568 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_aobjname
);
570 case IPADM_PROPFIELD_PROPERTY
:
571 (void) snprintf(buf
, bufsize
, "%s", propname
);
573 case IPADM_PROPFIELD_PERM
:
574 print_prop(statep
, IPADM_OPT_PERM
, buf
, bufsize
);
576 case IPADM_PROPFIELD_CURRENT
:
577 print_prop(statep
, IPADM_OPT_ACTIVE
, buf
, bufsize
);
579 case IPADM_PROPFIELD_PERSISTENT
:
580 print_prop(statep
, IPADM_OPT_PERSIST
, buf
, bufsize
);
582 case IPADM_PROPFIELD_DEFAULT
:
583 print_prop(statep
, IPADM_OPT_DEFAULT
, buf
, bufsize
);
585 case IPADM_PROPFIELD_POSSIBLE
:
586 print_prop(statep
, IPADM_OPT_POSSIBLE
, buf
, bufsize
);
589 if (statep
->sps_status
!= IPADM_SUCCESS
)
595 * Callback function called by the property walker (ipadm_walk_prop() or
596 * ipadm_walk_proptbl()), for every matched property. This function in turn
597 * calls ofmt_print() to print property information.
600 show_property(void *arg
, const char *pname
, uint_t proto
)
602 show_prop_state_t
*statep
= arg
;
604 statep
->sps_pname
= pname
;
605 statep
->sps_proto
= proto
;
606 statep
->sps_status
= IPADM_SUCCESS
;
607 ofmt_print(statep
->sps_ofmt
, arg
);
610 * if an object is not found or operation is not supported then
613 if (statep
->sps_status
== IPADM_NOTFOUND
||
614 statep
->sps_status
== IPADM_NOTSUP
)
620 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
621 * for all the properties for the specified object, relavant information, will
622 * be displayed. Otherwise, for the selected property set, display relevant
626 show_properties(void *arg
, int prop_class
)
628 show_prop_state_t
*statep
= arg
;
629 nvlist_t
*nvl
= statep
->sps_proplist
;
630 uint_t proto
= statep
->sps_proto
;
633 ipadm_status_t status
;
635 /* allocate sufficient buffer to hold a property value */
636 if ((buf
= malloc(MAXPROPVALLEN
)) == NULL
)
637 die("insufficient memory");
638 statep
->sps_propval
= buf
;
640 /* if no properties were specified, display all the properties */
642 (void) ipadm_walk_proptbl(proto
, prop_class
, show_property
,
645 for (curr_nvp
= nvlist_next_nvpair(nvl
, NULL
); curr_nvp
;
646 curr_nvp
= nvlist_next_nvpair(nvl
, curr_nvp
)) {
647 name
= nvpair_name(curr_nvp
);
648 status
= ipadm_walk_prop(name
, proto
, prop_class
,
649 show_property
, statep
);
650 if (status
== IPADM_PROP_UNKNOWN
)
651 (void) show_property(statep
, name
, proto
);
659 * Display information for all or specific interface properties, either for a
660 * given interface or for all the interfaces in the system.
663 do_show_ifprop(int argc
, char **argv
, const char *use
)
666 nvlist_t
*proplist
= NULL
;
667 char *fields_str
= NULL
;
671 uint_t ofmtflags
= 0;
673 boolean_t m_arg
= _B_FALSE
;
675 ipadm_if_info_t
*ifinfo
, *ifp
;
676 ipadm_status_t status
;
677 show_prop_state_t state
;
680 bzero(&state
, sizeof (state
));
681 state
.sps_propval
= NULL
;
682 state
.sps_parsable
= _B_FALSE
;
683 state
.sps_ifprop
= _B_TRUE
;
684 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
685 while ((option
= getopt_long(argc
, argv
, ":p:m:co:",
686 show_ifprop_longopts
, NULL
)) != -1) {
689 if (ipadm_str2nvlist(optarg
, &proplist
,
691 die("invalid interface properties specified");
694 state
.sps_parsable
= _B_TRUE
;
701 die("cannot specify more than one -m");
706 die_opterr(optopt
, option
, use
);
711 if (optind
== argc
- 1)
712 ifname
= argv
[optind
];
713 else if (optind
!= argc
)
714 die("Usage: %s", use
);
720 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
721 die("invalid protocol '%s' specified", protostr
);
723 state
.sps_proto
= proto
;
724 state
.sps_proplist
= proplist
;
726 if (state
.sps_parsable
)
727 ofmtflags
|= OFMT_PARSABLE
;
728 oferr
= ofmt_open(fields_str
, intfprop_fields
, ofmtflags
, 0, &ofmt
);
729 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
730 state
.sps_ofmt
= ofmt
;
732 /* retrieve interface(s) and print the properties */
733 status
= ipadm_if_info(iph
, ifname
, &ifinfo
, 0, LIFC_DEFAULT
);
734 if (ifname
!= NULL
&& status
== IPADM_ENXIO
)
735 die("no such object '%s': %s", ifname
,
736 ipadm_status2str(status
));
737 if (status
!= IPADM_SUCCESS
)
738 die("Error retrieving interface(s): %s",
739 ipadm_status2str(status
));
740 for (ifp
= ifinfo
; ifp
; ifp
= ifp
->ifi_next
) {
741 (void) strlcpy(state
.sps_ifname
, ifp
->ifi_name
, LIFNAMSIZ
);
742 state
.sps_proto
= proto
;
743 show_properties(&state
, IPADMPROP_CLASS_IF
);
746 ipadm_free_if_info(ifinfo
);
748 nvlist_free(proplist
);
751 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
758 * set/reset the interface property for a given interface.
761 set_ifprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
764 ipadm_status_t status
= IPADM_SUCCESS
;
765 boolean_t p_arg
= _B_FALSE
;
766 boolean_t m_arg
= _B_FALSE
;
767 char *ifname
, *nv
, *protostr
;
768 char *prop_name
, *prop_val
;
769 uint_t flags
= IPADM_OPT_PERSIST
;
773 while ((option
= getopt_long(argc
, argv
, ":m:p:t",
774 set_ifprop_longopts
, NULL
)) != -1) {
778 die("-p must be specified once only");
781 ipadm_check_propstr(optarg
, reset
, use
);
786 die("-m must be specified once only");
791 flags
&= ~IPADM_OPT_PERSIST
;
794 die_opterr(optopt
, option
, use
);
798 if (!m_arg
|| !p_arg
|| optind
!= argc
- 1)
799 die("Usage: %s", use
);
801 ifname
= argv
[optind
];
804 prop_val
= strchr(nv
, '=');
805 if (prop_val
!= NULL
)
808 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
809 die("invalid protocol '%s' specified", protostr
);
812 flags
|= IPADM_OPT_DEFAULT
;
814 flags
|= IPADM_OPT_ACTIVE
;
815 status
= ipadm_set_ifprop(iph
, ifname
, prop_name
, prop_val
, proto
,
819 if (status
!= IPADM_SUCCESS
) {
821 die("reset-ifprop: %s: %s",
822 prop_name
, ipadm_status2str(status
));
824 die("set-ifprop: %s: %s",
825 prop_name
, ipadm_status2str(status
));
830 do_set_ifprop(int argc
, char **argv
, const char *use
)
832 set_ifprop(argc
, argv
, _B_FALSE
, use
);
836 do_reset_ifprop(int argc
, char **argv
, const char *use
)
838 set_ifprop(argc
, argv
, _B_TRUE
, use
);
842 * Display information for all or specific protocol properties, either for a
843 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
846 do_show_prop(int argc
, char **argv
, const char *use
)
849 nvlist_t
*proplist
= NULL
;
850 char *fields_str
= NULL
;
852 show_prop_state_t state
;
855 uint_t ofmtflags
= 0;
857 boolean_t p_arg
= _B_FALSE
;
860 bzero(&state
, sizeof (state
));
861 state
.sps_propval
= NULL
;
862 state
.sps_parsable
= _B_FALSE
;
863 state
.sps_modprop
= _B_TRUE
;
864 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
865 while ((option
= getopt_long(argc
, argv
, ":p:co:", show_prop_longopts
,
870 die("-p must be specified once only");
872 if (ipadm_str2nvlist(optarg
, &proplist
,
874 die("invalid protocol properties specified");
877 state
.sps_parsable
= _B_TRUE
;
883 die_opterr(optopt
, option
, use
);
887 if (optind
== argc
- 1) {
888 protostr
= argv
[optind
];
889 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
890 die("invalid protocol '%s' specified", protostr
);
891 state
.sps_proto
= proto
;
892 } else if (optind
!= argc
) {
893 die("Usage: %s", use
);
896 die("protocol must be specified when "
897 "property name is used");
898 state
.sps_proto
= MOD_PROTO_NONE
;
901 state
.sps_proplist
= proplist
;
903 if (state
.sps_parsable
)
904 ofmtflags
|= OFMT_PARSABLE
;
906 ofmtflags
|= OFMT_WRAP
;
907 oferr
= ofmt_open(fields_str
, modprop_fields
, ofmtflags
, 0, &ofmt
);
908 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
909 state
.sps_ofmt
= ofmt
;
911 /* handles all the errors */
912 show_properties(&state
, IPADMPROP_CLASS_MODULE
);
914 nvlist_free(proplist
);
917 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
924 * Checks to see if there are any modifiers, + or -. If there are modifiers
925 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
928 parse_modifiers(const char *pstr
, uint_t
*flags
, const char *use
)
932 if ((p
= strchr(pstr
, '=')) == NULL
)
936 die("Invalid prop=val specified\n%s", use
);
940 *flags
|= IPADM_OPT_APPEND
;
942 *flags
|= IPADM_OPT_REMOVE
;
946 * set/reset the protocol property for a given protocol.
949 set_prop(int argc
, char **argv
, boolean_t reset
, const char *use
)
952 ipadm_status_t status
= IPADM_SUCCESS
;
953 char *protostr
, *nv
, *prop_name
, *prop_val
;
954 boolean_t p_arg
= _B_FALSE
;
956 uint_t flags
= IPADM_OPT_PERSIST
;
959 while ((option
= getopt_long(argc
, argv
, ":p:t", set_prop_longopts
,
964 die("-p must be specified once only");
967 ipadm_check_propstr(optarg
, reset
, use
);
971 flags
&= ~IPADM_OPT_PERSIST
;
974 die_opterr(optopt
, option
, use
);
978 if (!p_arg
|| optind
!= argc
- 1)
979 die("Usage: %s", use
);
981 parse_modifiers(nv
, &flags
, use
);
983 prop_val
= strchr(nv
, '=');
984 if (prop_val
!= NULL
) {
985 if (flags
& (IPADM_OPT_APPEND
|IPADM_OPT_REMOVE
))
986 *(prop_val
- 1) = '\0';
989 protostr
= argv
[optind
];
990 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
991 die("invalid protocol '%s' specified", protostr
);
994 flags
|= IPADM_OPT_DEFAULT
;
996 flags
|= IPADM_OPT_ACTIVE
;
997 status
= ipadm_set_prop(iph
, prop_name
, prop_val
, proto
, flags
);
999 if (status
!= IPADM_SUCCESS
) {
1001 die("reset-prop: %s: %s",
1002 prop_name
, ipadm_status2str(status
));
1004 die("set-prop: %s: %s",
1005 prop_name
, ipadm_status2str(status
));
1010 do_set_prop(int argc
, char **argv
, const char *use
)
1012 set_prop(argc
, argv
, _B_FALSE
, use
);
1016 do_reset_prop(int argc
, char **argv
, const char *use
)
1018 set_prop(argc
, argv
, _B_TRUE
, use
);
1023 warn(const char *format
, ...)
1027 format
= gettext(format
);
1028 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1030 va_start(alist
, format
);
1031 (void) vfprintf(stderr
, format
, alist
);
1034 (void) fprintf(stderr
, "\n");
1039 die(const char *format
, ...)
1043 format
= gettext(format
);
1044 (void) fprintf(stderr
, "%s: ", progname
);
1046 va_start(alist
, format
);
1047 (void) vfprintf(stderr
, format
, alist
);
1050 (void) putchar('\n');
1052 ipadm_destroy_addrobj(ipaddr
);
1058 die_opterr(int opt
, int opterr
, const char *usage
)
1062 die("option '-%c' requires a value\nusage: %s", opt
,
1067 die("unrecognized option '-%c'\nusage: %s", opt
,
1075 warn_ipadmerr(ipadm_status_t err
, const char *format
, ...)
1079 format
= gettext(format
);
1080 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1082 va_start(alist
, format
);
1083 (void) vfprintf(stderr
, format
, alist
);
1086 (void) fprintf(stderr
, "%s\n", ipadm_status2str(err
));
1090 process_static_addrargs(const char *use
, char *addrarg
, const char *aobjname
)
1096 char *save_input_arg
= addrarg
;
1097 boolean_t found_mismatch
= _B_FALSE
;
1098 ipadm_status_t status
;
1099 enum { A_LOCAL
, A_REMOTE
};
1100 static char *addr_optstr
[] = {
1106 while (*addrarg
!= '\0') {
1107 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1111 die("Multiple local addresses provided");
1116 die("Multiple remote addresses provided");
1121 die("Invalid address provided\nusage: %s", use
);
1122 found_mismatch
= _B_TRUE
;
1126 if (raddr
!= NULL
&& laddr
== NULL
)
1127 die("Missing local address\nusage: %s", use
);
1129 /* If only one address is provided, it is assumed a local address. */
1130 if (laddr
== NULL
) {
1132 laddr
= save_input_arg
;
1134 die("Missing local address\nusage: %s", use
);
1137 /* Initialize the addrobj for static addresses. */
1138 status
= ipadm_create_addrobj(IPADM_ADDR_STATIC
, aobjname
, &ipaddr
);
1139 if (status
!= IPADM_SUCCESS
) {
1140 die("Error in creating address object: %s",
1141 ipadm_status2str(status
));
1144 /* Set the local and remote addresses */
1145 status
= ipadm_set_addr(ipaddr
, laddr
, AF_UNSPEC
);
1146 if (status
!= IPADM_SUCCESS
) {
1147 die("Error in setting local address: %s",
1148 ipadm_status2str(status
));
1150 if (raddr
!= NULL
) {
1151 status
= ipadm_set_dst_addr(ipaddr
, raddr
, AF_UNSPEC
);
1152 if (status
!= IPADM_SUCCESS
) {
1153 die("Error in setting remote address: %s",
1154 ipadm_status2str(status
));
1160 process_addrconf_addrargs(const char *use
, char *addrarg
)
1164 enum { P_STATELESS
, P_STATEFUL
};
1165 static char *addr_optstr
[] = {
1170 boolean_t stateless
;
1171 boolean_t stateless_arg
= _B_FALSE
;
1173 boolean_t stateful_arg
= _B_FALSE
;
1174 ipadm_status_t status
;
1176 while (*addrarg
!= '\0') {
1177 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1181 die("Duplicate option");
1183 die("Invalid argument");
1184 if (strcmp(val
, "yes") == 0)
1185 stateless
= _B_TRUE
;
1186 else if (strcmp(val
, "no") == 0)
1187 stateless
= _B_FALSE
;
1189 die("Invalid argument");
1190 stateless_arg
= _B_TRUE
;
1194 die("Duplicate option");
1196 die("Invalid argument");
1197 if (strcmp(val
, "yes") == 0)
1199 else if (strcmp(val
, "no") == 0)
1200 stateful
= _B_FALSE
;
1202 die("Invalid argument");
1203 stateful_arg
= _B_TRUE
;
1206 die_opterr(optopt
, option
, use
);
1210 if (!stateless_arg
&& !stateful_arg
)
1211 die("Invalid arguments for option -p");
1213 /* Set the addrobj fields for addrconf */
1214 if (stateless_arg
) {
1215 status
= ipadm_set_stateless(ipaddr
, stateless
);
1216 if (status
!= IPADM_SUCCESS
) {
1217 die("Error in setting stateless option: %s",
1218 ipadm_status2str(status
));
1222 status
= ipadm_set_stateful(ipaddr
, stateful
);
1223 if (status
!= IPADM_SUCCESS
) {
1224 die("Error in setting stateful option: %s",
1225 ipadm_status2str(status
));
1231 * Creates static, dhcp or addrconf addresses and associates the created
1232 * addresses with the specified address object name.
1235 do_create_addr(int argc
, char *argv
[], const char *use
)
1237 ipadm_status_t status
;
1240 IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
|IPADM_OPT_UP
|IPADM_OPT_V46
;
1243 char *static_arg
= NULL
;
1244 char *addrconf_arg
= NULL
;
1245 char *interface_id
= NULL
;
1247 boolean_t s_opt
= _B_FALSE
; /* static addr options */
1248 boolean_t auto_opt
= _B_FALSE
; /* Addrconf options */
1249 boolean_t dhcp_opt
= _B_FALSE
; /* dhcp options */
1252 while ((option
= getopt_long(argc
, argv
, ":T:a:di:p:w:t",
1253 addr_longopts
, NULL
)) != -1) {
1259 static_arg
= optarg
;
1263 flags
&= ~IPADM_OPT_UP
;
1267 interface_id
= optarg
;
1271 addrconf_arg
= optarg
;
1279 flags
&= ~IPADM_OPT_PERSIST
;
1282 die_opterr(optopt
, option
, use
);
1285 if (atype
== NULL
|| optind
!= (argc
- 1)) {
1286 die("Invalid arguments\nusage: %s", use
);
1287 } else if ((cp
= strchr(argv
[optind
], '/')) == NULL
||
1288 strlen(++cp
) == 0) {
1289 die("invalid address object name: %s\nusage: %s",
1294 * Allocate and initialize the addrobj based on the address type.
1296 if (strcmp(atype
, "static") == 0) {
1297 if (static_arg
== NULL
|| auto_opt
|| dhcp_opt
) {
1298 die("Invalid arguments for type %s\nusage: %s",
1301 process_static_addrargs(use
, static_arg
, argv
[optind
]);
1302 } else if (strcmp(atype
, "dhcp") == 0) {
1303 if (auto_opt
|| s_opt
) {
1304 die("Invalid arguments for type %s\nusage: %s",
1308 /* Initialize the addrobj for dhcp addresses. */
1309 status
= ipadm_create_addrobj(IPADM_ADDR_DHCP
, argv
[optind
],
1311 if (status
!= IPADM_SUCCESS
) {
1312 die("Error in creating address object: %s",
1313 ipadm_status2str(status
));
1318 if (strcmp(wait
, "forever") == 0) {
1319 ipadm_wait
= IPADM_DHCP_WAIT_FOREVER
;
1322 long timeout
= strtol(wait
, &end
, 10);
1324 if (*end
!= '\0' || timeout
< 0)
1325 die("Invalid argument");
1326 ipadm_wait
= (int32_t)timeout
;
1328 status
= ipadm_set_wait_time(ipaddr
, ipadm_wait
);
1329 if (status
!= IPADM_SUCCESS
) {
1330 die("Error in setting wait time: %s",
1331 ipadm_status2str(status
));
1334 } else if (strcmp(atype
, "addrconf") == 0) {
1335 if (dhcp_opt
|| s_opt
) {
1336 die("Invalid arguments for type %s\nusage: %s",
1340 /* Initialize the addrobj for dhcp addresses. */
1341 status
= ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF
,
1342 argv
[optind
], &ipaddr
);
1343 if (status
!= IPADM_SUCCESS
) {
1344 die("Error in creating address object: %s",
1345 ipadm_status2str(status
));
1347 if (interface_id
!= NULL
) {
1348 status
= ipadm_set_interface_id(ipaddr
, interface_id
);
1349 if (status
!= IPADM_SUCCESS
) {
1350 die("Error in setting interface ID: %s",
1351 ipadm_status2str(status
));
1355 process_addrconf_addrargs(use
, addrconf_arg
);
1357 die("Invalid address type %s", atype
);
1360 status
= ipadm_create_addr(iph
, ipaddr
, flags
);
1361 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1362 warn_ipadmerr(status
, "");
1363 else if (status
!= IPADM_SUCCESS
)
1364 die("Could not create address: %s", ipadm_status2str(status
));
1368 * Used by some address management functions to parse the command line
1369 * arguments and create `ipaddr' address object.
1372 process_misc_addrargs(int argc
, char *argv
[], const char *use
, int *index
,
1378 while ((option
= getopt_long(argc
, argv
, ":t", addr_misc_longopts
,
1382 *flags
&= ~IPADM_OPT_PERSIST
;
1385 die_opterr(optopt
, option
, use
);
1388 if (optind
!= (argc
- 1))
1389 die("Usage: %s", use
);
1395 * Remove an addrobj from both active and persistent configuration.
1398 do_delete_addr(int argc
, char *argv
[], const char *use
)
1400 ipadm_status_t status
;
1401 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1405 while ((option
= getopt_long(argc
, argv
, ":r", addr_misc_longopts
,
1409 flags
|= IPADM_OPT_RELEASE
;
1412 die_opterr(optopt
, option
, use
);
1415 if (optind
!= (argc
- 1))
1416 die("Usage: %s", use
);
1418 status
= ipadm_delete_addr(iph
, argv
[optind
], flags
);
1419 if (status
!= IPADM_SUCCESS
) {
1420 die("could not delete address: %s",
1421 ipadm_status2str(status
));
1426 * Enable an IP address based on the persistent configuration for that
1430 do_enable_addr(int argc
, char *argv
[], const char *use
)
1432 ipadm_status_t status
;
1434 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1436 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1437 if (flags
& IPADM_OPT_PERSIST
)
1438 die("persistent operation not supported for enable-addr");
1440 status
= ipadm_enable_addr(iph
, argv
[index
], flags
);
1441 if (status
!= IPADM_SUCCESS
)
1442 die("could not enable address: %s", ipadm_status2str(status
));
1446 * Mark the address identified by addrobj 'up'
1449 do_up_addr(int argc
, char *argv
[], const char *use
)
1451 ipadm_status_t status
;
1453 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1455 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1456 status
= ipadm_up_addr(iph
, argv
[index
], flags
);
1457 if (status
!= IPADM_SUCCESS
) {
1458 die("Could not mark the address up: %s",
1459 ipadm_status2str(status
));
1464 * Disable the specified addrobj by removing it from active cofiguration
1467 do_disable_addr(int argc
, char *argv
[], const char *use
)
1469 ipadm_status_t status
;
1471 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1473 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1474 if (flags
& IPADM_OPT_PERSIST
)
1475 die("persistent operation not supported for disable-addr");
1477 status
= ipadm_disable_addr(iph
, argv
[index
], flags
);
1478 if (status
!= IPADM_SUCCESS
) {
1479 die("could not disable address: %s",
1480 ipadm_status2str(status
));
1485 * Mark the address identified by addrobj 'down'
1488 do_down_addr(int argc
, char *argv
[], const char *use
)
1490 ipadm_status_t status
;
1492 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1494 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1495 status
= ipadm_down_addr(iph
, argv
[index
], flags
);
1496 if (status
!= IPADM_SUCCESS
)
1497 die("Could not mark the address down: %s",
1498 ipadm_status2str(status
));
1502 * Restart DAD for static address. Extend lease duration for DHCP addresses
1505 do_refresh_addr(int argc
, char *argv
[], const char *use
)
1507 ipadm_status_t status
;
1512 while ((option
= getopt_long(argc
, argv
, ":i", addr_misc_longopts
,
1516 flags
|= IPADM_OPT_INFORM
;
1519 die_opterr(optopt
, option
, use
);
1522 if (optind
!= (argc
- 1))
1523 die("Usage: %s", use
);
1525 status
= ipadm_refresh_addr(iph
, argv
[optind
], flags
);
1526 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1527 warn_ipadmerr(status
, "");
1528 else if (status
!= IPADM_SUCCESS
)
1529 die("could not refresh address %s", ipadm_status2str(status
));
1533 sockaddr2str(const struct sockaddr_storage
*ssp
, char *buf
, uint_t bufsize
)
1536 struct sockaddr
*sp
= (struct sockaddr
*)ssp
;
1538 switch (ssp
->ss_family
) {
1540 socklen
= sizeof (struct sockaddr_in
);
1543 socklen
= sizeof (struct sockaddr_in6
);
1546 (void) strlcpy(buf
, STR_UNKNOWN_VAL
, bufsize
);
1550 (void) getnameinfo(sp
, socklen
, buf
, bufsize
, NULL
, 0,
1551 (NI_NOFQDN
| NI_NUMERICHOST
));
1555 flags2str(uint64_t flags
, fmask_t
*tbl
, boolean_t is_bits
,
1556 char *buf
, uint_t bufsize
)
1559 boolean_t first
= _B_TRUE
;
1562 for (i
= 0; tbl
[i
].name
; i
++) {
1563 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
)
1564 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1566 (void) strlcat(buf
, "-", bufsize
);
1569 for (i
= 0; tbl
[i
].name
; i
++) {
1570 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
) {
1572 (void) strlcat(buf
, ",", bufsize
);
1573 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1581 * return true if the address for lifname comes to us from the global zone
1582 * with 'allowed-ips' constraints.
1585 is_from_gz(const char *lifname
)
1587 ipadm_if_info_t
*if_info
;
1588 char phyname
[LIFNAMSIZ
], *cp
;
1589 boolean_t ret
= _B_FALSE
;
1590 ipadm_status_t status
;
1594 if ((zoneid
= getzoneid()) == GLOBAL_ZONEID
)
1595 return (_B_FALSE
); /* from-gz only makes sense in a NGZ */
1597 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &zflags
, sizeof (zflags
)) < 0)
1600 if (!(zflags
& ZF_NET_EXCL
))
1601 return (_B_TRUE
); /* everything is from the GZ for shared-ip */
1603 (void) strncpy(phyname
, lifname
, sizeof (phyname
));
1604 if ((cp
= strchr(phyname
, ':')) != NULL
)
1606 status
= ipadm_if_info(iph
, phyname
, &if_info
, 0, LIFC_DEFAULT
);
1607 if (status
!= IPADM_SUCCESS
)
1610 if (if_info
->ifi_cflags
& IFIF_L3PROTECT
)
1613 ipadm_free_if_info(if_info
);
1618 print_sa_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1620 show_addr_args_t
*arg
= ofarg
->ofmt_cbarg
;
1621 ipadm_addr_info_t
*ainfo
= arg
->sa_info
;
1622 char interface
[LIFNAMSIZ
];
1623 char addrbuf
[MAXPROPVALLEN
];
1624 char dstbuf
[MAXPROPVALLEN
];
1625 char prefixlenstr
[MAXPROPVALLEN
];
1627 struct sockaddr_in
*sin
;
1628 struct sockaddr_in6
*sin6
;
1630 char *phyname
= NULL
;
1631 struct ifaddrs
*ifa
= &ainfo
->ia_ifa
;
1632 fmask_t cflags_mask
[] = {
1633 { "U", IA_UP
, IA_UP
},
1634 { "u", IA_UNNUMBERED
, IA_UNNUMBERED
},
1635 { "p", IA_PRIVATE
, IA_PRIVATE
},
1636 { "t", IA_TEMPORARY
, IA_TEMPORARY
},
1637 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1640 fmask_t pflags_mask
[] = {
1641 { "U", IA_UP
, IA_UP
},
1642 { "p", IA_PRIVATE
, IA_PRIVATE
},
1643 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1647 { "static", IPADM_ADDR_STATIC
, IPADM_ALL_BITS
},
1648 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF
, IPADM_ALL_BITS
},
1649 { "dhcp", IPADM_ADDR_DHCP
, IPADM_ALL_BITS
},
1652 fmask_t addr_state
[] = {
1653 { "disabled", IFA_DISABLED
, IPADM_ALL_BITS
},
1654 { "duplicate", IFA_DUPLICATE
, IPADM_ALL_BITS
},
1655 { "down", IFA_DOWN
, IPADM_ALL_BITS
},
1656 { "tentative", IFA_TENTATIVE
, IPADM_ALL_BITS
},
1657 { "ok", IFA_OK
, IPADM_ALL_BITS
},
1658 { "inaccessible", IFA_INACCESSIBLE
, IPADM_ALL_BITS
},
1663 switch (ofarg
->ofmt_id
) {
1665 if (ainfo
->ia_aobjname
[0] == '\0') {
1666 (void) strncpy(interface
, ifa
->ifa_name
, LIFNAMSIZ
);
1667 phyname
= strrchr(interface
, ':');
1670 (void) snprintf(buf
, bufsize
, "%s/%s", interface
,
1673 (void) snprintf(buf
, bufsize
, "%s", ainfo
->ia_aobjname
);
1677 flags2str(ainfo
->ia_state
, addr_state
, _B_FALSE
,
1681 if (is_from_gz(ifa
->ifa_name
))
1682 (void) snprintf(buf
, bufsize
, "from-gz");
1684 flags2str(ainfo
->ia_atype
, type
, _B_FALSE
, buf
,
1688 flags2str(ainfo
->ia_cflags
, cflags_mask
, _B_TRUE
, buf
, bufsize
);
1691 flags2str(ainfo
->ia_pflags
, pflags_mask
, _B_TRUE
, buf
, bufsize
);
1694 af
= ifa
->ifa_addr
->sa_family
;
1696 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1697 * print STR_UNKNOWN_VAL.
1699 if (ainfo
->ia_atype
== IPADM_ADDR_DHCP
) {
1700 sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1701 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1702 if ((af
== AF_INET
&&
1703 sin
->sin_addr
.s_addr
== INADDR_ANY
) ||
1705 IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
))) {
1706 (void) snprintf(buf
, bufsize
, STR_UNKNOWN_VAL
);
1710 if (ifa
->ifa_netmask
== NULL
)
1713 prefixlen
= mask2plen(ifa
->ifa_netmask
);
1714 bzero(prefixlenstr
, sizeof (prefixlenstr
));
1715 if (prefixlen
> 0) {
1716 (void) snprintf(prefixlenstr
, sizeof (prefixlenstr
),
1719 bzero(addrbuf
, sizeof (addrbuf
));
1720 bzero(dstbuf
, sizeof (dstbuf
));
1721 if (ainfo
->ia_atype
== IPADM_ADDR_STATIC
) {
1723 * Print the hostname fields if the address is not
1724 * in active configuration.
1726 if (ainfo
->ia_state
== IFA_DISABLED
) {
1727 (void) snprintf(buf
, bufsize
, "%s",
1729 if (ainfo
->ia_dname
[0] != '\0') {
1730 (void) snprintf(dstbuf
, sizeof (dstbuf
),
1731 "->%s", ainfo
->ia_dname
);
1732 (void) strlcat(buf
, dstbuf
, bufsize
);
1734 (void) strlcat(buf
, prefixlenstr
,
1741 * For the non-persistent case, we need to show the
1742 * currently configured addresses for source and
1745 sockaddr2str((struct sockaddr_storage
*)ifa
->ifa_addr
,
1746 addrbuf
, sizeof (addrbuf
));
1747 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
1749 (struct sockaddr_storage
*)ifa
->ifa_dstaddr
,
1750 dstbuf
, sizeof (dstbuf
));
1751 (void) snprintf(buf
, bufsize
, "%s->%s", addrbuf
,
1754 (void) snprintf(buf
, bufsize
, "%s%s", addrbuf
,
1759 die("invalid input");
1767 * Display address information, either for the given address or
1768 * for all the addresses managed by ipadm.
1771 do_show_addr(int argc
, char *argv
[], const char *use
)
1773 ipadm_status_t status
;
1774 show_addr_state_t state
;
1775 char *def_fields_str
= "addrobj,type,state,addr";
1776 char *fields_str
= NULL
;
1777 ipadm_addr_info_t
*ainfo
;
1778 ipadm_addr_info_t
*ptr
;
1779 show_addr_args_t sargs
;
1782 ofmt_status_t oferr
;
1783 uint_t ofmtflags
= 0;
1785 char *ifname
= NULL
;
1787 boolean_t found
= _B_FALSE
;
1790 state
.sa_parsable
= _B_FALSE
;
1791 state
.sa_persist
= _B_FALSE
;
1792 while ((option
= getopt_long(argc
, argv
, "po:", show_addr_longopts
,
1796 state
.sa_parsable
= _B_TRUE
;
1799 fields_str
= optarg
;
1802 die_opterr(optopt
, option
, use
);
1806 if (state
.sa_parsable
&& fields_str
== NULL
)
1807 die("-p requires -o");
1809 if (optind
== argc
- 1) {
1810 aname
= argv
[optind
];
1811 if ((cp
= strchr(aname
, '/')) == NULL
)
1812 die("Invalid address object name provided");
1813 if (*(cp
+ 1) == '\0') {
1818 } else if (optind
== argc
) {
1821 die("Usage: %s", use
);
1824 if (state
.sa_parsable
)
1825 ofmtflags
|= OFMT_PARSABLE
;
1826 if (fields_str
== NULL
)
1827 fields_str
= def_fields_str
;
1828 oferr
= ofmt_open(fields_str
, show_addr_fields
, ofmtflags
, 0, &ofmt
);
1830 ipadm_ofmt_check(oferr
, state
.sa_parsable
, ofmt
);
1831 state
.sa_ofmt
= ofmt
;
1833 status
= ipadm_addr_info(iph
, ifname
, &ainfo
, 0, LIFC_DEFAULT
);
1835 * Return without printing any error, if no addresses were found,
1836 * for the case where all addresses are requested.
1838 if (status
!= IPADM_SUCCESS
)
1839 die("Could not get address: %s", ipadm_status2str(status
));
1840 if (ainfo
== NULL
) {
1845 bzero(&sargs
, sizeof (sargs
));
1846 sargs
.sa_state
= &state
;
1847 for (ptr
= ainfo
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
1848 sargs
.sa_info
= ptr
;
1849 if (aname
!= NULL
) {
1850 if (strcmp(sargs
.sa_info
->ia_aobjname
, aname
) != 0)
1854 ofmt_print(state
.sa_ofmt
, &sargs
);
1857 ipadm_free_addr_info(ainfo
);
1858 if (aname
!= NULL
&& !found
)
1859 die("Address object not found");
1863 print_si_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1865 show_if_args_t
*arg
= ofarg
->ofmt_cbarg
;
1866 ipadm_if_info_t
*ifinfo
= arg
->si_info
;
1867 char *ifname
= ifinfo
->ifi_name
;
1868 fmask_t intf_state
[] = {
1869 { "ok", IFIS_OK
, IPADM_ALL_BITS
},
1870 { "down", IFIS_DOWN
, IPADM_ALL_BITS
},
1871 { "disabled", IFIS_DISABLED
, IPADM_ALL_BITS
},
1872 { "failed", IFIS_FAILED
, IPADM_ALL_BITS
},
1873 { "offline", IFIS_OFFLINE
, IPADM_ALL_BITS
},
1876 fmask_t intf_pflags
[] = {
1877 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1878 { "4", IFIF_IPV4
, IFIF_IPV4
},
1879 { "6", IFIF_IPV6
, IFIF_IPV6
},
1882 fmask_t intf_cflags
[] = {
1883 { "b", IFIF_BROADCAST
, IFIF_BROADCAST
},
1884 { "m", IFIF_MULTICAST
, IFIF_MULTICAST
},
1885 { "p", IFIF_POINTOPOINT
, IFIF_POINTOPOINT
},
1886 { "v", IFIF_VIRTUAL
, IFIF_VIRTUAL
},
1887 { "I", IFIF_IPMP
, IFIF_IPMP
},
1888 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1889 { "i", IFIF_INACTIVE
, IFIF_INACTIVE
},
1890 { "V", IFIF_VRRP
, IFIF_VRRP
},
1891 { "a", IFIF_NOACCEPT
, IFIF_NOACCEPT
},
1892 { "Z", IFIF_L3PROTECT
, IFIF_L3PROTECT
},
1893 { "4", IFIF_IPV4
, IFIF_IPV4
},
1894 { "6", IFIF_IPV6
, IFIF_IPV6
},
1899 switch (ofarg
->ofmt_id
) {
1901 (void) snprintf(buf
, bufsize
, "%s", ifname
);
1904 flags2str(ifinfo
->ifi_state
, intf_state
, _B_FALSE
,
1908 flags2str(ifinfo
->ifi_cflags
, intf_cflags
, _B_TRUE
,
1912 flags2str(ifinfo
->ifi_pflags
, intf_pflags
, _B_TRUE
,
1916 die("invalid input");
1924 * Display interface information, either for the given interface or
1925 * for all the interfaces in the system.
1928 do_show_if(int argc
, char *argv
[], const char *use
)
1930 ipadm_status_t status
;
1931 show_if_state_t state
;
1932 char *fields_str
= NULL
;
1933 ipadm_if_info_t
*if_info
, *ptr
;
1934 show_if_args_t sargs
;
1937 ofmt_status_t oferr
;
1938 uint_t ofmtflags
= 0;
1939 char *ifname
= NULL
;
1942 state
.si_parsable
= _B_FALSE
;
1944 while ((option
= getopt_long(argc
, argv
, "po:", show_if_longopts
,
1948 state
.si_parsable
= _B_TRUE
;
1951 fields_str
= optarg
;
1954 die_opterr(optopt
, option
, use
);
1958 if (optind
== argc
- 1)
1959 ifname
= argv
[optind
];
1960 else if (optind
!= argc
)
1961 die("Usage: %s", use
);
1962 if (state
.si_parsable
)
1963 ofmtflags
|= OFMT_PARSABLE
;
1964 oferr
= ofmt_open(fields_str
, show_if_fields
, ofmtflags
, 0, &ofmt
);
1965 ipadm_ofmt_check(oferr
, state
.si_parsable
, ofmt
);
1966 state
.si_ofmt
= ofmt
;
1967 bzero(&sargs
, sizeof (sargs
));
1968 sargs
.si_state
= &state
;
1969 status
= ipadm_if_info(iph
, ifname
, &if_info
, 0, LIFC_DEFAULT
);
1971 * Return without printing any error, if no addresses were found.
1973 if (status
!= IPADM_SUCCESS
) {
1974 die("Could not get interface(s): %s",
1975 ipadm_status2str(status
));
1978 for (ptr
= if_info
; ptr
; ptr
= ptr
->ifi_next
) {
1979 sargs
.si_info
= ptr
;
1980 ofmt_print(state
.si_ofmt
, &sargs
);
1983 ipadm_free_if_info(if_info
);
1987 * set/reset the address property for a given address
1990 set_addrprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
1993 ipadm_status_t status
= IPADM_SUCCESS
;
1994 boolean_t p_arg
= _B_FALSE
;
1995 char *nv
, *aobjname
;
1996 char *prop_name
, *prop_val
;
1997 uint_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
2000 while ((option
= getopt_long(argc
, argv
, ":i:p:t", set_ifprop_longopts
,
2005 die("-p must be specified once only");
2008 ipadm_check_propstr(optarg
, reset
, use
);
2012 flags
&= ~IPADM_OPT_PERSIST
;
2015 die_opterr(optopt
, option
, use
);
2019 if (!p_arg
|| optind
!= (argc
- 1))
2020 die("Usage: %s", use
);
2023 prop_val
= strchr(nv
, '=');
2024 if (prop_val
!= NULL
)
2026 aobjname
= argv
[optind
];
2028 flags
|= IPADM_OPT_DEFAULT
;
2029 status
= ipadm_set_addrprop(iph
, prop_name
, prop_val
, aobjname
, flags
);
2030 if (status
!= IPADM_SUCCESS
) {
2032 die("reset-addrprop: %s: %s", prop_name
,
2033 ipadm_status2str(status
));
2035 die("set-addrprop: %s: %s", prop_name
,
2036 ipadm_status2str(status
));
2041 * Sets a property on an address object.
2044 do_set_addrprop(int argc
, char **argv
, const char *use
)
2046 set_addrprop(argc
, argv
, _B_FALSE
, use
);
2050 * Resets a property to its default value on an address object.
2053 do_reset_addrprop(int argc
, char **argv
, const char *use
)
2055 set_addrprop(argc
, argv
, _B_TRUE
, use
);
2059 * Display information for all or specific address properties, either for a
2060 * given address or for all the addresses in the system.
2063 do_show_addrprop(int argc
, char *argv
[], const char *use
)
2066 nvlist_t
*proplist
= NULL
;
2067 char *fields_str
= NULL
;
2068 show_prop_state_t state
;
2070 ofmt_status_t oferr
;
2071 uint_t ofmtflags
= 0;
2072 char *aobjname
= NULL
;
2073 char *ifname
= NULL
;
2075 ipadm_addr_info_t
*ainfop
= NULL
;
2076 ipadm_addr_info_t
*ptr
;
2077 ipadm_status_t status
;
2078 boolean_t found
= _B_FALSE
;
2081 bzero(&state
, sizeof (state
));
2082 state
.sps_propval
= NULL
;
2083 state
.sps_parsable
= _B_FALSE
;
2084 state
.sps_addrprop
= _B_TRUE
;
2085 state
.sps_proto
= MOD_PROTO_NONE
;
2086 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
2087 while ((option
= getopt_long(argc
, argv
, ":p:i:cPo:",
2088 show_prop_longopts
, NULL
)) != -1) {
2091 if (ipadm_str2nvlist(optarg
, &proplist
,
2093 die("invalid addrobj properties specified");
2096 state
.sps_parsable
= _B_TRUE
;
2099 fields_str
= optarg
;
2102 die_opterr(optopt
, option
, use
);
2106 if (optind
== argc
- 1) {
2107 aobjname
= argv
[optind
];
2108 cp
= strchr(aobjname
, '/');
2110 die("invalid addrobj name provided");
2111 if (*(cp
+ 1) == '\0') {
2116 } else if (optind
!= argc
) {
2117 die("Usage: %s", use
);
2119 state
.sps_proplist
= proplist
;
2120 if (state
.sps_parsable
)
2121 ofmtflags
|= OFMT_PARSABLE
;
2122 oferr
= ofmt_open(fields_str
, addrprop_fields
, ofmtflags
, 0, &ofmt
);
2123 ipadm_ofmt_check(oferr
, state
.sps_parsable
, ofmt
);
2124 state
.sps_ofmt
= ofmt
;
2126 status
= ipadm_addr_info(iph
, ifname
, &ainfop
, 0, LIFC_DEFAULT
);
2127 /* Return without printing any error, if no addresses were found */
2128 if (status
== IPADM_NOTFOUND
)
2130 if (status
!= IPADM_SUCCESS
)
2131 die("error retrieving address: %s", ipadm_status2str(status
));
2133 for (ptr
= ainfop
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
2134 char *taobjname
= ptr
->ia_aobjname
;
2136 if (taobjname
[0] == '\0')
2138 if (aobjname
!= NULL
) {
2139 if (strcmp(aobjname
, taobjname
) == 0)
2144 if (ptr
->ia_atype
== IPADM_ADDR_IPV6_ADDRCONF
) {
2150 (void) strlcpy(state
.sps_aobjname
, taobjname
,
2151 sizeof (state
.sps_aobjname
));
2152 show_properties(&state
, IPADMPROP_CLASS_ADDR
);
2156 ipadm_free_addr_info(ainfop
);
2158 if (aobjname
!= NULL
&& !found
)
2159 die("addrobj not found: %s", aobjname
);
2161 nvlist_free(proplist
);
2163 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
2170 ipadm_ofmt_check(ofmt_status_t oferr
, boolean_t parsable
,
2173 char buf
[OFMT_BUFSIZE
];
2175 if (oferr
== OFMT_SUCCESS
)
2177 (void) ofmt_strerror(ofmt
, oferr
, buf
, sizeof (buf
));
2179 * All errors are considered fatal in parsable mode.
2180 * NOMEM errors are always fatal, regardless of mode.
2181 * For other errors, we print diagnostics in human-readable
2182 * mode and processs what we can.
2184 if (parsable
|| oferr
== OFMT_ENOFIELDS
) {
2193 * check if the `pstr' adheres to following syntax
2194 * - prop=<value[,...]> (for set)
2195 * - prop (for reset)
2198 ipadm_check_propstr(const char *pstr
, boolean_t reset
, const char *use
)
2202 nv
= strchr(pstr
, '=');
2205 die("incorrect syntax used for -p.\n%s", use
);
2207 if (nv
== NULL
|| *++nv
== '\0')
2208 die("please specify the value to be set.\n%s", use
);
2209 nv
= strchr(nv
, '=');
2210 /* cannot have multiple 'prop=val' for single -p */
2212 die("cannot specify more than one prop=val at "
2213 "a time.\n%s", use
);