Print this page
Commit IPMP changes


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 #include <arpa/inet.h>
  26 #include <errno.h>
  27 #include <getopt.h>
  28 #include <inet/ip.h>
  29 #include <inet/iptun.h>
  30 #include <inet/tunables.h>
  31 #include <libdladm.h>
  32 #include <libdliptun.h>
  33 #include <libdllink.h>
  34 #include <libinetutil.h>
  35 #include <libipadm.h>


  36 #include <locale.h>
  37 #include <netdb.h>
  38 #include <netinet/in.h>
  39 #include <ofmt.h>
  40 #include <stdarg.h>
  41 #include <stddef.h>
  42 #include <stdio.h>
  43 #include <stdlib.h>
  44 #include <string.h>
  45 #include <strings.h>
  46 #include <sys/stat.h>
  47 #include <sys/types.h>
  48 #include <zone.h>


  49 
  50 #define STR_UNKNOWN_VAL "?"
  51 #define LIFC_DEFAULT    (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
  52                         LIFC_UNDER_IPMP)
  53 


  54 typedef void cmdfunc_t(int, char **, const char *);

  55 static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
  56 static cmdfunc_t do_show_if;
  57 static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
  58 static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
  59 static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
  60 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
  61 static cmdfunc_t do_enable_addr, do_disable_addr;
  62 static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
  63 
  64 typedef struct  cmd {
  65         char            *c_name;
  66         cmdfunc_t       *c_fn;
  67         const char      *c_usage;
  68 } cmd_t;
  69 
  70 static cmd_t    cmds[] = {
  71         /* interface management related sub-commands */








  72         { "create-if",  do_create_if,   "\tcreate-if\t[-t] <interface>"   },
  73         { "disable-if", do_disable_if,  "\tdisable-if\t-t <interface>"    },
  74         { "enable-if",  do_enable_if,   "\tenable-if\t-t <interface>"     },
  75         { "delete-if",  do_delete_if,   "\tdelete-if\t<interface>"        },
  76         { "show-if",    do_show_if,
  77             "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"    },
  78         { "set-ifprop", do_set_ifprop,
  79             "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
  80             "<interface>"                                                 },
  81         { "reset-ifprop", do_reset_ifprop,
  82             "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>"        },
  83         { "show-ifprop", do_show_ifprop,
  84             "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
  85             "\t\t\t[-m <protocol>] [interface]\n"                         },
  86 
  87         /* address management related sub-commands */
  88         { "create-addr", do_create_addr,
  89             "\tcreate-addr\t[-t] -T static [-d] "
  90             "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
  91             "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"


 267         show_addr_state_t       *sa_state;
 268         ipadm_addr_info_t       *sa_info;
 269 } show_addr_args_t;
 270 
 271 typedef struct show_if_args_s {
 272         show_if_state_t *si_state;
 273         ipadm_if_info_t *si_info;
 274 } show_if_args_t;
 275 
 276 typedef enum {
 277         SA_ADDROBJ,
 278         SA_TYPE,
 279         SA_STATE,
 280         SA_CURRENT,
 281         SA_PERSISTENT,
 282         SA_ADDR
 283 } sa_field_index_t;
 284 
 285 typedef enum {
 286         SI_IFNAME,

 287         SI_STATE,
 288         SI_CURRENT,
 289         SI_PERSISTENT
 290 } si_field_index_t;
 291 
 292 static ofmt_field_t show_addr_fields[] = {
 293 /* name,        field width,    id,             callback */
 294 { "ADDROBJ",    18,             SA_ADDROBJ,     print_sa_cb},
 295 { "TYPE",       9,              SA_TYPE,        print_sa_cb},
 296 { "STATE",      13,             SA_STATE,       print_sa_cb},
 297 { "CURRENT",    8,              SA_CURRENT,     print_sa_cb},
 298 { "PERSISTENT", 11,             SA_PERSISTENT,  print_sa_cb},
 299 { "ADDR",       46,             SA_ADDR,        print_sa_cb},
 300 { NULL,         0,              0,              NULL}
 301 };
 302 
 303 static ofmt_field_t show_if_fields[] = {
 304 /* name,        field width,    id,             callback */
 305 { "IFNAME",     11,             SI_IFNAME,      print_si_cb},

 306 { "STATE",      9,              SI_STATE,       print_si_cb},
 307 { "CURRENT",    13,             SI_CURRENT,     print_si_cb},
 308 { "PERSISTENT", 11,             SI_PERSISTENT,  print_si_cb},
 309 { NULL,         0,              0,              NULL}
 310 };
 311 
 312 #define IPADM_ALL_BITS  ((uint_t)-1)
 313 typedef struct intf_mask {
 314         char            *name;
 315         uint64_t        bits;
 316         uint64_t        mask;
 317 } fmask_t;
 318 





 319 /*
 320  * Handle to libipadm. Opened in main() before the sub-command specific
 321  * function is called and is closed before the program exits.
 322  */
 323 ipadm_handle_t  iph = NULL;
 324 
 325 /*
 326  * Opaque ipadm address object. Used by all the address management subcommands.
 327  */
 328 ipadm_addrobj_t ipaddr = NULL;
 329 
 330 static char *progname;
 331 
 332 static void     die(const char *, ...);
 333 static void     die_opterr(int, int, const char *);
 334 static void     warn_ipadmerr(ipadm_status_t, const char *, ...);
 335 static void     ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
 336 static void     ipadm_check_propstr(const char *, boolean_t, const char *);
 337 static void     process_misc_addrargs(int, char **, const char *, int *,
 338                     uint32_t *);

 339 
 340 static void
 341 usage(void)
 342 {
 343         int     i;
 344         cmd_t   *cmdp;
 345 
 346         (void) fprintf(stderr,
 347             gettext("usage:  ipadm <subcommand> <args> ...\n"));
 348         for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 349                 cmdp = &cmds[i];
 350                 if (cmdp->c_usage != NULL)
 351                         (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
 352         }
 353 
 354         ipadm_destroy_addrobj(ipaddr);
 355         ipadm_close(iph);
 356         exit(1);
 357 }
 358 


 381         }
 382 
 383         for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 384                 cmdp = &cmds[i];
 385                 if (strcmp(argv[1], cmdp->c_name) == 0) {
 386                         cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
 387                         ipadm_destroy_addrobj(ipaddr);
 388                         ipadm_close(iph);
 389                         exit(0);
 390                 }
 391         }
 392 
 393         (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
 394             progname, argv[1]);
 395         usage();
 396 
 397         return (0);
 398 }
 399 
 400 /*
 401  * Create an IP interface for which no saved configuration exists in the
 402  * persistent store.
 403  */
 404 static void
 405 do_create_if(int argc, char *argv[], const char *use)
 406 {
 407         ipadm_status_t  status;
 408         int             option;
 409         uint32_t        flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
 410 
 411         opterr = 0;
 412         while ((option = getopt_long(argc, argv, ":t", if_longopts,
 413             NULL)) != -1) {
 414                 switch (option) {
 415                 case 't':
 416                         /*
 417                          * "ifconfig" mode - plumb interface, but do not
 418                          * restore settings that may exist in db.
 419                          */
 420                         flags &= ~IPADM_OPT_PERSIST;
 421                         break;
 422                 default:
 423                         die_opterr(optopt, option, use);
 424                 }
 425         }
 426         if (optind != (argc - 1))
 427                 die("Usage: %s", use);
 428         status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
 429         if (status != IPADM_SUCCESS) {
 430                 die("Could not create %s : %s",
 431                     argv[optind], ipadm_status2str(status));
 432         }
 433 }
 434 
 435 /*






















































































































 436  * Enable an IP interface based on the persistent configuration for
 437  * that interface.
 438  */
 439 static void
 440 do_enable_if(int argc, char *argv[], const char *use)
 441 {
 442         ipadm_status_t  status;
 443         int             index;
 444         uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 445 
 446         process_misc_addrargs(argc, argv, use, &index, &flags);
 447         if (flags & IPADM_OPT_PERSIST)
 448                 die("persistent operation not supported for enable-if");
 449         status = ipadm_enable_if(iph, argv[index], flags);
 450         if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
 451                 warn_ipadmerr(status, "");
 452         } else if (status != IPADM_SUCCESS) {
 453                 die("Could not enable %s : %s",
 454                     argv[optind], ipadm_status2str(status));
 455         }


1891                 { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
1892                 { "4",  IFIF_IPV4,              IFIF_IPV4       },
1893                 { "6",  IFIF_IPV6,              IFIF_IPV6       },
1894                 { NULL, 0,                      0               }
1895         };
1896         fmask_t intf_cflags[] = {
1897                 { "b",  IFIF_BROADCAST,         IFIF_BROADCAST  },
1898                 { "m",  IFIF_MULTICAST,         IFIF_MULTICAST  },
1899                 { "p",  IFIF_POINTOPOINT,       IFIF_POINTOPOINT},
1900                 { "v",  IFIF_VIRTUAL,           IFIF_VIRTUAL    },
1901                 { "I",  IFIF_IPMP,              IFIF_IPMP       },
1902                 { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
1903                 { "i",  IFIF_INACTIVE,          IFIF_INACTIVE   },
1904                 { "V",  IFIF_VRRP,              IFIF_VRRP       },
1905                 { "a",  IFIF_NOACCEPT,          IFIF_NOACCEPT   },
1906                 { "Z",  IFIF_L3PROTECT,         IFIF_L3PROTECT  },
1907                 { "4",  IFIF_IPV4,              IFIF_IPV4       },
1908                 { "6",  IFIF_IPV6,              IFIF_IPV6       },
1909                 { NULL, 0,                      0               }
1910         };







1911 
1912         buf[0] = '\0';
1913         switch (ofarg->ofmt_id) {
1914         case SI_IFNAME:
1915                 (void) snprintf(buf, bufsize, "%s", ifname);
1916                 break;




1917         case SI_STATE:
1918                 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1919                     buf, bufsize);
1920                 break;
1921         case SI_CURRENT:
1922                 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1923                     buf, bufsize);
1924                 break;
1925         case SI_PERSISTENT:
1926                 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
1927                     buf, bufsize);
1928                 break;
1929         default:
1930                 die("invalid input");
1931                 break;
1932         }
1933 
1934         return (_B_TRUE);
1935 }
1936 




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 #include <arpa/inet.h>
  26 #include <errno.h>
  27 #include <getopt.h>
  28 #include <inet/ip.h>
  29 #include <inet/iptun.h>
  30 #include <inet/tunables.h>
  31 #include <libdladm.h>
  32 #include <libdliptun.h>
  33 #include <libdllink.h>
  34 #include <libinetutil.h>
  35 #include <libipadm.h>
  36 #include <ipmp.h>
  37 #include <ipmp_admin.h>
  38 #include <locale.h>
  39 #include <netdb.h>
  40 #include <netinet/in.h>
  41 #include <ofmt.h>
  42 #include <stdarg.h>
  43 #include <stddef.h>
  44 #include <stdio.h>
  45 #include <stdlib.h>
  46 #include <string.h>
  47 #include <strings.h>
  48 #include <sys/stat.h>
  49 #include <sys/types.h>
  50 #include <zone.h>
  51 #include <sys/list.h>
  52 #include <stddef.h>
  53 
  54 #define STR_UNKNOWN_VAL "?"
  55 #define LIFC_DEFAULT    (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
  56                         LIFC_UNDER_IPMP)
  57 
  58 static void do_create_if_common(int, char **, const char *, uint32_t);
  59 
  60 typedef void cmdfunc_t(int, char **, const char *);
  61 static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
  62 static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
  63 static cmdfunc_t do_show_if;
  64 static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
  65 static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
  66 static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
  67 static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
  68 static cmdfunc_t do_enable_addr, do_disable_addr;
  69 static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
  70 
  71 typedef struct  cmd {
  72         char            *c_name;
  73         cmdfunc_t       *c_fn;
  74         const char      *c_usage;
  75 } cmd_t;
  76 
  77 static cmd_t    cmds[] = {
  78         /* interface management related sub-commands */
  79         { "create-ipmp", do_create_ipmp, "\tcreate-ipmp\t[-t] <ipmp-group>"},
  80         { "delete-ipmp", do_delete_if, "\tdelete-ipmp\t[-t] <ipmp-group>"},
  81         { "add-ipmp", do_add_ipmp, "\tadd-ipmp\t[-t] -i"
  82             " <ipmp-member-interface> "
  83             "[-i <ipmp-member-interface>] <ipmp-group-interface>"},
  84         { "remove-ipmp", do_remove_ipmp, "\tremove-ipmp\t[-t] -i"
  85             " <ipmp-member-interface> "
  86             "[-i <ipmp-member-interface>] <ipmp-group-interface>"},
  87         { "create-if",  do_create_if,   "\tcreate-if\t[-t] <interface>"   },
  88         { "disable-if", do_disable_if,  "\tdisable-if\t-t <interface>"    },
  89         { "enable-if",  do_enable_if,   "\tenable-if\t-t <interface>"     },
  90         { "delete-if",  do_delete_if,   "\tdelete-if\t<interface>"        },
  91         { "show-if",    do_show_if,
  92             "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"    },
  93         { "set-ifprop", do_set_ifprop,
  94             "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
  95             "<interface>"                                                 },
  96         { "reset-ifprop", do_reset_ifprop,
  97             "\treset-ifprop\t[-t] -p <prop> -m <protocol> <interface>"        },
  98         { "show-ifprop", do_show_ifprop,
  99             "\tshow-ifprop\t[[-c] -o <field>,...] [-p <prop>,...]\n"
 100             "\t\t\t[-m <protocol>] [interface]\n"                         },
 101 
 102         /* address management related sub-commands */
 103         { "create-addr", do_create_addr,
 104             "\tcreate-addr\t[-t] -T static [-d] "
 105             "-a{local|remote}=addr[/prefixlen]\n\t\t\t<addrobj>\n"
 106             "\tcreate-addr\t[-t] -T dhcp [-w <seconds> | forever] <addrobj>\n"


 282         show_addr_state_t       *sa_state;
 283         ipadm_addr_info_t       *sa_info;
 284 } show_addr_args_t;
 285 
 286 typedef struct show_if_args_s {
 287         show_if_state_t *si_state;
 288         ipadm_if_info_t *si_info;
 289 } show_if_args_t;
 290 
 291 typedef enum {
 292         SA_ADDROBJ,
 293         SA_TYPE,
 294         SA_STATE,
 295         SA_CURRENT,
 296         SA_PERSISTENT,
 297         SA_ADDR
 298 } sa_field_index_t;
 299 
 300 typedef enum {
 301         SI_IFNAME,
 302         SI_IFCLASS,
 303         SI_STATE,
 304         SI_CURRENT,
 305         SI_PERSISTENT
 306 } si_field_index_t;
 307 
 308 static ofmt_field_t show_addr_fields[] = {
 309 /* name,        field width,    id,             callback */
 310 { "ADDROBJ",    18,             SA_ADDROBJ,     print_sa_cb},
 311 { "TYPE",       9,              SA_TYPE,        print_sa_cb},
 312 { "STATE",      13,             SA_STATE,       print_sa_cb},
 313 { "CURRENT",    8,              SA_CURRENT,     print_sa_cb},
 314 { "PERSISTENT", 11,             SA_PERSISTENT,  print_sa_cb},
 315 { "ADDR",       46,             SA_ADDR,        print_sa_cb},
 316 { NULL,         0,              0,              NULL}
 317 };
 318 
 319 static ofmt_field_t show_if_fields[] = {
 320 /* name,        field width,    id,             callback */
 321 { "IFNAME",     11,             SI_IFNAME,      print_si_cb},
 322 { "CLASS",      10,             SI_IFCLASS,     print_si_cb},
 323 { "STATE",      9,              SI_STATE,       print_si_cb},
 324 { "CURRENT",    13,             SI_CURRENT,     print_si_cb},
 325 { "PERSISTENT", 11,             SI_PERSISTENT,  print_si_cb},
 326 { NULL,         0,              0,              NULL}
 327 };
 328 
 329 #define IPADM_ALL_BITS  ((uint_t)-1)
 330 typedef struct intf_mask {
 331         char            *name;
 332         uint64_t        bits;
 333         uint64_t        mask;
 334 } fmask_t;
 335 
 336 typedef enum {
 337     IPMP_ADD_MEMBER,
 338     IPMP_REMOVE_MEMBER
 339 } ipmp_action_t;
 340 
 341 /*
 342  * Handle to libipadm. Opened in main() before the sub-command specific
 343  * function is called and is closed before the program exits.
 344  */
 345 ipadm_handle_t  iph = NULL;
 346 
 347 /*
 348  * Opaque ipadm address object. Used by all the address management subcommands.
 349  */
 350 ipadm_addrobj_t ipaddr = NULL;
 351 
 352 static char *progname;
 353 
 354 static void     die(const char *, ...);
 355 static void     die_opterr(int, int, const char *);
 356 static void     warn_ipadmerr(ipadm_status_t, const char *, ...);
 357 static void     ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
 358 static void     ipadm_check_propstr(const char *, boolean_t, const char *);
 359 static void     process_misc_addrargs(int, char **, const char *, int *,
 360                     uint32_t *);
 361 static void     do_action_ipmp(int, char **, const char *, ipmp_action_t);
 362 
 363 static void
 364 usage(void)
 365 {
 366         int     i;
 367         cmd_t   *cmdp;
 368 
 369         (void) fprintf(stderr,
 370             gettext("usage:  ipadm <subcommand> <args> ...\n"));
 371         for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 372                 cmdp = &cmds[i];
 373                 if (cmdp->c_usage != NULL)
 374                         (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
 375         }
 376 
 377         ipadm_destroy_addrobj(ipaddr);
 378         ipadm_close(iph);
 379         exit(1);
 380 }
 381 


 404         }
 405 
 406         for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 407                 cmdp = &cmds[i];
 408                 if (strcmp(argv[1], cmdp->c_name) == 0) {
 409                         cmdp->c_fn(argc - 1, &argv[1], gettext(cmdp->c_usage));
 410                         ipadm_destroy_addrobj(ipaddr);
 411                         ipadm_close(iph);
 412                         exit(0);
 413                 }
 414         }
 415 
 416         (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
 417             progname, argv[1]);
 418         usage();
 419 
 420         return (0);
 421 }
 422 
 423 /*
 424  * Create regular IP interface or IPMP group interface

 425  */
 426 static void
 427 do_create_if_common(int argc, char *argv[], const char *use, uint32_t flags)
 428 {
 429         ipadm_status_t  status;
 430         int             option;

 431 
 432         opterr = 0;
 433         while ((option = getopt_long(argc, argv,
 434             ":t", if_longopts, NULL)) != -1) {
 435                 switch (option) {
 436                 case 't':
 437                         /*
 438                          * "ifconfig" mode - plumb interface, but do not
 439                          * restore settings that may exist in db.
 440                          */
 441                         flags &= ~IPADM_OPT_PERSIST;
 442                         break;
 443                 default:
 444                         die_opterr(optopt, option, use);
 445                 }
 446         }
 447         if (optind != (argc - 1))
 448                 die("Usage: %s", use);
 449         status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
 450         if (status != IPADM_SUCCESS) {
 451                 die("Could not create %s : %s",
 452                     argv[optind], ipadm_status2str(status));
 453         }
 454 }
 455 
 456 /*
 457  * Create an IPMP group interface for which no saved configuration
 458  * exists in the persistent store.
 459  */
 460 static void
 461 do_create_ipmp(int argc, char *argv[], const char *use)
 462 {
 463         ipmp_handle_t ipmp_handle;
 464         int retval;
 465         uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE | IPADM_OPT_IPMP;
 466 
 467         retval = ipmp_open(&ipmp_handle);
 468         if (retval != IPMP_SUCCESS) {
 469                 die("Could not create IPMP handle: %s",
 470                     ipadm_status2str(retval));
 471         }
 472 
 473         retval = ipmp_ping_daemon(ipmp_handle);
 474         ipmp_close(ipmp_handle);
 475 
 476         if (retval != IPMP_SUCCESS) {
 477                 die("Cannot ping in.mpathd: %s", ipmp_errmsg(retval));
 478         }
 479 
 480         do_create_if_common(argc, argv, use, flags);
 481 }
 482 
 483 static void
 484 do_add_ipmp(int argc, char *argv[], const char *use)
 485 {
 486         do_action_ipmp(argc, argv, use, IPMP_ADD_MEMBER);
 487 }
 488 
 489 static void
 490 do_remove_ipmp(int argc, char *argv[], const char *use)
 491 {
 492         do_action_ipmp(argc, argv, use, IPMP_REMOVE_MEMBER);
 493 }
 494 
 495 static void
 496 do_action_ipmp(int argc, char *argv[], const char *use,
 497         ipmp_action_t action)
 498 {
 499         int     option;
 500         ipadm_status_t  status;
 501         ipadm_ipmp_members_t members;
 502         ipadm_ipmp_member_t *ipmp_member;
 503         uint32_t flags = IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE;
 504 
 505         list_create(&members, sizeof (ipadm_ipmp_member_t),
 506             offsetof(ipadm_ipmp_member_t, node));
 507 
 508         opterr = 0;
 509         while ((option = getopt_long(argc, argv,
 510             ":ti:", if_longopts, NULL)) != -1) {
 511                 switch (option) {
 512                 case 't':
 513                         flags &= ~IPADM_OPT_PERSIST;
 514                         break;
 515                 case 'i':
 516                         if ((ipmp_member = calloc(1,
 517                             sizeof (ipadm_ipmp_member_t))) == NULL)
 518                                 die("insufficient memory");
 519 
 520                         if (strlcpy(ipmp_member->if_name,
 521                             optarg, sizeof (ipmp_member->if_name)) >= LIFNAMSIZ)
 522                                 die("Incorrect length of interface"
 523                                     "name: %s", optarg);
 524 
 525                         list_insert_tail(&members, ipmp_member);
 526                         break;
 527                 default:
 528                         die_opterr(optopt, option, use);
 529                 }
 530         }
 531 
 532         if (optind != (argc - 1))
 533                 die("Usage: %s", use);
 534 
 535         while ((ipmp_member = list_remove_head(&members)) != NULL) {
 536                 switch (action) {
 537                         case IPMP_ADD_MEMBER:
 538                                 if ((status = ipadm_add_ipmp_member(iph,
 539                                     argv[optind], ipmp_member->if_name, flags))
 540                                     != IPADM_SUCCESS)
 541                                         die("Cannot add '%s' interface to"
 542                                             "'%s': %s",
 543                                             ipmp_member->if_name, argv[optind],
 544                                             ipadm_status2str(status));
 545                                 break;
 546                         case IPMP_REMOVE_MEMBER:
 547                                 if ((status = ipadm_remove_ipmp_member(iph,
 548                                     argv[optind], ipmp_member->if_name, flags))
 549                                     != IPADM_SUCCESS)
 550                                         die("Cannot remove '%s' interface from "
 551                                             "'%s': %s",
 552                                             ipmp_member->if_name, argv[optind],
 553                                             ipadm_status2str(status));
 554                                 break;
 555                 }
 556 
 557                 free(ipmp_member);
 558         }
 559 
 560         list_destroy(&members);
 561 }
 562 
 563 /*
 564  * Create an IP interface for which no saved configuration exists in the
 565  * persistent store.
 566  */
 567 static void
 568 do_create_if(int argc, char *argv[], const char *use)
 569 {
 570         do_create_if_common(argc, argv, use,
 571             IPADM_OPT_PERSIST | IPADM_OPT_ACTIVE);
 572 }
 573 
 574 /*
 575  * Enable an IP interface based on the persistent configuration for
 576  * that interface.
 577  */
 578 static void
 579 do_enable_if(int argc, char *argv[], const char *use)
 580 {
 581         ipadm_status_t  status;
 582         int             index;
 583         uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 584 
 585         process_misc_addrargs(argc, argv, use, &index, &flags);
 586         if (flags & IPADM_OPT_PERSIST)
 587                 die("persistent operation not supported for enable-if");
 588         status = ipadm_enable_if(iph, argv[index], flags);
 589         if (status == IPADM_ALL_ADDRS_NOT_ENABLED) {
 590                 warn_ipadmerr(status, "");
 591         } else if (status != IPADM_SUCCESS) {
 592                 die("Could not enable %s : %s",
 593                     argv[optind], ipadm_status2str(status));
 594         }


2030                 { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
2031                 { "4",  IFIF_IPV4,              IFIF_IPV4       },
2032                 { "6",  IFIF_IPV6,              IFIF_IPV6       },
2033                 { NULL, 0,                      0               }
2034         };
2035         fmask_t intf_cflags[] = {
2036                 { "b",  IFIF_BROADCAST,         IFIF_BROADCAST  },
2037                 { "m",  IFIF_MULTICAST,         IFIF_MULTICAST  },
2038                 { "p",  IFIF_POINTOPOINT,       IFIF_POINTOPOINT},
2039                 { "v",  IFIF_VIRTUAL,           IFIF_VIRTUAL    },
2040                 { "I",  IFIF_IPMP,              IFIF_IPMP       },
2041                 { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
2042                 { "i",  IFIF_INACTIVE,          IFIF_INACTIVE   },
2043                 { "V",  IFIF_VRRP,              IFIF_VRRP       },
2044                 { "a",  IFIF_NOACCEPT,          IFIF_NOACCEPT   },
2045                 { "Z",  IFIF_L3PROTECT,         IFIF_L3PROTECT  },
2046                 { "4",  IFIF_IPV4,              IFIF_IPV4       },
2047                 { "6",  IFIF_IPV6,              IFIF_IPV6       },
2048                 { NULL, 0,                      0               }
2049         };
2050         fmask_t intf_class[] = {
2051                 { "IP",         IPADM_IF_CLASS_REGULAR, IPADM_ALL_BITS},
2052                 { "IPMP",       IPADM_IF_CLASS_IPMP,    IPADM_ALL_BITS},
2053                 { "VIRTUAL",    IPADM_IF_CLASS_VIRTUAL, IPADM_ALL_BITS},
2054                 { "UNKNOWN",    IPADM_IF_CLASS_UNKNOWN, IPADM_ALL_BITS},
2055                 { NULL, 0,      0}
2056         };
2057 
2058         buf[0] = '\0';
2059         switch (ofarg->ofmt_id) {
2060         case SI_IFNAME:
2061                 (void) snprintf(buf, bufsize, "%s", ifname);
2062                 break;
2063         case SI_IFCLASS:
2064                 flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
2065                     buf, bufsize);
2066                 break;
2067         case SI_STATE:
2068                 flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
2069                     buf, bufsize);
2070                 break;
2071         case SI_CURRENT:
2072                 flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
2073                     buf, bufsize);
2074                 break;
2075         case SI_PERSISTENT:
2076                 flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
2077                     buf, bufsize);
2078                 break;
2079         default:
2080                 die("invalid input");
2081                 break;
2082         }
2083 
2084         return (_B_TRUE);
2085 }
2086