Print this page
NEX-7823 ipmgmtd can't properly remove interface from the old ipadm.conf format
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
NEX-6864 cannot create functional link-based IPMP interface
NEX-7793 unable to add/remove interface with existing address to/from IPMP group
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-2991 leaked buffer in libipadm`i_ipadm_init_ifs()
NEX-2395: new libipadm/ipadm/ipmgmtd shall be backward compatible with old ipadm.conf format
OS-161: Integrate IPMP changes

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libipadm/common/libipadm.c
          +++ new/usr/src/lib/libipadm/common/libipadm.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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  /*
  23   23   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2016 Nexenta Systems, Inc.
  25   25   * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
  26   26   */
  27   27  
  28   28  #include <stdio.h>
  29   29  #include <stdlib.h>
  30   30  #include <string.h>
  31   31  #include <errno.h>
  32   32  #include <fcntl.h>
  33   33  #include <unistd.h>
  34   34  #include <stropts.h>
↓ open down ↓ 486 lines elided ↑ open up ↑
 521  521                      DLADM_OPT_ACTIVE);
 522  522                  if (dlstatus == DLADM_STATUS_OK &&
 523  523                      params.iptun_param_type == IPTUN_TYPE_6TO4) {
 524  524                          return (B_TRUE);
 525  525                  }
 526  526          }
 527  527          return (B_FALSE);
 528  528  }
 529  529  
 530  530  /*
 531      - * Returns B_TRUE if `ifname' represents an IPMP underlying interface.
 532      - */
 533      -boolean_t
 534      -i_ipadm_is_under_ipmp(ipadm_handle_t iph, const char *ifname)
 535      -{
 536      -        struct lifreq   lifr;
 537      -
 538      -        (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
 539      -        if (ioctl(iph->iph_sock, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) {
 540      -                if (ioctl(iph->iph_sock6, SIOCGLIFGROUPNAME,
 541      -                    (caddr_t)&lifr) < 0) {
 542      -                        return (B_FALSE);
 543      -                }
 544      -        }
 545      -        return (lifr.lifr_groupname[0] != '\0');
 546      -}
 547      -
 548      -/*
 549      - * Returns B_TRUE if `ifname' represents an IPMP meta-interface.
 550      - */
 551      -boolean_t
 552      -i_ipadm_is_ipmp(ipadm_handle_t iph, const char *ifname)
 553      -{
 554      -        uint64_t flags;
 555      -
 556      -        if (i_ipadm_get_flags(iph, ifname, AF_INET, &flags) != IPADM_SUCCESS &&
 557      -            i_ipadm_get_flags(iph, ifname, AF_INET6, &flags) != IPADM_SUCCESS)
 558      -                return (B_FALSE);
 559      -
 560      -        return ((flags & IFF_IPMP) != 0);
 561      -}
 562      -
 563      -/*
 564  531   * For a given interface name, ipadm_if_enabled() checks if v4
 565  532   * or v6 or both IP interfaces exist in the active configuration.
 566  533   */
 567  534  boolean_t
 568  535  ipadm_if_enabled(ipadm_handle_t iph, const char *ifname, sa_family_t af)
 569  536  {
 570  537          struct lifreq   lifr;
 571  538          int             s4 = iph->iph_sock;
 572  539          int             s6 = iph->iph_sock6;
 573  540  
↓ open down ↓ 112 lines elided ↑ open up ↑
 686  653   * Instantiate the interface object by retrieving the configuration from
 687  654   * `ifnvl'. The nvlist `ifnvl' contains all the persistent configuration
 688  655   * (interface properties and address objects on that interface) for the
 689  656   * given `ifname'.
 690  657   */
 691  658  ipadm_status_t
 692  659  i_ipadm_init_ifobj(ipadm_handle_t iph, const char *ifname, nvlist_t *ifnvl)
 693  660  {
 694  661          nvlist_t        *nvl = NULL;
 695  662          nvpair_t        *nvp;
 696      -        char            *afstr;
 697      -        ipadm_status_t  status;
      663 +        ipadm_status_t  status = IPADM_ENXIO;
 698  664          ipadm_status_t  ret_status = IPADM_SUCCESS;
 699  665          char            newifname[LIFNAMSIZ];
 700  666          char            *aobjstr;
 701      -        sa_family_t     af = AF_UNSPEC;
 702      -        boolean_t       is_ngz = (iph->iph_zoneid != GLOBAL_ZONEID);
      667 +        uint16_t        *afs;
      668 +        char            *gifname;
      669 +        uint_t          nelem = 0;
      670 +        boolean_t       init_from_gz = B_FALSE;
      671 +        boolean_t       move_to_group = B_FALSE;
 703  672  
 704  673          (void) strlcpy(newifname, ifname, sizeof (newifname));
      674 +
 705  675          /*
 706      -         * First plumb the given interface and then apply all the persistent
 707      -         * interface properties and then instantiate any persistent addresses
 708      -         * objects on that interface.
      676 +         * First go through the ifnvl nvlist looking for nested nvlist
      677 +         * containing interface class and address families.
 709  678           */
 710  679          for (nvp = nvlist_next_nvpair(ifnvl, NULL); nvp != NULL;
 711  680              nvp = nvlist_next_nvpair(ifnvl, nvp)) {
 712      -                if (nvpair_value_nvlist(nvp, &nvl) != 0)
      681 +                char *icstr;
      682 +                char **mifnames;
      683 +                uint32_t ipadm_flags = IPADM_OPT_ACTIVE;
      684 +
      685 +                if (nvpair_value_nvlist(nvp, &nvl) != 0 ||
      686 +                    nvlist_lookup_uint16_array(nvl, IPADM_NVP_FAMILIES,
      687 +                    &afs, &nelem) != 0)
 713  688                          continue;
 714  689  
 715      -                if (nvlist_lookup_string(nvl, IPADM_NVP_FAMILY, &afstr) == 0) {
 716      -                        status = i_ipadm_plumb_if(iph, newifname, atoi(afstr),
 717      -                            IPADM_OPT_ACTIVE);
 718      -                        /*
 719      -                         * If the interface is already plumbed, we should
 720      -                         * ignore this error because there might be address
 721      -                         * address objects on that interface that needs to
 722      -                         * be enabled again.
 723      -                         */
      690 +                /* Check if this is IPMP group interface */
      691 +                if (nvlist_lookup_string(nvl, IPADM_NVP_IFCLASS,
      692 +                    &icstr) == 0 && atoi(icstr) == IPADM_IF_CLASS_IPMP)
      693 +                        ipadm_flags |= IPADM_OPT_IPMP;
      694 +
      695 +                /* Create interfaces for address families specified */
      696 +                while (nelem-- > 0) {
      697 +                        uint16_t af = afs[nelem];
      698 +
      699 +                        assert(af == AF_INET || af == AF_INET6);
      700 +
      701 +                        status = i_ipadm_plumb_if(iph, newifname, af,
      702 +                            ipadm_flags);
 724  703                          if (status == IPADM_IF_EXISTS)
 725  704                                  status = IPADM_SUCCESS;
      705 +                        if (status != IPADM_SUCCESS)
      706 +                                return (status);
      707 +                }
      708 +                if (nvlist_lookup_string(nvl, IPADM_NVP_GIFNAME,
      709 +                    &gifname) == 0) {
      710 +                        /*
      711 +                         * IPMP underlying interface. Move to the
      712 +                         * specified IPMP group.
      713 +                         */
      714 +                        move_to_group = B_TRUE;
      715 +                } else if ((ipadm_flags & IPADM_OPT_IPMP) &&
      716 +                    nvlist_lookup_string_array(nvl, IPADM_NVP_MIFNAMES,
      717 +                    &mifnames, &nelem) == 0) {
      718 +                        /* Non-empty IPMP group interface */
      719 +                        while (nelem-- > 0) {
      720 +                                (void) ipadm_add_ipmp_member(iph, newifname,
      721 +                                    mifnames[nelem], IPADM_OPT_ACTIVE);
      722 +                        }
      723 +                }
      724 +                if (iph->iph_zoneid != GLOBAL_ZONEID)
      725 +                        init_from_gz = B_TRUE;
      726 +        }
 726  727  
 727      -                        if (is_ngz)
 728      -                                af = atoi(afstr);
 729      -                } else if (nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
      728 +        if (status != IPADM_SUCCESS)
      729 +                return (status);
      730 +
      731 +        /*
      732 +         * Go through the ifnvl nvlist again, applying persistent configuration.
      733 +         */
      734 +        for (nvp = nvlist_next_nvpair(ifnvl, NULL); nvp != NULL;
      735 +            nvp = nvlist_next_nvpair(ifnvl, nvp)) {
      736 +                if (nvpair_value_nvlist(nvp, &nvl) != 0)
      737 +                        continue;
      738 +                if (nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
 730  739                      &aobjstr) == 0) {
 731  740                          /*
 732  741                           * For addresses, we need to relocate addrprops from the
 733  742                           * nvlist `ifnvl'.
 734  743                           */
 735  744                          if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR) ||
 736  745                              nvlist_exists(nvl, IPADM_NVP_IPV6ADDR) ||
 737  746                              nvlist_exists(nvl, IPADM_NVP_DHCP)) {
 738  747                                  status = i_ipadm_merge_addrprops_from_nvl(ifnvl,
 739  748                                      nvl, aobjstr);
      749 +
 740  750                                  if (status != IPADM_SUCCESS)
 741  751                                          continue;
 742  752                          }
 743  753                          status = i_ipadm_init_addrobj(iph, nvl);
      754 +
 744  755                          /*
 745  756                           * If this address is in use on some other interface,
 746  757                           * we want to record an error to be returned as
 747  758                           * a soft error and continue processing the rest of
 748  759                           * the addresses.
 749  760                           */
 750  761                          if (status == IPADM_ADDR_NOTAVAIL) {
 751  762                                  ret_status = IPADM_ALL_ADDRS_NOT_ENABLED;
 752  763                                  status = IPADM_SUCCESS;
 753  764                          }
 754      -                } else {
 755      -                        assert(nvlist_exists(nvl, IPADM_NVP_PROTONAME));
      765 +                } else if (nvlist_exists(nvl, IPADM_NVP_PROTONAME) == B_TRUE) {
 756  766                          status = i_ipadm_init_ifprop(iph, nvl);
 757  767                  }
 758  768                  if (status != IPADM_SUCCESS)
 759  769                          return (status);
 760  770          }
 761      -
 762      -        if (is_ngz && af != AF_UNSPEC)
      771 +        if (move_to_group) {
      772 +                (void) ipadm_add_ipmp_member(iph, gifname, newifname,
      773 +                    IPADM_OPT_ACTIVE);
      774 +        }
      775 +        if (init_from_gz)
 763  776                  ret_status = ipadm_init_net_from_gz(iph, newifname, NULL);
 764  777          return (ret_status);
 765  778  }
 766  779  
 767  780  /*
 768  781   * Retrieves the persistent configuration for the given interface(s) in `ifs'
 769  782   * by contacting the daemon and dumps the information in `allifs'.
 770  783   */
 771  784  ipadm_status_t
 772  785  i_ipadm_init_ifs(ipadm_handle_t iph, const char *ifs, nvlist_t **allifs)
↓ open down ↓ 179 lines elided ↑ open up ↑
 952  965                  }
 953  966                  /* munmap() the door buffer */
 954  967                  (void) munmap(darg.rbuf, darg.rsize);
 955  968          } else {
 956  969                  if (darg.rsize != rsize)
 957  970                          err = EBADE;
 958  971          }
 959  972          return (err);
 960  973  }
 961  974  
      975 +/*
      976 + * A helper that is used by i_ipadm_get_db_addr and i_ipadm_get_db_if
      977 + * to do a door_call to ipmgmtd, that should return persistent information
      978 + * about interfaces or/and addresses from ipadm DB
      979 + */
      980 +ipadm_status_t
      981 +i_ipadm_call_ipmgmtd(ipadm_handle_t iph, void *garg, size_t garg_size,
      982 +    nvlist_t **onvl)
      983 +{
      984 +        ipmgmt_get_rval_t       *rvalp;
      985 +        int                     err;
      986 +        size_t                  nvlsize;
      987 +        char                    *nvlbuf;
      988 +
      989 +        rvalp = malloc(sizeof (ipmgmt_get_rval_t));
      990 +        err = ipadm_door_call(iph, garg, garg_size, (void **)&rvalp,
      991 +            sizeof (*rvalp), B_TRUE);
      992 +        if (err == 0) {
      993 +                nvlsize = rvalp->ir_nvlsize;
      994 +                nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t);
      995 +                err = nvlist_unpack(nvlbuf, nvlsize, onvl, NV_ENCODE_NATIVE);
      996 +        }
      997 +        free(rvalp);
      998 +
      999 +        return (ipadm_errno2status(err));
     1000 +}
     1001 +
 962 1002  /*
 963 1003   * ipadm_is_nil_hostname() : Determine if the `hostname' is nil: i.e.,
 964 1004   *                      NULL, empty, or a single space (e.g., as returned by
 965 1005   *                      domainname(1M)/sysinfo).
 966 1006   *
 967 1007   *   input: const char *: the hostname to inspect;
 968 1008   *  output: boolean_t: B_TRUE if `hostname' is not NULL satisfies the
 969 1009   *                      criteria above; otherwise, B_FALSE;
 970 1010   */
 971 1011  
↓ open down ↓ 66 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX