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