Print this page
Commit IPMP changes

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
          +++ new/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
       23 + * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  24   24   */
  25   25  #include <arpa/inet.h>
  26   26  #include <errno.h>
  27   27  #include <getopt.h>
  28   28  #include <inet/ip.h>
  29   29  #include <inet/iptun.h>
  30   30  #include <inet/tunables.h>
  31   31  #include <libdladm.h>
  32   32  #include <libdliptun.h>
  33   33  #include <libdllink.h>
  34   34  #include <libinetutil.h>
  35   35  #include <libipadm.h>
       36 +#include <ipmp.h>
       37 +#include <ipmp_admin.h>
  36   38  #include <locale.h>
  37   39  #include <netdb.h>
  38   40  #include <netinet/in.h>
  39   41  #include <ofmt.h>
  40   42  #include <stdarg.h>
  41   43  #include <stddef.h>
  42   44  #include <stdio.h>
  43   45  #include <stdlib.h>
  44   46  #include <string.h>
  45   47  #include <strings.h>
  46   48  #include <sys/stat.h>
  47   49  #include <sys/types.h>
  48   50  #include <zone.h>
       51 +#include <sys/list.h>
       52 +#include <stddef.h>
  49   53  
  50   54  #define STR_UNKNOWN_VAL "?"
  51   55  #define LIFC_DEFAULT    (LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES |\
  52   56                          LIFC_UNDER_IPMP)
  53   57  
       58 +static void do_create_if_common(int, char **, const char *, uint32_t);
       59 +
  54   60  typedef void cmdfunc_t(int, char **, const char *);
       61 +static cmdfunc_t do_create_ipmp, do_add_ipmp, do_remove_ipmp;
  55   62  static cmdfunc_t do_create_if, do_delete_if, do_enable_if, do_disable_if;
  56   63  static cmdfunc_t do_show_if;
  57   64  static cmdfunc_t do_set_prop, do_show_prop, do_set_ifprop;
  58   65  static cmdfunc_t do_show_ifprop, do_reset_ifprop, do_reset_prop;
  59   66  static cmdfunc_t do_show_addrprop, do_set_addrprop, do_reset_addrprop;
  60   67  static cmdfunc_t do_create_addr, do_delete_addr, do_show_addr;
  61   68  static cmdfunc_t do_enable_addr, do_disable_addr;
  62   69  static cmdfunc_t do_up_addr, do_down_addr, do_refresh_addr;
  63   70  
  64   71  typedef struct  cmd {
  65   72          char            *c_name;
  66   73          cmdfunc_t       *c_fn;
  67   74          const char      *c_usage;
  68   75  } cmd_t;
  69   76  
  70   77  static cmd_t    cmds[] = {
  71   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>"},
  72   87          { "create-if",  do_create_if,   "\tcreate-if\t[-t] <interface>" },
  73   88          { "disable-if", do_disable_if,  "\tdisable-if\t-t <interface>"  },
  74   89          { "enable-if",  do_enable_if,   "\tenable-if\t-t <interface>"   },
  75   90          { "delete-if",  do_delete_if,   "\tdelete-if\t<interface>"      },
  76   91          { "show-if",    do_show_if,
  77   92              "\tshow-if\t\t[[-p] -o <field>,...] [<interface>]\n"        },
  78   93          { "set-ifprop", do_set_ifprop,
  79   94              "\tset-ifprop\t[-t] -p <prop>=<value[,...]> -m <protocol> "
  80   95              "<interface>"                                               },
  81   96          { "reset-ifprop", do_reset_ifprop,
↓ open down ↓ 195 lines elided ↑ open up ↑
 277  292          SA_ADDROBJ,
 278  293          SA_TYPE,
 279  294          SA_STATE,
 280  295          SA_CURRENT,
 281  296          SA_PERSISTENT,
 282  297          SA_ADDR
 283  298  } sa_field_index_t;
 284  299  
 285  300  typedef enum {
 286  301          SI_IFNAME,
      302 +        SI_IFCLASS,
 287  303          SI_STATE,
 288  304          SI_CURRENT,
 289  305          SI_PERSISTENT
 290  306  } si_field_index_t;
 291  307  
 292  308  static ofmt_field_t show_addr_fields[] = {
 293  309  /* name,        field width,    id,             callback */
 294  310  { "ADDROBJ",    18,             SA_ADDROBJ,     print_sa_cb},
 295  311  { "TYPE",       9,              SA_TYPE,        print_sa_cb},
 296  312  { "STATE",      13,             SA_STATE,       print_sa_cb},
 297  313  { "CURRENT",    8,              SA_CURRENT,     print_sa_cb},
 298  314  { "PERSISTENT", 11,             SA_PERSISTENT,  print_sa_cb},
 299  315  { "ADDR",       46,             SA_ADDR,        print_sa_cb},
 300  316  { NULL,         0,              0,              NULL}
 301  317  };
 302  318  
 303  319  static ofmt_field_t show_if_fields[] = {
 304  320  /* name,        field width,    id,             callback */
 305  321  { "IFNAME",     11,             SI_IFNAME,      print_si_cb},
      322 +{ "CLASS",      10,             SI_IFCLASS,     print_si_cb},
 306  323  { "STATE",      9,              SI_STATE,       print_si_cb},
 307  324  { "CURRENT",    13,             SI_CURRENT,     print_si_cb},
 308  325  { "PERSISTENT", 11,             SI_PERSISTENT,  print_si_cb},
 309  326  { NULL,         0,              0,              NULL}
 310  327  };
 311  328  
 312  329  #define IPADM_ALL_BITS  ((uint_t)-1)
 313  330  typedef struct intf_mask {
 314  331          char            *name;
 315  332          uint64_t        bits;
 316  333          uint64_t        mask;
 317  334  } fmask_t;
 318  335  
      336 +typedef enum {
      337 +    IPMP_ADD_MEMBER,
      338 +    IPMP_REMOVE_MEMBER
      339 +} ipmp_action_t;
      340 +
 319  341  /*
 320  342   * Handle to libipadm. Opened in main() before the sub-command specific
 321  343   * function is called and is closed before the program exits.
 322  344   */
 323  345  ipadm_handle_t  iph = NULL;
 324  346  
 325  347  /*
 326  348   * Opaque ipadm address object. Used by all the address management subcommands.
 327  349   */
 328  350  ipadm_addrobj_t ipaddr = NULL;
 329  351  
 330  352  static char *progname;
 331  353  
 332  354  static void     die(const char *, ...);
 333  355  static void     die_opterr(int, int, const char *);
 334  356  static void     warn_ipadmerr(ipadm_status_t, const char *, ...);
 335  357  static void     ipadm_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
 336  358  static void     ipadm_check_propstr(const char *, boolean_t, const char *);
 337  359  static void     process_misc_addrargs(int, char **, const char *, int *,
 338  360                      uint32_t *);
      361 +static void     do_action_ipmp(int, char **, const char *, ipmp_action_t);
 339  362  
 340  363  static void
 341  364  usage(void)
 342  365  {
 343  366          int     i;
 344  367          cmd_t   *cmdp;
 345  368  
 346  369          (void) fprintf(stderr,
 347  370              gettext("usage:  ipadm <subcommand> <args> ...\n"));
 348  371          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
↓ open down ↓ 42 lines elided ↑ open up ↑
 391  414          }
 392  415  
 393  416          (void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
 394  417              progname, argv[1]);
 395  418          usage();
 396  419  
 397  420          return (0);
 398  421  }
 399  422  
 400  423  /*
 401      - * Create an IP interface for which no saved configuration exists in the
 402      - * persistent store.
      424 + * Create regular IP interface or IPMP group interface
 403  425   */
 404  426  static void
 405      -do_create_if(int argc, char *argv[], const char *use)
      427 +do_create_if_common(int argc, char *argv[], const char *use, uint32_t flags)
 406  428  {
 407  429          ipadm_status_t  status;
 408  430          int             option;
 409      -        uint32_t        flags = IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE;
 410  431  
 411  432          opterr = 0;
 412      -        while ((option = getopt_long(argc, argv, ":t", if_longopts,
 413      -            NULL)) != -1) {
      433 +        while ((option = getopt_long(argc, argv,
      434 +            ":t", if_longopts, NULL)) != -1) {
 414  435                  switch (option) {
 415  436                  case 't':
 416  437                          /*
 417  438                           * "ifconfig" mode - plumb interface, but do not
 418  439                           * restore settings that may exist in db.
 419  440                           */
 420  441                          flags &= ~IPADM_OPT_PERSIST;
 421  442                          break;
 422  443                  default:
 423  444                          die_opterr(optopt, option, use);
↓ open down ↓ 2 lines elided ↑ open up ↑
 426  447          if (optind != (argc - 1))
 427  448                  die("Usage: %s", use);
 428  449          status = ipadm_create_if(iph, argv[optind], AF_UNSPEC, flags);
 429  450          if (status != IPADM_SUCCESS) {
 430  451                  die("Could not create %s : %s",
 431  452                      argv[optind], ipadm_status2str(status));
 432  453          }
 433  454  }
 434  455  
 435  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 +/*
 436  575   * Enable an IP interface based on the persistent configuration for
 437  576   * that interface.
 438  577   */
 439  578  static void
 440  579  do_enable_if(int argc, char *argv[], const char *use)
 441  580  {
 442  581          ipadm_status_t  status;
 443  582          int             index;
 444  583          uint32_t        flags = IPADM_OPT_ACTIVE|IPADM_OPT_PERSIST;
 445  584  
↓ open down ↓ 1455 lines elided ↑ open up ↑
1901 2040                  { "I",  IFIF_IPMP,              IFIF_IPMP       },
1902 2041                  { "s",  IFIF_STANDBY,           IFIF_STANDBY    },
1903 2042                  { "i",  IFIF_INACTIVE,          IFIF_INACTIVE   },
1904 2043                  { "V",  IFIF_VRRP,              IFIF_VRRP       },
1905 2044                  { "a",  IFIF_NOACCEPT,          IFIF_NOACCEPT   },
1906 2045                  { "Z",  IFIF_L3PROTECT,         IFIF_L3PROTECT  },
1907 2046                  { "4",  IFIF_IPV4,              IFIF_IPV4       },
1908 2047                  { "6",  IFIF_IPV6,              IFIF_IPV6       },
1909 2048                  { NULL, 0,                      0               }
1910 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 +        };
1911 2057  
1912 2058          buf[0] = '\0';
1913 2059          switch (ofarg->ofmt_id) {
1914 2060          case SI_IFNAME:
1915 2061                  (void) snprintf(buf, bufsize, "%s", ifname);
1916 2062                  break;
     2063 +        case SI_IFCLASS:
     2064 +                flags2str(ifinfo->ifi_class, intf_class, _B_FALSE,
     2065 +                    buf, bufsize);
     2066 +                break;
1917 2067          case SI_STATE:
1918 2068                  flags2str(ifinfo->ifi_state, intf_state, _B_FALSE,
1919 2069                      buf, bufsize);
1920 2070                  break;
1921 2071          case SI_CURRENT:
1922 2072                  flags2str(ifinfo->ifi_cflags, intf_cflags, _B_TRUE,
1923 2073                      buf, bufsize);
1924 2074                  break;
1925 2075          case SI_PERSISTENT:
1926 2076                  flags2str(ifinfo->ifi_pflags, intf_pflags, _B_TRUE,
↓ open down ↓ 298 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX