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