Print this page
Commit IPMP changes
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
+++ new/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25 #include <arpa/inet.h>
26 26 #include <errno.h>
27 27 #include <getopt.h>
28 28 #include <inet/ip.h>
29 29 #include <inet/iptun.h>
30 30 #include <inet/tunables.h>
31 31 #include <libdladm.h>
32 32 #include <libdliptun.h>
33 33 #include <libdllink.h>
34 34 #include <libinetutil.h>
35 35 #include <libipadm.h>
36 +#include <ipmp.h>
37 +#include <ipmp_admin.h>
36 38 #include <locale.h>
37 39 #include <netdb.h>
38 40 #include <netinet/in.h>
39 41 #include <ofmt.h>
40 42 #include <stdarg.h>
41 43 #include <stddef.h>
42 44 #include <stdio.h>
43 45 #include <stdlib.h>
44 46 #include <string.h>
45 47 #include <strings.h>
46 48 #include <sys/stat.h>
47 49 #include <sys/types.h>
48 50 #include <zone.h>
51 +#include <sys/list.h>
52 +#include <stddef.h>
49 53
50 54 #define STR_UNKNOWN_VAL "?"
51 55 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
52 56 LIFC_UNDER_IPMP)
53 57
58 +static void do_create_if_common(int, char **, const char *, uint32_t);
59 +
54 60 typedef void cmdfunc_t(int, char **, const char *);
61 +static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
55 62 static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
56 63 static cmdfunc_t do_show_if;
57 64 static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
58 65 static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
59 66 static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
60 67 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
61 68 static cmdfunc_t do_enable_addr, do_disable_addr;
62 69 static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
63 70
64 71 typedef struct cmd {
65 72 char *c_name;
66 73 cmdfunc_t *c_fn;
67 74 const char *c_usage;
68 75 } cmd_t;
69 76
70 77 static cmd_t cmds[] = {
71 78 /* interface management related sub-commands */
79 + { "create-ipmp", do_create_ipmp, "\tcreate-ipmp\t[-t] <ipmp-group>"},
80 + { "delete-ipmp", do_delete_if, "\tdelete-ipmp\t[-t] <ipmp-group>"},
81 + { "add-ipmp", do_add_ipmp, "\tadd-ipmp\t[-t] -i"
82 + " <ipmp-member-interface> "
83 + "[-i <ipmp-member-interface>] <ipmp-group-interface>"},
84 + { "remove-ipmp", do_remove_ipmp, "\tremove-ipmp\t[-t] -i"
85 + " <ipmp-member-interface> "
86 + "[-i <ipmp-member-interface>] <ipmp-group-interface>"},
72 87 { "create-if", do_create_if, "\tcreate-if\t[-t] <interface>" },
73 88 { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
74 89 { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
75 90 { "delete-if", do_delete_if, "\tdelete-if\t<interface>" },
76 91 { "show-if", do_show_if,
77 92 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
78 93 { "set-ifprop", do_set_ifprop,
79 94 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
80 95 "<interface>" },
81 96 { "reset-ifprop", do_reset_ifprop,
82 97 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
83 98 { "show-ifprop", do_show_ifprop,
84 99 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
85 100 "\t\t\t[-m <protocol>] [interface]\n" },
86 101
87 102 /* address management related sub-commands */
88 103 { "create-addr", do_create_addr,
89 104 "\tcreate-addr\t[-t] -T static [-d] "
90 105 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
91 106 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"
92 107 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
93 108 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
94 109 { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
95 110 { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
96 111 { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
97 112 { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>" },
98 113 { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
99 114 { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
100 115 { "show-addr", do_show_addr,
101 116 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
102 117 { "set-addrprop", do_set_addrprop,
103 118 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
104 119 { "reset-addrprop", do_reset_addrprop,
105 120 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
106 121 { "show-addrprop", do_show_addrprop,
107 122 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
108 123 "<addrobj>\n" },
109 124
110 125 /* protocol properties related sub-commands */
111 126 { "set-prop", do_set_prop,
112 127 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
113 128 { "reset-prop", do_reset_prop,
114 129 "\treset-prop\t[-t] -p <prop> <protocol>" },
115 130 { "show-prop", do_show_prop,
116 131 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
117 132 " [protocol]" }
118 133 };
119 134
120 135 static const struct option if_longopts[] = {
121 136 {"temporary", no_argument, 0, 't' },
122 137 { 0, 0, 0, 0 }
123 138 };
124 139
125 140 static const struct option show_prop_longopts[] = {
126 141 {"parsable", no_argument, 0, 'c' },
127 142 {"prop", required_argument, 0, 'p' },
128 143 {"output", required_argument, 0, 'o' },
129 144 { 0, 0, 0, 0 }
130 145 };
131 146
132 147 static const struct option show_ifprop_longopts[] = {
133 148 {"module", required_argument, 0, 'm' },
134 149 {"parsable", no_argument, 0, 'c' },
135 150 {"prop", required_argument, 0, 'p' },
136 151 {"output", required_argument, 0, 'o' },
137 152 { 0, 0, 0, 0 }
138 153 };
139 154
140 155 static const struct option set_prop_longopts[] = {
141 156 {"prop", required_argument, 0, 'p' },
142 157 {"temporary", no_argument, 0, 't' },
143 158 { 0, 0, 0, 0 }
144 159 };
145 160
146 161 static const struct option set_ifprop_longopts[] = {
147 162 {"module", required_argument, 0, 'm' },
148 163 {"prop", required_argument, 0, 'p' },
149 164 {"temporary", no_argument, 0, 't' },
150 165 { 0, 0, 0, 0 }
151 166 };
152 167
153 168 static const struct option addr_misc_longopts[] = {
154 169 {"inform", no_argument, 0, 'i' },
155 170 {"release", no_argument, 0, 'r' },
156 171 {"temporary", no_argument, 0, 't' },
157 172 { 0, 0, 0, 0 }
158 173 };
159 174
160 175 static const struct option addr_longopts[] = {
161 176 {"address", required_argument, 0, 'a' },
162 177 {"down", no_argument, 0, 'd' },
163 178 {"interface-id", required_argument, 0, 'i' },
164 179 {"prop", required_argument, 0, 'p' },
165 180 {"temporary", no_argument, 0, 't' },
166 181 {"type", required_argument, 0, 'T' },
167 182 {"wait", required_argument, 0, 'w' },
168 183 { 0, 0, 0, 0 }
169 184 };
170 185
171 186 static const struct option show_addr_longopts[] = {
172 187 {"parsable", no_argument, 0, 'p' },
173 188 {"output", required_argument, 0, 'o' },
174 189 { 0, 0, 0, 0 }
175 190 };
176 191
177 192 static const struct option show_if_longopts[] = {
178 193 {"parsable", no_argument, 0, 'p' },
179 194 {"output", required_argument, 0, 'o' },
180 195 { 0, 0, 0, 0 }
181 196 };
182 197
183 198 /* callback functions to print show-* subcommands output */
184 199 static ofmt_cb_t print_prop_cb;
185 200 static ofmt_cb_t print_sa_cb;
186 201 static ofmt_cb_t print_si_cb;
187 202
188 203 /* structures for 'ipadm show-*' subcommands */
189 204 typedef enum {
190 205 IPADM_PROPFIELD_IFNAME,
191 206 IPADM_PROPFIELD_PROTO,
192 207 IPADM_PROPFIELD_ADDROBJ,
193 208 IPADM_PROPFIELD_PROPERTY,
194 209 IPADM_PROPFIELD_PERM,
195 210 IPADM_PROPFIELD_CURRENT,
196 211 IPADM_PROPFIELD_PERSISTENT,
197 212 IPADM_PROPFIELD_DEFAULT,
198 213 IPADM_PROPFIELD_POSSIBLE
199 214 } ipadm_propfield_index_t;
200 215
201 216 static ofmt_field_t intfprop_fields[] = {
202 217 /* name, field width, index, callback */
203 218 { "IFNAME", 12, IPADM_PROPFIELD_IFNAME, print_prop_cb},
204 219 { "PROPERTY", 16, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
205 220 { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
206 221 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
207 222 { "CURRENT", 11, IPADM_PROPFIELD_CURRENT, print_prop_cb},
208 223 { "PERSISTENT", 11, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
209 224 { "DEFAULT", 11, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
210 225 { "POSSIBLE", 16, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
211 226 { NULL, 0, 0, NULL}
212 227 };
213 228
214 229
215 230 static ofmt_field_t modprop_fields[] = {
216 231 /* name, field width, index, callback */
217 232 { "PROTO", 6, IPADM_PROPFIELD_PROTO, print_prop_cb},
218 233 { "PROPERTY", 22, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
219 234 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
220 235 { "CURRENT", 13, IPADM_PROPFIELD_CURRENT, print_prop_cb},
221 236 { "PERSISTENT", 13, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
222 237 { "DEFAULT", 13, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
223 238 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
224 239 { NULL, 0, 0, NULL}
225 240 };
226 241
227 242 static ofmt_field_t addrprop_fields[] = {
228 243 /* name, field width, index, callback */
229 244 { "ADDROBJ", 18, IPADM_PROPFIELD_ADDROBJ, print_prop_cb},
230 245 { "PROPERTY", 11, IPADM_PROPFIELD_PROPERTY, print_prop_cb},
231 246 { "PERM", 5, IPADM_PROPFIELD_PERM, print_prop_cb},
232 247 { "CURRENT", 16, IPADM_PROPFIELD_CURRENT, print_prop_cb},
233 248 { "PERSISTENT", 16, IPADM_PROPFIELD_PERSISTENT, print_prop_cb},
234 249 { "DEFAULT", 16, IPADM_PROPFIELD_DEFAULT, print_prop_cb},
235 250 { "POSSIBLE", 15, IPADM_PROPFIELD_POSSIBLE, print_prop_cb},
236 251 { NULL, 0, 0, NULL}
237 252 };
238 253
239 254 typedef struct show_prop_state {
240 255 char sps_ifname[LIFNAMSIZ];
241 256 char sps_aobjname[IPADM_AOBJSIZ];
242 257 const char *sps_pname;
243 258 uint_t sps_proto;
244 259 char *sps_propval;
245 260 nvlist_t *sps_proplist;
246 261 boolean_t sps_parsable;
247 262 boolean_t sps_addrprop;
248 263 boolean_t sps_ifprop;
249 264 boolean_t sps_modprop;
250 265 ipadm_status_t sps_status;
251 266 ipadm_status_t sps_retstatus;
252 267 ofmt_handle_t sps_ofmt;
253 268 } show_prop_state_t;
254 269
255 270 typedef struct show_addr_state {
256 271 boolean_t sa_parsable;
257 272 boolean_t sa_persist;
258 273 ofmt_handle_t sa_ofmt;
259 274 } show_addr_state_t;
260 275
261 276 typedef struct show_if_state {
262 277 boolean_t si_parsable;
263 278 ofmt_handle_t si_ofmt;
264 279 } show_if_state_t;
265 280
266 281 typedef struct show_addr_args_s {
267 282 show_addr_state_t *sa_state;
268 283 ipadm_addr_info_t *sa_info;
269 284 } show_addr_args_t;
270 285
271 286 typedef struct show_if_args_s {
272 287 show_if_state_t *si_state;
273 288 ipadm_if_info_t *si_info;
274 289 } show_if_args_t;
275 290
276 291 typedef enum {
↓ open down ↓ |
195 lines elided |
↑ open up ↑ |
277 292 SA_ADDROBJ,
278 293 SA_TYPE,
279 294 SA_STATE,
280 295 SA_CURRENT,
281 296 SA_PERSISTENT,
282 297 SA_ADDR
283 298 } sa_field_index_t;
284 299
285 300 typedef enum {
286 301 SI_IFNAME,
302 + SI_IFCLASS,
287 303 SI_STATE,
288 304 SI_CURRENT,
289 305 SI_PERSISTENT
290 306 } si_field_index_t;
291 307
292 308 static ofmt_field_t show_addr_fields[] = {
293 309 /* name, field width, id, callback */
294 310 { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
295 311 { "TYPE", 9, SA_TYPE, print_sa_cb},
296 312 { "STATE", 13, SA_STATE, print_sa_cb},
297 313 { "CURRENT", 8, SA_CURRENT, print_sa_cb},
298 314 { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
299 315 { "ADDR", 46, SA_ADDR, print_sa_cb},
300 316 { NULL, 0, 0, NULL}
301 317 };
302 318
303 319 static ofmt_field_t show_if_fields[] = {
304 320 /* name, field width, id, callback */
305 321 { "IFNAME", 11, SI_IFNAME, print_si_cb},
322 +{ "CLASS", 10, SI_IFCLASS, print_si_cb},
306 323 { "STATE", 9, SI_STATE, print_si_cb},
307 324 { "CURRENT", 13, SI_CURRENT, print_si_cb},
308 325 { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
309 326 { NULL, 0, 0, NULL}
310 327 };
311 328
312 329 #define IPADM_ALL_BITS ((uint_t)-1)
313 330 typedef struct intf_mask {
314 331 char *name;
315 332 uint64_t bits;
316 333 uint64_t mask;
317 334 } fmask_t;
318 335
336 +typedef enum {
337 + IPMP_ADD_MEMBER,
338 + IPMP_REMOVE_MEMBER
339 +} ipmp_action_t;
340 +
319 341 /*
320 342 * Handle to libipadm. Opened in main() before the sub-command specific
321 343 * function is called and is closed before the program exits.
322 344 */
323 345 ipadm_handle_t iph = NULL;
324 346
325 347 /*
326 348 * Opaque ipadm address object. Used by all the address management subcommands.
327 349 */
328 350 ipadm_addrobj_t ipaddr = NULL;
329 351
330 352 static char *progname;
331 353
332 354 static void die(const char *, ...);
333 355 static void die_opterr(int, int, const char *);
334 356 static void warn_ipadmerr(ipadm_status_t, const char *, ...);
335 357 static void ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
336 358 static void ipadm_check_propstr(const char *, boolean_t, const char *);
337 359 static void process_misc_addrargs(int, char **, const char *, int *,
338 360 uint32_t *);
361 +static void do_action_ipmp(int, char **, const char *, ipmp_action_t);
339 362
340 363 static void
341 364 usage(void)
342 365 {
343 366 int i;
344 367 cmd_t *cmdp;
345 368
346 369 (void) fprintf(stderr,
347 370 gettext("usage: ipadm <subcommand> <args> ...\n"));
348 371 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
349 372 cmdp = &cmds[i];
350 373 if (cmdp->c_usage != NULL)
351 374 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
352 375 }
353 376
354 377 ipadm_destroy_addrobj(ipaddr);
355 378 ipadm_close(iph);
356 379 exit(1);
357 380 }
358 381
359 382 int
360 383 main(int argc, char *argv[])
361 384 {
362 385 int i;
363 386 cmd_t *cmdp;
364 387 ipadm_status_t status;
365 388
366 389 (void) setlocale(LC_ALL, "");
367 390 (void) textdomain(TEXT_DOMAIN);
368 391
369 392 if ((progname = strrchr(argv[0], '/')) == NULL)
370 393 progname = argv[0];
371 394 else
372 395 progname++;
373 396
374 397 if (argc < 2)
375 398 usage();
376 399
377 400 status = ipadm_open(&iph, 0);
378 401 if (status != IPADM_SUCCESS) {
379 402 die("Could not open handle to library - %s",
380 403 ipadm_status2str(status));
381 404 }
382 405
383 406 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
384 407 cmdp = &cmds[i];
385 408 if (strcmp(argv[1], cmdp->c_name) == 0) {
386 409 cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
387 410 ipadm_destroy_addrobj(ipaddr);
388 411 ipadm_close(iph);
389 412 exit(0);
390 413 }
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
391 414 }
392 415
393 416 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
394 417 progname, argv[1]);
395 418 usage();
396 419
397 420 return (0);
398 421 }
399 422
400 423 /*
401 - * Create an IP interface for which no saved configuration exists in the
402 - * persistent store.
424 + * Create regular IP interface or IPMP group interface
403 425 */
404 426 static void
405 -do_create_if(int argc, char *argv[], const char *use)
427 +do_create_if_common(int argc, char *argv[], const char *use, uint32_t flags)
406 428 {
407 429 ipadm_status_t status;
408 430 int option;
409 - uint32_t flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
410 431
411 432 opterr = 0;
412 - while ((option = getopt_long(argc, argv, ":t", if_longopts,
413 - NULL)) != -1) {
433 + while ((option = getopt_long(argc, argv,
434 + ":t", if_longopts, NULL)) != -1) {
414 435 switch (option) {
415 436 case 't':
416 437 /*
417 438 * "ifconfig" mode - plumb interface, but do not
418 439 * restore settings that may exist in db.
419 440 */
420 441 flags &= ~IPADM_OPT_PERSIST;
421 442 break;
422 443 default:
423 444 die_opterr(optopt, option, use);
424 445 }
425 446 }
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
426 447 if (optind != (argc - 1))
427 448 die("Usage: %s", use);
428 449 status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
429 450 if (status != IPADM_SUCCESS) {
430 451 die("Could not create %s : %s",
431 452 argv[optind], ipadm_status2str(status));
432 453 }
433 454 }
434 455
435 456 /*
457 + * Create an IPMP group interface for which no saved configuration
458 + * exists in the persistent store.
459 + */
460 +static void
461 +do_create_ipmp(int argc, char *argv[], const char *use)
462 +{
463 + ipmp_handle_t ipmp_handle;
464 + int retval;
465 + uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP;
466 +
467 + retval = ipmp_open(&ipmp_handle);
468 + if (retval != IPMP_SUCCESS) {
469 + die("Could not create IPMP handle: %s",
470 + ipadm_status2str(retval));
471 + }
472 +
473 + retval = ipmp_ping_daemon(ipmp_handle);
474 + ipmp_close(ipmp_handle);
475 +
476 + if (retval != IPMP_SUCCESS) {
477 + die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval));
478 + }
479 +
480 + do_create_if_common(argc, argv, use, flags);
481 +}
482 +
483 +static void
484 +do_add_ipmp(int argc, char *argv[], const char *use)
485 +{
486 + do_action_ipmp(argc, argv, use, IPMP_ADD_MEMBER);
487 +}
488 +
489 +static void
490 +do_remove_ipmp(int argc, char *argv[], const char *use)
491 +{
492 + do_action_ipmp(argc, argv, use, IPMP_REMOVE_MEMBER);
493 +}
494 +
495 +static void
496 +do_action_ipmp(int argc, char *argv[], const char *use,
497 + ipmp_action_t action)
498 +{
499 + int option;
500 + ipadm_status_t status;
501 + ipadm_ipmp_members_t members;
502 + ipadm_ipmp_member_t *ipmp_member;
503 + uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
504 +
505 + list_create(&members, sizeof (ipadm_ipmp_member_t),
506 + offsetof(ipadm_ipmp_member_t, node));
507 +
508 + opterr = 0;
509 + while ((option = getopt_long(argc, argv,
510 + ":ti:", if_longopts, NULL)) != -1) {
511 + switch (option) {
512 + case 't':
513 + flags &= ~IPADM_OPT_PERSIST;
514 + break;
515 + case 'i':
516 + if ((ipmp_member = calloc(1,
517 + sizeof (ipadm_ipmp_member_t))) == NULL)
518 + die("insufficient memory");
519 +
520 + if (strlcpy(ipmp_member->if_name,
521 + optarg, sizeof (ipmp_member->if_name)) >= LIFNAMSIZ)
522 + die("Incorrect length of interface"
523 + "name: %s", optarg);
524 +
525 + list_insert_tail(&members, ipmp_member);
526 + break;
527 + default:
528 + die_opterr(optopt, option, use);
529 + }
530 + }
531 +
532 + if (optind != (argc - 1))
533 + die("Usage: %s", use);
534 +
535 + while ((ipmp_member = list_remove_head(&members)) != NULL) {
536 + switch (action) {
537 + case IPMP_ADD_MEMBER:
538 + if ((status = ipadm_add_ipmp_member(iph,
539 + argv[optind], ipmp_member->if_name, flags))
540 + != IPADM_SUCCESS)
541 + die("Cannot add '%s' interface to"
542 + "'%s': %s",
543 + ipmp_member->if_name, argv[optind],
544 + ipadm_status2str(status));
545 + break;
546 + case IPMP_REMOVE_MEMBER:
547 + if ((status = ipadm_remove_ipmp_member(iph,
548 + argv[optind], ipmp_member->if_name, flags))
549 + != IPADM_SUCCESS)
550 + die("Cannot remove '%s' interface from "
551 + "'%s': %s",
552 + ipmp_member->if_name, argv[optind],
553 + ipadm_status2str(status));
554 + break;
555 + }
556 +
557 + free(ipmp_member);
558 + }
559 +
560 + list_destroy(&members);
561 +}
562 +
563 +/*
564 + * Create an IP interface for which no saved configuration exists in the
565 + * persistent store.
566 + */
567 +static void
568 +do_create_if(int argc, char *argv[], const char *use)
569 +{
570 + do_create_if_common(argc, argv, use,
571 + IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE);
572 +}
573 +
574 +/*
436 575 * Enable an IP interface based on the persistent configuration for
437 576 * that interface.
438 577 */
439 578 static void
440 579 do_enable_if(int argc, char *argv[], const char *use)
441 580 {
442 581 ipadm_status_t status;
443 582 int index;
444 583 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
445 584
446 585 process_misc_addrargs(argc, argv, use, &index, &flags);
447 586 if (flags & IPADM_OPT_PERSIST)
448 587 die("persistent operation not supported for enable-if");
449 588 status = ipadm_enable_if(iph, argv[index], flags);
450 589 if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
451 590 warn_ipadmerr(status, "");
452 591 } else if (status != IPADM_SUCCESS) {
453 592 die("Could not enable %s : %s",
454 593 argv[optind], ipadm_status2str(status));
455 594 }
456 595 }
457 596
458 597 /*
459 598 * Remove an IP interface from both active and persistent configuration.
460 599 */
461 600 static void
462 601 do_delete_if(int argc, char *argv[], const char *use)
463 602 {
464 603 ipadm_status_t status;
465 604 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
466 605
467 606 if (argc != 2)
468 607 die("Usage: %s", use);
469 608
470 609 status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
471 610 if (status != IPADM_SUCCESS) {
472 611 die("Could not delete %s: %s",
473 612 argv[optind], ipadm_status2str(status));
474 613 }
475 614 }
476 615
477 616 /*
478 617 * Disable an IP interface by removing it from active configuration.
479 618 */
480 619 static void
481 620 do_disable_if(int argc, char *argv[], const char *use)
482 621 {
483 622 ipadm_status_t status;
484 623 int index;
485 624 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
486 625
487 626 process_misc_addrargs(argc, argv, use, &index, &flags);
488 627 if (flags & IPADM_OPT_PERSIST)
489 628 die("persistent operation not supported for disable-if");
490 629 status = ipadm_disable_if(iph, argv[index], flags);
491 630 if (status != IPADM_SUCCESS) {
492 631 die("Could not disable %s: %s",
493 632 argv[optind], ipadm_status2str(status));
494 633 }
495 634 }
496 635
497 636 /*
498 637 * called in from print_prop_cb() and does the job of printing each
499 638 * individual column in the 'ipadm show-*prop' output.
500 639 */
501 640 static void
502 641 print_prop(show_prop_state_t *statep, uint_t flags, char *buf, size_t bufsize)
503 642 {
504 643 const char *prop_name = statep->sps_pname;
505 644 char *ifname = statep->sps_ifname;
506 645 char *propval = statep->sps_propval;
507 646 uint_t proto = statep->sps_proto;
508 647 size_t propsize = MAXPROPVALLEN;
509 648 char *object;
510 649 ipadm_status_t status;
511 650
512 651 if (statep->sps_ifprop) {
513 652 status = ipadm_get_ifprop(iph, ifname, prop_name, propval,
514 653 &propsize, proto, flags);
515 654 object = ifname;
516 655 } else if (statep->sps_modprop) {
517 656 status = ipadm_get_prop(iph, prop_name, propval, &propsize,
518 657 proto, flags);
519 658 object = ipadm_proto2str(proto);
520 659 } else {
521 660 status = ipadm_get_addrprop(iph, prop_name, propval, &propsize,
522 661 statep->sps_aobjname, flags);
523 662 object = statep->sps_aobjname;
524 663 }
525 664
526 665 if (status != IPADM_SUCCESS) {
527 666 if (status == IPADM_PROP_UNKNOWN ||
528 667 status == IPADM_INVALID_ARG) {
529 668 warn_ipadmerr(status, "cannot get property '%s' for "
530 669 "'%s'", prop_name, object);
531 670 } else if (status == IPADM_NOTSUP) {
532 671 warn_ipadmerr(status, "'%s'", object);
533 672 } else if (status == IPADM_NOTFOUND) {
534 673 if (flags & IPADM_OPT_PERSIST) {
535 674 propval[0] = '\0';
536 675 goto cont;
537 676 } else {
538 677 warn_ipadmerr(status, "no such object '%s'",
539 678 object);
540 679 }
541 680 } else if (status == IPADM_ENXIO) {
542 681 /* the interface is probably disabled */
543 682 propval[0] = '\0';
544 683 goto cont;
545 684 }
546 685 statep->sps_status = status;
547 686 statep->sps_retstatus = status;
548 687 return;
549 688 }
550 689 cont:
551 690 statep->sps_status = IPADM_SUCCESS;
552 691 (void) snprintf(buf, bufsize, "%s", propval);
553 692 }
554 693
555 694 /*
556 695 * callback function which displays output for set-prop, set-ifprop and
557 696 * set-addrprop subcommands.
558 697 */
559 698 static boolean_t
560 699 print_prop_cb(ofmt_arg_t *ofarg, char *buf, size_t bufsize)
561 700 {
562 701 show_prop_state_t *statep = ofarg->ofmt_cbarg;
563 702 const char *propname = statep->sps_pname;
564 703 uint_t proto = statep->sps_proto;
565 704 boolean_t cont = _B_TRUE;
566 705
567 706 /*
568 707 * Fail retrieving remaining fields, if you fail
569 708 * to retrieve a field.
570 709 */
571 710 if (statep->sps_status != IPADM_SUCCESS)
572 711 return (_B_FALSE);
573 712
574 713 switch (ofarg->ofmt_id) {
575 714 case IPADM_PROPFIELD_IFNAME:
576 715 (void) snprintf(buf, bufsize, "%s", statep->sps_ifname);
577 716 break;
578 717 case IPADM_PROPFIELD_PROTO:
579 718 (void) snprintf(buf, bufsize, "%s", ipadm_proto2str(proto));
580 719 break;
581 720 case IPADM_PROPFIELD_ADDROBJ:
582 721 (void) snprintf(buf, bufsize, "%s", statep->sps_aobjname);
583 722 break;
584 723 case IPADM_PROPFIELD_PROPERTY:
585 724 (void) snprintf(buf, bufsize, "%s", propname);
586 725 break;
587 726 case IPADM_PROPFIELD_PERM:
588 727 print_prop(statep, IPADM_OPT_PERM, buf, bufsize);
589 728 break;
590 729 case IPADM_PROPFIELD_CURRENT:
591 730 print_prop(statep, IPADM_OPT_ACTIVE, buf, bufsize);
592 731 break;
593 732 case IPADM_PROPFIELD_PERSISTENT:
594 733 print_prop(statep, IPADM_OPT_PERSIST, buf, bufsize);
595 734 break;
596 735 case IPADM_PROPFIELD_DEFAULT:
597 736 print_prop(statep, IPADM_OPT_DEFAULT, buf, bufsize);
598 737 break;
599 738 case IPADM_PROPFIELD_POSSIBLE:
600 739 print_prop(statep, IPADM_OPT_POSSIBLE, buf, bufsize);
601 740 break;
602 741 }
603 742 if (statep->sps_status != IPADM_SUCCESS)
604 743 cont = _B_FALSE;
605 744 return (cont);
606 745 }
607 746
608 747 /*
609 748 * Callback function called by the property walker (ipadm_walk_prop() or
610 749 * ipadm_walk_proptbl()), for every matched property. This function in turn
611 750 * calls ofmt_print() to print property information.
612 751 */
613 752 boolean_t
614 753 show_property(void *arg, const char *pname, uint_t proto)
615 754 {
616 755 show_prop_state_t *statep = arg;
617 756
618 757 statep->sps_pname = pname;
619 758 statep->sps_proto = proto;
620 759 statep->sps_status = IPADM_SUCCESS;
621 760 ofmt_print(statep->sps_ofmt, arg);
622 761
623 762 /*
624 763 * if an object is not found or operation is not supported then
625 764 * stop the walker.
626 765 */
627 766 if (statep->sps_status == IPADM_NOTFOUND ||
628 767 statep->sps_status == IPADM_NOTSUP)
629 768 return (_B_FALSE);
630 769 return (_B_TRUE);
631 770 }
632 771
633 772 /*
634 773 * Properties to be displayed is in `statep->sps_proplist'. If it is NULL,
635 774 * for all the properties for the specified object, relavant information, will
636 775 * be displayed. Otherwise, for the selected property set, display relevant
637 776 * information
638 777 */
639 778 static void
640 779 show_properties(void *arg, int prop_class)
641 780 {
642 781 show_prop_state_t *statep = arg;
643 782 nvlist_t *nvl = statep->sps_proplist;
644 783 uint_t proto = statep->sps_proto;
645 784 nvpair_t *curr_nvp;
646 785 char *buf, *name;
647 786 ipadm_status_t status;
648 787
649 788 /* allocate sufficient buffer to hold a property value */
650 789 if ((buf = malloc(MAXPROPVALLEN)) == NULL)
651 790 die("insufficient memory");
652 791 statep->sps_propval = buf;
653 792
654 793 /* if no properties were specified, display all the properties */
655 794 if (nvl == NULL) {
656 795 (void) ipadm_walk_proptbl(proto, prop_class, show_property,
657 796 statep);
658 797 } else {
659 798 for (curr_nvp = nvlist_next_nvpair(nvl, NULL); curr_nvp;
660 799 curr_nvp = nvlist_next_nvpair(nvl, curr_nvp)) {
661 800 name = nvpair_name(curr_nvp);
662 801 status = ipadm_walk_prop(name, proto, prop_class,
663 802 show_property, statep);
664 803 if (status == IPADM_PROP_UNKNOWN)
665 804 (void) show_property(statep, name, proto);
666 805 }
667 806 }
668 807
669 808 free(buf);
670 809 }
671 810
672 811 /*
673 812 * Display information for all or specific interface properties, either for a
674 813 * given interface or for all the interfaces in the system.
675 814 */
676 815 static void
677 816 do_show_ifprop(int argc, char **argv, const char *use)
678 817 {
679 818 int option;
680 819 nvlist_t *proplist = NULL;
681 820 char *fields_str = NULL;
682 821 char *ifname;
683 822 ofmt_handle_t ofmt;
684 823 ofmt_status_t oferr;
685 824 uint_t ofmtflags = 0;
686 825 uint_t proto;
687 826 boolean_t m_arg = _B_FALSE;
688 827 char *protostr;
689 828 ipadm_if_info_t *ifinfo, *ifp;
690 829 ipadm_status_t status;
691 830 show_prop_state_t state;
692 831
693 832 opterr = 0;
694 833 bzero(&state, sizeof (state));
695 834 state.sps_propval = NULL;
696 835 state.sps_parsable = _B_FALSE;
697 836 state.sps_ifprop = _B_TRUE;
698 837 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
699 838 while ((option = getopt_long(argc, argv, ":p:m:co:",
700 839 show_ifprop_longopts, NULL)) != -1) {
701 840 switch (option) {
702 841 case 'p':
703 842 if (ipadm_str2nvlist(optarg, &proplist,
704 843 IPADM_NORVAL) != 0)
705 844 die("invalid interface properties specified");
706 845 break;
707 846 case 'c':
708 847 state.sps_parsable = _B_TRUE;
709 848 break;
710 849 case 'o':
711 850 fields_str = optarg;
712 851 break;
713 852 case 'm':
714 853 if (m_arg)
715 854 die("cannot specify more than one -m");
716 855 m_arg = _B_TRUE;
717 856 protostr = optarg;
718 857 break;
719 858 default:
720 859 die_opterr(optopt, option, use);
721 860 break;
722 861 }
723 862 }
724 863
725 864 if (optind == argc - 1)
726 865 ifname = argv[optind];
727 866 else if (optind != argc)
728 867 die("Usage: %s", use);
729 868 else
730 869 ifname = NULL;
731 870
732 871 if (!m_arg)
733 872 protostr = "ip";
734 873 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
735 874 die("invalid protocol '%s' specified", protostr);
736 875
737 876 state.sps_proto = proto;
738 877 state.sps_proplist = proplist;
739 878
740 879 if (state.sps_parsable)
741 880 ofmtflags |= OFMT_PARSABLE;
742 881 oferr = ofmt_open(fields_str, intfprop_fields, ofmtflags, 0, &ofmt);
743 882 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
744 883 state.sps_ofmt = ofmt;
745 884
746 885 /* retrieve interface(s) and print the properties */
747 886 status = ipadm_if_info(iph, ifname, &ifinfo, 0, LIFC_DEFAULT);
748 887 if (ifname != NULL && status == IPADM_ENXIO)
749 888 die("no such object '%s': %s", ifname,
750 889 ipadm_status2str(status));
751 890 if (status != IPADM_SUCCESS)
752 891 die("Error retrieving interface(s): %s",
753 892 ipadm_status2str(status));
754 893 for (ifp = ifinfo; ifp; ifp = ifp->ifi_next) {
755 894 (void) strlcpy(state.sps_ifname, ifp->ifi_name, LIFNAMSIZ);
756 895 state.sps_proto = proto;
757 896 show_properties(&state, IPADMPROP_CLASS_IF);
758 897 }
759 898 if (ifinfo)
760 899 ipadm_free_if_info(ifinfo);
761 900
762 901 nvlist_free(proplist);
763 902 ofmt_close(ofmt);
764 903
765 904 if (state.sps_retstatus != IPADM_SUCCESS) {
766 905 ipadm_close(iph);
767 906 exit(EXIT_FAILURE);
768 907 }
769 908 }
770 909
771 910 /*
772 911 * set/reset the interface property for a given interface.
773 912 */
774 913 static void
775 914 set_ifprop(int argc, char **argv, boolean_t reset, const char *use)
776 915 {
777 916 int option;
778 917 ipadm_status_t status = IPADM_SUCCESS;
779 918 boolean_t p_arg = _B_FALSE;
780 919 boolean_t m_arg = _B_FALSE;
781 920 char *ifname, *nv, *protostr;
782 921 char *prop_name, *prop_val;
783 922 uint_t flags = IPADM_OPT_PERSIST;
784 923 uint_t proto;
785 924
786 925 opterr = 0;
787 926 while ((option = getopt_long(argc, argv, ":m:p:t",
788 927 set_ifprop_longopts, NULL)) != -1) {
789 928 switch (option) {
790 929 case 'p':
791 930 if (p_arg)
792 931 die("-p must be specified once only");
793 932 p_arg = _B_TRUE;
794 933
795 934 ipadm_check_propstr(optarg, reset, use);
796 935 nv = optarg;
797 936 break;
798 937 case 'm':
799 938 if (m_arg)
800 939 die("-m must be specified once only");
801 940 m_arg = _B_TRUE;
802 941 protostr = optarg;
803 942 break;
804 943 case 't':
805 944 flags &= ~IPADM_OPT_PERSIST;
806 945 break;
807 946 default:
808 947 die_opterr(optopt, option, use);
809 948 }
810 949 }
811 950
812 951 if (!m_arg || !p_arg || optind != argc - 1)
813 952 die("Usage: %s", use);
814 953
815 954 ifname = argv[optind];
816 955
817 956 prop_name = nv;
818 957 prop_val = strchr(nv, '=');
819 958 if (prop_val != NULL)
820 959 *prop_val++ = '\0';
821 960
822 961 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
823 962 die("invalid protocol '%s' specified", protostr);
824 963
825 964 if (reset)
826 965 flags |= IPADM_OPT_DEFAULT;
827 966 else
828 967 flags |= IPADM_OPT_ACTIVE;
829 968 status = ipadm_set_ifprop(iph, ifname, prop_name, prop_val, proto,
830 969 flags);
831 970
832 971 done:
833 972 if (status != IPADM_SUCCESS) {
834 973 if (reset)
835 974 die("reset-ifprop: %s: %s",
836 975 prop_name, ipadm_status2str(status));
837 976 else
838 977 die("set-ifprop: %s: %s",
839 978 prop_name, ipadm_status2str(status));
840 979 }
841 980 }
842 981
843 982 static void
844 983 do_set_ifprop(int argc, char **argv, const char *use)
845 984 {
846 985 set_ifprop(argc, argv, _B_FALSE, use);
847 986 }
848 987
849 988 static void
850 989 do_reset_ifprop(int argc, char **argv, const char *use)
851 990 {
852 991 set_ifprop(argc, argv, _B_TRUE, use);
853 992 }
854 993
855 994 /*
856 995 * Display information for all or specific protocol properties, either for a
857 996 * given protocol or for supported protocols (IP/IPv4/IPv6/TCP/UDP/SCTP)
858 997 */
859 998 static void
860 999 do_show_prop(int argc, char **argv, const char *use)
861 1000 {
862 1001 char option;
863 1002 nvlist_t *proplist = NULL;
864 1003 char *fields_str = NULL;
865 1004 char *protostr;
866 1005 show_prop_state_t state;
867 1006 ofmt_handle_t ofmt;
868 1007 ofmt_status_t oferr;
869 1008 uint_t ofmtflags = 0;
870 1009 uint_t proto;
871 1010 boolean_t p_arg = _B_FALSE;
872 1011
873 1012 opterr = 0;
874 1013 bzero(&state, sizeof (state));
875 1014 state.sps_propval = NULL;
876 1015 state.sps_parsable = _B_FALSE;
877 1016 state.sps_modprop = _B_TRUE;
878 1017 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
879 1018 while ((option = getopt_long(argc, argv, ":p:co:", show_prop_longopts,
880 1019 NULL)) != -1) {
881 1020 switch (option) {
882 1021 case 'p':
883 1022 if (p_arg)
884 1023 die("-p must be specified once only");
885 1024 p_arg = _B_TRUE;
886 1025 if (ipadm_str2nvlist(optarg, &proplist,
887 1026 IPADM_NORVAL) != 0)
888 1027 die("invalid protocol properties specified");
889 1028 break;
890 1029 case 'c':
891 1030 state.sps_parsable = _B_TRUE;
892 1031 break;
893 1032 case 'o':
894 1033 fields_str = optarg;
895 1034 break;
896 1035 default:
897 1036 die_opterr(optopt, option, use);
898 1037 break;
899 1038 }
900 1039 }
901 1040 if (optind == argc - 1) {
902 1041 protostr = argv[optind];
903 1042 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
904 1043 die("invalid protocol '%s' specified", protostr);
905 1044 state.sps_proto = proto;
906 1045 } else if (optind != argc) {
907 1046 die("Usage: %s", use);
908 1047 } else {
909 1048 if (p_arg)
910 1049 die("protocol must be specified when "
911 1050 "property name is used");
912 1051 state.sps_proto = MOD_PROTO_NONE;
913 1052 }
914 1053
915 1054 state.sps_proplist = proplist;
916 1055
917 1056 if (state.sps_parsable)
918 1057 ofmtflags |= OFMT_PARSABLE;
919 1058 else
920 1059 ofmtflags |= OFMT_WRAP;
921 1060 oferr = ofmt_open(fields_str, modprop_fields, ofmtflags, 0, &ofmt);
922 1061 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
923 1062 state.sps_ofmt = ofmt;
924 1063
925 1064 /* handles all the errors */
926 1065 show_properties(&state, IPADMPROP_CLASS_MODULE);
927 1066
928 1067 nvlist_free(proplist);
929 1068 ofmt_close(ofmt);
930 1069
931 1070 if (state.sps_retstatus != IPADM_SUCCESS) {
932 1071 ipadm_close(iph);
933 1072 exit(EXIT_FAILURE);
934 1073 }
935 1074 }
936 1075
937 1076 /*
938 1077 * Checks to see if there are any modifiers, + or -. If there are modifiers
939 1078 * then sets IPADM_OPT_APPEND or IPADM_OPT_REMOVE, accordingly.
940 1079 */
941 1080 static void
942 1081 parse_modifiers(const char *pstr, uint_t *flags, const char *use)
943 1082 {
944 1083 char *p;
945 1084
946 1085 if ((p = strchr(pstr, '=')) == NULL)
947 1086 return;
948 1087
949 1088 if (p == pstr)
950 1089 die("Invalid prop=val specified\n%s", use);
951 1090
952 1091 --p;
953 1092 if (*p == '+')
954 1093 *flags |= IPADM_OPT_APPEND;
955 1094 else if (*p == '-')
956 1095 *flags |= IPADM_OPT_REMOVE;
957 1096 }
958 1097
959 1098 /*
960 1099 * set/reset the protocol property for a given protocol.
961 1100 */
962 1101 static void
963 1102 set_prop(int argc, char **argv, boolean_t reset, const char *use)
964 1103 {
965 1104 int option;
966 1105 ipadm_status_t status = IPADM_SUCCESS;
967 1106 char *protostr, *nv, *prop_name, *prop_val;
968 1107 boolean_t p_arg = _B_FALSE;
969 1108 uint_t proto;
970 1109 uint_t flags = IPADM_OPT_PERSIST;
971 1110
972 1111 opterr = 0;
973 1112 while ((option = getopt_long(argc, argv, ":p:t", set_prop_longopts,
974 1113 NULL)) != -1) {
975 1114 switch (option) {
976 1115 case 'p':
977 1116 if (p_arg)
978 1117 die("-p must be specified once only");
979 1118 p_arg = _B_TRUE;
980 1119
981 1120 ipadm_check_propstr(optarg, reset, use);
982 1121 nv = optarg;
983 1122 break;
984 1123 case 't':
985 1124 flags &= ~IPADM_OPT_PERSIST;
986 1125 break;
987 1126 default:
988 1127 die_opterr(optopt, option, use);
989 1128 }
990 1129 }
991 1130
992 1131 if (!p_arg || optind != argc - 1)
993 1132 die("Usage: %s", use);
994 1133
995 1134 parse_modifiers(nv, &flags, use);
996 1135 prop_name = nv;
997 1136 prop_val = strchr(nv, '=');
998 1137 if (prop_val != NULL) {
999 1138 if (flags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))
1000 1139 *(prop_val - 1) = '\0';
1001 1140 *prop_val++ = '\0';
1002 1141 }
1003 1142 protostr = argv[optind];
1004 1143 if ((proto = ipadm_str2proto(protostr)) == MOD_PROTO_NONE)
1005 1144 die("invalid protocol '%s' specified", protostr);
1006 1145
1007 1146 if (reset)
1008 1147 flags |= IPADM_OPT_DEFAULT;
1009 1148 else
1010 1149 flags |= IPADM_OPT_ACTIVE;
1011 1150 status = ipadm_set_prop(iph, prop_name, prop_val, proto, flags);
1012 1151 done:
1013 1152 if (status != IPADM_SUCCESS) {
1014 1153 if (reset)
1015 1154 die("reset-prop: %s: %s",
1016 1155 prop_name, ipadm_status2str(status));
1017 1156 else
1018 1157 die("set-prop: %s: %s",
1019 1158 prop_name, ipadm_status2str(status));
1020 1159 }
1021 1160 }
1022 1161
1023 1162 static void
1024 1163 do_set_prop(int argc, char **argv, const char *use)
1025 1164 {
1026 1165 set_prop(argc, argv, _B_FALSE, use);
1027 1166 }
1028 1167
1029 1168 static void
1030 1169 do_reset_prop(int argc, char **argv, const char *use)
1031 1170 {
1032 1171 set_prop(argc, argv, _B_TRUE, use);
1033 1172 }
1034 1173
1035 1174 /* PRINTFLIKE1 */
1036 1175 static void
1037 1176 warn(const char *format, ...)
1038 1177 {
1039 1178 va_list alist;
1040 1179
1041 1180 format = gettext(format);
1042 1181 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1043 1182
1044 1183 va_start(alist, format);
1045 1184 (void) vfprintf(stderr, format, alist);
1046 1185 va_end(alist);
1047 1186
1048 1187 (void) fprintf(stderr, "\n");
1049 1188 }
1050 1189
1051 1190 /* PRINTFLIKE1 */
1052 1191 static void
1053 1192 die(const char *format, ...)
1054 1193 {
1055 1194 va_list alist;
1056 1195
1057 1196 format = gettext(format);
1058 1197 (void) fprintf(stderr, "%s: ", progname);
1059 1198
1060 1199 va_start(alist, format);
1061 1200 (void) vfprintf(stderr, format, alist);
1062 1201 va_end(alist);
1063 1202
1064 1203 (void) putchar('\n');
1065 1204
1066 1205 ipadm_destroy_addrobj(ipaddr);
1067 1206 ipadm_close(iph);
1068 1207 exit(EXIT_FAILURE);
1069 1208 }
1070 1209
1071 1210 static void
1072 1211 die_opterr(int opt, int opterr, const char *usage)
1073 1212 {
1074 1213 switch (opterr) {
1075 1214 case ':':
1076 1215 die("option '-%c' requires a value\nusage: %s", opt,
1077 1216 gettext(usage));
1078 1217 break;
1079 1218 case '?':
1080 1219 default:
1081 1220 die("unrecognized option '-%c'\nusage: %s", opt,
1082 1221 gettext(usage));
1083 1222 break;
1084 1223 }
1085 1224 }
1086 1225
1087 1226 /* PRINTFLIKE2 */
1088 1227 static void
1089 1228 warn_ipadmerr(ipadm_status_t err, const char *format, ...)
1090 1229 {
1091 1230 va_list alist;
1092 1231
1093 1232 format = gettext(format);
1094 1233 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1095 1234
1096 1235 va_start(alist, format);
1097 1236 (void) vfprintf(stderr, format, alist);
1098 1237 va_end(alist);
1099 1238
1100 1239 (void) fprintf(stderr, "%s\n", ipadm_status2str(err));
1101 1240 }
1102 1241
1103 1242 static void
1104 1243 process_static_addrargs(const char *use, char *addrarg, const char *aobjname)
1105 1244 {
1106 1245 int option;
1107 1246 char *val;
1108 1247 char *laddr = NULL;
1109 1248 char *raddr = NULL;
1110 1249 char *save_input_arg = addrarg;
1111 1250 boolean_t found_mismatch = _B_FALSE;
1112 1251 ipadm_status_t status;
1113 1252 enum { A_LOCAL, A_REMOTE };
1114 1253 static char *addr_optstr[] = {
1115 1254 "local",
1116 1255 "remote",
1117 1256 NULL,
1118 1257 };
1119 1258
1120 1259 while (*addrarg != '\0') {
1121 1260 option = getsubopt(&addrarg, addr_optstr, &val);
1122 1261 switch (option) {
1123 1262 case A_LOCAL:
1124 1263 if (laddr != NULL)
1125 1264 die("Multiple local addresses provided");
1126 1265 laddr = val;
1127 1266 break;
1128 1267 case A_REMOTE:
1129 1268 if (raddr != NULL)
1130 1269 die("Multiple remote addresses provided");
1131 1270 raddr = val;
1132 1271 break;
1133 1272 default:
1134 1273 if (found_mismatch)
1135 1274 die("Invalid address provided\nusage: %s", use);
1136 1275 found_mismatch = _B_TRUE;
1137 1276 break;
1138 1277 }
1139 1278 }
1140 1279 if (raddr != NULL && laddr == NULL)
1141 1280 die("Missing local address\nusage: %s", use);
1142 1281
1143 1282 /* If only one address is provided, it is assumed a local address. */
1144 1283 if (laddr == NULL) {
1145 1284 if (found_mismatch)
1146 1285 laddr = save_input_arg;
1147 1286 else
1148 1287 die("Missing local address\nusage: %s", use);
1149 1288 }
1150 1289
1151 1290 /* Initialize the addrobj for static addresses. */
1152 1291 status = ipadm_create_addrobj(IPADM_ADDR_STATIC, aobjname, &ipaddr);
1153 1292 if (status != IPADM_SUCCESS) {
1154 1293 die("Error in creating address object: %s",
1155 1294 ipadm_status2str(status));
1156 1295 }
1157 1296
1158 1297 /* Set the local and remote addresses */
1159 1298 status = ipadm_set_addr(ipaddr, laddr, AF_UNSPEC);
1160 1299 if (status != IPADM_SUCCESS) {
1161 1300 die("Error in setting local address: %s",
1162 1301 ipadm_status2str(status));
1163 1302 }
1164 1303 if (raddr != NULL) {
1165 1304 status = ipadm_set_dst_addr(ipaddr, raddr, AF_UNSPEC);
1166 1305 if (status != IPADM_SUCCESS) {
1167 1306 die("Error in setting remote address: %s",
1168 1307 ipadm_status2str(status));
1169 1308 }
1170 1309 }
1171 1310 }
1172 1311
1173 1312 static void
1174 1313 process_addrconf_addrargs(const char *use, char *addrarg)
1175 1314 {
1176 1315 int option;
1177 1316 char *val;
1178 1317 enum { P_STATELESS, P_STATEFUL };
1179 1318 static char *addr_optstr[] = {
1180 1319 "stateless",
1181 1320 "stateful",
1182 1321 NULL,
1183 1322 };
1184 1323 boolean_t stateless;
1185 1324 boolean_t stateless_arg = _B_FALSE;
1186 1325 boolean_t stateful;
1187 1326 boolean_t stateful_arg = _B_FALSE;
1188 1327 ipadm_status_t status;
1189 1328
1190 1329 while (*addrarg != '\0') {
1191 1330 option = getsubopt(&addrarg, addr_optstr, &val);
1192 1331 switch (option) {
1193 1332 case P_STATELESS:
1194 1333 if (stateless_arg)
1195 1334 die("Duplicate option");
1196 1335 if (val == NULL)
1197 1336 die("Invalid argument");
1198 1337 if (strcmp(val, "yes") == 0)
1199 1338 stateless = _B_TRUE;
1200 1339 else if (strcmp(val, "no") == 0)
1201 1340 stateless = _B_FALSE;
1202 1341 else
1203 1342 die("Invalid argument");
1204 1343 stateless_arg = _B_TRUE;
1205 1344 break;
1206 1345 case P_STATEFUL:
1207 1346 if (stateful_arg)
1208 1347 die("Duplicate option");
1209 1348 if (val == NULL)
1210 1349 die("Invalid argument");
1211 1350 if (strcmp(val, "yes") == 0)
1212 1351 stateful = _B_TRUE;
1213 1352 else if (strcmp(val, "no") == 0)
1214 1353 stateful = _B_FALSE;
1215 1354 else
1216 1355 die("Invalid argument");
1217 1356 stateful_arg = _B_TRUE;
1218 1357 break;
1219 1358 default:
1220 1359 die_opterr(optopt, option, use);
1221 1360 }
1222 1361 }
1223 1362
1224 1363 if (!stateless_arg && !stateful_arg)
1225 1364 die("Invalid arguments for option -p");
1226 1365
1227 1366 /* Set the addrobj fields for addrconf */
1228 1367 if (stateless_arg) {
1229 1368 status = ipadm_set_stateless(ipaddr, stateless);
1230 1369 if (status != IPADM_SUCCESS) {
1231 1370 die("Error in setting stateless option: %s",
1232 1371 ipadm_status2str(status));
1233 1372 }
1234 1373 }
1235 1374 if (stateful_arg) {
1236 1375 status = ipadm_set_stateful(ipaddr, stateful);
1237 1376 if (status != IPADM_SUCCESS) {
1238 1377 die("Error in setting stateful option: %s",
1239 1378 ipadm_status2str(status));
1240 1379 }
1241 1380 }
1242 1381 }
1243 1382
1244 1383 /*
1245 1384 * Creates static, dhcp or addrconf addresses and associates the created
1246 1385 * addresses with the specified address object name.
1247 1386 */
1248 1387 static void
1249 1388 do_create_addr(int argc, char *argv[], const char *use)
1250 1389 {
1251 1390 ipadm_status_t status;
1252 1391 int option;
1253 1392 uint32_t flags =
1254 1393 IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46;
1255 1394 char *cp;
1256 1395 char *atype = NULL;
1257 1396 char *static_arg = NULL;
1258 1397 char *addrconf_arg = NULL;
1259 1398 char *interface_id = NULL;
1260 1399 char *wait = NULL;
1261 1400 boolean_t s_opt = _B_FALSE; /* static addr options */
1262 1401 boolean_t auto_opt = _B_FALSE; /* Addrconf options */
1263 1402 boolean_t dhcp_opt = _B_FALSE; /* dhcp options */
1264 1403
1265 1404 opterr = 0;
1266 1405 while ((option = getopt_long(argc, argv, ":T:a:di:p:w:t",
1267 1406 addr_longopts, NULL)) != -1) {
1268 1407 switch (option) {
1269 1408 case 'T':
1270 1409 atype = optarg;
1271 1410 break;
1272 1411 case 'a':
1273 1412 static_arg = optarg;
1274 1413 s_opt = _B_TRUE;
1275 1414 break;
1276 1415 case 'd':
1277 1416 flags &= ~IPADM_OPT_UP;
1278 1417 s_opt = _B_TRUE;
1279 1418 break;
1280 1419 case 'i':
1281 1420 interface_id = optarg;
1282 1421 auto_opt = _B_TRUE;
1283 1422 break;
1284 1423 case 'p':
1285 1424 addrconf_arg = optarg;
1286 1425 auto_opt = _B_TRUE;
1287 1426 break;
1288 1427 case 'w':
1289 1428 wait = optarg;
1290 1429 dhcp_opt = _B_TRUE;
1291 1430 break;
1292 1431 case 't':
1293 1432 flags &= ~IPADM_OPT_PERSIST;
1294 1433 break;
1295 1434 default:
1296 1435 die_opterr(optopt, option, use);
1297 1436 }
1298 1437 }
1299 1438 if (atype == NULL || optind != (argc - 1)) {
1300 1439 die("Invalid arguments\nusage: %s", use);
1301 1440 } else if ((cp = strchr(argv[optind], '/')) == NULL ||
1302 1441 strlen(++cp) == 0) {
1303 1442 die("invalid address object name: %s\nusage: %s",
1304 1443 argv[optind], use);
1305 1444 }
1306 1445
1307 1446 /*
1308 1447 * Allocate and initialize the addrobj based on the address type.
1309 1448 */
1310 1449 if (strcmp(atype, "static") == 0) {
1311 1450 if (static_arg == NULL || auto_opt || dhcp_opt) {
1312 1451 die("Invalid arguments for type %s\nusage: %s",
1313 1452 atype, use);
1314 1453 }
1315 1454 process_static_addrargs(use, static_arg, argv[optind]);
1316 1455 } else if (strcmp(atype, "dhcp") == 0) {
1317 1456 if (auto_opt || s_opt) {
1318 1457 die("Invalid arguments for type %s\nusage: %s",
1319 1458 atype, use);
1320 1459 }
1321 1460
1322 1461 /* Initialize the addrobj for dhcp addresses. */
1323 1462 status = ipadm_create_addrobj(IPADM_ADDR_DHCP, argv[optind],
1324 1463 &ipaddr);
1325 1464 if (status != IPADM_SUCCESS) {
1326 1465 die("Error in creating address object: %s",
1327 1466 ipadm_status2str(status));
1328 1467 }
1329 1468 if (wait != NULL) {
1330 1469 int32_t ipadm_wait;
1331 1470
1332 1471 if (strcmp(wait, "forever") == 0) {
1333 1472 ipadm_wait = IPADM_DHCP_WAIT_FOREVER;
1334 1473 } else {
1335 1474 char *end;
1336 1475 long timeout = strtol(wait, &end, 10);
1337 1476
1338 1477 if (*end != '\0' || timeout < 0)
1339 1478 die("Invalid argument");
1340 1479 ipadm_wait = (int32_t)timeout;
1341 1480 }
1342 1481 status = ipadm_set_wait_time(ipaddr, ipadm_wait);
1343 1482 if (status != IPADM_SUCCESS) {
1344 1483 die("Error in setting wait time: %s",
1345 1484 ipadm_status2str(status));
1346 1485 }
1347 1486 }
1348 1487 } else if (strcmp(atype, "addrconf") == 0) {
1349 1488 if (dhcp_opt || s_opt) {
1350 1489 die("Invalid arguments for type %s\nusage: %s",
1351 1490 atype, use);
1352 1491 }
1353 1492
1354 1493 /* Initialize the addrobj for dhcp addresses. */
1355 1494 status = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF,
1356 1495 argv[optind], &ipaddr);
1357 1496 if (status != IPADM_SUCCESS) {
1358 1497 die("Error in creating address object: %s",
1359 1498 ipadm_status2str(status));
1360 1499 }
1361 1500 if (interface_id != NULL) {
1362 1501 status = ipadm_set_interface_id(ipaddr, interface_id);
1363 1502 if (status != IPADM_SUCCESS) {
1364 1503 die("Error in setting interface ID: %s",
1365 1504 ipadm_status2str(status));
1366 1505 }
1367 1506 }
1368 1507 if (addrconf_arg)
1369 1508 process_addrconf_addrargs(use, addrconf_arg);
1370 1509 } else {
1371 1510 die("Invalid address type %s", atype);
1372 1511 }
1373 1512
1374 1513 status = ipadm_create_addr(iph, ipaddr, flags);
1375 1514 if (status == IPADM_DHCP_IPC_TIMEOUT)
1376 1515 warn_ipadmerr(status, "");
1377 1516 else if (status != IPADM_SUCCESS)
1378 1517 die("Could not create address: %s", ipadm_status2str(status));
1379 1518 }
1380 1519
1381 1520 /*
1382 1521 * Used by some address management functions to parse the command line
1383 1522 * arguments and create `ipaddr' address object.
1384 1523 */
1385 1524 static void
1386 1525 process_misc_addrargs(int argc, char *argv[], const char *use, int *index,
1387 1526 uint32_t *flags)
1388 1527 {
1389 1528 int option;
1390 1529
1391 1530 opterr = 0;
1392 1531 while ((option = getopt_long(argc, argv, ":t", addr_misc_longopts,
1393 1532 NULL)) != -1) {
1394 1533 switch (option) {
1395 1534 case 't':
1396 1535 *flags &= ~IPADM_OPT_PERSIST;
1397 1536 break;
1398 1537 default:
1399 1538 die_opterr(optopt, option, use);
1400 1539 }
1401 1540 }
1402 1541 if (optind != (argc - 1))
1403 1542 die("Usage: %s", use);
1404 1543
1405 1544 *index = optind;
1406 1545 }
1407 1546
1408 1547 /*
1409 1548 * Remove an addrobj from both active and persistent configuration.
1410 1549 */
1411 1550 static void
1412 1551 do_delete_addr(int argc, char *argv[], const char *use)
1413 1552 {
1414 1553 ipadm_status_t status;
1415 1554 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1416 1555 int option;
1417 1556
1418 1557 opterr = 0;
1419 1558 while ((option = getopt_long(argc, argv, ":r", addr_misc_longopts,
1420 1559 NULL)) != -1) {
1421 1560 switch (option) {
1422 1561 case 'r':
1423 1562 flags |= IPADM_OPT_RELEASE;
1424 1563 break;
1425 1564 default:
1426 1565 die_opterr(optopt, option, use);
1427 1566 }
1428 1567 }
1429 1568 if (optind != (argc - 1))
1430 1569 die("Usage: %s", use);
1431 1570
1432 1571 status = ipadm_delete_addr(iph, argv[optind], flags);
1433 1572 if (status != IPADM_SUCCESS) {
1434 1573 die("could not delete address: %s",
1435 1574 ipadm_status2str(status));
1436 1575 }
1437 1576 }
1438 1577
1439 1578 /*
1440 1579 * Enable an IP address based on the persistent configuration for that
1441 1580 * IP address
1442 1581 */
1443 1582 static void
1444 1583 do_enable_addr(int argc, char *argv[], const char *use)
1445 1584 {
1446 1585 ipadm_status_t status;
1447 1586 int index;
1448 1587 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1449 1588
1450 1589 process_misc_addrargs(argc, argv, use, &index, &flags);
1451 1590 if (flags & IPADM_OPT_PERSIST)
1452 1591 die("persistent operation not supported for enable-addr");
1453 1592
1454 1593 status = ipadm_enable_addr(iph, argv[index], flags);
1455 1594 if (status != IPADM_SUCCESS)
1456 1595 die("could not enable address: %s", ipadm_status2str(status));
1457 1596 }
1458 1597
1459 1598 /*
1460 1599 * Mark the address identified by addrobj 'up'
1461 1600 */
1462 1601 static void
1463 1602 do_up_addr(int argc, char *argv[], const char *use)
1464 1603 {
1465 1604 ipadm_status_t status;
1466 1605 int index;
1467 1606 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1468 1607
1469 1608 process_misc_addrargs(argc, argv, use, &index, &flags);
1470 1609 status = ipadm_up_addr(iph, argv[index], flags);
1471 1610 if (status != IPADM_SUCCESS) {
1472 1611 die("Could not mark the address up: %s",
1473 1612 ipadm_status2str(status));
1474 1613 }
1475 1614 }
1476 1615
1477 1616 /*
1478 1617 * Disable the specified addrobj by removing it from active cofiguration
1479 1618 */
1480 1619 static void
1481 1620 do_disable_addr(int argc, char *argv[], const char *use)
1482 1621 {
1483 1622 ipadm_status_t status;
1484 1623 int index;
1485 1624 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1486 1625
1487 1626 process_misc_addrargs(argc, argv, use, &index, &flags);
1488 1627 if (flags & IPADM_OPT_PERSIST)
1489 1628 die("persistent operation not supported for disable-addr");
1490 1629
1491 1630 status = ipadm_disable_addr(iph, argv[index], flags);
1492 1631 if (status != IPADM_SUCCESS) {
1493 1632 die("could not disable address: %s",
1494 1633 ipadm_status2str(status));
1495 1634 }
1496 1635 }
1497 1636
1498 1637 /*
1499 1638 * Mark the address identified by addrobj 'down'
1500 1639 */
1501 1640 static void
1502 1641 do_down_addr(int argc, char *argv[], const char *use)
1503 1642 {
1504 1643 ipadm_status_t status;
1505 1644 int index;
1506 1645 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
1507 1646
1508 1647 process_misc_addrargs(argc, argv, use, &index, &flags);
1509 1648 status = ipadm_down_addr(iph, argv[index], flags);
1510 1649 if (status != IPADM_SUCCESS)
1511 1650 die("Could not mark the address down: %s",
1512 1651 ipadm_status2str(status));
1513 1652 }
1514 1653
1515 1654 /*
1516 1655 * Restart DAD for static address. Extend lease duration for DHCP addresses
1517 1656 */
1518 1657 static void
1519 1658 do_refresh_addr(int argc, char *argv[], const char *use)
1520 1659 {
1521 1660 ipadm_status_t status;
1522 1661 int option;
1523 1662 uint32_t flags = 0;
1524 1663
1525 1664 opterr = 0;
1526 1665 while ((option = getopt_long(argc, argv, ":i", addr_misc_longopts,
1527 1666 NULL)) != -1) {
1528 1667 switch (option) {
1529 1668 case 'i':
1530 1669 flags |= IPADM_OPT_INFORM;
1531 1670 break;
1532 1671 default:
1533 1672 die_opterr(optopt, option, use);
1534 1673 }
1535 1674 }
1536 1675 if (optind != (argc - 1))
1537 1676 die("Usage: %s", use);
1538 1677
1539 1678 status = ipadm_refresh_addr(iph, argv[optind], flags);
1540 1679 if (status == IPADM_DHCP_IPC_TIMEOUT)
1541 1680 warn_ipadmerr(status, "");
1542 1681 else if (status != IPADM_SUCCESS)
1543 1682 die("could not refresh address %s", ipadm_status2str(status));
1544 1683 }
1545 1684
1546 1685 static void
1547 1686 sockaddr2str(const struct sockaddr_storage *ssp, char *buf, uint_t bufsize)
1548 1687 {
1549 1688 socklen_t socklen;
1550 1689 struct sockaddr *sp = (struct sockaddr *)ssp;
1551 1690
1552 1691 switch (ssp->ss_family) {
1553 1692 case AF_INET:
1554 1693 socklen = sizeof (struct sockaddr_in);
1555 1694 break;
1556 1695 case AF_INET6:
1557 1696 socklen = sizeof (struct sockaddr_in6);
1558 1697 break;
1559 1698 default:
1560 1699 (void) strlcpy(buf, STR_UNKNOWN_VAL, bufsize);
1561 1700 return;
1562 1701 }
1563 1702
1564 1703 (void) getnameinfo(sp, socklen, buf, bufsize, NULL, 0,
1565 1704 (NI_NOFQDN | NI_NUMERICHOST));
1566 1705 }
1567 1706
1568 1707 static void
1569 1708 flags2str(uint64_t flags, fmask_t *tbl, boolean_t is_bits,
1570 1709 char *buf, uint_t bufsize)
1571 1710 {
1572 1711 int i;
1573 1712 boolean_t first = _B_TRUE;
1574 1713
1575 1714 if (is_bits) {
1576 1715 for (i = 0; tbl[i].name; i++) {
1577 1716 if ((flags & tbl[i].mask) == tbl[i].bits)
1578 1717 (void) strlcat(buf, tbl[i].name, bufsize);
1579 1718 else
1580 1719 (void) strlcat(buf, "-", bufsize);
1581 1720 }
1582 1721 } else {
1583 1722 for (i = 0; tbl[i].name; i++) {
1584 1723 if ((flags & tbl[i].mask) == tbl[i].bits) {
1585 1724 if (!first)
1586 1725 (void) strlcat(buf, ",", bufsize);
1587 1726 (void) strlcat(buf, tbl[i].name, bufsize);
1588 1727 first = _B_FALSE;
1589 1728 }
1590 1729 }
1591 1730 }
1592 1731 }
1593 1732
1594 1733 /*
1595 1734 * return true if the address for lifname comes to us from the global zone
1596 1735 * with 'allowed-ips' constraints.
1597 1736 */
1598 1737 static boolean_t
1599 1738 is_from_gz(const char *lifname)
1600 1739 {
1601 1740 ipadm_if_info_t *if_info;
1602 1741 char phyname[LIFNAMSIZ], *cp;
1603 1742 boolean_t ret = _B_FALSE;
1604 1743 ipadm_status_t status;
1605 1744 zoneid_t zoneid;
1606 1745 ushort_t zflags;
1607 1746
1608 1747 if ((zoneid = getzoneid()) == GLOBAL_ZONEID)
1609 1748 return (_B_FALSE); /* from-gz only makes sense in a NGZ */
1610 1749
1611 1750 if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &zflags, sizeof (zflags)) < 0)
1612 1751 return (_B_FALSE);
1613 1752
1614 1753 if (!(zflags & ZF_NET_EXCL))
1615 1754 return (_B_TRUE); /* everything is from the GZ for shared-ip */
1616 1755
1617 1756 (void) strncpy(phyname, lifname, sizeof (phyname));
1618 1757 if ((cp = strchr(phyname, ':')) != NULL)
1619 1758 *cp = '\0';
1620 1759 status = ipadm_if_info(iph, phyname, &if_info, 0, LIFC_DEFAULT);
1621 1760 if (status != IPADM_SUCCESS)
1622 1761 return (ret);
1623 1762
1624 1763 if (if_info->ifi_cflags & IFIF_L3PROTECT)
1625 1764 ret = _B_TRUE;
1626 1765 if (if_info)
1627 1766 ipadm_free_if_info(if_info);
1628 1767 return (ret);
1629 1768 }
1630 1769
1631 1770 static boolean_t
1632 1771 print_sa_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1633 1772 {
1634 1773 show_addr_args_t *arg = ofarg->ofmt_cbarg;
1635 1774 ipadm_addr_info_t *ainfo = arg->sa_info;
1636 1775 char interface[LIFNAMSIZ];
1637 1776 char addrbuf[MAXPROPVALLEN];
1638 1777 char dstbuf[MAXPROPVALLEN];
1639 1778 char prefixlenstr[MAXPROPVALLEN];
1640 1779 int prefixlen;
1641 1780 struct sockaddr_in *sin;
1642 1781 struct sockaddr_in6 *sin6;
1643 1782 sa_family_t af;
1644 1783 char *phyname = NULL;
1645 1784 struct ifaddrs *ifa = &ainfo->ia_ifa;
1646 1785 fmask_t cflags_mask[] = {
1647 1786 { "U", IA_UP, IA_UP },
1648 1787 { "u", IA_UNNUMBERED, IA_UNNUMBERED },
1649 1788 { "p", IA_PRIVATE, IA_PRIVATE },
1650 1789 { "t", IA_TEMPORARY, IA_TEMPORARY },
1651 1790 { "d", IA_DEPRECATED, IA_DEPRECATED },
1652 1791 { NULL, 0, 0 }
1653 1792 };
1654 1793 fmask_t pflags_mask[] = {
1655 1794 { "U", IA_UP, IA_UP },
1656 1795 { "p", IA_PRIVATE, IA_PRIVATE },
1657 1796 { "d", IA_DEPRECATED, IA_DEPRECATED },
1658 1797 { NULL, 0, 0 }
1659 1798 };
1660 1799 fmask_t type[] = {
1661 1800 { "static", IPADM_ADDR_STATIC, IPADM_ALL_BITS},
1662 1801 { "addrconf", IPADM_ADDR_IPV6_ADDRCONF, IPADM_ALL_BITS},
1663 1802 { "dhcp", IPADM_ADDR_DHCP, IPADM_ALL_BITS},
1664 1803 { NULL, 0, 0 }
1665 1804 };
1666 1805 fmask_t addr_state[] = {
1667 1806 { "disabled", IFA_DISABLED, IPADM_ALL_BITS},
1668 1807 { "duplicate", IFA_DUPLICATE, IPADM_ALL_BITS},
1669 1808 { "down", IFA_DOWN, IPADM_ALL_BITS},
1670 1809 { "tentative", IFA_TENTATIVE, IPADM_ALL_BITS},
1671 1810 { "ok", IFA_OK, IPADM_ALL_BITS},
1672 1811 { "inaccessible", IFA_INACCESSIBLE, IPADM_ALL_BITS},
1673 1812 { NULL, 0, 0 }
1674 1813 };
1675 1814
1676 1815 buf[0] = '\0';
1677 1816 switch (ofarg->ofmt_id) {
1678 1817 case SA_ADDROBJ:
1679 1818 if (ainfo->ia_aobjname[0] == '\0') {
1680 1819 (void) strncpy(interface, ifa->ifa_name, LIFNAMSIZ);
1681 1820 phyname = strrchr(interface, ':');
1682 1821 if (phyname)
1683 1822 *phyname = '\0';
1684 1823 (void) snprintf(buf, bufsize, "%s/%s", interface,
1685 1824 STR_UNKNOWN_VAL);
1686 1825 } else {
1687 1826 (void) snprintf(buf, bufsize, "%s", ainfo->ia_aobjname);
1688 1827 }
1689 1828 break;
1690 1829 case SA_STATE:
1691 1830 flags2str(ainfo->ia_state, addr_state, _B_FALSE,
1692 1831 buf, bufsize);
1693 1832 break;
1694 1833 case SA_TYPE:
1695 1834 if (is_from_gz(ifa->ifa_name))
1696 1835 (void) snprintf(buf, bufsize, "from-gz");
1697 1836 else
1698 1837 flags2str(ainfo->ia_atype, type, _B_FALSE, buf,
1699 1838 bufsize);
1700 1839 break;
1701 1840 case SA_CURRENT:
1702 1841 flags2str(ainfo->ia_cflags, cflags_mask, _B_TRUE, buf, bufsize);
1703 1842 break;
1704 1843 case SA_PERSISTENT:
1705 1844 flags2str(ainfo->ia_pflags, pflags_mask, _B_TRUE, buf, bufsize);
1706 1845 break;
1707 1846 case SA_ADDR:
1708 1847 af = ifa->ifa_addr->sa_family;
1709 1848 /*
1710 1849 * If the address is 0.0.0.0 or :: and the origin is DHCP,
1711 1850 * print STR_UNKNOWN_VAL.
1712 1851 */
1713 1852 if (ainfo->ia_atype == IPADM_ADDR_DHCP) {
1714 1853 sin = (struct sockaddr_in *)ifa->ifa_addr;
1715 1854 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1716 1855 if ((af == AF_INET &&
1717 1856 sin->sin_addr.s_addr == INADDR_ANY) ||
1718 1857 (af == AF_INET6 &&
1719 1858 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
1720 1859 (void) snprintf(buf, bufsize, STR_UNKNOWN_VAL);
1721 1860 break;
1722 1861 }
1723 1862 }
1724 1863 if (ifa->ifa_netmask == NULL)
1725 1864 prefixlen = 0;
1726 1865 else
1727 1866 prefixlen = mask2plen(ifa->ifa_netmask);
1728 1867 bzero(prefixlenstr, sizeof (prefixlenstr));
1729 1868 if (prefixlen > 0) {
1730 1869 (void) snprintf(prefixlenstr, sizeof (prefixlenstr),
1731 1870 "/%d", prefixlen);
1732 1871 }
1733 1872 bzero(addrbuf, sizeof (addrbuf));
1734 1873 bzero(dstbuf, sizeof (dstbuf));
1735 1874 if (ainfo->ia_atype == IPADM_ADDR_STATIC) {
1736 1875 /*
1737 1876 * Print the hostname fields if the address is not
1738 1877 * in active configuration.
1739 1878 */
1740 1879 if (ainfo->ia_state == IFA_DISABLED) {
1741 1880 (void) snprintf(buf, bufsize, "%s",
1742 1881 ainfo->ia_sname);
1743 1882 if (ainfo->ia_dname[0] != '\0') {
1744 1883 (void) snprintf(dstbuf, sizeof (dstbuf),
1745 1884 "->%s", ainfo->ia_dname);
1746 1885 (void) strlcat(buf, dstbuf, bufsize);
1747 1886 } else {
1748 1887 (void) strlcat(buf, prefixlenstr,
1749 1888 bufsize);
1750 1889 }
1751 1890 break;
1752 1891 }
1753 1892 }
1754 1893 /*
1755 1894 * For the non-persistent case, we need to show the
1756 1895 * currently configured addresses for source and
1757 1896 * destination.
1758 1897 */
1759 1898 sockaddr2str((struct sockaddr_storage *)ifa->ifa_addr,
1760 1899 addrbuf, sizeof (addrbuf));
1761 1900 if (ifa->ifa_flags & IFF_POINTOPOINT) {
1762 1901 sockaddr2str(
1763 1902 (struct sockaddr_storage *)ifa->ifa_dstaddr,
1764 1903 dstbuf, sizeof (dstbuf));
1765 1904 (void) snprintf(buf, bufsize, "%s->%s", addrbuf,
1766 1905 dstbuf);
1767 1906 } else {
1768 1907 (void) snprintf(buf, bufsize, "%s%s", addrbuf,
1769 1908 prefixlenstr);
1770 1909 }
1771 1910 break;
1772 1911 default:
1773 1912 die("invalid input");
1774 1913 break;
1775 1914 }
1776 1915
1777 1916 return (_B_TRUE);
1778 1917 }
1779 1918
1780 1919 /*
1781 1920 * Display address information, either for the given address or
1782 1921 * for all the addresses managed by ipadm.
1783 1922 */
1784 1923 static void
1785 1924 do_show_addr(int argc, char *argv[], const char *use)
1786 1925 {
1787 1926 ipadm_status_t status;
1788 1927 show_addr_state_t state;
1789 1928 char *def_fields_str = "addrobj,type,state,addr";
1790 1929 char *fields_str = NULL;
1791 1930 ipadm_addr_info_t *ainfo;
1792 1931 ipadm_addr_info_t *ptr;
1793 1932 show_addr_args_t sargs;
1794 1933 int option;
1795 1934 ofmt_handle_t ofmt;
1796 1935 ofmt_status_t oferr;
1797 1936 uint_t ofmtflags = 0;
1798 1937 char *aname;
1799 1938 char *ifname = NULL;
1800 1939 char *cp;
1801 1940 boolean_t found = _B_FALSE;
1802 1941
1803 1942 opterr = 0;
1804 1943 state.sa_parsable = _B_FALSE;
1805 1944 state.sa_persist = _B_FALSE;
1806 1945 while ((option = getopt_long(argc, argv, "po:", show_addr_longopts,
1807 1946 NULL)) != -1) {
1808 1947 switch (option) {
1809 1948 case 'p':
1810 1949 state.sa_parsable = _B_TRUE;
1811 1950 break;
1812 1951 case 'o':
1813 1952 fields_str = optarg;
1814 1953 break;
1815 1954 default:
1816 1955 die_opterr(optopt, option, use);
1817 1956 break;
1818 1957 }
1819 1958 }
1820 1959 if (state.sa_parsable && fields_str == NULL)
1821 1960 die("-p requires -o");
1822 1961
1823 1962 if (optind == argc - 1) {
1824 1963 aname = argv[optind];
1825 1964 if ((cp = strchr(aname, '/')) == NULL)
1826 1965 die("Invalid address object name provided");
1827 1966 if (*(cp + 1) == '\0') {
1828 1967 ifname = aname;
1829 1968 *cp = '\0';
1830 1969 aname = NULL;
1831 1970 }
1832 1971 } else if (optind == argc) {
1833 1972 aname = NULL;
1834 1973 } else {
1835 1974 die("Usage: %s", use);
1836 1975 }
1837 1976
1838 1977 if (state.sa_parsable)
1839 1978 ofmtflags |= OFMT_PARSABLE;
1840 1979 if (fields_str == NULL)
1841 1980 fields_str = def_fields_str;
1842 1981 oferr = ofmt_open(fields_str, show_addr_fields, ofmtflags, 0, &ofmt);
1843 1982
1844 1983 ipadm_ofmt_check(oferr, state.sa_parsable, ofmt);
1845 1984 state.sa_ofmt = ofmt;
1846 1985
1847 1986 status = ipadm_addr_info(iph, ifname, &ainfo, 0, LIFC_DEFAULT);
1848 1987 /*
1849 1988 * Return without printing any error, if no addresses were found,
1850 1989 * for the case where all addresses are requested.
1851 1990 */
1852 1991 if (status != IPADM_SUCCESS)
1853 1992 die("Could not get address: %s", ipadm_status2str(status));
1854 1993 if (ainfo == NULL) {
1855 1994 ofmt_close(ofmt);
1856 1995 return;
1857 1996 }
1858 1997
1859 1998 bzero(&sargs, sizeof (sargs));
1860 1999 sargs.sa_state = &state;
1861 2000 for (ptr = ainfo; ptr != NULL; ptr = IA_NEXT(ptr)) {
1862 2001 sargs.sa_info = ptr;
1863 2002 if (aname != NULL) {
1864 2003 if (strcmp(sargs.sa_info->ia_aobjname, aname) != 0)
1865 2004 continue;
1866 2005 found = _B_TRUE;
1867 2006 }
1868 2007 ofmt_print(state.sa_ofmt, &sargs);
1869 2008 }
1870 2009 if (ainfo)
1871 2010 ipadm_free_addr_info(ainfo);
1872 2011 if (aname != NULL && !found)
1873 2012 die("Address object not found");
1874 2013 }
1875 2014
1876 2015 static boolean_t
1877 2016 print_si_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
1878 2017 {
1879 2018 show_if_args_t *arg = ofarg->ofmt_cbarg;
1880 2019 ipadm_if_info_t *ifinfo = arg->si_info;
1881 2020 char *ifname = ifinfo->ifi_name;
1882 2021 fmask_t intf_state[] = {
1883 2022 { "ok", IFIS_OK, IPADM_ALL_BITS},
1884 2023 { "down", IFIS_DOWN, IPADM_ALL_BITS},
1885 2024 { "disabled", IFIS_DISABLED, IPADM_ALL_BITS},
1886 2025 { "failed", IFIS_FAILED, IPADM_ALL_BITS},
1887 2026 { "offline", IFIS_OFFLINE, IPADM_ALL_BITS},
1888 2027 { NULL, 0, 0 }
1889 2028 };
1890 2029 fmask_t intf_pflags[] = {
1891 2030 { "s", IFIF_STANDBY, IFIF_STANDBY },
1892 2031 { "4", IFIF_IPV4, IFIF_IPV4 },
1893 2032 { "6", IFIF_IPV6, IFIF_IPV6 },
1894 2033 { NULL, 0, 0 }
1895 2034 };
1896 2035 fmask_t intf_cflags[] = {
1897 2036 { "b", IFIF_BROADCAST, IFIF_BROADCAST },
1898 2037 { "m", IFIF_MULTICAST, IFIF_MULTICAST },
1899 2038 { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
1900 2039 { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
↓ open down ↓ |
1455 lines elided |
↑ open up ↑ |
1901 2040 { "I", IFIF_IPMP, IFIF_IPMP },
1902 2041 { "s", IFIF_STANDBY, IFIF_STANDBY },
1903 2042 { "i", IFIF_INACTIVE, IFIF_INACTIVE },
1904 2043 { "V", IFIF_VRRP, IFIF_VRRP },
1905 2044 { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
1906 2045 { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
1907 2046 { "4", IFIF_IPV4, IFIF_IPV4 },
1908 2047 { "6", IFIF_IPV6, IFIF_IPV6 },
1909 2048 { NULL, 0, 0 }
1910 2049 };
2050 + fmask_t intf_class[] = {
2051 + { "IP", IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS},
2052 + { "IPMP", IPADM_IF_CLASS_IPMP, IPADM_ALL_BITS},
2053 + { "VIRTUAL", IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS},
2054 + { "UNKNOWN", IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS},
2055 + { NULL, 0, 0}
2056 + };
1911 2057
1912 2058 buf[0] = '\0';
1913 2059 switch (ofarg->ofmt_id) {
1914 2060 case SI_IFNAME:
1915 2061 (void) snprintf(buf, bufsize, "%s", ifname);
1916 2062 break;
2063 + case SI_IFCLASS:
2064 + flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
2065 + buf, bufsize);
2066 + break;
1917 2067 case SI_STATE:
1918 2068 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1919 2069 buf, bufsize);
1920 2070 break;
1921 2071 case SI_CURRENT:
1922 2072 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1923 2073 buf, bufsize);
1924 2074 break;
1925 2075 case SI_PERSISTENT:
1926 2076 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
1927 2077 buf, bufsize);
1928 2078 break;
1929 2079 default:
1930 2080 die("invalid input");
1931 2081 break;
1932 2082 }
1933 2083
1934 2084 return (_B_TRUE);
1935 2085 }
1936 2086
1937 2087 /*
1938 2088 * Display interface information, either for the given interface or
1939 2089 * for all the interfaces in the system.
1940 2090 */
1941 2091 static void
1942 2092 do_show_if(int argc, char *argv[], const char *use)
1943 2093 {
1944 2094 ipadm_status_t status;
1945 2095 show_if_state_t state;
1946 2096 char *fields_str = NULL;
1947 2097 ipadm_if_info_t *if_info, *ptr;
1948 2098 show_if_args_t sargs;
1949 2099 int option;
1950 2100 ofmt_handle_t ofmt;
1951 2101 ofmt_status_t oferr;
1952 2102 uint_t ofmtflags = 0;
1953 2103 char *ifname = NULL;
1954 2104
1955 2105 opterr = 0;
1956 2106 state.si_parsable = _B_FALSE;
1957 2107
1958 2108 while ((option = getopt_long(argc, argv, "po:", show_if_longopts,
1959 2109 NULL)) != -1) {
1960 2110 switch (option) {
1961 2111 case 'p':
1962 2112 state.si_parsable = _B_TRUE;
1963 2113 break;
1964 2114 case 'o':
1965 2115 fields_str = optarg;
1966 2116 break;
1967 2117 default:
1968 2118 die_opterr(optopt, option, use);
1969 2119 break;
1970 2120 }
1971 2121 }
1972 2122 if (optind == argc - 1)
1973 2123 ifname = argv[optind];
1974 2124 else if (optind != argc)
1975 2125 die("Usage: %s", use);
1976 2126 if (state.si_parsable)
1977 2127 ofmtflags |= OFMT_PARSABLE;
1978 2128 oferr = ofmt_open(fields_str, show_if_fields, ofmtflags, 0, &ofmt);
1979 2129 ipadm_ofmt_check(oferr, state.si_parsable, ofmt);
1980 2130 state.si_ofmt = ofmt;
1981 2131 bzero(&sargs, sizeof (sargs));
1982 2132 sargs.si_state = &state;
1983 2133 status = ipadm_if_info(iph, ifname, &if_info, 0, LIFC_DEFAULT);
1984 2134 /*
1985 2135 * Return without printing any error, if no addresses were found.
1986 2136 */
1987 2137 if (status != IPADM_SUCCESS) {
1988 2138 die("Could not get interface(s): %s",
1989 2139 ipadm_status2str(status));
1990 2140 }
1991 2141
1992 2142 for (ptr = if_info; ptr; ptr = ptr->ifi_next) {
1993 2143 sargs.si_info = ptr;
1994 2144 ofmt_print(state.si_ofmt, &sargs);
1995 2145 }
1996 2146 if (if_info)
1997 2147 ipadm_free_if_info(if_info);
1998 2148 }
1999 2149
2000 2150 /*
2001 2151 * set/reset the address property for a given address
2002 2152 */
2003 2153 static void
2004 2154 set_addrprop(int argc, char **argv, boolean_t reset, const char *use)
2005 2155 {
2006 2156 int option;
2007 2157 ipadm_status_t status = IPADM_SUCCESS;
2008 2158 boolean_t p_arg = _B_FALSE;
2009 2159 char *nv, *aobjname;
2010 2160 char *prop_name, *prop_val;
2011 2161 uint_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
2012 2162
2013 2163 opterr = 0;
2014 2164 while ((option = getopt_long(argc, argv, ":i:p:t", set_ifprop_longopts,
2015 2165 NULL)) != -1) {
2016 2166 switch (option) {
2017 2167 case 'p':
2018 2168 if (p_arg)
2019 2169 die("-p must be specified once only");
2020 2170 p_arg = _B_TRUE;
2021 2171
2022 2172 ipadm_check_propstr(optarg, reset, use);
2023 2173 nv = optarg;
2024 2174 break;
2025 2175 case 't':
2026 2176 flags &= ~IPADM_OPT_PERSIST;
2027 2177 break;
2028 2178 default:
2029 2179 die_opterr(optopt, option, use);
2030 2180 }
2031 2181 }
2032 2182
2033 2183 if (!p_arg || optind != (argc - 1))
2034 2184 die("Usage: %s", use);
2035 2185
2036 2186 prop_name = nv;
2037 2187 prop_val = strchr(nv, '=');
2038 2188 if (prop_val != NULL)
2039 2189 *prop_val++ = '\0';
2040 2190 aobjname = argv[optind];
2041 2191 if (reset)
2042 2192 flags |= IPADM_OPT_DEFAULT;
2043 2193 status = ipadm_set_addrprop(iph, prop_name, prop_val, aobjname, flags);
2044 2194 if (status != IPADM_SUCCESS) {
2045 2195 if (reset)
2046 2196 die("reset-addrprop: %s: %s", prop_name,
2047 2197 ipadm_status2str(status));
2048 2198 else
2049 2199 die("set-addrprop: %s: %s", prop_name,
2050 2200 ipadm_status2str(status));
2051 2201 }
2052 2202 }
2053 2203
2054 2204 /*
2055 2205 * Sets a property on an address object.
2056 2206 */
2057 2207 static void
2058 2208 do_set_addrprop(int argc, char **argv, const char *use)
2059 2209 {
2060 2210 set_addrprop(argc, argv, _B_FALSE, use);
2061 2211 }
2062 2212
2063 2213 /*
2064 2214 * Resets a property to its default value on an address object.
2065 2215 */
2066 2216 static void
2067 2217 do_reset_addrprop(int argc, char **argv, const char *use)
2068 2218 {
2069 2219 set_addrprop(argc, argv, _B_TRUE, use);
2070 2220 }
2071 2221
2072 2222 /*
2073 2223 * Display information for all or specific address properties, either for a
2074 2224 * given address or for all the addresses in the system.
2075 2225 */
2076 2226 static void
2077 2227 do_show_addrprop(int argc, char *argv[], const char *use)
2078 2228 {
2079 2229 int option;
2080 2230 nvlist_t *proplist = NULL;
2081 2231 char *fields_str = NULL;
2082 2232 show_prop_state_t state;
2083 2233 ofmt_handle_t ofmt;
2084 2234 ofmt_status_t oferr;
2085 2235 uint_t ofmtflags = 0;
2086 2236 char *aobjname;
2087 2237 char *ifname = NULL;
2088 2238 char *cp;
2089 2239
2090 2240 opterr = 0;
2091 2241 bzero(&state, sizeof (state));
2092 2242 state.sps_propval = NULL;
2093 2243 state.sps_parsable = _B_FALSE;
2094 2244 state.sps_addrprop = _B_TRUE;
2095 2245 state.sps_proto = MOD_PROTO_NONE;
2096 2246 state.sps_status = state.sps_retstatus = IPADM_SUCCESS;
2097 2247 while ((option = getopt_long(argc, argv, ":p:i:cPo:",
2098 2248 show_prop_longopts, NULL)) != -1) {
2099 2249 switch (option) {
2100 2250 case 'p':
2101 2251 if (ipadm_str2nvlist(optarg, &proplist,
2102 2252 IPADM_NORVAL) != 0)
2103 2253 die("invalid interface properties specified");
2104 2254 break;
2105 2255 case 'c':
2106 2256 state.sps_parsable = _B_TRUE;
2107 2257 break;
2108 2258 case 'o':
2109 2259 fields_str = optarg;
2110 2260 break;
2111 2261 default:
2112 2262 die_opterr(optopt, option, use);
2113 2263 break;
2114 2264 }
2115 2265 }
2116 2266 if (optind == argc - 1) {
2117 2267 aobjname = argv[optind];
2118 2268 cp = strchr(aobjname, '/');
2119 2269 if (cp == NULL)
2120 2270 die("Invalid address object name provided");
2121 2271 if (*(cp + 1) == '\0') {
2122 2272 ifname = aobjname;
2123 2273 *cp = '\0';
2124 2274 aobjname = NULL;
2125 2275 }
2126 2276 } else if (optind == argc) {
2127 2277 aobjname = NULL;
2128 2278 } else {
2129 2279 die("Usage: %s", use);
2130 2280 }
2131 2281 state.sps_proplist = proplist;
2132 2282 if (state.sps_parsable)
2133 2283 ofmtflags |= OFMT_PARSABLE;
2134 2284 oferr = ofmt_open(fields_str, addrprop_fields, ofmtflags, 0, &ofmt);
2135 2285 ipadm_ofmt_check(oferr, state.sps_parsable, ofmt);
2136 2286 state.sps_ofmt = ofmt;
2137 2287
2138 2288 if (aobjname != NULL) {
2139 2289 (void) strlcpy(state.sps_aobjname, aobjname,
2140 2290 sizeof (state.sps_aobjname));
2141 2291 show_properties(&state, IPADMPROP_CLASS_ADDR);
2142 2292 } else {
2143 2293 ipadm_addr_info_t *ainfop = NULL;
2144 2294 ipadm_addr_info_t *ptr;
2145 2295 ipadm_status_t status;
2146 2296
2147 2297 status = ipadm_addr_info(iph, ifname, &ainfop, 0, LIFC_DEFAULT);
2148 2298 /*
2149 2299 * Return without printing any error, if no addresses were
2150 2300 * found.
2151 2301 */
2152 2302 if (status == IPADM_NOTFOUND)
2153 2303 return;
2154 2304 if (status != IPADM_SUCCESS) {
2155 2305 die("Error retrieving address: %s",
2156 2306 ipadm_status2str(status));
2157 2307 }
2158 2308 for (ptr = ainfop; ptr; ptr = IA_NEXT(ptr)) {
2159 2309 aobjname = ptr->ia_aobjname;
2160 2310 if (aobjname[0] == '\0' ||
2161 2311 ptr->ia_atype == IPADM_ADDR_IPV6_ADDRCONF) {
2162 2312 continue;
2163 2313 }
2164 2314 (void) strlcpy(state.sps_aobjname, aobjname,
2165 2315 sizeof (state.sps_aobjname));
2166 2316 show_properties(&state, IPADMPROP_CLASS_ADDR);
2167 2317 }
2168 2318 ipadm_free_addr_info(ainfop);
2169 2319 }
2170 2320 nvlist_free(proplist);
2171 2321 ofmt_close(ofmt);
2172 2322 if (state.sps_retstatus != IPADM_SUCCESS) {
2173 2323 ipadm_close(iph);
2174 2324 exit(EXIT_FAILURE);
2175 2325 }
2176 2326 }
2177 2327
2178 2328 static void
2179 2329 ipadm_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
2180 2330 ofmt_handle_t ofmt)
2181 2331 {
2182 2332 char buf[OFMT_BUFSIZE];
2183 2333
2184 2334 if (oferr == OFMT_SUCCESS)
2185 2335 return;
2186 2336 (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
2187 2337 /*
2188 2338 * All errors are considered fatal in parsable mode.
2189 2339 * NOMEM errors are always fatal, regardless of mode.
2190 2340 * For other errors, we print diagnostics in human-readable
2191 2341 * mode and processs what we can.
2192 2342 */
2193 2343 if (parsable || oferr == OFMT_ENOFIELDS) {
2194 2344 ofmt_close(ofmt);
2195 2345 die(buf);
2196 2346 } else {
2197 2347 warn(buf);
2198 2348 }
2199 2349 }
2200 2350
2201 2351 /*
2202 2352 * check if the `pstr' adheres to following syntax
2203 2353 * - prop=<value[,...]> (for set)
2204 2354 * - prop (for reset)
2205 2355 */
2206 2356 static void
2207 2357 ipadm_check_propstr(const char *pstr, boolean_t reset, const char *use)
2208 2358 {
2209 2359 char *nv;
2210 2360
2211 2361 nv = strchr(pstr, '=');
2212 2362 if (reset) {
2213 2363 if (nv != NULL)
2214 2364 die("incorrect syntax used for -p.\n%s", use);
2215 2365 } else {
2216 2366 if (nv == NULL || *++nv == '\0')
2217 2367 die("please specify the value to be set.\n%s", use);
2218 2368 nv = strchr(nv, '=');
2219 2369 /* cannot have multiple 'prop=val' for single -p */
2220 2370 if (nv != NULL)
2221 2371 die("cannot specify more than one prop=val at "
2222 2372 "a time.\n%s", use);
2223 2373 }
2224 2374 }
↓ open down ↓ |
298 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX