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 
 
 |