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