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.
25 * Copyright 2017 Joyent, Inc.
26 * Copyright 2017 Gary Mills
27 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
30 #include <arpa/inet.h>
34 #include <inet/iptun.h>
35 #include <inet/tunables.h>
37 #include <libdliptun.h>
38 #include <libdllink.h>
39 #include <libinetutil.h>
43 #include <netinet/in.h>
52 #include <sys/types.h>
55 #define STR_UNKNOWN_VAL "?"
56 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
59 typedef void cmdfunc_t(int, char **, const char *);
60 static cmdfunc_t do_create_if
, do_delete_if
, do_enable_if
, do_disable_if
;
61 static cmdfunc_t do_show_if
;
62 static cmdfunc_t do_set_prop
, do_show_prop
, do_set_ifprop
;
63 static cmdfunc_t do_show_ifprop
, do_reset_ifprop
, do_reset_prop
;
64 static cmdfunc_t do_show_addrprop
, do_set_addrprop
, do_reset_addrprop
;
65 static cmdfunc_t do_create_addr
, do_delete_addr
, do_show_addr
;
66 static cmdfunc_t do_enable_addr
, do_disable_addr
;
67 static cmdfunc_t do_up_addr
, do_down_addr
, do_refresh_addr
;
75 static cmd_t cmds
[] = {
76 /* interface management related sub-commands */
77 { "create-if", do_create_if
, "\tcreate-if\t[-t] <interface>" },
78 { "disable-if", do_disable_if
, "\tdisable-if\t-t <interface>" },
79 { "enable-if", do_enable_if
, "\tenable-if\t-t <interface>" },
80 { "delete-if", do_delete_if
, "\tdelete-if\t<interface>" },
81 { "show-if", do_show_if
,
82 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
83 { "set-ifprop", do_set_ifprop
,
84 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
86 { "reset-ifprop", do_reset_ifprop
,
87 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
88 { "show-ifprop", do_show_ifprop
,
89 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
90 "\t\t\t[-m <protocol>] [interface]\n" },
92 /* address management related sub-commands */
93 { "create-addr", do_create_addr
,
94 "\tcreate-addr\t[-t] -T static [-d] "
95 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
96 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
97 "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
98 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
99 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
100 { "down-addr", do_down_addr
, "\tdown-addr\t[-t] <addrobj>" },
101 { "up-addr", do_up_addr
, "\tup-addr\t\t[-t] <addrobj>" },
102 { "disable-addr", do_disable_addr
, "\tdisable-addr\t-t <addrobj>" },
103 { "enable-addr", do_enable_addr
, "\tenable-addr\t-t <addrobj>" },
104 { "refresh-addr", do_refresh_addr
, "\trefresh-addr\t[-i] <addrobj>" },
105 { "delete-addr", do_delete_addr
, "\tdelete-addr\t[-r] <addrobj>" },
106 { "show-addr", do_show_addr
,
107 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
108 { "set-addrprop", do_set_addrprop
,
109 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
110 { "reset-addrprop", do_reset_addrprop
,
111 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
112 { "show-addrprop", do_show_addrprop
,
113 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
116 /* protocol properties related sub-commands */
117 { "set-prop", do_set_prop
,
118 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
119 { "reset-prop", do_reset_prop
,
120 "\treset-prop\t[-t] -p <prop> <protocol>" },
121 { "show-prop", do_show_prop
,
122 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
126 static const struct option if_longopts
[] = {
127 {"temporary", no_argument
, 0, 't' },
131 static const struct option show_prop_longopts
[] = {
132 {"parsable", no_argument
, 0, 'c' },
133 {"prop", required_argument
, 0, 'p' },
134 {"output", required_argument
, 0, 'o' },
138 static const struct option show_ifprop_longopts
[] = {
139 {"module", required_argument
, 0, 'm' },
140 {"parsable", no_argument
, 0, 'c' },
141 {"prop", required_argument
, 0, 'p' },
142 {"output", required_argument
, 0, 'o' },
146 static const struct option set_prop_longopts
[] = {
147 {"prop", required_argument
, 0, 'p' },
148 {"temporary", no_argument
, 0, 't' },
152 static const struct option set_ifprop_longopts
[] = {
153 {"module", required_argument
, 0, 'm' },
154 {"prop", required_argument
, 0, 'p' },
155 {"temporary", no_argument
, 0, 't' },
159 static const struct option addr_misc_longopts
[] = {
160 {"inform", no_argument
, 0, 'i' },
161 {"release", no_argument
, 0, 'r' },
162 {"temporary", no_argument
, 0, 't' },
166 static const struct option addr_longopts
[] = {
167 {"address", required_argument
, 0, 'a' },
168 {"down", no_argument
, 0, 'd' },
169 {"interface-id", required_argument
, 0, 'i' },
170 {"primary", no_argument
, 0, '1' },
171 {"prop", required_argument
, 0, 'p' },
172 {"reqhost", required_argument
, 0, 'h' },
173 {"temporary", no_argument
, 0, 't' },
174 {"type", required_argument
, 0, 'T' },
175 {"wait", required_argument
, 0, 'w' },
179 static const struct option show_addr_longopts
[] = {
180 {"parsable", no_argument
, 0, 'p' },
181 {"output", required_argument
, 0, 'o' },
185 static const struct option show_if_longopts
[] = {
186 {"parsable", no_argument
, 0, 'p' },
187 {"output", required_argument
, 0, 'o' },
191 /* callback functions to print show-* subcommands output */
192 static ofmt_cb_t print_prop_cb
;
193 static ofmt_cb_t print_sa_cb
;
194 static ofmt_cb_t print_si_cb
;
196 /* structures for 'ipadm show-*' subcommands */
198 IPADM_PROPFIELD_IFNAME
,
199 IPADM_PROPFIELD_PROTO
,
200 IPADM_PROPFIELD_ADDROBJ
,
201 IPADM_PROPFIELD_PROPERTY
,
202 IPADM_PROPFIELD_PERM
,
203 IPADM_PROPFIELD_CURRENT
,
204 IPADM_PROPFIELD_PERSISTENT
,
205 IPADM_PROPFIELD_DEFAULT
,
206 IPADM_PROPFIELD_POSSIBLE
207 } ipadm_propfield_index_t
;
209 static ofmt_field_t intfprop_fields
[] = {
210 /* name, field width, index, callback */
211 { "IFNAME", 12, IPADM_PROPFIELD_IFNAME
, print_prop_cb
},
212 { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
213 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
214 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
215 { "CURRENT", 11, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
216 { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
217 { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
218 { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
223 static ofmt_field_t modprop_fields
[] = {
224 /* name, field width, index, callback */
225 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
226 { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
227 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
228 { "CURRENT", 13, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
229 { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
230 { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
231 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
235 static ofmt_field_t addrprop_fields
[] = {
236 /* name, field width, index, callback */
237 { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ
, print_prop_cb
},
238 { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
239 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
240 { "CURRENT", 16, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
241 { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
242 { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
243 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
247 typedef struct show_prop_state
{
248 char sps_ifname
[LIFNAMSIZ
];
249 char sps_aobjname
[IPADM_AOBJSIZ
];
250 const char *sps_pname
;
253 nvlist_t
*sps_proplist
;
254 boolean_t sps_parsable
;
255 boolean_t sps_addrprop
;
256 boolean_t sps_ifprop
;
257 boolean_t sps_modprop
;
258 ipadm_status_t sps_status
;
259 ipadm_status_t sps_retstatus
;
260 ofmt_handle_t sps_ofmt
;
263 typedef struct show_addr_state
{
264 boolean_t sa_parsable
;
265 boolean_t sa_persist
;
266 ofmt_handle_t sa_ofmt
;
269 typedef struct show_if_state
{
270 boolean_t si_parsable
;
271 ofmt_handle_t si_ofmt
;
274 typedef struct show_addr_args_s
{
275 show_addr_state_t
*sa_state
;
276 ipadm_addr_info_t
*sa_info
;
279 typedef struct show_if_args_s
{
280 show_if_state_t
*si_state
;
281 ipadm_if_info_t
*si_info
;
300 static ofmt_field_t show_addr_fields
[] = {
301 /* name, field width, id, callback */
302 { "ADDROBJ", 18, SA_ADDROBJ
, print_sa_cb
},
303 { "TYPE", 9, SA_TYPE
, print_sa_cb
},
304 { "STATE", 13, SA_STATE
, print_sa_cb
},
305 { "CURRENT", 8, SA_CURRENT
, print_sa_cb
},
306 { "PERSISTENT", 11, SA_PERSISTENT
, print_sa_cb
},
307 { "ADDR", 46, SA_ADDR
, print_sa_cb
},
311 static ofmt_field_t show_if_fields
[] = {
312 /* name, field width, id, callback */
313 { "IFNAME", 11, SI_IFNAME
, print_si_cb
},
314 { "STATE", 9, SI_STATE
, print_si_cb
},
315 { "CURRENT", 13, SI_CURRENT
, print_si_cb
},
316 { "PERSISTENT", 11, SI_PERSISTENT
, print_si_cb
},
320 #define IPADM_ALL_BITS ((uint_t)-1)
321 typedef struct intf_mask
{
328 * Handle to libipadm. Opened in main() before the sub-command specific
329 * function is called and is closed before the program exits.
331 ipadm_handle_t iph
= NULL
;
334 * Opaque ipadm address object. Used by all the address management subcommands.
336 ipadm_addrobj_t ipaddr
= NULL
;
338 static char *progname
;
341 static void warn(const char *, ...);
342 static void die(const char *, ...) __NORETURN
;
343 static void die_opterr(int, int, const char *) __NORETURN
;
344 static void warn_ipadmerr(ipadm_status_t
, const char *, ...);
345 static void ipadm_check_propstr(const char *, boolean_t
, const char *);
346 static void process_misc_addrargs(int, char **, const char *, int *,
355 (void) fprintf(stderr
,
356 gettext("usage: ipadm <subcommand> <args> ...\n"));
357 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
359 if (cmdp
->c_usage
!= NULL
)
360 (void) fprintf(stderr
, "%s\n", gettext(cmdp
->c_usage
));
363 ipadm_destroy_addrobj(ipaddr
);
369 main(int argc
, char *argv
[])
373 ipadm_status_t status
;
375 (void) setlocale(LC_ALL
, "");
376 (void) textdomain(TEXT_DOMAIN
);
378 if ((progname
= strrchr(argv
[0], '/')) == NULL
)
383 status
= ipadm_open(&iph
, 0);
384 if (status
!= IPADM_SUCCESS
) {
385 die("Could not open handle to library - %s",
386 ipadm_status2str(status
));
390 char *args
= "show-addr";
391 do_show_addr(1, &args
, args
);
396 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
398 if (strcmp(argv
[1], cmdp
->c_name
) == 0) {
399 cmdp
->c_fn(argc
- 1, &argv
[1], gettext(cmdp
->c_usage
));
400 ipadm_destroy_addrobj(ipaddr
);
406 (void) fprintf(stderr
, gettext("%s: unknown subcommand '%s'\n"),
414 * Create an IP interface for which no saved configuration exists in the
418 do_create_if(int argc
, char *argv
[], const char *use
)
420 ipadm_status_t status
;
422 uint32_t flags
= IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
;
425 while ((option
= getopt_long(argc
, argv
, ":t", if_longopts
,
430 * "ifconfig" mode - plumb interface, but do not
431 * restore settings that may exist in db.
433 flags
&= ~IPADM_OPT_PERSIST
;
436 die_opterr(optopt
, option
, use
);
439 if (optind
!= (argc
- 1))
440 die("Usage: %s", use
);
441 status
= ipadm_create_if(iph
, argv
[optind
], AF_UNSPEC
, flags
);
442 if (status
!= IPADM_SUCCESS
) {
443 die("Could not create %s : %s",
444 argv
[optind
], ipadm_status2str(status
));
449 * Enable an IP interface based on the persistent configuration for
453 do_enable_if(int argc
, char *argv
[], const char *use
)
455 ipadm_status_t status
;
457 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
459 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
460 if (flags
& IPADM_OPT_PERSIST
)
461 die("persistent operation not supported for enable-if");
462 status
= ipadm_enable_if(iph
, argv
[index
], flags
);
463 if (status
== IPADM_ALL_ADDRS_NOT_ENABLED
) {
464 warn_ipadmerr(status
, "");
465 } else if (status
!= IPADM_SUCCESS
) {
466 die("Could not enable %s : %s",
467 argv
[optind
], ipadm_status2str(status
));
472 * Remove an IP interface from both active and persistent configuration.
475 do_delete_if(int argc
, char *argv
[], const char *use
)
477 ipadm_status_t status
;
478 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
481 die("Usage: %s", use
);
483 status
= ipadm_delete_if(iph
, argv
[1], AF_UNSPEC
, flags
);
484 if (status
!= IPADM_SUCCESS
) {
485 die("Could not delete %s: %s",
486 argv
[optind
], ipadm_status2str(status
));
491 * Disable an IP interface by removing it from active configuration.
494 do_disable_if(int argc
, char *argv
[], const char *use
)
496 ipadm_status_t status
;
498 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
500 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
501 if (flags
& IPADM_OPT_PERSIST
)
502 die("persistent operation not supported for disable-if");
503 status
= ipadm_disable_if(iph
, argv
[index
], flags
);
504 if (status
!= IPADM_SUCCESS
) {
505 die("Could not disable %s: %s",
506 argv
[optind
], ipadm_status2str(status
));
511 * Print individual columns for the show-*prop subcommands.
514 print_prop(show_prop_state_t
*statep
, uint_t flags
, char *buf
, size_t bufsize
)
516 const char *prop_name
= statep
->sps_pname
;
517 char *ifname
= statep
->sps_ifname
;
518 char *propval
= statep
->sps_propval
;
519 uint_t proto
= statep
->sps_proto
;
520 size_t propsize
= MAXPROPVALLEN
;
521 ipadm_status_t status
;
523 if (statep
->sps_ifprop
) {
524 status
= ipadm_get_ifprop(iph
, ifname
, prop_name
, propval
,
525 &propsize
, proto
, flags
);
526 } else if (statep
->sps_modprop
) {
527 status
= ipadm_get_prop(iph
, prop_name
, propval
, &propsize
,
530 status
= ipadm_get_addrprop(iph
, prop_name
, propval
, &propsize
,
531 statep
->sps_aobjname
, flags
);
534 if (status
!= IPADM_SUCCESS
) {
535 if ((status
== IPADM_NOTFOUND
&& (flags
& IPADM_OPT_PERSIST
)) ||
536 status
== IPADM_ENXIO
) {
540 statep
->sps_status
= status
;
541 statep
->sps_retstatus
= status
;
545 statep
->sps_status
= IPADM_SUCCESS
;
546 (void) snprintf(buf
, bufsize
, "%s", propval
);
550 * Callback function for show-*prop subcommands.
553 print_prop_cb(ofmt_arg_t
*ofarg
, char *buf
, size_t bufsize
)
555 show_prop_state_t
*statep
= ofarg
->ofmt_cbarg
;
556 const char *propname
= statep
->sps_pname
;
557 uint_t proto
= statep
->sps_proto
;
558 boolean_t cont
= B_TRUE
;
561 * Fail retrieving remaining fields, if you fail
562 * to retrieve a field.
564 if (statep
->sps_status
!= IPADM_SUCCESS
)
567 switch (ofarg
->ofmt_id
) {
568 case IPADM_PROPFIELD_IFNAME
:
569 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_ifname
);
571 case IPADM_PROPFIELD_PROTO
:
572 (void) snprintf(buf
, bufsize
, "%s", ipadm_proto2str(proto
));
574 case IPADM_PROPFIELD_ADDROBJ
:
575 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_aobjname
);
577 case IPADM_PROPFIELD_PROPERTY
:
578 (void) snprintf(buf
, bufsize
, "%s", propname
);
580 case IPADM_PROPFIELD_PERM
:
581 print_prop(statep
, IPADM_OPT_PERM
, buf
, bufsize
);
583 case IPADM_PROPFIELD_CURRENT
:
584 print_prop(statep
, IPADM_OPT_ACTIVE
, buf
, bufsize
);
586 case IPADM_PROPFIELD_PERSISTENT
:
587 print_prop(statep
, IPADM_OPT_PERSIST
, buf
, bufsize
);
589 case IPADM_PROPFIELD_DEFAULT
:
590 print_prop(statep
, IPADM_OPT_DEFAULT
, buf
, bufsize
);
592 case IPADM_PROPFIELD_POSSIBLE
:
593 print_prop(statep
, IPADM_OPT_POSSIBLE
, buf
, bufsize
);
596 if (statep
->sps_status
!= IPADM_SUCCESS
)
602 * Callback function called by the property walker (ipadm_walk_prop() or
603 * ipadm_walk_proptbl()), for every matched property. This function in turn
604 * calls ofmt_print() to print property information.
607 show_property(void *arg
, const char *pname
, uint_t proto
)
609 show_prop_state_t
*statep
= arg
;
611 statep
->sps_pname
= pname
;
612 statep
->sps_proto
= proto
;
613 statep
->sps_status
= IPADM_SUCCESS
;
614 ofmt_print(statep
->sps_ofmt
, arg
);
617 * if an object is not found or operation is not supported then
620 if (statep
->sps_status
== IPADM_NOTFOUND
||
621 statep
->sps_status
== IPADM_NOTSUP
)
627 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
628 * for all the properties for the specified object, display relevant
629 * information. Otherwise, for the selected property set, display relevant
633 show_properties(void *arg
, int prop_class
)
635 show_prop_state_t
*statep
= arg
;
636 nvlist_t
*nvl
= statep
->sps_proplist
;
637 uint_t proto
= statep
->sps_proto
;
640 ipadm_status_t status
;
642 /* allocate sufficient buffer to hold a property value */
643 if ((buf
= malloc(MAXPROPVALLEN
)) == NULL
)
644 die("insufficient memory");
645 statep
->sps_propval
= buf
;
647 /* if no properties were specified, display all the properties */
649 (void) ipadm_walk_proptbl(proto
, prop_class
, show_property
,
652 for (curr_nvp
= nvlist_next_nvpair(nvl
, NULL
); curr_nvp
;
653 curr_nvp
= nvlist_next_nvpair(nvl
, curr_nvp
)) {
654 name
= nvpair_name(curr_nvp
);
655 status
= ipadm_walk_prop(name
, proto
, prop_class
,
656 show_property
, statep
);
657 if (status
== IPADM_PROP_UNKNOWN
)
658 (void) show_property(statep
, name
, proto
);
666 * Display information for all or specific interface properties, either for a
667 * given interface or for all the interfaces in the system.
670 do_show_ifprop(int argc
, char **argv
, const char *use
)
673 nvlist_t
*proplist
= NULL
;
674 char *fields_str
= NULL
;
678 uint_t ofmtflags
= 0;
680 boolean_t m_arg
= B_FALSE
;
682 ipadm_if_info_t
*ifinfo
, *ifp
;
683 ipadm_status_t status
;
684 show_prop_state_t state
;
688 bzero(&state
, sizeof (state
));
689 state
.sps_propval
= NULL
;
690 state
.sps_parsable
= B_FALSE
;
691 state
.sps_ifprop
= B_TRUE
;
692 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
693 while ((option
= getopt_long(argc
, argv
, ":p:m:co:",
694 show_ifprop_longopts
, NULL
)) != -1) {
697 if (ipadm_str2nvlist(optarg
, &proplist
,
699 die("invalid interface properties specified");
702 state
.sps_parsable
= B_TRUE
;
709 die("cannot specify more than one -m");
714 die_opterr(optopt
, option
, use
);
719 if (optind
== argc
- 1)
720 ifname
= argv
[optind
];
721 else if (optind
!= argc
)
722 die("Usage: %s", use
);
726 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
727 die("invalid protocol '%s' specified", protostr
);
729 state
.sps_proto
= proto
;
730 state
.sps_proplist
= proplist
;
732 if (state
.sps_parsable
)
733 ofmtflags
|= OFMT_PARSABLE
;
734 oferr
= ofmt_open(fields_str
, intfprop_fields
, ofmtflags
, 0, &ofmt
);
735 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
736 state
.sps_ofmt
= ofmt
;
738 /* retrieve interface(s) and print the properties */
739 status
= ipadm_if_info(iph
, ifname
, &ifinfo
, 0, LIFC_DEFAULT
);
740 if (ifname
!= NULL
&& status
== IPADM_ENXIO
)
741 die("no such object '%s': %s", ifname
,
742 ipadm_status2str(status
));
743 if (status
!= IPADM_SUCCESS
)
744 die("Error retrieving interface(s): %s",
745 ipadm_status2str(status
));
746 for (ifp
= ifinfo
; ifp
; ifp
= ifp
->ifi_next
) {
747 (void) strlcpy(state
.sps_ifname
, ifp
->ifi_name
, LIFNAMSIZ
);
748 state
.sps_proto
= proto
;
749 show_properties(&state
, IPADMPROP_CLASS_IF
);
752 ipadm_free_if_info(ifinfo
);
754 nvlist_free(proplist
);
757 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
764 * set/reset the interface property for a given interface.
767 set_ifprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
770 ipadm_status_t status
= IPADM_SUCCESS
;
771 boolean_t p_arg
= B_FALSE
;
772 boolean_t m_arg
= B_FALSE
;
773 char *ifname
, *nv
, *protostr
;
774 char *prop_name
, *prop_val
;
775 uint_t flags
= IPADM_OPT_PERSIST
;
781 while ((option
= getopt_long(argc
, argv
, ":m:p:t",
782 set_ifprop_longopts
, NULL
)) != -1) {
786 die("-p must be specified once only");
789 ipadm_check_propstr(optarg
, reset
, use
);
794 die("-m must be specified once only");
799 flags
&= ~IPADM_OPT_PERSIST
;
802 die_opterr(optopt
, option
, use
);
806 if (!m_arg
|| !p_arg
|| optind
!= argc
- 1)
807 die("Usage: %s", use
);
809 ifname
= argv
[optind
];
812 prop_val
= strchr(nv
, '=');
813 if (prop_val
!= NULL
)
816 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
817 die("invalid protocol '%s' specified", protostr
);
820 flags
|= IPADM_OPT_DEFAULT
;
822 flags
|= IPADM_OPT_ACTIVE
;
823 status
= ipadm_set_ifprop(iph
, ifname
, prop_name
, prop_val
, proto
,
826 if (status
!= IPADM_SUCCESS
) {
828 die("reset-ifprop: %s: %s",
829 prop_name
, ipadm_status2str(status
));
831 die("set-ifprop: %s: %s",
832 prop_name
, ipadm_status2str(status
));
837 do_set_ifprop(int argc
, char **argv
, const char *use
)
839 set_ifprop(argc
, argv
, B_FALSE
, use
);
843 do_reset_ifprop(int argc
, char **argv
, const char *use
)
845 set_ifprop(argc
, argv
, B_TRUE
, use
);
849 * Display information for all or specific protocol properties, either for a
850 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
853 do_show_prop(int argc
, char **argv
, const char *use
)
856 nvlist_t
*proplist
= NULL
;
857 char *fields_str
= NULL
;
859 show_prop_state_t state
;
862 uint_t ofmtflags
= 0;
864 boolean_t p_arg
= B_FALSE
;
867 bzero(&state
, sizeof (state
));
868 state
.sps_propval
= NULL
;
869 state
.sps_parsable
= B_FALSE
;
870 state
.sps_modprop
= B_TRUE
;
871 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
872 while ((option
= getopt_long(argc
, argv
, ":p:co:", show_prop_longopts
,
877 die("-p must be specified once only");
879 if (ipadm_str2nvlist(optarg
, &proplist
,
881 die("invalid protocol properties specified");
884 state
.sps_parsable
= B_TRUE
;
890 die_opterr(optopt
, option
, use
);
894 if (optind
== argc
- 1) {
895 protostr
= argv
[optind
];
896 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
897 die("invalid protocol '%s' specified", protostr
);
898 state
.sps_proto
= proto
;
899 } else if (optind
!= argc
) {
900 die("Usage: %s", use
);
903 die("protocol must be specified when "
904 "property name is used");
905 state
.sps_proto
= MOD_PROTO_NONE
;
908 state
.sps_proplist
= proplist
;
910 if (state
.sps_parsable
)
911 ofmtflags
|= OFMT_PARSABLE
;
913 ofmtflags
|= OFMT_WRAP
;
914 oferr
= ofmt_open(fields_str
, modprop_fields
, ofmtflags
, 0, &ofmt
);
915 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
916 state
.sps_ofmt
= ofmt
;
918 /* handles all the errors */
919 show_properties(&state
, IPADMPROP_CLASS_MODULE
);
921 nvlist_free(proplist
);
924 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
931 * Checks to see if there are any modifiers, + or -. If there are modifiers
932 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
935 parse_modifiers(const char *pstr
, uint_t
*flags
, const char *use
)
939 if ((p
= strchr(pstr
, '=')) == NULL
)
943 die("Invalid prop=val specified\n%s", use
);
947 *flags
|= IPADM_OPT_APPEND
;
949 *flags
|= IPADM_OPT_REMOVE
;
953 * set/reset the protocol property for a given protocol.
956 set_prop(int argc
, char **argv
, boolean_t reset
, const char *use
)
959 ipadm_status_t status
= IPADM_SUCCESS
;
960 char *protostr
, *nv
, *prop_name
, *prop_val
;
961 boolean_t p_arg
= B_FALSE
;
963 uint_t flags
= IPADM_OPT_PERSIST
;
967 while ((option
= getopt_long(argc
, argv
, ":p:t", set_prop_longopts
,
972 die("-p must be specified once only");
975 ipadm_check_propstr(optarg
, reset
, use
);
979 flags
&= ~IPADM_OPT_PERSIST
;
982 die_opterr(optopt
, option
, use
);
986 if (!p_arg
|| optind
!= argc
- 1)
987 die("Usage: %s", use
);
989 parse_modifiers(nv
, &flags
, use
);
991 prop_val
= strchr(nv
, '=');
992 if (prop_val
!= NULL
) {
993 if (flags
& (IPADM_OPT_APPEND
|IPADM_OPT_REMOVE
))
994 *(prop_val
- 1) = '\0';
997 protostr
= argv
[optind
];
998 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
999 die("invalid protocol '%s' specified", protostr
);
1002 flags
|= IPADM_OPT_DEFAULT
;
1004 flags
|= IPADM_OPT_ACTIVE
;
1005 status
= ipadm_set_prop(iph
, prop_name
, prop_val
, proto
, flags
);
1007 if (status
!= IPADM_SUCCESS
) {
1009 die("reset-prop: %s: %s",
1010 prop_name
, ipadm_status2str(status
));
1012 die("set-prop: %s: %s",
1013 prop_name
, ipadm_status2str(status
));
1018 do_set_prop(int argc
, char **argv
, const char *use
)
1020 set_prop(argc
, argv
, B_FALSE
, use
);
1024 do_reset_prop(int argc
, char **argv
, const char *use
)
1026 set_prop(argc
, argv
, B_TRUE
, use
);
1031 warn(const char *format
, ...)
1035 format
= gettext(format
);
1036 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1038 va_start(alist
, format
);
1039 (void) vfprintf(stderr
, format
, alist
);
1042 (void) fprintf(stderr
, "\n");
1047 die(const char *format
, ...)
1051 format
= gettext(format
);
1052 (void) fprintf(stderr
, "%s: ", progname
);
1054 va_start(alist
, format
);
1055 (void) vfprintf(stderr
, format
, alist
);
1058 (void) putchar('\n');
1060 ipadm_destroy_addrobj(ipaddr
);
1066 die_opterr(int opt
, int opterr
, const char *usage
)
1070 die("option '-%c' requires a value\nusage: %s", opt
,
1075 die("unrecognized option '-%c'\nusage: %s", opt
,
1083 warn_ipadmerr(ipadm_status_t err
, const char *format
, ...)
1087 format
= gettext(format
);
1088 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1090 va_start(alist
, format
);
1091 (void) vfprintf(stderr
, format
, alist
);
1094 (void) fprintf(stderr
, "%s\n", ipadm_status2str(err
));
1098 process_static_addrargs(const char *use
, char *addrarg
, const char *aobjname
)
1104 char *save_input_arg
= addrarg
;
1105 boolean_t found_mismatch
= B_FALSE
;
1106 ipadm_status_t status
;
1107 enum { A_LOCAL
, A_REMOTE
};
1108 static char *addr_optstr
[] = {
1114 while (*addrarg
!= '\0') {
1115 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1119 die("Multiple local addresses provided");
1124 die("Multiple remote addresses provided");
1129 die("Invalid address provided\nusage: %s", use
);
1130 found_mismatch
= B_TRUE
;
1134 if (raddr
!= NULL
&& laddr
== NULL
)
1135 die("Missing local address\nusage: %s", use
);
1137 /* If only one address is provided, it is assumed a local address. */
1138 if (laddr
== NULL
) {
1140 laddr
= save_input_arg
;
1142 die("Missing local address\nusage: %s", use
);
1145 /* Initialize the addrobj for static addresses. */
1146 status
= ipadm_create_addrobj(IPADM_ADDR_STATIC
, aobjname
, &ipaddr
);
1147 if (status
!= IPADM_SUCCESS
) {
1148 die("Error in creating address object: %s",
1149 ipadm_status2str(status
));
1152 /* Set the local and remote addresses */
1153 status
= ipadm_set_addr(ipaddr
, laddr
, AF_UNSPEC
);
1154 if (status
!= IPADM_SUCCESS
) {
1155 die("Error in setting local address: %s",
1156 ipadm_status2str(status
));
1158 if (raddr
!= NULL
) {
1159 status
= ipadm_set_dst_addr(ipaddr
, raddr
, AF_UNSPEC
);
1160 if (status
!= IPADM_SUCCESS
) {
1161 die("Error in setting remote address: %s",
1162 ipadm_status2str(status
));
1168 process_addrconf_addrargs(const char *use
, char *addrarg
)
1172 enum { P_STATELESS
, P_STATEFUL
};
1173 static char *addr_optstr
[] = {
1178 boolean_t stateless
= B_FALSE
;
1179 boolean_t stateless_arg
= B_FALSE
;
1180 boolean_t stateful
= B_FALSE
;
1181 boolean_t stateful_arg
= B_FALSE
;
1182 ipadm_status_t status
;
1184 while (*addrarg
!= '\0') {
1185 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1189 die("Duplicate option");
1191 die("Invalid argument");
1192 if (strcmp(val
, "yes") == 0)
1194 else if (strcmp(val
, "no") == 0)
1195 stateless
= B_FALSE
;
1197 die("Invalid argument");
1198 stateless_arg
= B_TRUE
;
1202 die("Duplicate option");
1204 die("Invalid argument");
1205 if (strcmp(val
, "yes") == 0)
1207 else if (strcmp(val
, "no") == 0)
1210 die("Invalid argument");
1211 stateful_arg
= B_TRUE
;
1214 die_opterr(optopt
, option
, use
);
1218 if (!stateless_arg
&& !stateful_arg
)
1219 die("Invalid arguments for option -p");
1221 /* Set the addrobj fields for addrconf */
1222 if (stateless_arg
) {
1223 status
= ipadm_set_stateless(ipaddr
, stateless
);
1224 if (status
!= IPADM_SUCCESS
) {
1225 die("Error in setting stateless option: %s",
1226 ipadm_status2str(status
));
1230 status
= ipadm_set_stateful(ipaddr
, stateful
);
1231 if (status
!= IPADM_SUCCESS
) {
1232 die("Error in setting stateful option: %s",
1233 ipadm_status2str(status
));
1239 * Creates static, dhcp or addrconf addresses and associates the created
1240 * addresses with the specified address object name.
1243 do_create_addr(int argc
, char *argv
[], const char *use
)
1245 ipadm_status_t status
;
1248 IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
|IPADM_OPT_UP
|IPADM_OPT_V46
;
1251 char *static_arg
= NULL
;
1252 char *addrconf_arg
= NULL
;
1253 char *interface_id
= NULL
;
1255 char *reqhost
= NULL
;
1256 boolean_t s_opt
= B_FALSE
; /* static addr options */
1257 boolean_t auto_opt
= B_FALSE
; /* Addrconf options */
1258 boolean_t dhcp_opt
= B_FALSE
; /* dhcp options */
1259 boolean_t primary_opt
= B_FALSE
; /* dhcp primary option */
1262 while ((option
= getopt_long(argc
, argv
, ":1T:a:dh:i:p:w:t",
1263 addr_longopts
, NULL
)) != -1) {
1266 primary_opt
= B_TRUE
;
1272 static_arg
= optarg
;
1276 flags
&= ~IPADM_OPT_UP
;
1283 interface_id
= optarg
;
1287 addrconf_arg
= optarg
;
1295 flags
&= ~IPADM_OPT_PERSIST
;
1298 die_opterr(optopt
, option
, use
);
1301 if (atype
== NULL
|| optind
!= (argc
- 1)) {
1302 die("Invalid arguments\nusage: %s", use
);
1303 } else if ((cp
= strchr(argv
[optind
], '/')) == NULL
||
1304 strlen(++cp
) == 0) {
1305 die("invalid address object name: %s\nusage: %s",
1310 * Allocate and initialize the addrobj based on the address type.
1312 if (strcmp(atype
, "static") == 0) {
1313 if (static_arg
== NULL
|| auto_opt
|| dhcp_opt
||
1314 reqhost
!= NULL
|| primary_opt
) {
1315 die("Invalid arguments for type %s\nusage: %s",
1318 process_static_addrargs(use
, static_arg
, argv
[optind
]);
1319 } else if (strcmp(atype
, "dhcp") == 0) {
1320 if (auto_opt
|| s_opt
) {
1321 die("Invalid arguments for type %s\nusage: %s",
1325 /* Initialize the addrobj for dhcp addresses. */
1326 status
= ipadm_create_addrobj(IPADM_ADDR_DHCP
, argv
[optind
],
1328 if (status
!= IPADM_SUCCESS
) {
1329 die("Error in creating address object: %s",
1330 ipadm_status2str(status
));
1335 if (strcmp(wait
, "forever") == 0) {
1336 ipadm_wait
= IPADM_DHCP_WAIT_FOREVER
;
1339 long timeout
= strtol(wait
, &end
, 10);
1341 if (*end
!= '\0' || timeout
< 0)
1342 die("Invalid argument");
1343 ipadm_wait
= (int32_t)timeout
;
1345 status
= ipadm_set_wait_time(ipaddr
, ipadm_wait
);
1346 if (status
!= IPADM_SUCCESS
) {
1347 die("Error in setting wait time: %s",
1348 ipadm_status2str(status
));
1352 status
= ipadm_set_primary(ipaddr
, B_TRUE
);
1353 if (status
!= IPADM_SUCCESS
) {
1354 die("Error in setting primary flag: %s",
1355 ipadm_status2str(status
));
1358 if (reqhost
!= NULL
) {
1359 status
= ipadm_set_reqhost(ipaddr
, reqhost
);
1360 if (status
!= IPADM_SUCCESS
) {
1361 die("Error in setting reqhost: %s",
1362 ipadm_status2str(status
));
1365 } else if (strcmp(atype
, "addrconf") == 0) {
1366 if (dhcp_opt
|| s_opt
|| reqhost
!= NULL
|| primary_opt
) {
1367 die("Invalid arguments for type %s\nusage: %s",
1371 /* Initialize the addrobj for ipv6-addrconf addresses. */
1372 status
= ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF
,
1373 argv
[optind
], &ipaddr
);
1374 if (status
!= IPADM_SUCCESS
) {
1375 die("Error in creating address object: %s",
1376 ipadm_status2str(status
));
1378 if (interface_id
!= NULL
) {
1379 status
= ipadm_set_interface_id(ipaddr
, interface_id
);
1380 if (status
!= IPADM_SUCCESS
) {
1381 die("Error in setting interface ID: %s",
1382 ipadm_status2str(status
));
1386 process_addrconf_addrargs(use
, addrconf_arg
);
1388 die("Invalid address type %s", atype
);
1391 status
= ipadm_create_addr(iph
, ipaddr
, flags
);
1392 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1393 warn_ipadmerr(status
, "");
1394 else if (status
!= IPADM_SUCCESS
)
1395 die("Could not create address: %s", ipadm_status2str(status
));
1399 * Used by some address management functions to parse the command line
1400 * arguments and create `ipaddr' address object.
1403 process_misc_addrargs(int argc
, char *argv
[], const char *use
, int *index
,
1409 while ((option
= getopt_long(argc
, argv
, ":t", addr_misc_longopts
,
1413 *flags
&= ~IPADM_OPT_PERSIST
;
1416 die_opterr(optopt
, option
, use
);
1419 if (optind
!= (argc
- 1))
1420 die("Usage: %s", use
);
1426 * Remove an addrobj from both active and persistent configuration.
1429 do_delete_addr(int argc
, char *argv
[], const char *use
)
1431 ipadm_status_t status
;
1432 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1436 while ((option
= getopt_long(argc
, argv
, ":r", addr_misc_longopts
,
1440 flags
|= IPADM_OPT_RELEASE
;
1443 die_opterr(optopt
, option
, use
);
1446 if (optind
!= (argc
- 1))
1447 die("Usage: %s", use
);
1449 status
= ipadm_delete_addr(iph
, argv
[optind
], flags
);
1450 if (status
!= IPADM_SUCCESS
) {
1451 die("could not delete address: %s",
1452 ipadm_status2str(status
));
1457 * Enable an IP address based on the persistent configuration for that
1461 do_enable_addr(int argc
, char *argv
[], const char *use
)
1463 ipadm_status_t status
;
1465 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1467 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1468 if (flags
& IPADM_OPT_PERSIST
)
1469 die("persistent operation not supported for enable-addr");
1471 status
= ipadm_enable_addr(iph
, argv
[index
], flags
);
1472 if (status
!= IPADM_SUCCESS
)
1473 die("could not enable address: %s", ipadm_status2str(status
));
1477 * Mark the address identified by addrobj 'up'
1480 do_up_addr(int argc
, char *argv
[], const char *use
)
1482 ipadm_status_t status
;
1484 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1486 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1487 status
= ipadm_up_addr(iph
, argv
[index
], flags
);
1488 if (status
!= IPADM_SUCCESS
) {
1489 die("Could not mark the address up: %s",
1490 ipadm_status2str(status
));
1495 * Disable the specified addrobj by removing it from active cofiguration
1498 do_disable_addr(int argc
, char *argv
[], const char *use
)
1500 ipadm_status_t status
;
1502 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1504 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1505 if (flags
& IPADM_OPT_PERSIST
)
1506 die("persistent operation not supported for disable-addr");
1508 status
= ipadm_disable_addr(iph
, argv
[index
], flags
);
1509 if (status
!= IPADM_SUCCESS
) {
1510 die("could not disable address: %s",
1511 ipadm_status2str(status
));
1516 * Mark the address identified by addrobj 'down'
1519 do_down_addr(int argc
, char *argv
[], const char *use
)
1521 ipadm_status_t status
;
1523 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1525 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1526 status
= ipadm_down_addr(iph
, argv
[index
], flags
);
1527 if (status
!= IPADM_SUCCESS
)
1528 die("Could not mark the address down: %s",
1529 ipadm_status2str(status
));
1533 * Restart DAD for static address. Extend lease duration for DHCP addresses
1536 do_refresh_addr(int argc
, char *argv
[], const char *use
)
1538 ipadm_status_t status
;
1543 while ((option
= getopt_long(argc
, argv
, ":i", addr_misc_longopts
,
1547 flags
|= IPADM_OPT_INFORM
;
1550 die_opterr(optopt
, option
, use
);
1553 if (optind
!= (argc
- 1))
1554 die("Usage: %s", use
);
1556 status
= ipadm_refresh_addr(iph
, argv
[optind
], flags
);
1557 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1558 warn_ipadmerr(status
, "");
1559 else if (status
!= IPADM_SUCCESS
)
1560 die("could not refresh address %s", ipadm_status2str(status
));
1564 sockaddr2str(const struct sockaddr_storage
*ssp
, char *buf
, uint_t bufsize
)
1567 struct sockaddr
*sp
= (struct sockaddr
*)ssp
;
1569 switch (ssp
->ss_family
) {
1571 socklen
= sizeof (struct sockaddr_in
);
1574 socklen
= sizeof (struct sockaddr_in6
);
1577 (void) strlcpy(buf
, STR_UNKNOWN_VAL
, bufsize
);
1581 (void) getnameinfo(sp
, socklen
, buf
, bufsize
, NULL
, 0,
1582 (NI_NOFQDN
| NI_NUMERICHOST
));
1586 flags2str(uint64_t flags
, fmask_t
*tbl
, boolean_t is_bits
,
1587 char *buf
, uint_t bufsize
)
1590 boolean_t first
= B_TRUE
;
1593 for (i
= 0; tbl
[i
].name
; i
++) {
1594 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
)
1595 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1597 (void) strlcat(buf
, "-", bufsize
);
1600 for (i
= 0; tbl
[i
].name
; i
++) {
1601 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
) {
1603 (void) strlcat(buf
, ",", bufsize
);
1604 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1612 * return true if the address for lifname comes to us from the global zone
1613 * with 'allowed-ips' constraints.
1616 is_from_gz(const char *lifname
)
1618 ipadm_if_info_t
*if_info
;
1619 char phyname
[LIFNAMSIZ
], *cp
;
1620 boolean_t ret
= B_FALSE
;
1621 ipadm_status_t status
;
1625 if ((zoneid
= getzoneid()) == GLOBAL_ZONEID
)
1626 return (B_FALSE
); /* from-gz only makes sense in a NGZ */
1628 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &zflags
, sizeof (zflags
)) < 0)
1631 if (!(zflags
& ZF_NET_EXCL
))
1632 return (B_TRUE
); /* everything is from the GZ for shared-ip */
1634 (void) strncpy(phyname
, lifname
, sizeof (phyname
));
1635 if ((cp
= strchr(phyname
, ':')) != NULL
)
1637 status
= ipadm_if_info(iph
, phyname
, &if_info
, 0, LIFC_DEFAULT
);
1638 if (status
!= IPADM_SUCCESS
)
1641 if (if_info
->ifi_cflags
& IFIF_L3PROTECT
)
1644 ipadm_free_if_info(if_info
);
1649 print_sa_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1651 show_addr_args_t
*arg
= ofarg
->ofmt_cbarg
;
1652 ipadm_addr_info_t
*ainfo
= arg
->sa_info
;
1653 char interface
[LIFNAMSIZ
];
1654 char addrbuf
[MAXPROPVALLEN
];
1655 char dstbuf
[MAXPROPVALLEN
];
1656 char prefixlenstr
[MAXPROPVALLEN
];
1658 struct sockaddr_in
*sin
;
1659 struct sockaddr_in6
*sin6
;
1661 char *phyname
= NULL
;
1662 struct ifaddrs
*ifa
= &ainfo
->ia_ifa
;
1663 fmask_t cflags_mask
[] = {
1664 { "U", IA_UP
, IA_UP
},
1665 { "u", IA_UNNUMBERED
, IA_UNNUMBERED
},
1666 { "p", IA_PRIVATE
, IA_PRIVATE
},
1667 { "t", IA_TEMPORARY
, IA_TEMPORARY
},
1668 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1671 fmask_t pflags_mask
[] = {
1672 { "U", IA_UP
, IA_UP
},
1673 { "p", IA_PRIVATE
, IA_PRIVATE
},
1674 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1678 { "static", IPADM_ADDR_STATIC
, IPADM_ALL_BITS
},
1679 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF
, IPADM_ALL_BITS
},
1680 { "dhcp", IPADM_ADDR_DHCP
, IPADM_ALL_BITS
},
1683 fmask_t addr_state
[] = {
1684 { "disabled", IFA_DISABLED
, IPADM_ALL_BITS
},
1685 { "duplicate", IFA_DUPLICATE
, IPADM_ALL_BITS
},
1686 { "down", IFA_DOWN
, IPADM_ALL_BITS
},
1687 { "tentative", IFA_TENTATIVE
, IPADM_ALL_BITS
},
1688 { "ok", IFA_OK
, IPADM_ALL_BITS
},
1689 { "inaccessible", IFA_INACCESSIBLE
, IPADM_ALL_BITS
},
1694 switch (ofarg
->ofmt_id
) {
1696 if (ainfo
->ia_aobjname
[0] == '\0') {
1697 (void) strncpy(interface
, ifa
->ifa_name
, LIFNAMSIZ
);
1698 phyname
= strrchr(interface
, ':');
1701 (void) snprintf(buf
, bufsize
, "%s/%s", interface
,
1704 (void) snprintf(buf
, bufsize
, "%s", ainfo
->ia_aobjname
);
1708 flags2str(ainfo
->ia_state
, addr_state
, B_FALSE
,
1712 if (is_from_gz(ifa
->ifa_name
))
1713 (void) snprintf(buf
, bufsize
, "from-gz");
1715 flags2str(ainfo
->ia_atype
, type
, B_FALSE
, buf
,
1719 flags2str(ainfo
->ia_cflags
, cflags_mask
, B_TRUE
, buf
, bufsize
);
1722 flags2str(ainfo
->ia_pflags
, pflags_mask
, B_TRUE
, buf
, bufsize
);
1725 af
= ifa
->ifa_addr
->sa_family
;
1727 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1728 * print STR_UNKNOWN_VAL.
1730 if (ainfo
->ia_atype
== IPADM_ADDR_DHCP
) {
1731 sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1732 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1733 if ((af
== AF_INET
&&
1734 sin
->sin_addr
.s_addr
== INADDR_ANY
) ||
1736 IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
))) {
1737 (void) snprintf(buf
, bufsize
, STR_UNKNOWN_VAL
);
1741 if (ifa
->ifa_netmask
== NULL
)
1744 prefixlen
= mask2plen(ifa
->ifa_netmask
);
1745 bzero(prefixlenstr
, sizeof (prefixlenstr
));
1746 if (prefixlen
> 0) {
1747 (void) snprintf(prefixlenstr
, sizeof (prefixlenstr
),
1750 bzero(addrbuf
, sizeof (addrbuf
));
1751 bzero(dstbuf
, sizeof (dstbuf
));
1752 if (ainfo
->ia_atype
== IPADM_ADDR_STATIC
) {
1754 * Print the hostname fields if the address is not
1755 * in active configuration.
1757 if (ainfo
->ia_state
== IFA_DISABLED
) {
1758 (void) snprintf(buf
, bufsize
, "%s",
1760 if (ainfo
->ia_dname
[0] != '\0') {
1761 (void) snprintf(dstbuf
, sizeof (dstbuf
),
1762 "->%s", ainfo
->ia_dname
);
1763 (void) strlcat(buf
, dstbuf
, bufsize
);
1765 (void) strlcat(buf
, prefixlenstr
,
1772 * For the non-persistent case, we need to show the
1773 * currently configured addresses for source and
1776 sockaddr2str((struct sockaddr_storage
*)ifa
->ifa_addr
,
1777 addrbuf
, sizeof (addrbuf
));
1778 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
1780 (struct sockaddr_storage
*)ifa
->ifa_dstaddr
,
1781 dstbuf
, sizeof (dstbuf
));
1782 (void) snprintf(buf
, bufsize
, "%s->%s", addrbuf
,
1785 (void) snprintf(buf
, bufsize
, "%s%s", addrbuf
,
1790 die("invalid input");
1798 * Display address information, either for the given address or
1799 * for all the addresses managed by ipadm.
1802 do_show_addr(int argc
, char *argv
[], const char *use
)
1804 ipadm_status_t status
;
1805 show_addr_state_t state
;
1806 char *def_fields_str
= "addrobj,type,state,addr";
1807 char *fields_str
= NULL
;
1808 ipadm_addr_info_t
*ainfo
;
1809 ipadm_addr_info_t
*ptr
;
1810 show_addr_args_t sargs
;
1813 ofmt_status_t oferr
;
1814 uint_t ofmtflags
= 0;
1816 char *ifname
= NULL
;
1818 boolean_t found
= B_FALSE
;
1821 state
.sa_parsable
= B_FALSE
;
1822 state
.sa_persist
= B_FALSE
;
1823 while ((option
= getopt_long(argc
, argv
, "po:", show_addr_longopts
,
1827 state
.sa_parsable
= B_TRUE
;
1830 fields_str
= optarg
;
1833 die_opterr(optopt
, option
, use
);
1837 if (state
.sa_parsable
&& fields_str
== NULL
)
1838 die("-p requires -o");
1840 if (optind
== argc
- 1) {
1841 aname
= argv
[optind
];
1842 if ((cp
= strchr(aname
, '/')) == NULL
)
1843 die("Invalid address object name provided");
1844 if (*(cp
+ 1) == '\0') {
1849 } else if (optind
== argc
) {
1852 die("Usage: %s", use
);
1855 if (state
.sa_parsable
)
1856 ofmtflags
|= OFMT_PARSABLE
;
1857 if (fields_str
== NULL
)
1858 fields_str
= def_fields_str
;
1859 oferr
= ofmt_open(fields_str
, show_addr_fields
, ofmtflags
, 0, &ofmt
);
1861 ofmt_check(oferr
, state
.sa_parsable
, ofmt
, die
, warn
);
1862 state
.sa_ofmt
= ofmt
;
1864 status
= ipadm_addr_info(iph
, ifname
, &ainfo
, 0, LIFC_DEFAULT
);
1866 * Return without printing any error, if no addresses were found,
1867 * for the case where all addresses are requested.
1869 if (status
!= IPADM_SUCCESS
)
1870 die("Could not get address: %s", ipadm_status2str(status
));
1871 if (ainfo
== NULL
) {
1876 bzero(&sargs
, sizeof (sargs
));
1877 sargs
.sa_state
= &state
;
1878 for (ptr
= ainfo
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
1879 sargs
.sa_info
= ptr
;
1880 if (aname
!= NULL
) {
1881 if (strcmp(sargs
.sa_info
->ia_aobjname
, aname
) != 0)
1885 ofmt_print(state
.sa_ofmt
, &sargs
);
1888 ipadm_free_addr_info(ainfo
);
1889 if (aname
!= NULL
&& !found
)
1890 die("Address object not found");
1894 print_si_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1896 show_if_args_t
*arg
= ofarg
->ofmt_cbarg
;
1897 ipadm_if_info_t
*ifinfo
= arg
->si_info
;
1898 char *ifname
= ifinfo
->ifi_name
;
1899 fmask_t intf_state
[] = {
1900 { "ok", IFIS_OK
, IPADM_ALL_BITS
},
1901 { "down", IFIS_DOWN
, IPADM_ALL_BITS
},
1902 { "disabled", IFIS_DISABLED
, IPADM_ALL_BITS
},
1903 { "failed", IFIS_FAILED
, IPADM_ALL_BITS
},
1904 { "offline", IFIS_OFFLINE
, IPADM_ALL_BITS
},
1907 fmask_t intf_pflags
[] = {
1908 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1909 { "4", IFIF_IPV4
, IFIF_IPV4
},
1910 { "6", IFIF_IPV6
, IFIF_IPV6
},
1913 fmask_t intf_cflags
[] = {
1914 { "b", IFIF_BROADCAST
, IFIF_BROADCAST
},
1915 { "m", IFIF_MULTICAST
, IFIF_MULTICAST
},
1916 { "p", IFIF_POINTOPOINT
, IFIF_POINTOPOINT
},
1917 { "v", IFIF_VIRTUAL
, IFIF_VIRTUAL
},
1918 { "I", IFIF_IPMP
, IFIF_IPMP
},
1919 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1920 { "i", IFIF_INACTIVE
, IFIF_INACTIVE
},
1921 { "V", IFIF_VRRP
, IFIF_VRRP
},
1922 { "a", IFIF_NOACCEPT
, IFIF_NOACCEPT
},
1923 { "Z", IFIF_L3PROTECT
, IFIF_L3PROTECT
},
1924 { "4", IFIF_IPV4
, IFIF_IPV4
},
1925 { "6", IFIF_IPV6
, IFIF_IPV6
},
1930 switch (ofarg
->ofmt_id
) {
1932 (void) snprintf(buf
, bufsize
, "%s", ifname
);
1935 flags2str(ifinfo
->ifi_state
, intf_state
, B_FALSE
,
1939 flags2str(ifinfo
->ifi_cflags
, intf_cflags
, B_TRUE
,
1943 flags2str(ifinfo
->ifi_pflags
, intf_pflags
, B_TRUE
,
1947 die("invalid input");
1955 * Display interface information, either for the given interface or
1956 * for all the interfaces in the system.
1959 do_show_if(int argc
, char *argv
[], const char *use
)
1961 ipadm_status_t status
;
1962 show_if_state_t state
;
1963 char *fields_str
= NULL
;
1964 ipadm_if_info_t
*if_info
, *ptr
;
1965 show_if_args_t sargs
;
1968 ofmt_status_t oferr
;
1969 uint_t ofmtflags
= 0;
1970 char *ifname
= NULL
;
1973 state
.si_parsable
= B_FALSE
;
1975 while ((option
= getopt_long(argc
, argv
, "po:", show_if_longopts
,
1979 state
.si_parsable
= B_TRUE
;
1982 fields_str
= optarg
;
1985 die_opterr(optopt
, option
, use
);
1989 if (optind
== argc
- 1)
1990 ifname
= argv
[optind
];
1991 else if (optind
!= argc
)
1992 die("Usage: %s", use
);
1993 if (state
.si_parsable
)
1994 ofmtflags
|= OFMT_PARSABLE
;
1995 oferr
= ofmt_open(fields_str
, show_if_fields
, ofmtflags
, 0, &ofmt
);
1996 ofmt_check(oferr
, state
.si_parsable
, ofmt
, die
, warn
);
1997 state
.si_ofmt
= ofmt
;
1998 bzero(&sargs
, sizeof (sargs
));
1999 sargs
.si_state
= &state
;
2000 status
= ipadm_if_info(iph
, ifname
, &if_info
, 0, LIFC_DEFAULT
);
2002 * Return without printing any error, if no addresses were found.
2004 if (status
!= IPADM_SUCCESS
) {
2005 die("Could not get interface(s): %s",
2006 ipadm_status2str(status
));
2009 for (ptr
= if_info
; ptr
; ptr
= ptr
->ifi_next
) {
2010 sargs
.si_info
= ptr
;
2011 ofmt_print(state
.si_ofmt
, &sargs
);
2014 ipadm_free_if_info(if_info
);
2018 * set/reset the address property for a given address
2021 set_addrprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
2024 ipadm_status_t status
= IPADM_SUCCESS
;
2025 boolean_t p_arg
= B_FALSE
;
2026 char *nv
, *aobjname
;
2027 char *prop_name
, *prop_val
;
2028 uint_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
2032 while ((option
= getopt_long(argc
, argv
, ":i:p:t", set_ifprop_longopts
,
2037 die("-p must be specified once only");
2040 ipadm_check_propstr(optarg
, reset
, use
);
2044 flags
&= ~IPADM_OPT_PERSIST
;
2047 die_opterr(optopt
, option
, use
);
2051 if (!p_arg
|| optind
!= (argc
- 1))
2052 die("Usage: %s", use
);
2055 prop_val
= strchr(nv
, '=');
2056 if (prop_val
!= NULL
)
2058 aobjname
= argv
[optind
];
2060 flags
|= IPADM_OPT_DEFAULT
;
2061 status
= ipadm_set_addrprop(iph
, prop_name
, prop_val
, aobjname
, flags
);
2062 if (status
!= IPADM_SUCCESS
) {
2064 die("reset-addrprop: %s: %s", prop_name
,
2065 ipadm_status2str(status
));
2067 die("set-addrprop: %s: %s", prop_name
,
2068 ipadm_status2str(status
));
2073 * Sets a property on an address object.
2076 do_set_addrprop(int argc
, char **argv
, const char *use
)
2078 set_addrprop(argc
, argv
, B_FALSE
, use
);
2082 * Resets a property to its default value on an address object.
2085 do_reset_addrprop(int argc
, char **argv
, const char *use
)
2087 set_addrprop(argc
, argv
, B_TRUE
, use
);
2091 * Display information for all or specific address properties, either for a
2092 * given address or for all the addresses in the system.
2095 do_show_addrprop(int argc
, char *argv
[], const char *use
)
2098 nvlist_t
*proplist
= NULL
;
2099 char *fields_str
= NULL
;
2100 show_prop_state_t state
;
2102 ofmt_status_t oferr
;
2103 uint_t ofmtflags
= 0;
2104 char *aobjname
= NULL
;
2105 char *ifname
= NULL
;
2107 ipadm_addr_info_t
*ainfop
= NULL
;
2108 ipadm_addr_info_t
*ptr
;
2109 ipadm_status_t status
;
2110 boolean_t found
= B_FALSE
;
2113 bzero(&state
, sizeof (state
));
2114 state
.sps_propval
= NULL
;
2115 state
.sps_parsable
= B_FALSE
;
2116 state
.sps_addrprop
= B_TRUE
;
2117 state
.sps_proto
= MOD_PROTO_NONE
;
2118 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
2119 while ((option
= getopt_long(argc
, argv
, ":p:i:cPo:",
2120 show_prop_longopts
, NULL
)) != -1) {
2123 if (ipadm_str2nvlist(optarg
, &proplist
,
2125 die("invalid addrobj properties specified");
2128 state
.sps_parsable
= B_TRUE
;
2131 fields_str
= optarg
;
2134 die_opterr(optopt
, option
, use
);
2138 if (optind
== argc
- 1) {
2139 aobjname
= argv
[optind
];
2140 cp
= strchr(aobjname
, '/');
2142 die("invalid addrobj name provided");
2143 if (*(cp
+ 1) == '\0') {
2148 } else if (optind
!= argc
) {
2149 die("Usage: %s", use
);
2151 state
.sps_proplist
= proplist
;
2152 if (state
.sps_parsable
)
2153 ofmtflags
|= OFMT_PARSABLE
;
2154 oferr
= ofmt_open(fields_str
, addrprop_fields
, ofmtflags
, 0, &ofmt
);
2155 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
2156 state
.sps_ofmt
= ofmt
;
2158 status
= ipadm_addr_info(iph
, ifname
, &ainfop
, 0, LIFC_DEFAULT
);
2159 /* Return without printing any error, if no addresses were found */
2160 if (status
== IPADM_NOTFOUND
)
2162 if (status
!= IPADM_SUCCESS
)
2163 die("error retrieving address: %s", ipadm_status2str(status
));
2165 for (ptr
= ainfop
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
2166 char *taobjname
= ptr
->ia_aobjname
;
2168 if (taobjname
[0] == '\0')
2170 if (aobjname
!= NULL
) {
2171 if (strcmp(aobjname
, taobjname
) == 0)
2176 if (ptr
->ia_atype
== IPADM_ADDR_IPV6_ADDRCONF
) {
2182 (void) strlcpy(state
.sps_aobjname
, taobjname
,
2183 sizeof (state
.sps_aobjname
));
2184 show_properties(&state
, IPADMPROP_CLASS_ADDR
);
2188 ipadm_free_addr_info(ainfop
);
2190 if (aobjname
!= NULL
&& !found
)
2191 die("addrobj not found: %s", aobjname
);
2193 nvlist_free(proplist
);
2195 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
2202 * check if the `pstr' adheres to following syntax
2203 * - prop=<value[,...]> (for set)
2204 * - prop (for reset)
2207 ipadm_check_propstr(const char *pstr
, boolean_t reset
, const char *use
)
2211 nv
= strchr(pstr
, '=');
2214 die("incorrect syntax used for -p.\n%s", use
);
2216 if (nv
== NULL
|| *++nv
== '\0')
2217 die("please specify the value to be set.\n%s", use
);
2218 nv
= strchr(nv
, '=');
2219 /* cannot have multiple 'prop=val' for single -p */
2221 die("cannot specify more than one prop=val at "
2222 "a time.\n%s", use
);