21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc.
25 * Copyright 2017 Joyent, Inc.
26 * Copyright 2017 Gary Mills
27 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
28 */
29
30 #include <arpa/inet.h>
31 #include <errno.h>
32 #include <getopt.h>
33 #include <inet/ip.h>
34 #include <inet/iptun.h>
35 #include <inet/tunables.h>
36 #include <libdladm.h>
37 #include <libdliptun.h>
38 #include <libdllink.h>
39 #include <libinetutil.h>
40 #include <libipadm.h>
41 #include <locale.h>
42 #include <netdb.h>
43 #include <netinet/in.h>
44 #include <ofmt.h>
45 #include <stdarg.h>
46 #include <stddef.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <strings.h>
51 #include <sys/stat.h>
52 #include <sys/types.h>
53 #include <zone.h>
54
55 #define STR_UNKNOWN_VAL "?"
56 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
57 LIFC_UNDER_IPMP)
58
59 typedef void cmdfunc_t(int, char **, const char *);
60 static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
61 static cmdfunc_t do_show_if;
62 static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
63 static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
64 static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
65 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
66 static cmdfunc_t do_enable_addr, do_disable_addr;
67 static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
68
69 static void warn(const char *, ...);
70 static void die(const char *, ...);
71
72 typedef struct cmd {
73 char *c_name;
74 cmdfunc_t *c_fn;
75 const char *c_usage;
76 } cmd_t;
77
78 static cmd_t cmds[] = {
79 /* interface management related sub-commands */
80 { "create-if", do_create_if, "\tcreate-if\t[-t] <interface>" },
81 { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
82 { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
83 { "delete-if", do_delete_if, "\tdelete-if\t<interface>" },
84 { "show-if", do_show_if,
85 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
86 { "set-ifprop", do_set_ifprop,
87 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
88 "<interface>" },
89 { "reset-ifprop", do_reset_ifprop,
90 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
91 { "show-ifprop", do_show_ifprop,
92 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
93 "\t\t\t[-m <protocol>] [interface]\n" },
94
95 /* address management related sub-commands */
96 { "create-addr", do_create_addr,
97 "\tcreate-addr\t[-t] -T static [-d] "
98 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
99 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
100 "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
101 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
102 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
103 { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
104 { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
105 { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
106 { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>" },
107 { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
108 { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
109 { "show-addr", do_show_addr,
110 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]\n" },
111 { "set-addrprop", do_set_addrprop,
112 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
113 { "reset-addrprop", do_reset_addrprop,
114 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
115 { "show-addrprop", do_show_addrprop,
116 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
117 "<addrobj>\n" },
118
119 /* protocol properties related sub-commands */
120 { "set-prop", do_set_prop,
121 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
122 { "reset-prop", do_reset_prop,
123 "\treset-prop\t[-t] -p <prop> <protocol>" },
124 { "show-prop", do_show_prop,
125 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
126 " [protocol]" }
127 };
128
129 static const struct option if_longopts[] = {
130 {"temporary", no_argument, 0, 't' },
278 show_addr_state_t *sa_state;
279 ipadm_addr_info_t *sa_info;
280 } show_addr_args_t;
281
282 typedef struct show_if_args_s {
283 show_if_state_t *si_state;
284 ipadm_if_info_t *si_info;
285 } show_if_args_t;
286
287 typedef enum {
288 SA_ADDROBJ,
289 SA_TYPE,
290 SA_STATE,
291 SA_CURRENT,
292 SA_PERSISTENT,
293 SA_ADDR
294 } sa_field_index_t;
295
296 typedef enum {
297 SI_IFNAME,
298 SI_STATE,
299 SI_CURRENT,
300 SI_PERSISTENT
301 } si_field_index_t;
302
303 static ofmt_field_t show_addr_fields[] = {
304 /* name, field width, id, callback */
305 { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
306 { "TYPE", 9, SA_TYPE, print_sa_cb},
307 { "STATE", 13, SA_STATE, print_sa_cb},
308 { "CURRENT", 8, SA_CURRENT, print_sa_cb},
309 { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
310 { "ADDR", 46, SA_ADDR, print_sa_cb},
311 { NULL, 0, 0, NULL}
312 };
313
314 static ofmt_field_t show_if_fields[] = {
315 /* name, field width, id, callback */
316 { "IFNAME", 11, SI_IFNAME, print_si_cb},
317 { "STATE", 9, SI_STATE, print_si_cb},
318 { "CURRENT", 13, SI_CURRENT, print_si_cb},
319 { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
320 { NULL, 0, 0, NULL}
321 };
322
323 #define IPADM_ALL_BITS ((uint_t)-1)
324 typedef struct intf_mask {
325 char *name;
326 uint64_t bits;
327 uint64_t mask;
328 } fmask_t;
329
330 /*
331 * Handle to libipadm. Opened in main() before the sub-command specific
332 * function is called and is closed before the program exits.
333 */
334 ipadm_handle_t iph = NULL;
335
336 /*
337 * Opaque ipadm address object. Used by all the address management subcommands.
338 */
339 ipadm_addrobj_t ipaddr = NULL;
340
341 static char *progname;
342
343 static void die(const char *, ...);
344 static void die_opterr(int, int, const char *);
345 static void warn_ipadmerr(ipadm_status_t, const char *, ...);
346 static void ipadm_check_propstr(const char *, boolean_t, const char *);
347 static void process_misc_addrargs(int, char **, const char *, int *,
348 uint32_t *);
349
350 static void
351 usage(void)
352 {
353 int i;
354 cmd_t *cmdp;
355
356 (void) fprintf(stderr,
357 gettext("usage: ipadm <subcommand> <args> ...\n"));
358 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
359 cmdp = &cmds[i];
360 if (cmdp->c_usage != NULL)
361 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
362 }
363
364 ipadm_destroy_addrobj(ipaddr);
365 ipadm_close(iph);
366 exit(1);
367 }
368
391 }
392
393 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
394 cmdp = &cmds[i];
395 if (strcmp(argv[1], cmdp->c_name) == 0) {
396 cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
397 ipadm_destroy_addrobj(ipaddr);
398 ipadm_close(iph);
399 exit(0);
400 }
401 }
402
403 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
404 progname, argv[1]);
405 usage();
406
407 return (0);
408 }
409
410 /*
411 * Create an IP interface for which no saved configuration exists in the
412 * persistent store.
413 */
414 static void
415 do_create_if(int argc, char *argv[], const char *use)
416 {
417 ipadm_status_t status;
418 int option;
419 uint32_t flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
420
421 opterr = 0;
422 while ((option = getopt_long(argc, argv, ":t", if_longopts,
423 NULL)) != -1) {
424 switch (option) {
425 case 't':
426 /*
427 * "ifconfig" mode - plumb interface, but do not
428 * restore settings that may exist in db.
429 */
430 flags &= ~IPADM_OPT_PERSIST;
431 break;
432 default:
433 die_opterr(optopt, option, use);
434 }
435 }
436 if (optind != (argc - 1))
437 die("Usage: %s", use);
438 status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
439 if (status != IPADM_SUCCESS) {
440 die("Could not create %s : %s",
441 argv[optind], ipadm_status2str(status));
442 }
443 }
444
445 /*
446 * Enable an IP interface based on the persistent configuration for
447 * that interface.
448 */
449 static void
450 do_enable_if(int argc, char *argv[], const char *use)
451 {
452 ipadm_status_t status;
453 int index;
454 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
455
456 process_misc_addrargs(argc, argv, use, &index, &flags);
457 if (flags & IPADM_OPT_PERSIST)
458 die("persistent operation not supported for enable-if");
459 status = ipadm_enable_if(iph, argv[index], flags);
460 if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
461 warn_ipadmerr(status, "");
462 } else if (status != IPADM_SUCCESS) {
463 die("Could not enable %s : %s",
464 argv[optind], ipadm_status2str(status));
465 }
466 }
467
468 /*
469 * Remove an IP interface from both active and persistent configuration.
470 */
471 static void
472 do_delete_if(int argc, char *argv[], const char *use)
473 {
474 ipadm_status_t status;
475 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
476
477 if (argc != 2)
478 die("Usage: %s", use);
479
480 status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
481 if (status != IPADM_SUCCESS) {
482 die("Could not delete %s: %s",
483 argv[optind], ipadm_status2str(status));
484 }
485 }
486
487 /*
488 * Disable an IP interface by removing it from active configuration.
489 */
490 static void
491 do_disable_if(int argc, char *argv[], const char *use)
492 {
1027 warn(const char *format, ...)
1028 {
1029 va_list alist;
1030
1031 format = gettext(format);
1032 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1033
1034 va_start(alist, format);
1035 (void) vfprintf(stderr, format, alist);
1036 va_end(alist);
1037
1038 (void) fprintf(stderr, "\n");
1039 }
1040
1041 /* PRINTFLIKE1 */
1042 static void
1043 die(const char *format, ...)
1044 {
1045 va_list alist;
1046
1047 format = gettext(format);
1048 (void) fprintf(stderr, "%s: ", progname);
1049
1050 va_start(alist, format);
1051 (void) vfprintf(stderr, format, alist);
1052 va_end(alist);
1053
1054 (void) putchar('\n');
1055
1056 ipadm_destroy_addrobj(ipaddr);
1057 ipadm_close(iph);
1058 exit(EXIT_FAILURE);
1059 }
1060
1061 static void
1062 die_opterr(int opt, int opterr, const char *usage)
1063 {
1064 switch (opterr) {
1065 case ':':
1066 die("option '-%c' requires a value\nusage: %s", opt,
1067 gettext(usage));
1068 break;
1069 case '?':
1070 default:
1071 die("unrecognized option '-%c'\nusage: %s", opt,
1072 gettext(usage));
1073 break;
1074 }
1904 { "s", IFIF_STANDBY, IFIF_STANDBY },
1905 { "4", IFIF_IPV4, IFIF_IPV4 },
1906 { "6", IFIF_IPV6, IFIF_IPV6 },
1907 { NULL, 0, 0 }
1908 };
1909 fmask_t intf_cflags[] = {
1910 { "b", IFIF_BROADCAST, IFIF_BROADCAST },
1911 { "m", IFIF_MULTICAST, IFIF_MULTICAST },
1912 { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
1913 { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
1914 { "I", IFIF_IPMP, IFIF_IPMP },
1915 { "s", IFIF_STANDBY, IFIF_STANDBY },
1916 { "i", IFIF_INACTIVE, IFIF_INACTIVE },
1917 { "V", IFIF_VRRP, IFIF_VRRP },
1918 { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
1919 { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
1920 { "4", IFIF_IPV4, IFIF_IPV4 },
1921 { "6", IFIF_IPV6, IFIF_IPV6 },
1922 { NULL, 0, 0 }
1923 };
1924
1925 buf[0] = '\0';
1926 switch (ofarg->ofmt_id) {
1927 case SI_IFNAME:
1928 (void) snprintf(buf, bufsize, "%s", ifname);
1929 break;
1930 case SI_STATE:
1931 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1932 buf, bufsize);
1933 break;
1934 case SI_CURRENT:
1935 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1936 buf, bufsize);
1937 break;
1938 case SI_PERSISTENT:
1939 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
1940 buf, bufsize);
1941 break;
1942 default:
1943 die("invalid input");
1944 break;
1945 }
1946
1947 return (_B_TRUE);
1948 }
1949
|
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc.
25 * Copyright 2017 Joyent, Inc.
26 * Copyright 2017 Gary Mills
27 * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
28 */
29
30 #include <arpa/inet.h>
31 #include <errno.h>
32 #include <getopt.h>
33 #include <inet/ip.h>
34 #include <inet/iptun.h>
35 #include <inet/tunables.h>
36 #include <libdladm.h>
37 #include <libdliptun.h>
38 #include <libdllink.h>
39 #include <libinetutil.h>
40 #include <libipadm.h>
41 #include <ipmp.h>
42 #include <ipmp_admin.h>
43 #include <locale.h>
44 #include <netdb.h>
45 #include <netinet/in.h>
46 #include <ofmt.h>
47 #include <stdarg.h>
48 #include <stddef.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <strings.h>
53 #include <sys/stat.h>
54 #include <sys/types.h>
55 #include <zone.h>
56 #include <sys/list.h>
57 #include <stddef.h>
58
59 #define STR_UNKNOWN_VAL "?"
60 #define LIFC_DEFAULT (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
61 LIFC_UNDER_IPMP)
62
63 static void do_create_ip_common(int, char **, const char *, uint32_t);
64
65 typedef void cmdfunc_t(int, char **, const char *);
66 static cmdfunc_t do_create_ip, do_delete_ip;
67 static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
68 static cmdfunc_t do_disable_if, do_enable_if, do_show_if;
69 static cmdfunc_t do_set_ifprop, do_reset_ifprop, do_show_ifprop;
70 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr, do_refresh_addr;
71 static cmdfunc_t do_disable_addr, do_enable_addr, do_down_addr, do_up_addr;
72 static cmdfunc_t do_set_addrprop, do_reset_addrprop, do_show_addrprop;
73 static cmdfunc_t do_set_prop, do_reset_prop, do_show_prop;
74
75 static void warn(const char *, ...);
76 static void die(const char *, ...);
77
78 typedef struct cmd {
79 char *c_name;
80 cmdfunc_t *c_fn;
81 const char *c_usage;
82 } cmd_t;
83
84 static cmd_t cmds[] = {
85 /* interface management related sub-commands */
86 { "create-ip", do_create_ip, "\tcreate-ip\t[-t] <interface>" },
87 { "create-if", do_create_ip, NULL },
88 { "delete-ip", do_delete_ip, "\tdelete-ip\t<interface>\n" },
89 { "delete-if", do_delete_ip, NULL },
90
91 { "create-ipmp", do_create_ipmp,
92 "\tcreate-ipmp\t[-t] <ipmp-interface>" },
93 { "delete-ipmp", do_delete_ip,
94 "\tdelete-ipmp\t<ipmp-interface>" },
95 { "add-ipmp", do_add_ipmp,
96 "\tadd-ipmp\t[-t] -i <interface> ... "
97 "<ipmp-interface>" },
98 { "remove-ipmp", do_remove_ipmp,
99 "\tremove-ipmp\t[-t] -i <interface> ... "
100 "<ipmp-interface>\n" },
101
102 { "disable-if", do_disable_if, "\tdisable-if\t-t <interface>" },
103 { "enable-if", do_enable_if, "\tenable-if\t-t <interface>" },
104 { "show-if", do_show_if,
105 "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n" },
106
107 { "set-ifprop", do_set_ifprop,
108 "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
109 "<interface>" },
110 { "reset-ifprop", do_reset_ifprop,
111 "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>" },
112 { "show-ifprop", do_show_ifprop,
113 "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
114 "\t\t\t[-m <protocol>] [interface]\n" },
115
116 /* address management related sub-commands */
117 { "create-addr", do_create_addr,
118 "\tcreate-addr\t[-t] -T static [-d] "
119 "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
120 "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever]\n"
121 "\t\t\t[-1] [-h <hostname>] <addrobj>\n"
122 "\tcreate-addr\t[-t] -T addrconf [-i interface-id]\n"
123 "\t\t\t[-p {stateful|stateless}={yes|no}] <addrobj>" },
124 { "delete-addr", do_delete_addr, "\tdelete-addr\t[-r] <addrobj>" },
125 { "show-addr", do_show_addr,
126 "\tshow-addr\t[[-p] -o <field>,...] [<addrobj>]" },
127 { "refresh-addr", do_refresh_addr, "\trefresh-addr\t[-i] <addrobj>" },
128 { "down-addr", do_down_addr, "\tdown-addr\t[-t] <addrobj>" },
129 { "up-addr", do_up_addr, "\tup-addr\t\t[-t] <addrobj>" },
130 { "disable-addr", do_disable_addr, "\tdisable-addr\t-t <addrobj>" },
131 { "enable-addr", do_enable_addr, "\tenable-addr\t-t <addrobj>\n" },
132
133 { "set-addrprop", do_set_addrprop,
134 "\tset-addrprop\t[-t] -p <prop>=<value[,...]> <addrobj>" },
135 { "reset-addrprop", do_reset_addrprop,
136 "\treset-addrprop\t[-t] -p <prop> <addrobj>" },
137 { "show-addrprop", do_show_addrprop,
138 "\tshow-addrprop\t[[-c] -o <field>,...] [-p <prop>,...] "
139 "<addrobj>\n" },
140
141 /* protocol properties related sub-commands */
142 { "set-prop", do_set_prop,
143 "\tset-prop\t[-t] -p <prop>[+|-]=<value[,...]> <protocol>" },
144 { "reset-prop", do_reset_prop,
145 "\treset-prop\t[-t] -p <prop> <protocol>" },
146 { "show-prop", do_show_prop,
147 "\tshow-prop\t[[-c] -o <field>,...] [-p <prop>,...]"
148 " [protocol]" }
149 };
150
151 static const struct option if_longopts[] = {
152 {"temporary", no_argument, 0, 't' },
300 show_addr_state_t *sa_state;
301 ipadm_addr_info_t *sa_info;
302 } show_addr_args_t;
303
304 typedef struct show_if_args_s {
305 show_if_state_t *si_state;
306 ipadm_if_info_t *si_info;
307 } show_if_args_t;
308
309 typedef enum {
310 SA_ADDROBJ,
311 SA_TYPE,
312 SA_STATE,
313 SA_CURRENT,
314 SA_PERSISTENT,
315 SA_ADDR
316 } sa_field_index_t;
317
318 typedef enum {
319 SI_IFNAME,
320 SI_IFCLASS,
321 SI_STATE,
322 SI_CURRENT,
323 SI_PERSISTENT
324 } si_field_index_t;
325
326 static ofmt_field_t show_addr_fields[] = {
327 /* name, field width, id, callback */
328 { "ADDROBJ", 18, SA_ADDROBJ, print_sa_cb},
329 { "TYPE", 9, SA_TYPE, print_sa_cb},
330 { "STATE", 13, SA_STATE, print_sa_cb},
331 { "CURRENT", 8, SA_CURRENT, print_sa_cb},
332 { "PERSISTENT", 11, SA_PERSISTENT, print_sa_cb},
333 { "ADDR", 46, SA_ADDR, print_sa_cb},
334 { NULL, 0, 0, NULL}
335 };
336
337 static ofmt_field_t show_if_fields[] = {
338 /* name, field width, id, callback */
339 { "IFNAME", 11, SI_IFNAME, print_si_cb},
340 { "CLASS", 10, SI_IFCLASS, print_si_cb},
341 { "STATE", 9, SI_STATE, print_si_cb},
342 { "CURRENT", 13, SI_CURRENT, print_si_cb},
343 { "PERSISTENT", 11, SI_PERSISTENT, print_si_cb},
344 { NULL, 0, 0, NULL}
345 };
346
347 #define IPADM_ALL_BITS ((uint_t)-1)
348 typedef struct intf_mask {
349 char *name;
350 uint64_t bits;
351 uint64_t mask;
352 } fmask_t;
353
354 typedef enum {
355 IPMP_ADD_MEMBER,
356 IPMP_REMOVE_MEMBER
357 } ipmp_action_t;
358
359 /*
360 * Handle to libipadm. Opened in main() before the sub-command specific
361 * function is called and is closed before the program exits.
362 */
363 ipadm_handle_t iph = NULL;
364
365 /*
366 * Opaque ipadm address object. Used by all the address management subcommands.
367 */
368 ipadm_addrobj_t ipaddr = NULL;
369
370 static char *progname;
371
372 static void die(const char *, ...);
373 static void die_opterr(int, int, const char *);
374 static void warn_ipadmerr(ipadm_status_t, const char *, ...);
375 static void ipadm_check_propstr(const char *, boolean_t, const char *);
376 static void process_misc_addrargs(int, char **, const char *, int *,
377 uint32_t *);
378 static void do_action_ipmp(int, char **, const char *, ipmp_action_t);
379
380 static void
381 usage(void)
382 {
383 int i;
384 cmd_t *cmdp;
385
386 (void) fprintf(stderr,
387 gettext("usage: ipadm <subcommand> <args> ...\n"));
388 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
389 cmdp = &cmds[i];
390 if (cmdp->c_usage != NULL)
391 (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
392 }
393
394 ipadm_destroy_addrobj(ipaddr);
395 ipadm_close(iph);
396 exit(1);
397 }
398
421 }
422
423 for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
424 cmdp = &cmds[i];
425 if (strcmp(argv[1], cmdp->c_name) == 0) {
426 cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
427 ipadm_destroy_addrobj(ipaddr);
428 ipadm_close(iph);
429 exit(0);
430 }
431 }
432
433 (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
434 progname, argv[1]);
435 usage();
436
437 return (0);
438 }
439
440 /*
441 * Create regular IP interface or IPMP group interface
442 */
443 static void
444 do_create_ip_common(int argc, char *argv[], const char *use, uint32_t flags)
445 {
446 ipadm_status_t status;
447 int option;
448
449 opterr = 0;
450 while ((option = getopt_long(argc, argv,
451 ":t", if_longopts, NULL)) != -1) {
452 switch (option) {
453 case 't':
454 /*
455 * "ifconfig" mode - plumb interface, but do not
456 * restore settings that may exist in db.
457 */
458 flags &= ~IPADM_OPT_PERSIST;
459 break;
460 default:
461 die_opterr(optopt, option, use);
462 }
463 }
464 if (optind != (argc - 1)) {
465 if (use != NULL)
466 die("usage: %s", use);
467 else
468 die(NULL);
469 }
470 status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
471 if (status != IPADM_SUCCESS) {
472 die("Could not create %s : %s",
473 argv[optind], ipadm_status2str(status));
474 }
475 }
476
477 /*
478 * Create an IPMP group interface for which no saved configuration
479 * exists in the persistent store.
480 */
481 static void
482 do_create_ipmp(int argc, char *argv[], const char *use)
483 {
484 ipmp_handle_t ipmp_handle;
485 int retval;
486 uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP;
487
488 retval = ipmp_open(&ipmp_handle);
489 if (retval != IPMP_SUCCESS) {
490 die("Could not create IPMP handle: %s",
491 ipadm_status2str(retval));
492 }
493
494 retval = ipmp_ping_daemon(ipmp_handle);
495 ipmp_close(ipmp_handle);
496
497 if (retval != IPMP_SUCCESS) {
498 die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval));
499 }
500
501 do_create_ip_common(argc, argv, use, flags);
502 }
503
504 static void
505 do_add_ipmp(int argc, char *argv[], const char *use)
506 {
507 do_action_ipmp(argc, argv, use, IPMP_ADD_MEMBER);
508 }
509
510 static void
511 do_remove_ipmp(int argc, char *argv[], const char *use)
512 {
513 do_action_ipmp(argc, argv, use, IPMP_REMOVE_MEMBER);
514 }
515
516 static void
517 do_action_ipmp(int argc, char *argv[], const char *use,
518 ipmp_action_t action)
519 {
520 int option;
521 ipadm_status_t status;
522 ipadm_ipmp_members_t members;
523 ipadm_ipmp_member_t *ipmp_member;
524 uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
525
526 list_create(&members, sizeof (ipadm_ipmp_member_t),
527 offsetof(ipadm_ipmp_member_t, node));
528
529 opterr = 0;
530 while ((option = getopt_long(argc, argv,
531 ":ti:", if_longopts, NULL)) != -1) {
532 switch (option) {
533 case 't':
534 flags &= ~IPADM_OPT_PERSIST;
535 break;
536 case 'i':
537 if ((ipmp_member = calloc(1,
538 sizeof (ipadm_ipmp_member_t))) == NULL)
539 die("insufficient memory");
540
541 if (strlcpy(ipmp_member->if_name,
542 optarg, sizeof (ipmp_member->if_name)) >= LIFNAMSIZ)
543 die("Incorrect length of interface"
544 "name: %s", optarg);
545
546 list_insert_tail(&members, ipmp_member);
547 break;
548 default:
549 die_opterr(optopt, option, use);
550 }
551 }
552
553 if (optind != (argc - 1))
554 die("Usage: %s", use);
555
556 while ((ipmp_member = list_remove_head(&members)) != NULL) {
557 switch (action) {
558 case IPMP_ADD_MEMBER:
559 if ((status = ipadm_add_ipmp_member(iph,
560 argv[optind], ipmp_member->if_name, flags))
561 != IPADM_SUCCESS)
562 die("Cannot add interface '%s' to "
563 "IPMP interface '%s': %s",
564 ipmp_member->if_name, argv[optind],
565 ipadm_status2str(status));
566 break;
567 case IPMP_REMOVE_MEMBER:
568 if ((status = ipadm_remove_ipmp_member(iph,
569 argv[optind], ipmp_member->if_name, flags))
570 != IPADM_SUCCESS)
571 die("Cannot remove interface '%s' from "
572 "IPMP interface '%s': %s",
573 ipmp_member->if_name, argv[optind],
574 ipadm_status2str(status));
575 break;
576 }
577
578 free(ipmp_member);
579 }
580
581 list_destroy(&members);
582 }
583
584 /*
585 * Create an IP interface for which no saved configuration exists in the
586 * persistent store.
587 */
588 static void
589 do_create_ip(int argc, char *argv[], const char *use)
590 {
591 do_create_ip_common(argc, argv, use,
592 IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE);
593 }
594
595 /*
596 * Enable an IP interface based on the persistent configuration for
597 * that interface.
598 */
599 static void
600 do_enable_if(int argc, char *argv[], const char *use)
601 {
602 ipadm_status_t status;
603 int index;
604 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
605
606 process_misc_addrargs(argc, argv, use, &index, &flags);
607 if (flags & IPADM_OPT_PERSIST)
608 die("persistent operation not supported for enable-if");
609 status = ipadm_enable_if(iph, argv[index], flags);
610 if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
611 warn_ipadmerr(status, "");
612 } else if (status != IPADM_SUCCESS) {
613 die("Could not enable %s : %s",
614 argv[optind], ipadm_status2str(status));
615 }
616 }
617
618 /*
619 * Remove an IP interface from both active and persistent configuration.
620 */
621 static void
622 do_delete_ip(int argc, char *argv[], const char *use)
623 {
624 ipadm_status_t status;
625 uint32_t flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
626
627 if (argc != 2)
628 die("Usage: %s", use);
629
630 status = ipadm_delete_if(iph, argv[1], AF_UNSPEC, flags);
631 if (status != IPADM_SUCCESS) {
632 die("Could not delete %s: %s",
633 argv[optind], ipadm_status2str(status));
634 }
635 }
636
637 /*
638 * Disable an IP interface by removing it from active configuration.
639 */
640 static void
641 do_disable_if(int argc, char *argv[], const char *use)
642 {
1177 warn(const char *format, ...)
1178 {
1179 va_list alist;
1180
1181 format = gettext(format);
1182 (void) fprintf(stderr, gettext("%s: warning: "), progname);
1183
1184 va_start(alist, format);
1185 (void) vfprintf(stderr, format, alist);
1186 va_end(alist);
1187
1188 (void) fprintf(stderr, "\n");
1189 }
1190
1191 /* PRINTFLIKE1 */
1192 static void
1193 die(const char *format, ...)
1194 {
1195 va_list alist;
1196
1197 if (format != NULL) {
1198 format = gettext(format);
1199 (void) fprintf(stderr, "%s: ", progname);
1200
1201 va_start(alist, format);
1202 (void) vfprintf(stderr, format, alist);
1203 va_end(alist);
1204
1205 (void) putchar('\n');
1206 }
1207
1208 ipadm_destroy_addrobj(ipaddr);
1209 ipadm_close(iph);
1210 exit(EXIT_FAILURE);
1211 }
1212
1213 static void
1214 die_opterr(int opt, int opterr, const char *usage)
1215 {
1216 switch (opterr) {
1217 case ':':
1218 die("option '-%c' requires a value\nusage: %s", opt,
1219 gettext(usage));
1220 break;
1221 case '?':
1222 default:
1223 die("unrecognized option '-%c'\nusage: %s", opt,
1224 gettext(usage));
1225 break;
1226 }
2056 { "s", IFIF_STANDBY, IFIF_STANDBY },
2057 { "4", IFIF_IPV4, IFIF_IPV4 },
2058 { "6", IFIF_IPV6, IFIF_IPV6 },
2059 { NULL, 0, 0 }
2060 };
2061 fmask_t intf_cflags[] = {
2062 { "b", IFIF_BROADCAST, IFIF_BROADCAST },
2063 { "m", IFIF_MULTICAST, IFIF_MULTICAST },
2064 { "p", IFIF_POINTOPOINT, IFIF_POINTOPOINT},
2065 { "v", IFIF_VIRTUAL, IFIF_VIRTUAL },
2066 { "I", IFIF_IPMP, IFIF_IPMP },
2067 { "s", IFIF_STANDBY, IFIF_STANDBY },
2068 { "i", IFIF_INACTIVE, IFIF_INACTIVE },
2069 { "V", IFIF_VRRP, IFIF_VRRP },
2070 { "a", IFIF_NOACCEPT, IFIF_NOACCEPT },
2071 { "Z", IFIF_L3PROTECT, IFIF_L3PROTECT },
2072 { "4", IFIF_IPV4, IFIF_IPV4 },
2073 { "6", IFIF_IPV6, IFIF_IPV6 },
2074 { NULL, 0, 0 }
2075 };
2076 fmask_t intf_class[] = {
2077 { "IP", IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS},
2078 { "IPMP", IPADM_IF_CLASS_IPMP, IPADM_ALL_BITS},
2079 { "VIRTUAL", IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS},
2080 { "UNKNOWN", IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS},
2081 { NULL, 0, 0}
2082 };
2083
2084 buf[0] = '\0';
2085 switch (ofarg->ofmt_id) {
2086 case SI_IFNAME:
2087 (void) snprintf(buf, bufsize, "%s", ifname);
2088 break;
2089 case SI_IFCLASS:
2090 flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
2091 buf, bufsize);
2092 break;
2093 case SI_STATE:
2094 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
2095 buf, bufsize);
2096 break;
2097 case SI_CURRENT:
2098 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
2099 buf, bufsize);
2100 break;
2101 case SI_PERSISTENT:
2102 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
2103 buf, bufsize);
2104 break;
2105 default:
2106 die("invalid input");
2107 break;
2108 }
2109
2110 return (_B_TRUE);
2111 }
2112
|