6923 ipadm show-prop output is ugly when property doesn't exist
[unleashed.git] / usr / src / cmd / cmd-inet / usr.sbin / ipadm / ipadm.c
blobc4b7fd225f6986debabcc4039293a97c88fa444d
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc.
27 #include <arpa/inet.h>
28 #include <errno.h>
29 #include <getopt.h>
30 #include <inet/ip.h>
31 #include <inet/iptun.h>
32 #include <inet/tunables.h>
33 #include <libdladm.h>
34 #include <libdliptun.h>
35 #include <libdllink.h>
36 #include <libinetutil.h>
37 #include <libipadm.h>
38 #include <locale.h>
39 #include <netdb.h>
40 #include <netinet/in.h>
41 #include <ofmt.h>
42 #include <stdarg.h>
43 #include <stddef.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <strings.h>
48 #include <sys/stat.h>
49 #include <sys/types.h>
50 #include <zone.h>
52 #define STR_UNKNOWN_VAL "?"
53 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
54 LIFC_UNDER_IPMP)
56 typedef void cmdfunc_t(int, char **, const char *);
57 static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
58 static cmdfunc_t do_show_if;
59 static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
60 static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
61 static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
62 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
63 static cmdfunc_t do_enable_addr, do_disable_addr;
64 static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
66 typedef struct cmd {
67 char *c_name;
68 cmdfunc_t *c_fn;
69 const char *c_usage;
70 } cmd_t;
72 static cmd_t cmds[] = {
73 /* interface management related sub-commands */
74 { "create-if", do_create_if, "\tcreate-if\t[-t] <interface>" },
75 { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
76 { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
77 { "delete-if", do_delete_if, "\tdelete-if\t<interface>" },
78 { "show-if", do_show_if,
79 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
80 { "set-ifprop", do_set_ifprop,
81 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
82 "<interface>" },
83 { "reset-ifprop", do_reset_ifprop,
84 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
85 { "show-ifprop", do_show_ifprop,
86 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
87 "\t\t\t[-m <protocol>] [interface]\n" },
89 /* address management related sub-commands */
90 { "create-addr", do_create_addr,
91 "\tcreate-addr\t[-t] -T static [-d] "
92 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
93 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"
94 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
95 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
96 { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
97 { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
98 { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
99 { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>" },
100 { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
101 { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
102 { "show-addr", do_show_addr,
103 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
104 { "set-addrprop", do_set_addrprop,
105 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
106 { "reset-addrprop", do_reset_addrprop,
107 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
108 { "show-addrprop", do_show_addrprop,
109 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
110 "<addrobj>\n" },
112 /* protocol properties related sub-commands */
113 { "set-prop", do_set_prop,
114 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
115 { "reset-prop", do_reset_prop,
116 "\treset-prop\t[-t] -p <prop> <protocol>" },
117 { "show-prop", do_show_prop,
118 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
119 " [protocol]" }
122 static const struct option if_longopts[] = {
123 {"temporary", no_argument, 0, 't' },
124 { 0, 0, 0, 0 }
127 static const struct option show_prop_longopts[] = {
128 {"parsable", no_argument, 0, 'c' },
129 {"prop", required_argument, 0, 'p' },
130 {"output", required_argument, 0, 'o' },
131 { 0, 0, 0, 0 }
134 static const struct option show_ifprop_longopts[] = {
135 {"module", required_argument, 0, 'm' },
136 {"parsable", no_argument, 0, 'c' },
137 {"prop", required_argument, 0, 'p' },
138 {"output", required_argument, 0, 'o' },
139 { 0, 0, 0, 0 }
142 static const struct option set_prop_longopts[] = {
143 {"prop", required_argument, 0, 'p' },
144 {"temporary", no_argument, 0, 't' },
145 { 0, 0, 0, 0 }
148 static const struct option set_ifprop_longopts[] = {
149 {"module", required_argument, 0, 'm' },
150 {"prop", required_argument, 0, 'p' },
151 {"temporary", no_argument, 0, 't' },
152 { 0, 0, 0, 0 }
155 static const struct option addr_misc_longopts[] = {
156 {"inform", no_argument, 0, 'i' },
157 {"release", no_argument, 0, 'r' },
158 {"temporary", no_argument, 0, 't' },
159 { 0, 0, 0, 0 }
162 static const struct option addr_longopts[] = {
163 {"address", required_argument, 0, 'a' },
164 {"down", no_argument, 0, 'd' },
165 {"interface-id", required_argument, 0, 'i' },
166 {"prop", required_argument, 0, 'p' },
167 {"temporary", no_argument, 0, 't' },
168 {"type", required_argument, 0, 'T' },
169 {"wait", required_argument, 0, 'w' },
170 { 0, 0, 0, 0 }
173 static const struct option show_addr_longopts[] = {
174 {"parsable", no_argument, 0, 'p' },
175 {"output", required_argument, 0, 'o' },
176 { 0, 0, 0, 0 }
179 static const struct option show_if_longopts[] = {
180 {"parsable", no_argument, 0, 'p' },
181 {"output", required_argument, 0, 'o' },
182 { 0, 0, 0, 0 }
185 /* callback functions to print show-* subcommands output */
186 static ofmt_cb_t print_prop_cb;
187 static ofmt_cb_t print_sa_cb;
188 static ofmt_cb_t print_si_cb;
190 /* structures for 'ipadm show-*' subcommands */
191 typedef enum {
192 IPADM_PROPFIELD_IFNAME,
193 IPADM_PROPFIELD_PROTO,
194 IPADM_PROPFIELD_ADDROBJ,
195 IPADM_PROPFIELD_PROPERTY,
196 IPADM_PROPFIELD_PERM,
197 IPADM_PROPFIELD_CURRENT,
198 IPADM_PROPFIELD_PERSISTENT,
199 IPADM_PROPFIELD_DEFAULT,
200 IPADM_PROPFIELD_POSSIBLE
201 } ipadm_propfield_index_t;
203 static ofmt_field_t intfprop_fields[] = {
204 /* name, field width, index, callback */
205 { "IFNAME", 12, IPADM_PROPFIELD_IFNAME, print_prop_cb},
206 { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
207 { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
208 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
209 { "CURRENT", 11, IPADM_PROPFIELD_CURRENT, print_prop_cb},
210 { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
211 { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
212 { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
213 { NULL, 0, 0, NULL}
217 static ofmt_field_t modprop_fields[] = {
218 /* name, field width, index, callback */
219 { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
220 { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
221 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
222 { "CURRENT", 13, IPADM_PROPFIELD_CURRENT, print_prop_cb},
223 { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
224 { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
225 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
226 { NULL, 0, 0, NULL}
229 static ofmt_field_t addrprop_fields[] = {
230 /* name, field width, index, callback */
231 { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ, print_prop_cb},
232 { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
233 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
234 { "CURRENT", 16, IPADM_PROPFIELD_CURRENT, print_prop_cb},
235 { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
236 { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
237 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
238 { NULL, 0, 0, NULL}
241 typedef struct show_prop_state {
242 char sps_ifname[LIFNAMSIZ];
243 char sps_aobjname[IPADM_AOBJSIZ];
244 const char *sps_pname;
245 uint_t sps_proto;
246 char *sps_propval;
247 nvlist_t *sps_proplist;
248 boolean_t sps_parsable;
249 boolean_t sps_addrprop;
250 boolean_t sps_ifprop;
251 boolean_t sps_modprop;
252 ipadm_status_t sps_status;
253 ipadm_status_t sps_retstatus;
254 ofmt_handle_t sps_ofmt;
255 } show_prop_state_t;
257 typedef struct show_addr_state {
258 boolean_t sa_parsable;
259 boolean_t sa_persist;
260 ofmt_handle_t sa_ofmt;
261 } show_addr_state_t;
263 typedef struct show_if_state {
264 boolean_t si_parsable;
265 ofmt_handle_t si_ofmt;
266 } show_if_state_t;
268 typedef struct show_addr_args_s {
269 show_addr_state_t *sa_state;
270 ipadm_addr_info_t *sa_info;
271 } show_addr_args_t;
273 typedef struct show_if_args_s {
274 show_if_state_t *si_state;
275 ipadm_if_info_t *si_info;
276 } show_if_args_t;
278 typedef enum {
279 SA_ADDROBJ,
280 SA_TYPE,
281 SA_STATE,
282 SA_CURRENT,
283 SA_PERSISTENT,
284 SA_ADDR
285 } sa_field_index_t;
287 typedef enum {
288 SI_IFNAME,
289 SI_STATE,
290 SI_CURRENT,
291 SI_PERSISTENT
292 } si_field_index_t;
294 static ofmt_field_t show_addr_fields[] = {
295 /* name, field width, id, callback */
296 { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
297 { "TYPE", 9, SA_TYPE, print_sa_cb},
298 { "STATE", 13, SA_STATE, print_sa_cb},
299 { "CURRENT", 8, SA_CURRENT, print_sa_cb},
300 { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
301 { "ADDR", 46, SA_ADDR, print_sa_cb},
302 { NULL, 0, 0, NULL}
305 static ofmt_field_t show_if_fields[] = {
306 /* name, field width, id, callback */
307 { "IFNAME", 11, SI_IFNAME, print_si_cb},
308 { "STATE", 9, SI_STATE, print_si_cb},
309 { "CURRENT", 13, SI_CURRENT, print_si_cb},
310 { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
311 { NULL, 0, 0, NULL}
314 #define IPADM_ALL_BITS ((uint_t)-1)
315 typedef struct intf_mask {
316 char *name;
317 uint64_t bits;
318 uint64_t mask;
319 } fmask_t;
322 * Handle to libipadm. Opened in main() before the sub-command specific
323 * function is called and is closed before the program exits.
325 ipadm_handle_t iph = NULL;
328 * Opaque ipadm address object. Used by all the address management subcommands.
330 ipadm_addrobj_t ipaddr = NULL;
332 static char *progname;
334 static void die(const char *, ...);
335 static void die_opterr(int, int, const char *);
336 static void warn_ipadmerr(ipadm_status_t, const char *, ...);
337 static void ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
338 static void ipadm_check_propstr(const char *, boolean_t, const char *);
339 static void process_misc_addrargs(int, char **, const char *, int *,
340 uint32_t *);
342 static void
343 usage(void)
345 int i;
346 cmd_t *cmdp;
348 (void) fprintf(stderr,
349 gettext("usage: ipadm <subcommand> <args> ...\n"));
350 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
351 cmdp = &cmds[i];
352 if (cmdp->c_usage != NULL)
353 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
356 ipadm_destroy_addrobj(ipaddr);
357 ipadm_close(iph);
358 exit(1);
362 main(int argc, char *argv[])
364 int i;
365 cmd_t *cmdp;
366 ipadm_status_t status;
368 (void) setlocale(LC_ALL, "");
369 (void) textdomain(TEXT_DOMAIN);
371 if ((progname = strrchr(argv[0], '/')) == NULL)
372 progname = argv[0];
373 else
374 progname++;
376 if (argc < 2)
377 usage();
379 status = ipadm_open(&iph, 0);
380 if (status != IPADM_SUCCESS) {
381 die("Could not open handle to library - %s",
382 ipadm_status2str(status));
385 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
386 cmdp = &cmds[i];
387 if (strcmp(argv[1], cmdp->c_name) == 0) {
388 cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
389 ipadm_destroy_addrobj(ipaddr);
390 ipadm_close(iph);
391 exit(0);
395 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
396 progname, argv[1]);
397 usage();
399 return (0);
403 * Create an IP interface for which no saved configuration exists in the
404 * persistent store.
406 static void
407 do_create_if(int argc, char *argv[], const char *use)
409 ipadm_status_t status;
410 int option;
411 uint32_t flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
413 opterr = 0;
414 while ((option = getopt_long(argc, argv, ":t", if_longopts,
415 NULL)) != -1) {
416 switch (option) {
417 case 't':
419 * "ifconfig" mode - plumb interface, but do not
420 * restore settings that may exist in db.
422 flags &= ~IPADM_OPT_PERSIST;
423 break;
424 default:
425 die_opterr(optopt, option, use);
428 if (optind != (argc - 1))
429 die("Usage: %s", use);
430 status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
431 if (status != IPADM_SUCCESS) {
432 die("Could not create %s : %s",
433 argv[optind], ipadm_status2str(status));
438 * Enable an IP interface based on the persistent configuration for
439 * that interface.
441 static void
442 do_enable_if(int argc, char *argv[], const char *use)
444 ipadm_status_t status;
445 int index;
446 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
448 process_misc_addrargs(argc, argv, use, &index, &flags);
449 if (flags & IPADM_OPT_PERSIST)
450 die("persistent operation not supported for enable-if");
451 status = ipadm_enable_if(iph, argv[index], flags);
452 if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
453 warn_ipadmerr(status, "");
454 } else if (status != IPADM_SUCCESS) {
455 die("Could not enable %s : %s",
456 argv[optind], ipadm_status2str(status));
461 * Remove an IP interface from both active and persistent configuration.
463 static void
464 do_delete_if(int argc, char *argv[], const char *use)
466 ipadm_status_t status;
467 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
469 if (argc != 2)
470 die("Usage: %s", use);
472 status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
473 if (status != IPADM_SUCCESS) {
474 die("Could not delete %s: %s",
475 argv[optind], ipadm_status2str(status));
480 * Disable an IP interface by removing it from active configuration.
482 static void
483 do_disable_if(int argc, char *argv[], const char *use)
485 ipadm_status_t status;
486 int index;
487 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
489 process_misc_addrargs(argc, argv, use, &index, &flags);
490 if (flags & IPADM_OPT_PERSIST)
491 die("persistent operation not supported for disable-if");
492 status = ipadm_disable_if(iph, argv[index], flags);
493 if (status != IPADM_SUCCESS) {
494 die("Could not disable %s: %s",
495 argv[optind], ipadm_status2str(status));
500 * Print individual columns for the show-*prop subcommands.
502 static void
503 print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
505 const char *prop_name = statep->sps_pname;
506 char *ifname = statep->sps_ifname;
507 char *propval = statep->sps_propval;
508 uint_t proto = statep->sps_proto;
509 size_t propsize = MAXPROPVALLEN;
510 char *object;
511 ipadm_status_t status;
513 if (statep->sps_ifprop) {
514 status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
515 &propsize, proto, flags);
516 object = ifname;
517 } else if (statep->sps_modprop) {
518 status = ipadm_get_prop(iph, prop_name, propval, &propsize,
519 proto, flags);
520 object = ipadm_proto2str(proto);
521 } else {
522 status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
523 statep->sps_aobjname, flags);
524 object = statep->sps_aobjname;
527 if (status != IPADM_SUCCESS) {
528 if ((status == IPADM_NOTFOUND && (flags & IPADM_OPT_PERSIST)) ||
529 status == IPADM_ENXIO) {
530 propval[0] = '\0';
531 goto cont;
533 statep->sps_status = status;
534 statep->sps_retstatus = status;
535 return;
537 cont:
538 statep->sps_status = IPADM_SUCCESS;
539 (void) snprintf(buf, bufsize, "%s", propval);
543 * Callback function for show-*prop subcommands.
545 static boolean_t
546 print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
548 show_prop_state_t *statep = ofarg->ofmt_cbarg;
549 const char *propname = statep->sps_pname;
550 uint_t proto = statep->sps_proto;
551 boolean_t cont = _B_TRUE;
554 * Fail retrieving remaining fields, if you fail
555 * to retrieve a field.
557 if (statep->sps_status != IPADM_SUCCESS)
558 return (_B_FALSE);
560 switch (ofarg->ofmt_id) {
561 case IPADM_PROPFIELD_IFNAME:
562 (void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
563 break;
564 case IPADM_PROPFIELD_PROTO:
565 (void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
566 break;
567 case IPADM_PROPFIELD_ADDROBJ:
568 (void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
569 break;
570 case IPADM_PROPFIELD_PROPERTY:
571 (void) snprintf(buf, bufsize, "%s", propname);
572 break;
573 case IPADM_PROPFIELD_PERM:
574 print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
575 break;
576 case IPADM_PROPFIELD_CURRENT:
577 print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
578 break;
579 case IPADM_PROPFIELD_PERSISTENT:
580 print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
581 break;
582 case IPADM_PROPFIELD_DEFAULT:
583 print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
584 break;
585 case IPADM_PROPFIELD_POSSIBLE:
586 print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
587 break;
589 if (statep->sps_status != IPADM_SUCCESS)
590 cont = _B_FALSE;
591 return (cont);
595 * Callback function called by the property walker (ipadm_walk_prop() or
596 * ipadm_walk_proptbl()), for every matched property. This function in turn
597 * calls ofmt_print() to print property information.
599 boolean_t
600 show_property(void *arg, const char *pname, uint_t proto)
602 show_prop_state_t *statep = arg;
604 statep->sps_pname = pname;
605 statep->sps_proto = proto;
606 statep->sps_status = IPADM_SUCCESS;
607 ofmt_print(statep->sps_ofmt, arg);
610 * if an object is not found or operation is not supported then
611 * stop the walker.
613 if (statep->sps_status == IPADM_NOTFOUND ||
614 statep->sps_status == IPADM_NOTSUP)
615 return (_B_FALSE);
616 return (_B_TRUE);
620 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
621 * for all the properties for the specified object, relavant information, will
622 * be displayed. Otherwise, for the selected property set, display relevant
623 * information
625 static void
626 show_properties(void *arg, int prop_class)
628 show_prop_state_t *statep = arg;
629 nvlist_t *nvl = statep->sps_proplist;
630 uint_t proto = statep->sps_proto;
631 nvpair_t *curr_nvp;
632 char *buf, *name;
633 ipadm_status_t status;
635 /* allocate sufficient buffer to hold a property value */
636 if ((buf = malloc(MAXPROPVALLEN)) == NULL)
637 die("insufficient memory");
638 statep->sps_propval = buf;
640 /* if no properties were specified, display all the properties */
641 if (nvl == NULL) {
642 (void) ipadm_walk_proptbl(proto, prop_class, show_property,
643 statep);
644 } else {
645 for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
646 curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
647 name = nvpair_name(curr_nvp);
648 status = ipadm_walk_prop(name, proto, prop_class,
649 show_property, statep);
650 if (status == IPADM_PROP_UNKNOWN)
651 (void) show_property(statep, name, proto);
655 free(buf);
659 * Display information for all or specific interface properties, either for a
660 * given interface or for all the interfaces in the system.
662 static void
663 do_show_ifprop(int argc, char **argv, const char *use)
665 int option;
666 nvlist_t *proplist = NULL;
667 char *fields_str = NULL;
668 char *ifname;
669 ofmt_handle_t ofmt;
670 ofmt_status_t oferr;
671 uint_t ofmtflags = 0;
672 uint_t proto;
673 boolean_t m_arg = _B_FALSE;
674 char *protostr;
675 ipadm_if_info_t *ifinfo, *ifp;
676 ipadm_status_t status;
677 show_prop_state_t state;
679 opterr = 0;
680 bzero(&state, sizeof (state));
681 state.sps_propval = NULL;
682 state.sps_parsable = _B_FALSE;
683 state.sps_ifprop = _B_TRUE;
684 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
685 while ((option = getopt_long(argc, argv, ":p:m:co:",
686 show_ifprop_longopts, NULL)) != -1) {
687 switch (option) {
688 case 'p':
689 if (ipadm_str2nvlist(optarg, &proplist,
690 IPADM_NORVAL) != 0)
691 die("invalid interface properties specified");
692 break;
693 case 'c':
694 state.sps_parsable = _B_TRUE;
695 break;
696 case 'o':
697 fields_str = optarg;
698 break;
699 case 'm':
700 if (m_arg)
701 die("cannot specify more than one -m");
702 m_arg = _B_TRUE;
703 protostr = optarg;
704 break;
705 default:
706 die_opterr(optopt, option, use);
707 break;
711 if (optind == argc - 1)
712 ifname = argv[optind];
713 else if (optind != argc)
714 die("Usage: %s", use);
715 else
716 ifname = NULL;
718 if (!m_arg)
719 protostr = "ip";
720 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
721 die("invalid protocol '%s' specified", protostr);
723 state.sps_proto = proto;
724 state.sps_proplist = proplist;
726 if (state.sps_parsable)
727 ofmtflags |= OFMT_PARSABLE;
728 oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
729 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
730 state.sps_ofmt = ofmt;
732 /* retrieve interface(s) and print the properties */
733 status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
734 if (ifname != NULL && status == IPADM_ENXIO)
735 die("no such object '%s': %s", ifname,
736 ipadm_status2str(status));
737 if (status != IPADM_SUCCESS)
738 die("Error retrieving interface(s): %s",
739 ipadm_status2str(status));
740 for (ifp = ifinfo; ifp; ifp = ifp->ifi_next) {
741 (void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
742 state.sps_proto = proto;
743 show_properties(&state, IPADMPROP_CLASS_IF);
745 if (ifinfo)
746 ipadm_free_if_info(ifinfo);
748 nvlist_free(proplist);
749 ofmt_close(ofmt);
751 if (state.sps_retstatus != IPADM_SUCCESS) {
752 ipadm_close(iph);
753 exit(EXIT_FAILURE);
758 * set/reset the interface property for a given interface.
760 static void
761 set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
763 int option;
764 ipadm_status_t status = IPADM_SUCCESS;
765 boolean_t p_arg = _B_FALSE;
766 boolean_t m_arg = _B_FALSE;
767 char *ifname, *nv, *protostr;
768 char *prop_name, *prop_val;
769 uint_t flags = IPADM_OPT_PERSIST;
770 uint_t proto;
772 opterr = 0;
773 while ((option = getopt_long(argc, argv, ":m:p:t",
774 set_ifprop_longopts, NULL)) != -1) {
775 switch (option) {
776 case 'p':
777 if (p_arg)
778 die("-p must be specified once only");
779 p_arg = _B_TRUE;
781 ipadm_check_propstr(optarg, reset, use);
782 nv = optarg;
783 break;
784 case 'm':
785 if (m_arg)
786 die("-m must be specified once only");
787 m_arg = _B_TRUE;
788 protostr = optarg;
789 break;
790 case 't':
791 flags &= ~IPADM_OPT_PERSIST;
792 break;
793 default:
794 die_opterr(optopt, option, use);
798 if (!m_arg || !p_arg || optind != argc - 1)
799 die("Usage: %s", use);
801 ifname = argv[optind];
803 prop_name = nv;
804 prop_val = strchr(nv, '=');
805 if (prop_val != NULL)
806 *prop_val++ = '\0';
808 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
809 die("invalid protocol '%s' specified", protostr);
811 if (reset)
812 flags |= IPADM_OPT_DEFAULT;
813 else
814 flags |= IPADM_OPT_ACTIVE;
815 status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
816 flags);
818 done:
819 if (status != IPADM_SUCCESS) {
820 if (reset)
821 die("reset-ifprop: %s: %s",
822 prop_name, ipadm_status2str(status));
823 else
824 die("set-ifprop: %s: %s",
825 prop_name, ipadm_status2str(status));
829 static void
830 do_set_ifprop(int argc, char **argv, const char *use)
832 set_ifprop(argc, argv, _B_FALSE, use);
835 static void
836 do_reset_ifprop(int argc, char **argv, const char *use)
838 set_ifprop(argc, argv, _B_TRUE, use);
842 * Display information for all or specific protocol properties, either for a
843 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
845 static void
846 do_show_prop(int argc, char **argv, const char *use)
848 char option;
849 nvlist_t *proplist = NULL;
850 char *fields_str = NULL;
851 char *protostr;
852 show_prop_state_t state;
853 ofmt_handle_t ofmt;
854 ofmt_status_t oferr;
855 uint_t ofmtflags = 0;
856 uint_t proto;
857 boolean_t p_arg = _B_FALSE;
859 opterr = 0;
860 bzero(&state, sizeof (state));
861 state.sps_propval = NULL;
862 state.sps_parsable = _B_FALSE;
863 state.sps_modprop = _B_TRUE;
864 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
865 while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
866 NULL)) != -1) {
867 switch (option) {
868 case 'p':
869 if (p_arg)
870 die("-p must be specified once only");
871 p_arg = _B_TRUE;
872 if (ipadm_str2nvlist(optarg, &proplist,
873 IPADM_NORVAL) != 0)
874 die("invalid protocol properties specified");
875 break;
876 case 'c':
877 state.sps_parsable = _B_TRUE;
878 break;
879 case 'o':
880 fields_str = optarg;
881 break;
882 default:
883 die_opterr(optopt, option, use);
884 break;
887 if (optind == argc - 1) {
888 protostr = argv[optind];
889 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
890 die("invalid protocol '%s' specified", protostr);
891 state.sps_proto = proto;
892 } else if (optind != argc) {
893 die("Usage: %s", use);
894 } else {
895 if (p_arg)
896 die("protocol must be specified when "
897 "property name is used");
898 state.sps_proto = MOD_PROTO_NONE;
901 state.sps_proplist = proplist;
903 if (state.sps_parsable)
904 ofmtflags |= OFMT_PARSABLE;
905 else
906 ofmtflags |= OFMT_WRAP;
907 oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
908 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
909 state.sps_ofmt = ofmt;
911 /* handles all the errors */
912 show_properties(&state, IPADMPROP_CLASS_MODULE);
914 nvlist_free(proplist);
915 ofmt_close(ofmt);
917 if (state.sps_retstatus != IPADM_SUCCESS) {
918 ipadm_close(iph);
919 exit(EXIT_FAILURE);
924 * Checks to see if there are any modifiers, + or -. If there are modifiers
925 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
927 static void
928 parse_modifiers(const char *pstr, uint_t *flags, const char *use)
930 char *p;
932 if ((p = strchr(pstr, '=')) == NULL)
933 return;
935 if (p == pstr)
936 die("Invalid prop=val specified\n%s", use);
938 --p;
939 if (*p == '+')
940 *flags |= IPADM_OPT_APPEND;
941 else if (*p == '-')
942 *flags |= IPADM_OPT_REMOVE;
946 * set/reset the protocol property for a given protocol.
948 static void
949 set_prop(int argc, char **argv, boolean_t reset, const char *use)
951 int option;
952 ipadm_status_t status = IPADM_SUCCESS;
953 char *protostr, *nv, *prop_name, *prop_val;
954 boolean_t p_arg = _B_FALSE;
955 uint_t proto;
956 uint_t flags = IPADM_OPT_PERSIST;
958 opterr = 0;
959 while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
960 NULL)) != -1) {
961 switch (option) {
962 case 'p':
963 if (p_arg)
964 die("-p must be specified once only");
965 p_arg = _B_TRUE;
967 ipadm_check_propstr(optarg, reset, use);
968 nv = optarg;
969 break;
970 case 't':
971 flags &= ~IPADM_OPT_PERSIST;
972 break;
973 default:
974 die_opterr(optopt, option, use);
978 if (!p_arg || optind != argc - 1)
979 die("Usage: %s", use);
981 parse_modifiers(nv, &flags, use);
982 prop_name = nv;
983 prop_val = strchr(nv, '=');
984 if (prop_val != NULL) {
985 if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
986 *(prop_val - 1) = '\0';
987 *prop_val++ = '\0';
989 protostr = argv[optind];
990 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
991 die("invalid protocol '%s' specified", protostr);
993 if (reset)
994 flags |= IPADM_OPT_DEFAULT;
995 else
996 flags |= IPADM_OPT_ACTIVE;
997 status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
998 done:
999 if (status != IPADM_SUCCESS) {
1000 if (reset)
1001 die("reset-prop: %s: %s",
1002 prop_name, ipadm_status2str(status));
1003 else
1004 die("set-prop: %s: %s",
1005 prop_name, ipadm_status2str(status));
1009 static void
1010 do_set_prop(int argc, char **argv, const char *use)
1012 set_prop(argc, argv, _B_FALSE, use);
1015 static void
1016 do_reset_prop(int argc, char **argv, const char *use)
1018 set_prop(argc, argv, _B_TRUE, use);
1021 /* PRINTFLIKE1 */
1022 static void
1023 warn(const char *format, ...)
1025 va_list alist;
1027 format = gettext(format);
1028 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1030 va_start(alist, format);
1031 (void) vfprintf(stderr, format, alist);
1032 va_end(alist);
1034 (void) fprintf(stderr, "\n");
1037 /* PRINTFLIKE1 */
1038 static void
1039 die(const char *format, ...)
1041 va_list alist;
1043 format = gettext(format);
1044 (void) fprintf(stderr, "%s: ", progname);
1046 va_start(alist, format);
1047 (void) vfprintf(stderr, format, alist);
1048 va_end(alist);
1050 (void) putchar('\n');
1052 ipadm_destroy_addrobj(ipaddr);
1053 ipadm_close(iph);
1054 exit(EXIT_FAILURE);
1057 static void
1058 die_opterr(int opt, int opterr, const char *usage)
1060 switch (opterr) {
1061 case ':':
1062 die("option '-%c' requires a value\nusage: %s", opt,
1063 gettext(usage));
1064 break;
1065 case '?':
1066 default:
1067 die("unrecognized option '-%c'\nusage: %s", opt,
1068 gettext(usage));
1069 break;
1073 /* PRINTFLIKE2 */
1074 static void
1075 warn_ipadmerr(ipadm_status_t err, const char *format, ...)
1077 va_list alist;
1079 format = gettext(format);
1080 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1082 va_start(alist, format);
1083 (void) vfprintf(stderr, format, alist);
1084 va_end(alist);
1086 (void) fprintf(stderr, "%s\n", ipadm_status2str(err));
1089 static void
1090 process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
1092 int option;
1093 char *val;
1094 char *laddr = NULL;
1095 char *raddr = NULL;
1096 char *save_input_arg = addrarg;
1097 boolean_t found_mismatch = _B_FALSE;
1098 ipadm_status_t status;
1099 enum { A_LOCAL, A_REMOTE };
1100 static char *addr_optstr[] = {
1101 "local",
1102 "remote",
1103 NULL,
1106 while (*addrarg != '\0') {
1107 option = getsubopt(&addrarg, addr_optstr, &val);
1108 switch (option) {
1109 case A_LOCAL:
1110 if (laddr != NULL)
1111 die("Multiple local addresses provided");
1112 laddr = val;
1113 break;
1114 case A_REMOTE:
1115 if (raddr != NULL)
1116 die("Multiple remote addresses provided");
1117 raddr = val;
1118 break;
1119 default:
1120 if (found_mismatch)
1121 die("Invalid address provided\nusage: %s", use);
1122 found_mismatch = _B_TRUE;
1123 break;
1126 if (raddr != NULL && laddr == NULL)
1127 die("Missing local address\nusage: %s", use);
1129 /* If only one address is provided, it is assumed a local address. */
1130 if (laddr == NULL) {
1131 if (found_mismatch)
1132 laddr = save_input_arg;
1133 else
1134 die("Missing local address\nusage: %s", use);
1137 /* Initialize the addrobj for static addresses. */
1138 status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
1139 if (status != IPADM_SUCCESS) {
1140 die("Error in creating address object: %s",
1141 ipadm_status2str(status));
1144 /* Set the local and remote addresses */
1145 status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
1146 if (status != IPADM_SUCCESS) {
1147 die("Error in setting local address: %s",
1148 ipadm_status2str(status));
1150 if (raddr != NULL) {
1151 status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
1152 if (status != IPADM_SUCCESS) {
1153 die("Error in setting remote address: %s",
1154 ipadm_status2str(status));
1159 static void
1160 process_addrconf_addrargs(const char *use, char *addrarg)
1162 int option;
1163 char *val;
1164 enum { P_STATELESS, P_STATEFUL };
1165 static char *addr_optstr[] = {
1166 "stateless",
1167 "stateful",
1168 NULL,
1170 boolean_t stateless;
1171 boolean_t stateless_arg = _B_FALSE;
1172 boolean_t stateful;
1173 boolean_t stateful_arg = _B_FALSE;
1174 ipadm_status_t status;
1176 while (*addrarg != '\0') {
1177 option = getsubopt(&addrarg, addr_optstr, &val);
1178 switch (option) {
1179 case P_STATELESS:
1180 if (stateless_arg)
1181 die("Duplicate option");
1182 if (val == NULL)
1183 die("Invalid argument");
1184 if (strcmp(val, "yes") == 0)
1185 stateless = _B_TRUE;
1186 else if (strcmp(val, "no") == 0)
1187 stateless = _B_FALSE;
1188 else
1189 die("Invalid argument");
1190 stateless_arg = _B_TRUE;
1191 break;
1192 case P_STATEFUL:
1193 if (stateful_arg)
1194 die("Duplicate option");
1195 if (val == NULL)
1196 die("Invalid argument");
1197 if (strcmp(val, "yes") == 0)
1198 stateful = _B_TRUE;
1199 else if (strcmp(val, "no") == 0)
1200 stateful = _B_FALSE;
1201 else
1202 die("Invalid argument");
1203 stateful_arg = _B_TRUE;
1204 break;
1205 default:
1206 die_opterr(optopt, option, use);
1210 if (!stateless_arg && !stateful_arg)
1211 die("Invalid arguments for option -p");
1213 /* Set the addrobj fields for addrconf */
1214 if (stateless_arg) {
1215 status = ipadm_set_stateless(ipaddr, stateless);
1216 if (status != IPADM_SUCCESS) {
1217 die("Error in setting stateless option: %s",
1218 ipadm_status2str(status));
1221 if (stateful_arg) {
1222 status = ipadm_set_stateful(ipaddr, stateful);
1223 if (status != IPADM_SUCCESS) {
1224 die("Error in setting stateful option: %s",
1225 ipadm_status2str(status));
1231 * Creates static, dhcp or addrconf addresses and associates the created
1232 * addresses with the specified address object name.
1234 static void
1235 do_create_addr(int argc, char *argv[], const char *use)
1237 ipadm_status_t status;
1238 int option;
1239 uint32_t flags =
1240 IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
1241 char *cp;
1242 char *atype = NULL;
1243 char *static_arg = NULL;
1244 char *addrconf_arg = NULL;
1245 char *interface_id = NULL;
1246 char *wait = NULL;
1247 boolean_t s_opt = _B_FALSE; /* static addr options */
1248 boolean_t auto_opt = _B_FALSE; /* Addrconf options */
1249 boolean_t dhcp_opt = _B_FALSE; /* dhcp options */
1251 opterr = 0;
1252 while ((option = getopt_long(argc, argv, ":T:a:di:p:w:t",
1253 addr_longopts, NULL)) != -1) {
1254 switch (option) {
1255 case 'T':
1256 atype = optarg;
1257 break;
1258 case 'a':
1259 static_arg = optarg;
1260 s_opt = _B_TRUE;
1261 break;
1262 case 'd':
1263 flags &= ~IPADM_OPT_UP;
1264 s_opt = _B_TRUE;
1265 break;
1266 case 'i':
1267 interface_id = optarg;
1268 auto_opt = _B_TRUE;
1269 break;
1270 case 'p':
1271 addrconf_arg = optarg;
1272 auto_opt = _B_TRUE;
1273 break;
1274 case 'w':
1275 wait = optarg;
1276 dhcp_opt = _B_TRUE;
1277 break;
1278 case 't':
1279 flags &= ~IPADM_OPT_PERSIST;
1280 break;
1281 default:
1282 die_opterr(optopt, option, use);
1285 if (atype == NULL || optind != (argc - 1)) {
1286 die("Invalid arguments\nusage: %s", use);
1287 } else if ((cp = strchr(argv[optind], '/')) == NULL ||
1288 strlen(++cp) == 0) {
1289 die("invalid address object name: %s\nusage: %s",
1290 argv[optind], use);
1294 * Allocate and initialize the addrobj based on the address type.
1296 if (strcmp(atype, "static") == 0) {
1297 if (static_arg == NULL || auto_opt || dhcp_opt) {
1298 die("Invalid arguments for type %s\nusage: %s",
1299 atype, use);
1301 process_static_addrargs(use, static_arg, argv[optind]);
1302 } else if (strcmp(atype, "dhcp") == 0) {
1303 if (auto_opt || s_opt) {
1304 die("Invalid arguments for type %s\nusage: %s",
1305 atype, use);
1308 /* Initialize the addrobj for dhcp addresses. */
1309 status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
1310 &ipaddr);
1311 if (status != IPADM_SUCCESS) {
1312 die("Error in creating address object: %s",
1313 ipadm_status2str(status));
1315 if (wait != NULL) {
1316 int32_t ipadm_wait;
1318 if (strcmp(wait, "forever") == 0) {
1319 ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
1320 } else {
1321 char *end;
1322 long timeout = strtol(wait, &end, 10);
1324 if (*end != '\0' || timeout < 0)
1325 die("Invalid argument");
1326 ipadm_wait = (int32_t)timeout;
1328 status = ipadm_set_wait_time(ipaddr, ipadm_wait);
1329 if (status != IPADM_SUCCESS) {
1330 die("Error in setting wait time: %s",
1331 ipadm_status2str(status));
1334 } else if (strcmp(atype, "addrconf") == 0) {
1335 if (dhcp_opt || s_opt) {
1336 die("Invalid arguments for type %s\nusage: %s",
1337 atype, use);
1340 /* Initialize the addrobj for dhcp addresses. */
1341 status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
1342 argv[optind], &ipaddr);
1343 if (status != IPADM_SUCCESS) {
1344 die("Error in creating address object: %s",
1345 ipadm_status2str(status));
1347 if (interface_id != NULL) {
1348 status = ipadm_set_interface_id(ipaddr, interface_id);
1349 if (status != IPADM_SUCCESS) {
1350 die("Error in setting interface ID: %s",
1351 ipadm_status2str(status));
1354 if (addrconf_arg)
1355 process_addrconf_addrargs(use, addrconf_arg);
1356 } else {
1357 die("Invalid address type %s", atype);
1360 status = ipadm_create_addr(iph, ipaddr, flags);
1361 if (status == IPADM_DHCP_IPC_TIMEOUT)
1362 warn_ipadmerr(status, "");
1363 else if (status != IPADM_SUCCESS)
1364 die("Could not create address: %s", ipadm_status2str(status));
1368 * Used by some address management functions to parse the command line
1369 * arguments and create `ipaddr' address object.
1371 static void
1372 process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
1373 uint32_t *flags)
1375 int option;
1377 opterr = 0;
1378 while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
1379 NULL)) != -1) {
1380 switch (option) {
1381 case 't':
1382 *flags &= ~IPADM_OPT_PERSIST;
1383 break;
1384 default:
1385 die_opterr(optopt, option, use);
1388 if (optind != (argc - 1))
1389 die("Usage: %s", use);
1391 *index = optind;
1395 * Remove an addrobj from both active and persistent configuration.
1397 static void
1398 do_delete_addr(int argc, char *argv[], const char *use)
1400 ipadm_status_t status;
1401 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1402 int option;
1404 opterr = 0;
1405 while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
1406 NULL)) != -1) {
1407 switch (option) {
1408 case 'r':
1409 flags |= IPADM_OPT_RELEASE;
1410 break;
1411 default:
1412 die_opterr(optopt, option, use);
1415 if (optind != (argc - 1))
1416 die("Usage: %s", use);
1418 status = ipadm_delete_addr(iph, argv[optind], flags);
1419 if (status != IPADM_SUCCESS) {
1420 die("could not delete address: %s",
1421 ipadm_status2str(status));
1426 * Enable an IP address based on the persistent configuration for that
1427 * IP address
1429 static void
1430 do_enable_addr(int argc, char *argv[], const char *use)
1432 ipadm_status_t status;
1433 int index;
1434 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1436 process_misc_addrargs(argc, argv, use, &index, &flags);
1437 if (flags & IPADM_OPT_PERSIST)
1438 die("persistent operation not supported for enable-addr");
1440 status = ipadm_enable_addr(iph, argv[index], flags);
1441 if (status != IPADM_SUCCESS)
1442 die("could not enable address: %s", ipadm_status2str(status));
1446 * Mark the address identified by addrobj 'up'
1448 static void
1449 do_up_addr(int argc, char *argv[], const char *use)
1451 ipadm_status_t status;
1452 int index;
1453 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1455 process_misc_addrargs(argc, argv, use, &index, &flags);
1456 status = ipadm_up_addr(iph, argv[index], flags);
1457 if (status != IPADM_SUCCESS) {
1458 die("Could not mark the address up: %s",
1459 ipadm_status2str(status));
1464 * Disable the specified addrobj by removing it from active cofiguration
1466 static void
1467 do_disable_addr(int argc, char *argv[], const char *use)
1469 ipadm_status_t status;
1470 int index;
1471 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1473 process_misc_addrargs(argc, argv, use, &index, &flags);
1474 if (flags & IPADM_OPT_PERSIST)
1475 die("persistent operation not supported for disable-addr");
1477 status = ipadm_disable_addr(iph, argv[index], flags);
1478 if (status != IPADM_SUCCESS) {
1479 die("could not disable address: %s",
1480 ipadm_status2str(status));
1485 * Mark the address identified by addrobj 'down'
1487 static void
1488 do_down_addr(int argc, char *argv[], const char *use)
1490 ipadm_status_t status;
1491 int index;
1492 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1494 process_misc_addrargs(argc, argv, use, &index, &flags);
1495 status = ipadm_down_addr(iph, argv[index], flags);
1496 if (status != IPADM_SUCCESS)
1497 die("Could not mark the address down: %s",
1498 ipadm_status2str(status));
1502 * Restart DAD for static address. Extend lease duration for DHCP addresses
1504 static void
1505 do_refresh_addr(int argc, char *argv[], const char *use)
1507 ipadm_status_t status;
1508 int option;
1509 uint32_t flags = 0;
1511 opterr = 0;
1512 while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
1513 NULL)) != -1) {
1514 switch (option) {
1515 case 'i':
1516 flags |= IPADM_OPT_INFORM;
1517 break;
1518 default:
1519 die_opterr(optopt, option, use);
1522 if (optind != (argc - 1))
1523 die("Usage: %s", use);
1525 status = ipadm_refresh_addr(iph, argv[optind], flags);
1526 if (status == IPADM_DHCP_IPC_TIMEOUT)
1527 warn_ipadmerr(status, "");
1528 else if (status != IPADM_SUCCESS)
1529 die("could not refresh address %s", ipadm_status2str(status));
1532 static void
1533 sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
1535 socklen_t socklen;
1536 struct sockaddr *sp = (struct sockaddr *)ssp;
1538 switch (ssp->ss_family) {
1539 case AF_INET:
1540 socklen = sizeof (struct sockaddr_in);
1541 break;
1542 case AF_INET6:
1543 socklen = sizeof (struct sockaddr_in6);
1544 break;
1545 default:
1546 (void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
1547 return;
1550 (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
1551 (NI_NOFQDN | NI_NUMERICHOST));
1554 static void
1555 flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
1556 char *buf, uint_t bufsize)
1558 int i;
1559 boolean_t first = _B_TRUE;
1561 if (is_bits) {
1562 for (i = 0; tbl[i].name; i++) {
1563 if ((flags & tbl[i].mask) == tbl[i].bits)
1564 (void) strlcat(buf, tbl[i].name, bufsize);
1565 else
1566 (void) strlcat(buf, "-", bufsize);
1568 } else {
1569 for (i = 0; tbl[i].name; i++) {
1570 if ((flags & tbl[i].mask) == tbl[i].bits) {
1571 if (!first)
1572 (void) strlcat(buf, ",", bufsize);
1573 (void) strlcat(buf, tbl[i].name, bufsize);
1574 first = _B_FALSE;
1581 * return true if the address for lifname comes to us from the global zone
1582 * with 'allowed-ips' constraints.
1584 static boolean_t
1585 is_from_gz(const char *lifname)
1587 ipadm_if_info_t *if_info;
1588 char phyname[LIFNAMSIZ], *cp;
1589 boolean_t ret = _B_FALSE;
1590 ipadm_status_t status;
1591 zoneid_t zoneid;
1592 ushort_t zflags;
1594 if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1595 return (_B_FALSE); /* from-gz only makes sense in a NGZ */
1597 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1598 return (_B_FALSE);
1600 if (!(zflags & ZF_NET_EXCL))
1601 return (_B_TRUE); /* everything is from the GZ for shared-ip */
1603 (void) strncpy(phyname, lifname, sizeof (phyname));
1604 if ((cp = strchr(phyname, ':')) != NULL)
1605 *cp = '\0';
1606 status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1607 if (status != IPADM_SUCCESS)
1608 return (ret);
1610 if (if_info->ifi_cflags & IFIF_L3PROTECT)
1611 ret = _B_TRUE;
1612 if (if_info)
1613 ipadm_free_if_info(if_info);
1614 return (ret);
1617 static boolean_t
1618 print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1620 show_addr_args_t *arg = ofarg->ofmt_cbarg;
1621 ipadm_addr_info_t *ainfo = arg->sa_info;
1622 char interface[LIFNAMSIZ];
1623 char addrbuf[MAXPROPVALLEN];
1624 char dstbuf[MAXPROPVALLEN];
1625 char prefixlenstr[MAXPROPVALLEN];
1626 int prefixlen;
1627 struct sockaddr_in *sin;
1628 struct sockaddr_in6 *sin6;
1629 sa_family_t af;
1630 char *phyname = NULL;
1631 struct ifaddrs *ifa = &ainfo->ia_ifa;
1632 fmask_t cflags_mask[] = {
1633 { "U", IA_UP, IA_UP },
1634 { "u", IA_UNNUMBERED, IA_UNNUMBERED },
1635 { "p", IA_PRIVATE, IA_PRIVATE },
1636 { "t", IA_TEMPORARY, IA_TEMPORARY },
1637 { "d", IA_DEPRECATED, IA_DEPRECATED },
1638 { NULL, 0, 0 }
1640 fmask_t pflags_mask[] = {
1641 { "U", IA_UP, IA_UP },
1642 { "p", IA_PRIVATE, IA_PRIVATE },
1643 { "d", IA_DEPRECATED, IA_DEPRECATED },
1644 { NULL, 0, 0 }
1646 fmask_t type[] = {
1647 { "static", IPADM_ADDR_STATIC, IPADM_ALL_BITS},
1648 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
1649 { "dhcp", IPADM_ADDR_DHCP, IPADM_ALL_BITS},
1650 { NULL, 0, 0 }
1652 fmask_t addr_state[] = {
1653 { "disabled", IFA_DISABLED, IPADM_ALL_BITS},
1654 { "duplicate", IFA_DUPLICATE, IPADM_ALL_BITS},
1655 { "down", IFA_DOWN, IPADM_ALL_BITS},
1656 { "tentative", IFA_TENTATIVE, IPADM_ALL_BITS},
1657 { "ok", IFA_OK, IPADM_ALL_BITS},
1658 { "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
1659 { NULL, 0, 0 }
1662 buf[0] = '\0';
1663 switch (ofarg->ofmt_id) {
1664 case SA_ADDROBJ:
1665 if (ainfo->ia_aobjname[0] == '\0') {
1666 (void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
1667 phyname = strrchr(interface, ':');
1668 if (phyname)
1669 *phyname = '\0';
1670 (void) snprintf(buf, bufsize, "%s/%s", interface,
1671 STR_UNKNOWN_VAL);
1672 } else {
1673 (void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
1675 break;
1676 case SA_STATE:
1677 flags2str(ainfo->ia_state, addr_state, _B_FALSE,
1678 buf, bufsize);
1679 break;
1680 case SA_TYPE:
1681 if (is_from_gz(ifa->ifa_name))
1682 (void) snprintf(buf, bufsize, "from-gz");
1683 else
1684 flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1685 bufsize);
1686 break;
1687 case SA_CURRENT:
1688 flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
1689 break;
1690 case SA_PERSISTENT:
1691 flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
1692 break;
1693 case SA_ADDR:
1694 af = ifa->ifa_addr->sa_family;
1696 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1697 * print STR_UNKNOWN_VAL.
1699 if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
1700 sin = (struct sockaddr_in *)ifa->ifa_addr;
1701 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1702 if ((af == AF_INET &&
1703 sin->sin_addr.s_addr == INADDR_ANY) ||
1704 (af == AF_INET6 &&
1705 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
1706 (void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
1707 break;
1710 if (ifa->ifa_netmask == NULL)
1711 prefixlen = 0;
1712 else
1713 prefixlen = mask2plen(ifa->ifa_netmask);
1714 bzero(prefixlenstr, sizeof (prefixlenstr));
1715 if (prefixlen > 0) {
1716 (void) snprintf(prefixlenstr, sizeof (prefixlenstr),
1717 "/%d", prefixlen);
1719 bzero(addrbuf, sizeof (addrbuf));
1720 bzero(dstbuf, sizeof (dstbuf));
1721 if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
1723 * Print the hostname fields if the address is not
1724 * in active configuration.
1726 if (ainfo->ia_state == IFA_DISABLED) {
1727 (void) snprintf(buf, bufsize, "%s",
1728 ainfo->ia_sname);
1729 if (ainfo->ia_dname[0] != '\0') {
1730 (void) snprintf(dstbuf, sizeof (dstbuf),
1731 "->%s", ainfo->ia_dname);
1732 (void) strlcat(buf, dstbuf, bufsize);
1733 } else {
1734 (void) strlcat(buf, prefixlenstr,
1735 bufsize);
1737 break;
1741 * For the non-persistent case, we need to show the
1742 * currently configured addresses for source and
1743 * destination.
1745 sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
1746 addrbuf, sizeof (addrbuf));
1747 if (ifa->ifa_flags & IFF_POINTOPOINT) {
1748 sockaddr2str(
1749 (struct sockaddr_storage *)ifa->ifa_dstaddr,
1750 dstbuf, sizeof (dstbuf));
1751 (void) snprintf(buf, bufsize, "%s->%s", addrbuf,
1752 dstbuf);
1753 } else {
1754 (void) snprintf(buf, bufsize, "%s%s", addrbuf,
1755 prefixlenstr);
1757 break;
1758 default:
1759 die("invalid input");
1760 break;
1763 return (_B_TRUE);
1767 * Display address information, either for the given address or
1768 * for all the addresses managed by ipadm.
1770 static void
1771 do_show_addr(int argc, char *argv[], const char *use)
1773 ipadm_status_t status;
1774 show_addr_state_t state;
1775 char *def_fields_str = "addrobj,type,state,addr";
1776 char *fields_str = NULL;
1777 ipadm_addr_info_t *ainfo;
1778 ipadm_addr_info_t *ptr;
1779 show_addr_args_t sargs;
1780 int option;
1781 ofmt_handle_t ofmt;
1782 ofmt_status_t oferr;
1783 uint_t ofmtflags = 0;
1784 char *aname;
1785 char *ifname = NULL;
1786 char *cp;
1787 boolean_t found = _B_FALSE;
1789 opterr = 0;
1790 state.sa_parsable = _B_FALSE;
1791 state.sa_persist = _B_FALSE;
1792 while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
1793 NULL)) != -1) {
1794 switch (option) {
1795 case 'p':
1796 state.sa_parsable = _B_TRUE;
1797 break;
1798 case 'o':
1799 fields_str = optarg;
1800 break;
1801 default:
1802 die_opterr(optopt, option, use);
1803 break;
1806 if (state.sa_parsable && fields_str == NULL)
1807 die("-p requires -o");
1809 if (optind == argc - 1) {
1810 aname = argv[optind];
1811 if ((cp = strchr(aname, '/')) == NULL)
1812 die("Invalid address object name provided");
1813 if (*(cp + 1) == '\0') {
1814 ifname = aname;
1815 *cp = '\0';
1816 aname = NULL;
1818 } else if (optind == argc) {
1819 aname = NULL;
1820 } else {
1821 die("Usage: %s", use);
1824 if (state.sa_parsable)
1825 ofmtflags |= OFMT_PARSABLE;
1826 if (fields_str == NULL)
1827 fields_str = def_fields_str;
1828 oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
1830 ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
1831 state.sa_ofmt = ofmt;
1833 status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
1835 * Return without printing any error, if no addresses were found,
1836 * for the case where all addresses are requested.
1838 if (status != IPADM_SUCCESS)
1839 die("Could not get address: %s", ipadm_status2str(status));
1840 if (ainfo == NULL) {
1841 ofmt_close(ofmt);
1842 return;
1845 bzero(&sargs, sizeof (sargs));
1846 sargs.sa_state = &state;
1847 for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
1848 sargs.sa_info = ptr;
1849 if (aname != NULL) {
1850 if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
1851 continue;
1852 found = _B_TRUE;
1854 ofmt_print(state.sa_ofmt, &sargs);
1856 if (ainfo)
1857 ipadm_free_addr_info(ainfo);
1858 if (aname != NULL && !found)
1859 die("Address object not found");
1862 static boolean_t
1863 print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1865 show_if_args_t *arg = ofarg->ofmt_cbarg;
1866 ipadm_if_info_t *ifinfo = arg->si_info;
1867 char *ifname = ifinfo->ifi_name;
1868 fmask_t intf_state[] = {
1869 { "ok", IFIS_OK, IPADM_ALL_BITS},
1870 { "down", IFIS_DOWN, IPADM_ALL_BITS},
1871 { "disabled", IFIS_DISABLED, IPADM_ALL_BITS},
1872 { "failed", IFIS_FAILED, IPADM_ALL_BITS},
1873 { "offline", IFIS_OFFLINE, IPADM_ALL_BITS},
1874 { NULL, 0, 0 }
1876 fmask_t intf_pflags[] = {
1877 { "s", IFIF_STANDBY, IFIF_STANDBY },
1878 { "4", IFIF_IPV4, IFIF_IPV4 },
1879 { "6", IFIF_IPV6, IFIF_IPV6 },
1880 { NULL, 0, 0 }
1882 fmask_t intf_cflags[] = {
1883 { "b", IFIF_BROADCAST, IFIF_BROADCAST },
1884 { "m", IFIF_MULTICAST, IFIF_MULTICAST },
1885 { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
1886 { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
1887 { "I", IFIF_IPMP, IFIF_IPMP },
1888 { "s", IFIF_STANDBY, IFIF_STANDBY },
1889 { "i", IFIF_INACTIVE, IFIF_INACTIVE },
1890 { "V", IFIF_VRRP, IFIF_VRRP },
1891 { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
1892 { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
1893 { "4", IFIF_IPV4, IFIF_IPV4 },
1894 { "6", IFIF_IPV6, IFIF_IPV6 },
1895 { NULL, 0, 0 }
1898 buf[0] = '\0';
1899 switch (ofarg->ofmt_id) {
1900 case SI_IFNAME:
1901 (void) snprintf(buf, bufsize, "%s", ifname);
1902 break;
1903 case SI_STATE:
1904 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1905 buf, bufsize);
1906 break;
1907 case SI_CURRENT:
1908 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1909 buf, bufsize);
1910 break;
1911 case SI_PERSISTENT:
1912 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
1913 buf, bufsize);
1914 break;
1915 default:
1916 die("invalid input");
1917 break;
1920 return (_B_TRUE);
1924 * Display interface information, either for the given interface or
1925 * for all the interfaces in the system.
1927 static void
1928 do_show_if(int argc, char *argv[], const char *use)
1930 ipadm_status_t status;
1931 show_if_state_t state;
1932 char *fields_str = NULL;
1933 ipadm_if_info_t *if_info, *ptr;
1934 show_if_args_t sargs;
1935 int option;
1936 ofmt_handle_t ofmt;
1937 ofmt_status_t oferr;
1938 uint_t ofmtflags = 0;
1939 char *ifname = NULL;
1941 opterr = 0;
1942 state.si_parsable = _B_FALSE;
1944 while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
1945 NULL)) != -1) {
1946 switch (option) {
1947 case 'p':
1948 state.si_parsable = _B_TRUE;
1949 break;
1950 case 'o':
1951 fields_str = optarg;
1952 break;
1953 default:
1954 die_opterr(optopt, option, use);
1955 break;
1958 if (optind == argc - 1)
1959 ifname = argv[optind];
1960 else if (optind != argc)
1961 die("Usage: %s", use);
1962 if (state.si_parsable)
1963 ofmtflags |= OFMT_PARSABLE;
1964 oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
1965 ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
1966 state.si_ofmt = ofmt;
1967 bzero(&sargs, sizeof (sargs));
1968 sargs.si_state = &state;
1969 status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
1971 * Return without printing any error, if no addresses were found.
1973 if (status != IPADM_SUCCESS) {
1974 die("Could not get interface(s): %s",
1975 ipadm_status2str(status));
1978 for (ptr = if_info; ptr; ptr = ptr->ifi_next) {
1979 sargs.si_info = ptr;
1980 ofmt_print(state.si_ofmt, &sargs);
1982 if (if_info)
1983 ipadm_free_if_info(if_info);
1987 * set/reset the address property for a given address
1989 static void
1990 set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
1992 int option;
1993 ipadm_status_t status = IPADM_SUCCESS;
1994 boolean_t p_arg = _B_FALSE;
1995 char *nv, *aobjname;
1996 char *prop_name, *prop_val;
1997 uint_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1999 opterr = 0;
2000 while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
2001 NULL)) != -1) {
2002 switch (option) {
2003 case 'p':
2004 if (p_arg)
2005 die("-p must be specified once only");
2006 p_arg = _B_TRUE;
2008 ipadm_check_propstr(optarg, reset, use);
2009 nv = optarg;
2010 break;
2011 case 't':
2012 flags &= ~IPADM_OPT_PERSIST;
2013 break;
2014 default:
2015 die_opterr(optopt, option, use);
2019 if (!p_arg || optind != (argc - 1))
2020 die("Usage: %s", use);
2022 prop_name = nv;
2023 prop_val = strchr(nv, '=');
2024 if (prop_val != NULL)
2025 *prop_val++ = '\0';
2026 aobjname = argv[optind];
2027 if (reset)
2028 flags |= IPADM_OPT_DEFAULT;
2029 status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
2030 if (status != IPADM_SUCCESS) {
2031 if (reset)
2032 die("reset-addrprop: %s: %s", prop_name,
2033 ipadm_status2str(status));
2034 else
2035 die("set-addrprop: %s: %s", prop_name,
2036 ipadm_status2str(status));
2041 * Sets a property on an address object.
2043 static void
2044 do_set_addrprop(int argc, char **argv, const char *use)
2046 set_addrprop(argc, argv, _B_FALSE, use);
2050 * Resets a property to its default value on an address object.
2052 static void
2053 do_reset_addrprop(int argc, char **argv, const char *use)
2055 set_addrprop(argc, argv, _B_TRUE, use);
2059 * Display information for all or specific address properties, either for a
2060 * given address or for all the addresses in the system.
2062 static void
2063 do_show_addrprop(int argc, char *argv[], const char *use)
2065 int option;
2066 nvlist_t *proplist = NULL;
2067 char *fields_str = NULL;
2068 show_prop_state_t state;
2069 ofmt_handle_t ofmt;
2070 ofmt_status_t oferr;
2071 uint_t ofmtflags = 0;
2072 char *aobjname = NULL;
2073 char *ifname = NULL;
2074 char *cp;
2075 ipadm_addr_info_t *ainfop = NULL;
2076 ipadm_addr_info_t *ptr;
2077 ipadm_status_t status;
2078 boolean_t found = _B_FALSE;
2080 opterr = 0;
2081 bzero(&state, sizeof (state));
2082 state.sps_propval = NULL;
2083 state.sps_parsable = _B_FALSE;
2084 state.sps_addrprop = _B_TRUE;
2085 state.sps_proto = MOD_PROTO_NONE;
2086 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
2087 while ((option = getopt_long(argc, argv, ":p:i:cPo:",
2088 show_prop_longopts, NULL)) != -1) {
2089 switch (option) {
2090 case 'p':
2091 if (ipadm_str2nvlist(optarg, &proplist,
2092 IPADM_NORVAL) != 0)
2093 die("invalid addrobj properties specified");
2094 break;
2095 case 'c':
2096 state.sps_parsable = _B_TRUE;
2097 break;
2098 case 'o':
2099 fields_str = optarg;
2100 break;
2101 default:
2102 die_opterr(optopt, option, use);
2103 break;
2106 if (optind == argc - 1) {
2107 aobjname = argv[optind];
2108 cp = strchr(aobjname, '/');
2109 if (cp == NULL)
2110 die("invalid addrobj name provided");
2111 if (*(cp + 1) == '\0') {
2112 ifname = aobjname;
2113 *cp = '\0';
2114 aobjname = NULL;
2116 } else if (optind != argc) {
2117 die("Usage: %s", use);
2119 state.sps_proplist = proplist;
2120 if (state.sps_parsable)
2121 ofmtflags |= OFMT_PARSABLE;
2122 oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
2123 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
2124 state.sps_ofmt = ofmt;
2126 status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
2127 /* Return without printing any error, if no addresses were found */
2128 if (status == IPADM_NOTFOUND)
2129 return;
2130 if (status != IPADM_SUCCESS)
2131 die("error retrieving address: %s", ipadm_status2str(status));
2133 for (ptr = ainfop; ptr != NULL; ptr = IA_NEXT(ptr)) {
2134 char *taobjname = ptr->ia_aobjname;
2136 if (taobjname[0] == '\0')
2137 continue;
2138 if (aobjname != NULL) {
2139 if (strcmp(aobjname, taobjname) == 0)
2140 found = _B_TRUE;
2141 else
2142 continue;
2144 if (ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
2145 if (found)
2146 break;
2147 else
2148 continue;
2150 (void) strlcpy(state.sps_aobjname, taobjname,
2151 sizeof (state.sps_aobjname));
2152 show_properties(&state, IPADMPROP_CLASS_ADDR);
2153 if (found)
2154 break;
2156 ipadm_free_addr_info(ainfop);
2158 if (aobjname != NULL && !found)
2159 die("addrobj not found: %s", aobjname);
2161 nvlist_free(proplist);
2162 ofmt_close(ofmt);
2163 if (state.sps_retstatus != IPADM_SUCCESS) {
2164 ipadm_close(iph);
2165 exit(EXIT_FAILURE);
2169 static void
2170 ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
2171 ofmt_handle_t ofmt)
2173 char buf[OFMT_BUFSIZE];
2175 if (oferr == OFMT_SUCCESS)
2176 return;
2177 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
2179 * All errors are considered fatal in parsable mode.
2180 * NOMEM errors are always fatal, regardless of mode.
2181 * For other errors, we print diagnostics in human-readable
2182 * mode and processs what we can.
2184 if (parsable || oferr == OFMT_ENOFIELDS) {
2185 ofmt_close(ofmt);
2186 die(buf);
2187 } else {
2188 warn(buf);
2193 * check if the `pstr' adheres to following syntax
2194 * - prop=<value[,...]> (for set)
2195 * - prop (for reset)
2197 static void
2198 ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
2200 char *nv;
2202 nv = strchr(pstr, '=');
2203 if (reset) {
2204 if (nv != NULL)
2205 die("incorrect syntax used for -p.\n%s", use);
2206 } else {
2207 if (nv == NULL || *++nv == '\0')
2208 die("please specify the value to be set.\n%s", use);
2209 nv = strchr(nv, '=');
2210 /* cannot have multiple 'prop=val' for single -p */
2211 if (nv != NULL)
2212 die("cannot specify more than one prop=val at "
2213 "a time.\n%s", use);