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
;
69 static void warn(const char *, ...);
70 static void die(const char *, ...);
78 static cmd_t cmds
[] = {
79 /* interface management related sub-commands */
80 { "create-if", do_create_if
, "\tcreate-if\t[-t] <interface>" },
81 { "disable-if", do_disable_if
, "\tdisable-if\t-t <interface>" },
82 { "enable-if", do_enable_if
, "\tenable-if\t-t <interface>" },
83 { "delete-if", do_delete_if
, "\tdelete-if\t<interface>" },
84 { "show-if", do_show_if
,
85 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
86 { "set-ifprop", do_set_ifprop
,
87 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
89 { "reset-ifprop", do_reset_ifprop
,
90 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
91 { "show-ifprop", do_show_ifprop
,
92 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
93 "\t\t\t[-m <protocol>] [interface]\n" },
95 /* address management related sub-commands */
96 { "create-addr", do_create_addr
,
97 "\tcreate-addr\t[-t] -T static [-d] "
98 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
99 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
100 "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
101 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
102 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
103 { "down-addr", do_down_addr
, "\tdown-addr\t[-t] <addrobj>" },
104 { "up-addr", do_up_addr
, "\tup-addr\t\t[-t] <addrobj>" },
105 { "disable-addr", do_disable_addr
, "\tdisable-addr\t-t <addrobj>" },
106 { "enable-addr", do_enable_addr
, "\tenable-addr\t-t <addrobj>" },
107 { "refresh-addr", do_refresh_addr
, "\trefresh-addr\t[-i] <addrobj>" },
108 { "delete-addr", do_delete_addr
, "\tdelete-addr\t[-r] <addrobj>" },
109 { "show-addr", do_show_addr
,
110 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
111 { "set-addrprop", do_set_addrprop
,
112 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
113 { "reset-addrprop", do_reset_addrprop
,
114 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
115 { "show-addrprop", do_show_addrprop
,
116 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
119 /* protocol properties related sub-commands */
120 { "set-prop", do_set_prop
,
121 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
122 { "reset-prop", do_reset_prop
,
123 "\treset-prop\t[-t] -p <prop> <protocol>" },
124 { "show-prop", do_show_prop
,
125 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
129 static const struct option if_longopts
[] = {
130 {"temporary", no_argument
, 0, 't' },
134 static const struct option show_prop_longopts
[] = {
135 {"parsable", no_argument
, 0, 'c' },
136 {"prop", required_argument
, 0, 'p' },
137 {"output", required_argument
, 0, 'o' },
141 static const struct option show_ifprop_longopts
[] = {
142 {"module", required_argument
, 0, 'm' },
143 {"parsable", no_argument
, 0, 'c' },
144 {"prop", required_argument
, 0, 'p' },
145 {"output", required_argument
, 0, 'o' },
149 static const struct option set_prop_longopts
[] = {
150 {"prop", required_argument
, 0, 'p' },
151 {"temporary", no_argument
, 0, 't' },
155 static const struct option set_ifprop_longopts
[] = {
156 {"module", required_argument
, 0, 'm' },
157 {"prop", required_argument
, 0, 'p' },
158 {"temporary", no_argument
, 0, 't' },
162 static const struct option addr_misc_longopts
[] = {
163 {"inform", no_argument
, 0, 'i' },
164 {"release", no_argument
, 0, 'r' },
165 {"temporary", no_argument
, 0, 't' },
169 static const struct option addr_longopts
[] = {
170 {"address", required_argument
, 0, 'a' },
171 {"down", no_argument
, 0, 'd' },
172 {"interface-id", required_argument
, 0, 'i' },
173 {"primary", no_argument
, 0, '1' },
174 {"prop", required_argument
, 0, 'p' },
175 {"reqhost", required_argument
, 0, 'h' },
176 {"temporary", no_argument
, 0, 't' },
177 {"type", required_argument
, 0, 'T' },
178 {"wait", required_argument
, 0, 'w' },
182 static const struct option show_addr_longopts
[] = {
183 {"parsable", no_argument
, 0, 'p' },
184 {"output", required_argument
, 0, 'o' },
188 static const struct option show_if_longopts
[] = {
189 {"parsable", no_argument
, 0, 'p' },
190 {"output", required_argument
, 0, 'o' },
194 /* callback functions to print show-* subcommands output */
195 static ofmt_cb_t print_prop_cb
;
196 static ofmt_cb_t print_sa_cb
;
197 static ofmt_cb_t print_si_cb
;
199 /* structures for 'ipadm show-*' subcommands */
201 IPADM_PROPFIELD_IFNAME
,
202 IPADM_PROPFIELD_PROTO
,
203 IPADM_PROPFIELD_ADDROBJ
,
204 IPADM_PROPFIELD_PROPERTY
,
205 IPADM_PROPFIELD_PERM
,
206 IPADM_PROPFIELD_CURRENT
,
207 IPADM_PROPFIELD_PERSISTENT
,
208 IPADM_PROPFIELD_DEFAULT
,
209 IPADM_PROPFIELD_POSSIBLE
210 } ipadm_propfield_index_t
;
212 static ofmt_field_t intfprop_fields
[] = {
213 /* name, field width, index, callback */
214 { "IFNAME", 12, IPADM_PROPFIELD_IFNAME
, print_prop_cb
},
215 { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
216 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
217 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
218 { "CURRENT", 11, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
219 { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
220 { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
221 { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
226 static ofmt_field_t modprop_fields
[] = {
227 /* name, field width, index, callback */
228 { "PROTO", 6, IPADM_PROPFIELD_PROTO
, print_prop_cb
},
229 { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
230 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
231 { "CURRENT", 13, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
232 { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
233 { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
234 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
238 static ofmt_field_t addrprop_fields
[] = {
239 /* name, field width, index, callback */
240 { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ
, print_prop_cb
},
241 { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY
, print_prop_cb
},
242 { "PERM", 5, IPADM_PROPFIELD_PERM
, print_prop_cb
},
243 { "CURRENT", 16, IPADM_PROPFIELD_CURRENT
, print_prop_cb
},
244 { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT
, print_prop_cb
},
245 { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT
, print_prop_cb
},
246 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE
, print_prop_cb
},
250 typedef struct show_prop_state
{
251 char sps_ifname
[LIFNAMSIZ
];
252 char sps_aobjname
[IPADM_AOBJSIZ
];
253 const char *sps_pname
;
256 nvlist_t
*sps_proplist
;
257 boolean_t sps_parsable
;
258 boolean_t sps_addrprop
;
259 boolean_t sps_ifprop
;
260 boolean_t sps_modprop
;
261 ipadm_status_t sps_status
;
262 ipadm_status_t sps_retstatus
;
263 ofmt_handle_t sps_ofmt
;
266 typedef struct show_addr_state
{
267 boolean_t sa_parsable
;
268 boolean_t sa_persist
;
269 ofmt_handle_t sa_ofmt
;
272 typedef struct show_if_state
{
273 boolean_t si_parsable
;
274 ofmt_handle_t si_ofmt
;
277 typedef struct show_addr_args_s
{
278 show_addr_state_t
*sa_state
;
279 ipadm_addr_info_t
*sa_info
;
282 typedef struct show_if_args_s
{
283 show_if_state_t
*si_state
;
284 ipadm_if_info_t
*si_info
;
303 static ofmt_field_t show_addr_fields
[] = {
304 /* name, field width, id, callback */
305 { "ADDROBJ", 18, SA_ADDROBJ
, print_sa_cb
},
306 { "TYPE", 9, SA_TYPE
, print_sa_cb
},
307 { "STATE", 13, SA_STATE
, print_sa_cb
},
308 { "CURRENT", 8, SA_CURRENT
, print_sa_cb
},
309 { "PERSISTENT", 11, SA_PERSISTENT
, print_sa_cb
},
310 { "ADDR", 46, SA_ADDR
, print_sa_cb
},
314 static ofmt_field_t show_if_fields
[] = {
315 /* name, field width, id, callback */
316 { "IFNAME", 11, SI_IFNAME
, print_si_cb
},
317 { "STATE", 9, SI_STATE
, print_si_cb
},
318 { "CURRENT", 13, SI_CURRENT
, print_si_cb
},
319 { "PERSISTENT", 11, SI_PERSISTENT
, print_si_cb
},
323 #define IPADM_ALL_BITS ((uint_t)-1)
324 typedef struct intf_mask
{
331 * Handle to libipadm. Opened in main() before the sub-command specific
332 * function is called and is closed before the program exits.
334 ipadm_handle_t iph
= NULL
;
337 * Opaque ipadm address object. Used by all the address management subcommands.
339 ipadm_addrobj_t ipaddr
= NULL
;
341 static char *progname
;
343 static void die(const char *, ...);
344 static void die_opterr(int, int, const char *);
345 static void warn_ipadmerr(ipadm_status_t
, const char *, ...);
346 static void ipadm_check_propstr(const char *, boolean_t
, const char *);
347 static void process_misc_addrargs(int, char **, const char *, int *,
356 (void) fprintf(stderr
,
357 gettext("usage: ipadm <subcommand> <args> ...\n"));
358 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
360 if (cmdp
->c_usage
!= NULL
)
361 (void) fprintf(stderr
, "%s\n", gettext(cmdp
->c_usage
));
364 ipadm_destroy_addrobj(ipaddr
);
370 main(int argc
, char *argv
[])
374 ipadm_status_t status
;
376 (void) setlocale(LC_ALL
, "");
377 (void) textdomain(TEXT_DOMAIN
);
379 if ((progname
= strrchr(argv
[0], '/')) == NULL
)
387 status
= ipadm_open(&iph
, 0);
388 if (status
!= IPADM_SUCCESS
) {
389 die("Could not open handle to library - %s",
390 ipadm_status2str(status
));
393 for (i
= 0; i
< sizeof (cmds
) / sizeof (cmds
[0]); i
++) {
395 if (strcmp(argv
[1], cmdp
->c_name
) == 0) {
396 cmdp
->c_fn(argc
- 1, &argv
[1], gettext(cmdp
->c_usage
));
397 ipadm_destroy_addrobj(ipaddr
);
403 (void) fprintf(stderr
, gettext("%s: unknown subcommand '%s'\n"),
411 * Create an IP interface for which no saved configuration exists in the
415 do_create_if(int argc
, char *argv
[], const char *use
)
417 ipadm_status_t status
;
419 uint32_t flags
= IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
;
422 while ((option
= getopt_long(argc
, argv
, ":t", if_longopts
,
427 * "ifconfig" mode - plumb interface, but do not
428 * restore settings that may exist in db.
430 flags
&= ~IPADM_OPT_PERSIST
;
433 die_opterr(optopt
, option
, use
);
436 if (optind
!= (argc
- 1))
437 die("Usage: %s", use
);
438 status
= ipadm_create_if(iph
, argv
[optind
], AF_UNSPEC
, flags
);
439 if (status
!= IPADM_SUCCESS
) {
440 die("Could not create %s : %s",
441 argv
[optind
], ipadm_status2str(status
));
446 * Enable an IP interface based on the persistent configuration for
450 do_enable_if(int argc
, char *argv
[], const char *use
)
452 ipadm_status_t status
;
454 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
456 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
457 if (flags
& IPADM_OPT_PERSIST
)
458 die("persistent operation not supported for enable-if");
459 status
= ipadm_enable_if(iph
, argv
[index
], flags
);
460 if (status
== IPADM_ALL_ADDRS_NOT_ENABLED
) {
461 warn_ipadmerr(status
, "");
462 } else if (status
!= IPADM_SUCCESS
) {
463 die("Could not enable %s : %s",
464 argv
[optind
], ipadm_status2str(status
));
469 * Remove an IP interface from both active and persistent configuration.
472 do_delete_if(int argc
, char *argv
[], const char *use
)
474 ipadm_status_t status
;
475 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
478 die("Usage: %s", use
);
480 status
= ipadm_delete_if(iph
, argv
[1], AF_UNSPEC
, flags
);
481 if (status
!= IPADM_SUCCESS
) {
482 die("Could not delete %s: %s",
483 argv
[optind
], ipadm_status2str(status
));
488 * Disable an IP interface by removing it from active configuration.
491 do_disable_if(int argc
, char *argv
[], const char *use
)
493 ipadm_status_t status
;
495 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
497 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
498 if (flags
& IPADM_OPT_PERSIST
)
499 die("persistent operation not supported for disable-if");
500 status
= ipadm_disable_if(iph
, argv
[index
], flags
);
501 if (status
!= IPADM_SUCCESS
) {
502 die("Could not disable %s: %s",
503 argv
[optind
], ipadm_status2str(status
));
508 * Print individual columns for the show-*prop subcommands.
511 print_prop(show_prop_state_t
*statep
, uint_t flags
, char *buf
, size_t bufsize
)
513 const char *prop_name
= statep
->sps_pname
;
514 char *ifname
= statep
->sps_ifname
;
515 char *propval
= statep
->sps_propval
;
516 uint_t proto
= statep
->sps_proto
;
517 size_t propsize
= MAXPROPVALLEN
;
518 ipadm_status_t status
;
520 if (statep
->sps_ifprop
) {
521 status
= ipadm_get_ifprop(iph
, ifname
, prop_name
, propval
,
522 &propsize
, proto
, flags
);
523 } else if (statep
->sps_modprop
) {
524 status
= ipadm_get_prop(iph
, prop_name
, propval
, &propsize
,
527 status
= ipadm_get_addrprop(iph
, prop_name
, propval
, &propsize
,
528 statep
->sps_aobjname
, flags
);
531 if (status
!= IPADM_SUCCESS
) {
532 if ((status
== IPADM_NOTFOUND
&& (flags
& IPADM_OPT_PERSIST
)) ||
533 status
== IPADM_ENXIO
) {
537 statep
->sps_status
= status
;
538 statep
->sps_retstatus
= status
;
542 statep
->sps_status
= IPADM_SUCCESS
;
543 (void) snprintf(buf
, bufsize
, "%s", propval
);
547 * Callback function for show-*prop subcommands.
550 print_prop_cb(ofmt_arg_t
*ofarg
, char *buf
, size_t bufsize
)
552 show_prop_state_t
*statep
= ofarg
->ofmt_cbarg
;
553 const char *propname
= statep
->sps_pname
;
554 uint_t proto
= statep
->sps_proto
;
555 boolean_t cont
= _B_TRUE
;
558 * Fail retrieving remaining fields, if you fail
559 * to retrieve a field.
561 if (statep
->sps_status
!= IPADM_SUCCESS
)
564 switch (ofarg
->ofmt_id
) {
565 case IPADM_PROPFIELD_IFNAME
:
566 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_ifname
);
568 case IPADM_PROPFIELD_PROTO
:
569 (void) snprintf(buf
, bufsize
, "%s", ipadm_proto2str(proto
));
571 case IPADM_PROPFIELD_ADDROBJ
:
572 (void) snprintf(buf
, bufsize
, "%s", statep
->sps_aobjname
);
574 case IPADM_PROPFIELD_PROPERTY
:
575 (void) snprintf(buf
, bufsize
, "%s", propname
);
577 case IPADM_PROPFIELD_PERM
:
578 print_prop(statep
, IPADM_OPT_PERM
, buf
, bufsize
);
580 case IPADM_PROPFIELD_CURRENT
:
581 print_prop(statep
, IPADM_OPT_ACTIVE
, buf
, bufsize
);
583 case IPADM_PROPFIELD_PERSISTENT
:
584 print_prop(statep
, IPADM_OPT_PERSIST
, buf
, bufsize
);
586 case IPADM_PROPFIELD_DEFAULT
:
587 print_prop(statep
, IPADM_OPT_DEFAULT
, buf
, bufsize
);
589 case IPADM_PROPFIELD_POSSIBLE
:
590 print_prop(statep
, IPADM_OPT_POSSIBLE
, buf
, bufsize
);
593 if (statep
->sps_status
!= IPADM_SUCCESS
)
599 * Callback function called by the property walker (ipadm_walk_prop() or
600 * ipadm_walk_proptbl()), for every matched property. This function in turn
601 * calls ofmt_print() to print property information.
604 show_property(void *arg
, const char *pname
, uint_t proto
)
606 show_prop_state_t
*statep
= arg
;
608 statep
->sps_pname
= pname
;
609 statep
->sps_proto
= proto
;
610 statep
->sps_status
= IPADM_SUCCESS
;
611 ofmt_print(statep
->sps_ofmt
, arg
);
614 * if an object is not found or operation is not supported then
617 if (statep
->sps_status
== IPADM_NOTFOUND
||
618 statep
->sps_status
== IPADM_NOTSUP
)
624 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
625 * for all the properties for the specified object, display relevant
626 * information. Otherwise, for the selected property set, display relevant
630 show_properties(void *arg
, int prop_class
)
632 show_prop_state_t
*statep
= arg
;
633 nvlist_t
*nvl
= statep
->sps_proplist
;
634 uint_t proto
= statep
->sps_proto
;
637 ipadm_status_t status
;
639 /* allocate sufficient buffer to hold a property value */
640 if ((buf
= malloc(MAXPROPVALLEN
)) == NULL
)
641 die("insufficient memory");
642 statep
->sps_propval
= buf
;
644 /* if no properties were specified, display all the properties */
646 (void) ipadm_walk_proptbl(proto
, prop_class
, show_property
,
649 for (curr_nvp
= nvlist_next_nvpair(nvl
, NULL
); curr_nvp
;
650 curr_nvp
= nvlist_next_nvpair(nvl
, curr_nvp
)) {
651 name
= nvpair_name(curr_nvp
);
652 status
= ipadm_walk_prop(name
, proto
, prop_class
,
653 show_property
, statep
);
654 if (status
== IPADM_PROP_UNKNOWN
)
655 (void) show_property(statep
, name
, proto
);
663 * Display information for all or specific interface properties, either for a
664 * given interface or for all the interfaces in the system.
667 do_show_ifprop(int argc
, char **argv
, const char *use
)
670 nvlist_t
*proplist
= NULL
;
671 char *fields_str
= NULL
;
675 uint_t ofmtflags
= 0;
677 boolean_t m_arg
= _B_FALSE
;
679 ipadm_if_info_t
*ifinfo
, *ifp
;
680 ipadm_status_t status
;
681 show_prop_state_t state
;
684 bzero(&state
, sizeof (state
));
685 state
.sps_propval
= NULL
;
686 state
.sps_parsable
= _B_FALSE
;
687 state
.sps_ifprop
= _B_TRUE
;
688 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
689 while ((option
= getopt_long(argc
, argv
, ":p:m:co:",
690 show_ifprop_longopts
, NULL
)) != -1) {
693 if (ipadm_str2nvlist(optarg
, &proplist
,
695 die("invalid interface properties specified");
698 state
.sps_parsable
= _B_TRUE
;
705 die("cannot specify more than one -m");
710 die_opterr(optopt
, option
, use
);
715 if (optind
== argc
- 1)
716 ifname
= argv
[optind
];
717 else if (optind
!= argc
)
718 die("Usage: %s", use
);
724 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
725 die("invalid protocol '%s' specified", protostr
);
727 state
.sps_proto
= proto
;
728 state
.sps_proplist
= proplist
;
730 if (state
.sps_parsable
)
731 ofmtflags
|= OFMT_PARSABLE
;
732 oferr
= ofmt_open(fields_str
, intfprop_fields
, ofmtflags
, 0, &ofmt
);
733 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
734 state
.sps_ofmt
= ofmt
;
736 /* retrieve interface(s) and print the properties */
737 status
= ipadm_if_info(iph
, ifname
, &ifinfo
, 0, LIFC_DEFAULT
);
738 if (ifname
!= NULL
&& status
== IPADM_ENXIO
)
739 die("no such object '%s': %s", ifname
,
740 ipadm_status2str(status
));
741 if (status
!= IPADM_SUCCESS
)
742 die("Error retrieving interface(s): %s",
743 ipadm_status2str(status
));
744 for (ifp
= ifinfo
; ifp
; ifp
= ifp
->ifi_next
) {
745 (void) strlcpy(state
.sps_ifname
, ifp
->ifi_name
, LIFNAMSIZ
);
746 state
.sps_proto
= proto
;
747 show_properties(&state
, IPADMPROP_CLASS_IF
);
750 ipadm_free_if_info(ifinfo
);
752 nvlist_free(proplist
);
755 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
762 * set/reset the interface property for a given interface.
765 set_ifprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
768 ipadm_status_t status
= IPADM_SUCCESS
;
769 boolean_t p_arg
= _B_FALSE
;
770 boolean_t m_arg
= _B_FALSE
;
771 char *ifname
, *nv
, *protostr
;
772 char *prop_name
, *prop_val
;
773 uint_t flags
= IPADM_OPT_PERSIST
;
777 while ((option
= getopt_long(argc
, argv
, ":m:p:t",
778 set_ifprop_longopts
, NULL
)) != -1) {
782 die("-p must be specified once only");
785 ipadm_check_propstr(optarg
, reset
, use
);
790 die("-m must be specified once only");
795 flags
&= ~IPADM_OPT_PERSIST
;
798 die_opterr(optopt
, option
, use
);
802 if (!m_arg
|| !p_arg
|| optind
!= argc
- 1)
803 die("Usage: %s", use
);
805 ifname
= argv
[optind
];
808 prop_val
= strchr(nv
, '=');
809 if (prop_val
!= NULL
)
812 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
813 die("invalid protocol '%s' specified", protostr
);
816 flags
|= IPADM_OPT_DEFAULT
;
818 flags
|= IPADM_OPT_ACTIVE
;
819 status
= ipadm_set_ifprop(iph
, ifname
, prop_name
, prop_val
, proto
,
823 if (status
!= IPADM_SUCCESS
) {
825 die("reset-ifprop: %s: %s",
826 prop_name
, ipadm_status2str(status
));
828 die("set-ifprop: %s: %s",
829 prop_name
, ipadm_status2str(status
));
834 do_set_ifprop(int argc
, char **argv
, const char *use
)
836 set_ifprop(argc
, argv
, _B_FALSE
, use
);
840 do_reset_ifprop(int argc
, char **argv
, const char *use
)
842 set_ifprop(argc
, argv
, _B_TRUE
, use
);
846 * Display information for all or specific protocol properties, either for a
847 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
850 do_show_prop(int argc
, char **argv
, const char *use
)
853 nvlist_t
*proplist
= NULL
;
854 char *fields_str
= NULL
;
856 show_prop_state_t state
;
859 uint_t ofmtflags
= 0;
861 boolean_t p_arg
= _B_FALSE
;
864 bzero(&state
, sizeof (state
));
865 state
.sps_propval
= NULL
;
866 state
.sps_parsable
= _B_FALSE
;
867 state
.sps_modprop
= _B_TRUE
;
868 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
869 while ((option
= getopt_long(argc
, argv
, ":p:co:", show_prop_longopts
,
874 die("-p must be specified once only");
876 if (ipadm_str2nvlist(optarg
, &proplist
,
878 die("invalid protocol properties specified");
881 state
.sps_parsable
= _B_TRUE
;
887 die_opterr(optopt
, option
, use
);
891 if (optind
== argc
- 1) {
892 protostr
= argv
[optind
];
893 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
894 die("invalid protocol '%s' specified", protostr
);
895 state
.sps_proto
= proto
;
896 } else if (optind
!= argc
) {
897 die("Usage: %s", use
);
900 die("protocol must be specified when "
901 "property name is used");
902 state
.sps_proto
= MOD_PROTO_NONE
;
905 state
.sps_proplist
= proplist
;
907 if (state
.sps_parsable
)
908 ofmtflags
|= OFMT_PARSABLE
;
910 ofmtflags
|= OFMT_WRAP
;
911 oferr
= ofmt_open(fields_str
, modprop_fields
, ofmtflags
, 0, &ofmt
);
912 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
913 state
.sps_ofmt
= ofmt
;
915 /* handles all the errors */
916 show_properties(&state
, IPADMPROP_CLASS_MODULE
);
918 nvlist_free(proplist
);
921 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
928 * Checks to see if there are any modifiers, + or -. If there are modifiers
929 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
932 parse_modifiers(const char *pstr
, uint_t
*flags
, const char *use
)
936 if ((p
= strchr(pstr
, '=')) == NULL
)
940 die("Invalid prop=val specified\n%s", use
);
944 *flags
|= IPADM_OPT_APPEND
;
946 *flags
|= IPADM_OPT_REMOVE
;
950 * set/reset the protocol property for a given protocol.
953 set_prop(int argc
, char **argv
, boolean_t reset
, const char *use
)
956 ipadm_status_t status
= IPADM_SUCCESS
;
957 char *protostr
, *nv
, *prop_name
, *prop_val
;
958 boolean_t p_arg
= _B_FALSE
;
960 uint_t flags
= IPADM_OPT_PERSIST
;
963 while ((option
= getopt_long(argc
, argv
, ":p:t", set_prop_longopts
,
968 die("-p must be specified once only");
971 ipadm_check_propstr(optarg
, reset
, use
);
975 flags
&= ~IPADM_OPT_PERSIST
;
978 die_opterr(optopt
, option
, use
);
982 if (!p_arg
|| optind
!= argc
- 1)
983 die("Usage: %s", use
);
985 parse_modifiers(nv
, &flags
, use
);
987 prop_val
= strchr(nv
, '=');
988 if (prop_val
!= NULL
) {
989 if (flags
& (IPADM_OPT_APPEND
|IPADM_OPT_REMOVE
))
990 *(prop_val
- 1) = '\0';
993 protostr
= argv
[optind
];
994 if ((proto
= ipadm_str2proto(protostr
)) == MOD_PROTO_NONE
)
995 die("invalid protocol '%s' specified", protostr
);
998 flags
|= IPADM_OPT_DEFAULT
;
1000 flags
|= IPADM_OPT_ACTIVE
;
1001 status
= ipadm_set_prop(iph
, prop_name
, prop_val
, proto
, flags
);
1003 if (status
!= IPADM_SUCCESS
) {
1005 die("reset-prop: %s: %s",
1006 prop_name
, ipadm_status2str(status
));
1008 die("set-prop: %s: %s",
1009 prop_name
, ipadm_status2str(status
));
1014 do_set_prop(int argc
, char **argv
, const char *use
)
1016 set_prop(argc
, argv
, _B_FALSE
, use
);
1020 do_reset_prop(int argc
, char **argv
, const char *use
)
1022 set_prop(argc
, argv
, _B_TRUE
, use
);
1027 warn(const char *format
, ...)
1031 format
= gettext(format
);
1032 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1034 va_start(alist
, format
);
1035 (void) vfprintf(stderr
, format
, alist
);
1038 (void) fprintf(stderr
, "\n");
1043 die(const char *format
, ...)
1047 format
= gettext(format
);
1048 (void) fprintf(stderr
, "%s: ", progname
);
1050 va_start(alist
, format
);
1051 (void) vfprintf(stderr
, format
, alist
);
1054 (void) putchar('\n');
1056 ipadm_destroy_addrobj(ipaddr
);
1062 die_opterr(int opt
, int opterr
, const char *usage
)
1066 die("option '-%c' requires a value\nusage: %s", opt
,
1071 die("unrecognized option '-%c'\nusage: %s", opt
,
1079 warn_ipadmerr(ipadm_status_t err
, const char *format
, ...)
1083 format
= gettext(format
);
1084 (void) fprintf(stderr
, gettext("%s: warning: "), progname
);
1086 va_start(alist
, format
);
1087 (void) vfprintf(stderr
, format
, alist
);
1090 (void) fprintf(stderr
, "%s\n", ipadm_status2str(err
));
1094 process_static_addrargs(const char *use
, char *addrarg
, const char *aobjname
)
1100 char *save_input_arg
= addrarg
;
1101 boolean_t found_mismatch
= _B_FALSE
;
1102 ipadm_status_t status
;
1103 enum { A_LOCAL
, A_REMOTE
};
1104 static char *addr_optstr
[] = {
1110 while (*addrarg
!= '\0') {
1111 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1115 die("Multiple local addresses provided");
1120 die("Multiple remote addresses provided");
1125 die("Invalid address provided\nusage: %s", use
);
1126 found_mismatch
= _B_TRUE
;
1130 if (raddr
!= NULL
&& laddr
== NULL
)
1131 die("Missing local address\nusage: %s", use
);
1133 /* If only one address is provided, it is assumed a local address. */
1134 if (laddr
== NULL
) {
1136 laddr
= save_input_arg
;
1138 die("Missing local address\nusage: %s", use
);
1141 /* Initialize the addrobj for static addresses. */
1142 status
= ipadm_create_addrobj(IPADM_ADDR_STATIC
, aobjname
, &ipaddr
);
1143 if (status
!= IPADM_SUCCESS
) {
1144 die("Error in creating address object: %s",
1145 ipadm_status2str(status
));
1148 /* Set the local and remote addresses */
1149 status
= ipadm_set_addr(ipaddr
, laddr
, AF_UNSPEC
);
1150 if (status
!= IPADM_SUCCESS
) {
1151 die("Error in setting local address: %s",
1152 ipadm_status2str(status
));
1154 if (raddr
!= NULL
) {
1155 status
= ipadm_set_dst_addr(ipaddr
, raddr
, AF_UNSPEC
);
1156 if (status
!= IPADM_SUCCESS
) {
1157 die("Error in setting remote address: %s",
1158 ipadm_status2str(status
));
1164 process_addrconf_addrargs(const char *use
, char *addrarg
)
1168 enum { P_STATELESS
, P_STATEFUL
};
1169 static char *addr_optstr
[] = {
1174 boolean_t stateless
;
1175 boolean_t stateless_arg
= _B_FALSE
;
1177 boolean_t stateful_arg
= _B_FALSE
;
1178 ipadm_status_t status
;
1180 while (*addrarg
!= '\0') {
1181 option
= getsubopt(&addrarg
, addr_optstr
, &val
);
1185 die("Duplicate option");
1187 die("Invalid argument");
1188 if (strcmp(val
, "yes") == 0)
1189 stateless
= _B_TRUE
;
1190 else if (strcmp(val
, "no") == 0)
1191 stateless
= _B_FALSE
;
1193 die("Invalid argument");
1194 stateless_arg
= _B_TRUE
;
1198 die("Duplicate option");
1200 die("Invalid argument");
1201 if (strcmp(val
, "yes") == 0)
1203 else if (strcmp(val
, "no") == 0)
1204 stateful
= _B_FALSE
;
1206 die("Invalid argument");
1207 stateful_arg
= _B_TRUE
;
1210 die_opterr(optopt
, option
, use
);
1214 if (!stateless_arg
&& !stateful_arg
)
1215 die("Invalid arguments for option -p");
1217 /* Set the addrobj fields for addrconf */
1218 if (stateless_arg
) {
1219 status
= ipadm_set_stateless(ipaddr
, stateless
);
1220 if (status
!= IPADM_SUCCESS
) {
1221 die("Error in setting stateless option: %s",
1222 ipadm_status2str(status
));
1226 status
= ipadm_set_stateful(ipaddr
, stateful
);
1227 if (status
!= IPADM_SUCCESS
) {
1228 die("Error in setting stateful option: %s",
1229 ipadm_status2str(status
));
1235 * Creates static, dhcp or addrconf addresses and associates the created
1236 * addresses with the specified address object name.
1239 do_create_addr(int argc
, char *argv
[], const char *use
)
1241 ipadm_status_t status
;
1244 IPADM_OPT_PERSIST
|IPADM_OPT_ACTIVE
|IPADM_OPT_UP
|IPADM_OPT_V46
;
1247 char *static_arg
= NULL
;
1248 char *addrconf_arg
= NULL
;
1249 char *interface_id
= NULL
;
1251 char *reqhost
= NULL
;
1252 boolean_t s_opt
= _B_FALSE
; /* static addr options */
1253 boolean_t auto_opt
= _B_FALSE
; /* Addrconf options */
1254 boolean_t dhcp_opt
= _B_FALSE
; /* dhcp options */
1255 boolean_t primary_opt
= _B_FALSE
; /* dhcp primary option */
1258 while ((option
= getopt_long(argc
, argv
, ":1T:a:dh:i:p:w:t",
1259 addr_longopts
, NULL
)) != -1) {
1262 primary_opt
= _B_TRUE
;
1268 static_arg
= optarg
;
1272 flags
&= ~IPADM_OPT_UP
;
1279 interface_id
= optarg
;
1283 addrconf_arg
= optarg
;
1291 flags
&= ~IPADM_OPT_PERSIST
;
1294 die_opterr(optopt
, option
, use
);
1297 if (atype
== NULL
|| optind
!= (argc
- 1)) {
1298 die("Invalid arguments\nusage: %s", use
);
1299 } else if ((cp
= strchr(argv
[optind
], '/')) == NULL
||
1300 strlen(++cp
) == 0) {
1301 die("invalid address object name: %s\nusage: %s",
1306 * Allocate and initialize the addrobj based on the address type.
1308 if (strcmp(atype
, "static") == 0) {
1309 if (static_arg
== NULL
|| auto_opt
|| dhcp_opt
||
1310 reqhost
!= NULL
|| primary_opt
) {
1311 die("Invalid arguments for type %s\nusage: %s",
1314 process_static_addrargs(use
, static_arg
, argv
[optind
]);
1315 } else if (strcmp(atype
, "dhcp") == 0) {
1316 if (auto_opt
|| s_opt
) {
1317 die("Invalid arguments for type %s\nusage: %s",
1321 /* Initialize the addrobj for dhcp addresses. */
1322 status
= ipadm_create_addrobj(IPADM_ADDR_DHCP
, argv
[optind
],
1324 if (status
!= IPADM_SUCCESS
) {
1325 die("Error in creating address object: %s",
1326 ipadm_status2str(status
));
1331 if (strcmp(wait
, "forever") == 0) {
1332 ipadm_wait
= IPADM_DHCP_WAIT_FOREVER
;
1335 long timeout
= strtol(wait
, &end
, 10);
1337 if (*end
!= '\0' || timeout
< 0)
1338 die("Invalid argument");
1339 ipadm_wait
= (int32_t)timeout
;
1341 status
= ipadm_set_wait_time(ipaddr
, ipadm_wait
);
1342 if (status
!= IPADM_SUCCESS
) {
1343 die("Error in setting wait time: %s",
1344 ipadm_status2str(status
));
1348 status
= ipadm_set_primary(ipaddr
, _B_TRUE
);
1349 if (status
!= IPADM_SUCCESS
) {
1350 die("Error in setting primary flag: %s",
1351 ipadm_status2str(status
));
1354 if (reqhost
!= NULL
) {
1355 status
= ipadm_set_reqhost(ipaddr
, reqhost
);
1356 if (status
!= IPADM_SUCCESS
) {
1357 die("Error in setting reqhost: %s",
1358 ipadm_status2str(status
));
1361 } else if (strcmp(atype
, "addrconf") == 0) {
1362 if (dhcp_opt
|| s_opt
|| reqhost
!= NULL
|| primary_opt
) {
1363 die("Invalid arguments for type %s\nusage: %s",
1367 /* Initialize the addrobj for ipv6-addrconf addresses. */
1368 status
= ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF
,
1369 argv
[optind
], &ipaddr
);
1370 if (status
!= IPADM_SUCCESS
) {
1371 die("Error in creating address object: %s",
1372 ipadm_status2str(status
));
1374 if (interface_id
!= NULL
) {
1375 status
= ipadm_set_interface_id(ipaddr
, interface_id
);
1376 if (status
!= IPADM_SUCCESS
) {
1377 die("Error in setting interface ID: %s",
1378 ipadm_status2str(status
));
1382 process_addrconf_addrargs(use
, addrconf_arg
);
1384 die("Invalid address type %s", atype
);
1387 status
= ipadm_create_addr(iph
, ipaddr
, flags
);
1388 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1389 warn_ipadmerr(status
, "");
1390 else if (status
!= IPADM_SUCCESS
)
1391 die("Could not create address: %s", ipadm_status2str(status
));
1395 * Used by some address management functions to parse the command line
1396 * arguments and create `ipaddr' address object.
1399 process_misc_addrargs(int argc
, char *argv
[], const char *use
, int *index
,
1405 while ((option
= getopt_long(argc
, argv
, ":t", addr_misc_longopts
,
1409 *flags
&= ~IPADM_OPT_PERSIST
;
1412 die_opterr(optopt
, option
, use
);
1415 if (optind
!= (argc
- 1))
1416 die("Usage: %s", use
);
1422 * Remove an addrobj from both active and persistent configuration.
1425 do_delete_addr(int argc
, char *argv
[], const char *use
)
1427 ipadm_status_t status
;
1428 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1432 while ((option
= getopt_long(argc
, argv
, ":r", addr_misc_longopts
,
1436 flags
|= IPADM_OPT_RELEASE
;
1439 die_opterr(optopt
, option
, use
);
1442 if (optind
!= (argc
- 1))
1443 die("Usage: %s", use
);
1445 status
= ipadm_delete_addr(iph
, argv
[optind
], flags
);
1446 if (status
!= IPADM_SUCCESS
) {
1447 die("could not delete address: %s",
1448 ipadm_status2str(status
));
1453 * Enable an IP address based on the persistent configuration for that
1457 do_enable_addr(int argc
, char *argv
[], const char *use
)
1459 ipadm_status_t status
;
1461 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1463 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1464 if (flags
& IPADM_OPT_PERSIST
)
1465 die("persistent operation not supported for enable-addr");
1467 status
= ipadm_enable_addr(iph
, argv
[index
], flags
);
1468 if (status
!= IPADM_SUCCESS
)
1469 die("could not enable address: %s", ipadm_status2str(status
));
1473 * Mark the address identified by addrobj 'up'
1476 do_up_addr(int argc
, char *argv
[], const char *use
)
1478 ipadm_status_t status
;
1480 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1482 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1483 status
= ipadm_up_addr(iph
, argv
[index
], flags
);
1484 if (status
!= IPADM_SUCCESS
) {
1485 die("Could not mark the address up: %s",
1486 ipadm_status2str(status
));
1491 * Disable the specified addrobj by removing it from active cofiguration
1494 do_disable_addr(int argc
, char *argv
[], const char *use
)
1496 ipadm_status_t status
;
1498 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1500 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1501 if (flags
& IPADM_OPT_PERSIST
)
1502 die("persistent operation not supported for disable-addr");
1504 status
= ipadm_disable_addr(iph
, argv
[index
], flags
);
1505 if (status
!= IPADM_SUCCESS
) {
1506 die("could not disable address: %s",
1507 ipadm_status2str(status
));
1512 * Mark the address identified by addrobj 'down'
1515 do_down_addr(int argc
, char *argv
[], const char *use
)
1517 ipadm_status_t status
;
1519 uint32_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
1521 process_misc_addrargs(argc
, argv
, use
, &index
, &flags
);
1522 status
= ipadm_down_addr(iph
, argv
[index
], flags
);
1523 if (status
!= IPADM_SUCCESS
)
1524 die("Could not mark the address down: %s",
1525 ipadm_status2str(status
));
1529 * Restart DAD for static address. Extend lease duration for DHCP addresses
1532 do_refresh_addr(int argc
, char *argv
[], const char *use
)
1534 ipadm_status_t status
;
1539 while ((option
= getopt_long(argc
, argv
, ":i", addr_misc_longopts
,
1543 flags
|= IPADM_OPT_INFORM
;
1546 die_opterr(optopt
, option
, use
);
1549 if (optind
!= (argc
- 1))
1550 die("Usage: %s", use
);
1552 status
= ipadm_refresh_addr(iph
, argv
[optind
], flags
);
1553 if (status
== IPADM_DHCP_IPC_TIMEOUT
)
1554 warn_ipadmerr(status
, "");
1555 else if (status
!= IPADM_SUCCESS
)
1556 die("could not refresh address %s", ipadm_status2str(status
));
1560 sockaddr2str(const struct sockaddr_storage
*ssp
, char *buf
, uint_t bufsize
)
1563 struct sockaddr
*sp
= (struct sockaddr
*)ssp
;
1565 switch (ssp
->ss_family
) {
1567 socklen
= sizeof (struct sockaddr_in
);
1570 socklen
= sizeof (struct sockaddr_in6
);
1573 (void) strlcpy(buf
, STR_UNKNOWN_VAL
, bufsize
);
1577 (void) getnameinfo(sp
, socklen
, buf
, bufsize
, NULL
, 0,
1578 (NI_NOFQDN
| NI_NUMERICHOST
));
1582 flags2str(uint64_t flags
, fmask_t
*tbl
, boolean_t is_bits
,
1583 char *buf
, uint_t bufsize
)
1586 boolean_t first
= _B_TRUE
;
1589 for (i
= 0; tbl
[i
].name
; i
++) {
1590 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
)
1591 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1593 (void) strlcat(buf
, "-", bufsize
);
1596 for (i
= 0; tbl
[i
].name
; i
++) {
1597 if ((flags
& tbl
[i
].mask
) == tbl
[i
].bits
) {
1599 (void) strlcat(buf
, ",", bufsize
);
1600 (void) strlcat(buf
, tbl
[i
].name
, bufsize
);
1608 * return true if the address for lifname comes to us from the global zone
1609 * with 'allowed-ips' constraints.
1612 is_from_gz(const char *lifname
)
1614 ipadm_if_info_t
*if_info
;
1615 char phyname
[LIFNAMSIZ
], *cp
;
1616 boolean_t ret
= _B_FALSE
;
1617 ipadm_status_t status
;
1621 if ((zoneid
= getzoneid()) == GLOBAL_ZONEID
)
1622 return (_B_FALSE
); /* from-gz only makes sense in a NGZ */
1624 if (zone_getattr(zoneid
, ZONE_ATTR_FLAGS
, &zflags
, sizeof (zflags
)) < 0)
1627 if (!(zflags
& ZF_NET_EXCL
))
1628 return (_B_TRUE
); /* everything is from the GZ for shared-ip */
1630 (void) strncpy(phyname
, lifname
, sizeof (phyname
));
1631 if ((cp
= strchr(phyname
, ':')) != NULL
)
1633 status
= ipadm_if_info(iph
, phyname
, &if_info
, 0, LIFC_DEFAULT
);
1634 if (status
!= IPADM_SUCCESS
)
1637 if (if_info
->ifi_cflags
& IFIF_L3PROTECT
)
1640 ipadm_free_if_info(if_info
);
1645 print_sa_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1647 show_addr_args_t
*arg
= ofarg
->ofmt_cbarg
;
1648 ipadm_addr_info_t
*ainfo
= arg
->sa_info
;
1649 char interface
[LIFNAMSIZ
];
1650 char addrbuf
[MAXPROPVALLEN
];
1651 char dstbuf
[MAXPROPVALLEN
];
1652 char prefixlenstr
[MAXPROPVALLEN
];
1654 struct sockaddr_in
*sin
;
1655 struct sockaddr_in6
*sin6
;
1657 char *phyname
= NULL
;
1658 struct ifaddrs
*ifa
= &ainfo
->ia_ifa
;
1659 fmask_t cflags_mask
[] = {
1660 { "U", IA_UP
, IA_UP
},
1661 { "u", IA_UNNUMBERED
, IA_UNNUMBERED
},
1662 { "p", IA_PRIVATE
, IA_PRIVATE
},
1663 { "t", IA_TEMPORARY
, IA_TEMPORARY
},
1664 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1667 fmask_t pflags_mask
[] = {
1668 { "U", IA_UP
, IA_UP
},
1669 { "p", IA_PRIVATE
, IA_PRIVATE
},
1670 { "d", IA_DEPRECATED
, IA_DEPRECATED
},
1674 { "static", IPADM_ADDR_STATIC
, IPADM_ALL_BITS
},
1675 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF
, IPADM_ALL_BITS
},
1676 { "dhcp", IPADM_ADDR_DHCP
, IPADM_ALL_BITS
},
1679 fmask_t addr_state
[] = {
1680 { "disabled", IFA_DISABLED
, IPADM_ALL_BITS
},
1681 { "duplicate", IFA_DUPLICATE
, IPADM_ALL_BITS
},
1682 { "down", IFA_DOWN
, IPADM_ALL_BITS
},
1683 { "tentative", IFA_TENTATIVE
, IPADM_ALL_BITS
},
1684 { "ok", IFA_OK
, IPADM_ALL_BITS
},
1685 { "inaccessible", IFA_INACCESSIBLE
, IPADM_ALL_BITS
},
1690 switch (ofarg
->ofmt_id
) {
1692 if (ainfo
->ia_aobjname
[0] == '\0') {
1693 (void) strncpy(interface
, ifa
->ifa_name
, LIFNAMSIZ
);
1694 phyname
= strrchr(interface
, ':');
1697 (void) snprintf(buf
, bufsize
, "%s/%s", interface
,
1700 (void) snprintf(buf
, bufsize
, "%s", ainfo
->ia_aobjname
);
1704 flags2str(ainfo
->ia_state
, addr_state
, _B_FALSE
,
1708 if (is_from_gz(ifa
->ifa_name
))
1709 (void) snprintf(buf
, bufsize
, "from-gz");
1711 flags2str(ainfo
->ia_atype
, type
, _B_FALSE
, buf
,
1715 flags2str(ainfo
->ia_cflags
, cflags_mask
, _B_TRUE
, buf
, bufsize
);
1718 flags2str(ainfo
->ia_pflags
, pflags_mask
, _B_TRUE
, buf
, bufsize
);
1721 af
= ifa
->ifa_addr
->sa_family
;
1723 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1724 * print STR_UNKNOWN_VAL.
1726 if (ainfo
->ia_atype
== IPADM_ADDR_DHCP
) {
1727 sin
= (struct sockaddr_in
*)ifa
->ifa_addr
;
1728 sin6
= (struct sockaddr_in6
*)ifa
->ifa_addr
;
1729 if ((af
== AF_INET
&&
1730 sin
->sin_addr
.s_addr
== INADDR_ANY
) ||
1732 IN6_IS_ADDR_UNSPECIFIED(&sin6
->sin6_addr
))) {
1733 (void) snprintf(buf
, bufsize
, STR_UNKNOWN_VAL
);
1737 if (ifa
->ifa_netmask
== NULL
)
1740 prefixlen
= mask2plen(ifa
->ifa_netmask
);
1741 bzero(prefixlenstr
, sizeof (prefixlenstr
));
1742 if (prefixlen
> 0) {
1743 (void) snprintf(prefixlenstr
, sizeof (prefixlenstr
),
1746 bzero(addrbuf
, sizeof (addrbuf
));
1747 bzero(dstbuf
, sizeof (dstbuf
));
1748 if (ainfo
->ia_atype
== IPADM_ADDR_STATIC
) {
1750 * Print the hostname fields if the address is not
1751 * in active configuration.
1753 if (ainfo
->ia_state
== IFA_DISABLED
) {
1754 (void) snprintf(buf
, bufsize
, "%s",
1756 if (ainfo
->ia_dname
[0] != '\0') {
1757 (void) snprintf(dstbuf
, sizeof (dstbuf
),
1758 "->%s", ainfo
->ia_dname
);
1759 (void) strlcat(buf
, dstbuf
, bufsize
);
1761 (void) strlcat(buf
, prefixlenstr
,
1768 * For the non-persistent case, we need to show the
1769 * currently configured addresses for source and
1772 sockaddr2str((struct sockaddr_storage
*)ifa
->ifa_addr
,
1773 addrbuf
, sizeof (addrbuf
));
1774 if (ifa
->ifa_flags
& IFF_POINTOPOINT
) {
1776 (struct sockaddr_storage
*)ifa
->ifa_dstaddr
,
1777 dstbuf
, sizeof (dstbuf
));
1778 (void) snprintf(buf
, bufsize
, "%s->%s", addrbuf
,
1781 (void) snprintf(buf
, bufsize
, "%s%s", addrbuf
,
1786 die("invalid input");
1794 * Display address information, either for the given address or
1795 * for all the addresses managed by ipadm.
1798 do_show_addr(int argc
, char *argv
[], const char *use
)
1800 ipadm_status_t status
;
1801 show_addr_state_t state
;
1802 char *def_fields_str
= "addrobj,type,state,addr";
1803 char *fields_str
= NULL
;
1804 ipadm_addr_info_t
*ainfo
;
1805 ipadm_addr_info_t
*ptr
;
1806 show_addr_args_t sargs
;
1809 ofmt_status_t oferr
;
1810 uint_t ofmtflags
= 0;
1812 char *ifname
= NULL
;
1814 boolean_t found
= _B_FALSE
;
1817 state
.sa_parsable
= _B_FALSE
;
1818 state
.sa_persist
= _B_FALSE
;
1819 while ((option
= getopt_long(argc
, argv
, "po:", show_addr_longopts
,
1823 state
.sa_parsable
= _B_TRUE
;
1826 fields_str
= optarg
;
1829 die_opterr(optopt
, option
, use
);
1833 if (state
.sa_parsable
&& fields_str
== NULL
)
1834 die("-p requires -o");
1836 if (optind
== argc
- 1) {
1837 aname
= argv
[optind
];
1838 if ((cp
= strchr(aname
, '/')) == NULL
)
1839 die("Invalid address object name provided");
1840 if (*(cp
+ 1) == '\0') {
1845 } else if (optind
== argc
) {
1848 die("Usage: %s", use
);
1851 if (state
.sa_parsable
)
1852 ofmtflags
|= OFMT_PARSABLE
;
1853 if (fields_str
== NULL
)
1854 fields_str
= def_fields_str
;
1855 oferr
= ofmt_open(fields_str
, show_addr_fields
, ofmtflags
, 0, &ofmt
);
1857 ofmt_check(oferr
, state
.sa_parsable
, ofmt
, die
, warn
);
1858 state
.sa_ofmt
= ofmt
;
1860 status
= ipadm_addr_info(iph
, ifname
, &ainfo
, 0, LIFC_DEFAULT
);
1862 * Return without printing any error, if no addresses were found,
1863 * for the case where all addresses are requested.
1865 if (status
!= IPADM_SUCCESS
)
1866 die("Could not get address: %s", ipadm_status2str(status
));
1867 if (ainfo
== NULL
) {
1872 bzero(&sargs
, sizeof (sargs
));
1873 sargs
.sa_state
= &state
;
1874 for (ptr
= ainfo
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
1875 sargs
.sa_info
= ptr
;
1876 if (aname
!= NULL
) {
1877 if (strcmp(sargs
.sa_info
->ia_aobjname
, aname
) != 0)
1881 ofmt_print(state
.sa_ofmt
, &sargs
);
1884 ipadm_free_addr_info(ainfo
);
1885 if (aname
!= NULL
&& !found
)
1886 die("Address object not found");
1890 print_si_cb(ofmt_arg_t
*ofarg
, char *buf
, uint_t bufsize
)
1892 show_if_args_t
*arg
= ofarg
->ofmt_cbarg
;
1893 ipadm_if_info_t
*ifinfo
= arg
->si_info
;
1894 char *ifname
= ifinfo
->ifi_name
;
1895 fmask_t intf_state
[] = {
1896 { "ok", IFIS_OK
, IPADM_ALL_BITS
},
1897 { "down", IFIS_DOWN
, IPADM_ALL_BITS
},
1898 { "disabled", IFIS_DISABLED
, IPADM_ALL_BITS
},
1899 { "failed", IFIS_FAILED
, IPADM_ALL_BITS
},
1900 { "offline", IFIS_OFFLINE
, IPADM_ALL_BITS
},
1903 fmask_t intf_pflags
[] = {
1904 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1905 { "4", IFIF_IPV4
, IFIF_IPV4
},
1906 { "6", IFIF_IPV6
, IFIF_IPV6
},
1909 fmask_t intf_cflags
[] = {
1910 { "b", IFIF_BROADCAST
, IFIF_BROADCAST
},
1911 { "m", IFIF_MULTICAST
, IFIF_MULTICAST
},
1912 { "p", IFIF_POINTOPOINT
, IFIF_POINTOPOINT
},
1913 { "v", IFIF_VIRTUAL
, IFIF_VIRTUAL
},
1914 { "I", IFIF_IPMP
, IFIF_IPMP
},
1915 { "s", IFIF_STANDBY
, IFIF_STANDBY
},
1916 { "i", IFIF_INACTIVE
, IFIF_INACTIVE
},
1917 { "V", IFIF_VRRP
, IFIF_VRRP
},
1918 { "a", IFIF_NOACCEPT
, IFIF_NOACCEPT
},
1919 { "Z", IFIF_L3PROTECT
, IFIF_L3PROTECT
},
1920 { "4", IFIF_IPV4
, IFIF_IPV4
},
1921 { "6", IFIF_IPV6
, IFIF_IPV6
},
1926 switch (ofarg
->ofmt_id
) {
1928 (void) snprintf(buf
, bufsize
, "%s", ifname
);
1931 flags2str(ifinfo
->ifi_state
, intf_state
, _B_FALSE
,
1935 flags2str(ifinfo
->ifi_cflags
, intf_cflags
, _B_TRUE
,
1939 flags2str(ifinfo
->ifi_pflags
, intf_pflags
, _B_TRUE
,
1943 die("invalid input");
1951 * Display interface information, either for the given interface or
1952 * for all the interfaces in the system.
1955 do_show_if(int argc
, char *argv
[], const char *use
)
1957 ipadm_status_t status
;
1958 show_if_state_t state
;
1959 char *fields_str
= NULL
;
1960 ipadm_if_info_t
*if_info
, *ptr
;
1961 show_if_args_t sargs
;
1964 ofmt_status_t oferr
;
1965 uint_t ofmtflags
= 0;
1966 char *ifname
= NULL
;
1969 state
.si_parsable
= _B_FALSE
;
1971 while ((option
= getopt_long(argc
, argv
, "po:", show_if_longopts
,
1975 state
.si_parsable
= _B_TRUE
;
1978 fields_str
= optarg
;
1981 die_opterr(optopt
, option
, use
);
1985 if (optind
== argc
- 1)
1986 ifname
= argv
[optind
];
1987 else if (optind
!= argc
)
1988 die("Usage: %s", use
);
1989 if (state
.si_parsable
)
1990 ofmtflags
|= OFMT_PARSABLE
;
1991 oferr
= ofmt_open(fields_str
, show_if_fields
, ofmtflags
, 0, &ofmt
);
1992 ofmt_check(oferr
, state
.si_parsable
, ofmt
, die
, warn
);
1993 state
.si_ofmt
= ofmt
;
1994 bzero(&sargs
, sizeof (sargs
));
1995 sargs
.si_state
= &state
;
1996 status
= ipadm_if_info(iph
, ifname
, &if_info
, 0, LIFC_DEFAULT
);
1998 * Return without printing any error, if no addresses were found.
2000 if (status
!= IPADM_SUCCESS
) {
2001 die("Could not get interface(s): %s",
2002 ipadm_status2str(status
));
2005 for (ptr
= if_info
; ptr
; ptr
= ptr
->ifi_next
) {
2006 sargs
.si_info
= ptr
;
2007 ofmt_print(state
.si_ofmt
, &sargs
);
2010 ipadm_free_if_info(if_info
);
2014 * set/reset the address property for a given address
2017 set_addrprop(int argc
, char **argv
, boolean_t reset
, const char *use
)
2020 ipadm_status_t status
= IPADM_SUCCESS
;
2021 boolean_t p_arg
= _B_FALSE
;
2022 char *nv
, *aobjname
;
2023 char *prop_name
, *prop_val
;
2024 uint_t flags
= IPADM_OPT_ACTIVE
|IPADM_OPT_PERSIST
;
2027 while ((option
= getopt_long(argc
, argv
, ":i:p:t", set_ifprop_longopts
,
2032 die("-p must be specified once only");
2035 ipadm_check_propstr(optarg
, reset
, use
);
2039 flags
&= ~IPADM_OPT_PERSIST
;
2042 die_opterr(optopt
, option
, use
);
2046 if (!p_arg
|| optind
!= (argc
- 1))
2047 die("Usage: %s", use
);
2050 prop_val
= strchr(nv
, '=');
2051 if (prop_val
!= NULL
)
2053 aobjname
= argv
[optind
];
2055 flags
|= IPADM_OPT_DEFAULT
;
2056 status
= ipadm_set_addrprop(iph
, prop_name
, prop_val
, aobjname
, flags
);
2057 if (status
!= IPADM_SUCCESS
) {
2059 die("reset-addrprop: %s: %s", prop_name
,
2060 ipadm_status2str(status
));
2062 die("set-addrprop: %s: %s", prop_name
,
2063 ipadm_status2str(status
));
2068 * Sets a property on an address object.
2071 do_set_addrprop(int argc
, char **argv
, const char *use
)
2073 set_addrprop(argc
, argv
, _B_FALSE
, use
);
2077 * Resets a property to its default value on an address object.
2080 do_reset_addrprop(int argc
, char **argv
, const char *use
)
2082 set_addrprop(argc
, argv
, _B_TRUE
, use
);
2086 * Display information for all or specific address properties, either for a
2087 * given address or for all the addresses in the system.
2090 do_show_addrprop(int argc
, char *argv
[], const char *use
)
2093 nvlist_t
*proplist
= NULL
;
2094 char *fields_str
= NULL
;
2095 show_prop_state_t state
;
2097 ofmt_status_t oferr
;
2098 uint_t ofmtflags
= 0;
2099 char *aobjname
= NULL
;
2100 char *ifname
= NULL
;
2102 ipadm_addr_info_t
*ainfop
= NULL
;
2103 ipadm_addr_info_t
*ptr
;
2104 ipadm_status_t status
;
2105 boolean_t found
= _B_FALSE
;
2108 bzero(&state
, sizeof (state
));
2109 state
.sps_propval
= NULL
;
2110 state
.sps_parsable
= _B_FALSE
;
2111 state
.sps_addrprop
= _B_TRUE
;
2112 state
.sps_proto
= MOD_PROTO_NONE
;
2113 state
.sps_status
= state
.sps_retstatus
= IPADM_SUCCESS
;
2114 while ((option
= getopt_long(argc
, argv
, ":p:i:cPo:",
2115 show_prop_longopts
, NULL
)) != -1) {
2118 if (ipadm_str2nvlist(optarg
, &proplist
,
2120 die("invalid addrobj properties specified");
2123 state
.sps_parsable
= _B_TRUE
;
2126 fields_str
= optarg
;
2129 die_opterr(optopt
, option
, use
);
2133 if (optind
== argc
- 1) {
2134 aobjname
= argv
[optind
];
2135 cp
= strchr(aobjname
, '/');
2137 die("invalid addrobj name provided");
2138 if (*(cp
+ 1) == '\0') {
2143 } else if (optind
!= argc
) {
2144 die("Usage: %s", use
);
2146 state
.sps_proplist
= proplist
;
2147 if (state
.sps_parsable
)
2148 ofmtflags
|= OFMT_PARSABLE
;
2149 oferr
= ofmt_open(fields_str
, addrprop_fields
, ofmtflags
, 0, &ofmt
);
2150 ofmt_check(oferr
, state
.sps_parsable
, ofmt
, die
, warn
);
2151 state
.sps_ofmt
= ofmt
;
2153 status
= ipadm_addr_info(iph
, ifname
, &ainfop
, 0, LIFC_DEFAULT
);
2154 /* Return without printing any error, if no addresses were found */
2155 if (status
== IPADM_NOTFOUND
)
2157 if (status
!= IPADM_SUCCESS
)
2158 die("error retrieving address: %s", ipadm_status2str(status
));
2160 for (ptr
= ainfop
; ptr
!= NULL
; ptr
= IA_NEXT(ptr
)) {
2161 char *taobjname
= ptr
->ia_aobjname
;
2163 if (taobjname
[0] == '\0')
2165 if (aobjname
!= NULL
) {
2166 if (strcmp(aobjname
, taobjname
) == 0)
2171 if (ptr
->ia_atype
== IPADM_ADDR_IPV6_ADDRCONF
) {
2177 (void) strlcpy(state
.sps_aobjname
, taobjname
,
2178 sizeof (state
.sps_aobjname
));
2179 show_properties(&state
, IPADMPROP_CLASS_ADDR
);
2183 ipadm_free_addr_info(ainfop
);
2185 if (aobjname
!= NULL
&& !found
)
2186 die("addrobj not found: %s", aobjname
);
2188 nvlist_free(proplist
);
2190 if (state
.sps_retstatus
!= IPADM_SUCCESS
) {
2197 * check if the `pstr' adheres to following syntax
2198 * - prop=<value[,...]> (for set)
2199 * - prop (for reset)
2202 ipadm_check_propstr(const char *pstr
, boolean_t reset
, const char *use
)
2206 nv
= strchr(pstr
, '=');
2209 die("incorrect syntax used for -p.\n%s", use
);
2211 if (nv
== NULL
|| *++nv
== '\0')
2212 die("please specify the value to be set.\n%s", use
);
2213 nv
= strchr(nv
, '=');
2214 /* cannot have multiple 'prop=val' for single -p */
2216 die("cannot specify more than one prop=val at "
2217 "a time.\n%s", use
);