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-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/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.c
          +++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_persist.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 2016 Nexenta Systems, Inc.
  24   25   * Copyright 2016 Argo Technologie SA.
  25   26   * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
  26   27   */
  27   28  
  28   29  /*
  29   30   * Contains DB walker functions, which are of type `db_wfunc_t';
  30   31   *
  31   32   * typedef boolean_t db_wfunc_t(void *cbarg, nvlist_t *db_nvl, char *buf,
  32   33   *                              size_t bufsize, int *errp);
  33   34   *
↓ open down ↓ 38 lines elided ↑ open up ↑
  72   73   * flag used by ipmgmt_persist_aobjmap() to indicate address type is
  73   74   * IPADM_ADDR_IPV6_ADDRCONF.
  74   75   */
  75   76  #define IPMGMT_ATYPE_V6ACONF    0x1
  76   77  
  77   78  extern pthread_rwlock_t ipmgmt_dbconf_lock;
  78   79  
  79   80  /* signifies whether volatile copy of data store is in use */
  80   81  static boolean_t ipmgmt_rdonly_root = B_FALSE;
  81   82  
       83 +typedef int ipmgmt_if_updater_func_t(nvlist_t *, nvpair_t *, uint_t);
       84 +
       85 +static ipmgmt_if_updater_func_t ipmgmt_if_family_updater;
       86 +static ipmgmt_if_updater_func_t ipmgmt_if_groupmembers_updater;
       87 +
       88 +static int ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl);
       89 +
       90 +typedef struct {
       91 +        const char      *name;
       92 +        ipmgmt_if_updater_func_t        *func;
       93 +} ipmgmt_if_updater_ent_t;
       94 +
       95 +static ipmgmt_if_updater_ent_t ipmgmt_if_updater_ent[] = {
       96 +        {IPADM_NVP_FAMILIES, ipmgmt_if_family_updater},
       97 +        {IPADM_NVP_MIFNAMES, ipmgmt_if_groupmembers_updater},
       98 +        {NULL, NULL}
       99 +};
      100 +
      101 +static ipmgmt_if_updater_ent_t *
      102 +ipmgmt_find_if_field_updater(const char *field_name)
      103 +{
      104 +        int i;
      105 +
      106 +        for (i = 0; ipmgmt_if_updater_ent[i].name != NULL; i++) {
      107 +                if (strcmp(field_name, ipmgmt_if_updater_ent[i].name) == 0) {
      108 +                        break;
      109 +                }
      110 +        }
      111 +
      112 +        return (&ipmgmt_if_updater_ent[i]);
      113 +}
      114 +
      115 +static int
      116 +ipmgmt_if_groupmembers_updater(nvlist_t *db_nvl, nvpair_t *member_nvp,
      117 +    uint_t flags)
      118 +{
      119 +        char    **members;
      120 +        char    *member;
      121 +        char    *out_members[256];
      122 +        uint_t  nelem = 0, cnt = 0;
      123 +        int     err;
      124 +
      125 +        if ((err = nvpair_value_string(member_nvp, &member)) != 0)
      126 +                return (err);
      127 +
      128 +        err = nvlist_lookup_string_array(db_nvl, IPADM_NVP_MIFNAMES,
      129 +            &members, &nelem);
      130 +
      131 +        if (err != 0 && (flags & IPMGMT_REMOVE))
      132 +                return (ENOENT);
      133 +
      134 +        while (nelem-- > 0) {
      135 +                if ((flags & IPMGMT_REMOVE) &&
      136 +                    (strcmp(member, members[nelem]) == 0))
      137 +                        continue;
      138 +
      139 +                if ((out_members[cnt] = strdup(members[nelem])) == NULL) {
      140 +                        err = ENOMEM;
      141 +                        goto fail;
      142 +                }
      143 +
      144 +                cnt++;
      145 +        }
      146 +
      147 +        if (flags & IPMGMT_APPEND) {
      148 +                if ((out_members[cnt] = strdup(member)) == NULL) {
      149 +                        err = ENOMEM;
      150 +                        goto fail;
      151 +                }
      152 +                cnt++;
      153 +        }
      154 +
      155 +        if (cnt == 0) {
      156 +                err = nvlist_remove(db_nvl, IPADM_NVP_MIFNAMES,
      157 +                    DATA_TYPE_STRING_ARRAY);
      158 +        } else {
      159 +                err = nvlist_add_string_array(db_nvl, IPADM_NVP_MIFNAMES,
      160 +                    out_members, cnt);
      161 +        }
      162 +
      163 +fail:
      164 +        while (cnt--)
      165 +                free(out_members[cnt]);
      166 +
      167 +        return (err);
      168 +}
      169 +
      170 +static int
      171 +ipmgmt_if_family_updater(nvlist_t *db_nvl, nvpair_t *families_nvp, uint_t flags)
      172 +{
      173 +        uint16_t *families;
      174 +        uint_t  nelem = 0;
      175 +        int     err;
      176 +
      177 +        if ((err = nvpair_value_uint16_array(families_nvp, &families,
      178 +            &nelem)) != 0)
      179 +                return (err);
      180 +
      181 +        return (ipmgmt_update_family_nvp(db_nvl, families[0], flags));
      182 +}
      183 +
      184 +int
      185 +ipmgmt_update_family_nvp(nvlist_t *nvl, sa_family_t af, uint_t flags)
      186 +{
      187 +        uint16_t        *families = NULL;
      188 +        uint16_t        out_families[2];
      189 +        uint_t  nelem = 0, cnt;
      190 +        int     err;
      191 +
      192 +        err = nvlist_lookup_uint16_array(nvl, IPADM_NVP_FAMILIES,
      193 +            &families, &nelem);
      194 +        if (err != 0 && (flags & IPMGMT_REMOVE)) {
      195 +                return (ENOENT);
      196 +        }
      197 +
      198 +        if (flags & IPMGMT_APPEND) {
      199 +                if (families != NULL) {
      200 +                        if (nelem == 2 || families[0] == af) {
      201 +                                return (EEXIST);
      202 +                        }
      203 +                        out_families[0] = families[0];
      204 +                        out_families[1] = af;
      205 +                        cnt = 2;
      206 +                } else {
      207 +                        out_families[0] = af;
      208 +                        cnt = 1;
      209 +                }
      210 +        } else {
      211 +                assert(nelem == 1 || nelem == 2);
      212 +                cnt = 0;
      213 +                while (nelem-- > 0) {
      214 +                        if (families[nelem] != af) {
      215 +                                out_families[cnt] = families[nelem];
      216 +                                cnt++;
      217 +                        }
      218 +                }
      219 +        }
      220 +
      221 +        if (cnt != 0) {
      222 +                return (nvlist_add_uint16_array(nvl, IPADM_NVP_FAMILIES,
      223 +                    out_families, cnt));
      224 +        }
      225 +        return (nvlist_remove(nvl, IPADM_NVP_FAMILIES, DATA_TYPE_UINT16_ARRAY));
      226 +}
      227 +
  82  228  /*
  83  229   * Checks if the database nvl, `db_nvl' contains and matches ALL of the passed
  84  230   * in private nvpairs `proto', `ifname' & `aobjname'.
  85  231   */
  86  232  static boolean_t
  87  233  ipmgmt_nvlist_match(nvlist_t *db_nvl, const char *proto, const char *ifname,
  88  234      const char *aobjname)
  89  235  {
  90  236          char            *db_proto = NULL, *db_ifname = NULL;
  91  237          char            *db_aobjname = NULL;
↓ open down ↓ 228 lines elided ↑ open up ↑
 320  466   * found, when one of the following occurs first.
 321  467   * - the input aobjname matches the db aobjname. Return the db address.
 322  468   * - the input interface matches the db interface. Return all the
 323  469   *   matching db lines with addresses.
 324  470   */
 325  471  /* ARGSUSED */
 326  472  boolean_t
 327  473  ipmgmt_db_getaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 328  474      int *errp)
 329  475  {
 330      -        ipmgmt_getaddr_cbarg_t  *cbarg = arg;
      476 +        ipmgmt_get_cbarg_t      *cbarg = arg;
 331  477          char            *db_aobjname = NULL;
 332  478          char            *db_ifname = NULL;
 333  479          nvlist_t        *db_addr = NULL;
 334  480          char            name[IPMGMT_STRSIZE];
 335  481          nvpair_t        *nvp;
 336  482          boolean_t       add_nvl = B_FALSE;
 337  483  
 338  484          /* Parse db nvlist */
 339  485          for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL;
 340  486              nvp = nvlist_next_nvpair(db_nvl, nvp)) {
↓ open down ↓ 205 lines elided ↑ open up ↑
 546  692          if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
 547  693                  /* buffer overflow */
 548  694                  *errp = ENOBUFS;
 549  695          }
 550  696  
 551  697          /* we updated the DB entry, so do not continue */
 552  698          return (B_FALSE);
 553  699  }
 554  700  
 555  701  /*
 556      - * For the given `cbarg->cb_ifname' interface, retrieves any persistent
 557      - * interface information (used in 'ipadm show-if')
      702 + * This function is used to update a DB line that describes
      703 + * an interface, its family and group interface
      704 + *
 558  705   */
 559      -/* ARGSUSED */
 560  706  boolean_t
 561      -ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
      707 +ipmgmt_db_update_if(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 562  708      int *errp)
 563  709  {
 564      -        ipmgmt_getif_cbarg_t    *cbarg = arg;
 565      -        char                    *ifname = cbarg->cb_ifname;
 566      -        char                    *intf = NULL;
 567      -        ipadm_if_info_t         *ifp = NULL;
 568      -        sa_family_t             af;
 569      -        char                    *afstr;
      710 +        ipadm_dbwrite_cbarg_t *cb = arg;
      711 +        ipmgmt_if_updater_ent_t *updater;
      712 +        nvlist_t        *in_nvl = cb->dbw_nvl;
      713 +        uint_t          flags = cb->dbw_flags;
      714 +        nvpair_t        *nvp;
      715 +        char            *name;
      716 +        char            *db_ifname;
      717 +        char            *gifname = NULL;
      718 +        char            *mifname = NULL;
 570  719  
 571  720          *errp = 0;
 572      -        if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) != 0 ||
 573      -            nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &intf) != 0 ||
 574      -            (ifname[0] != '\0' && strcmp(ifname, intf) != 0)) {
      721 +
      722 +        /* Only one flag */
      723 +        if ((flags & (IPMGMT_APPEND | IPMGMT_REMOVE)) == 0 ||
      724 +            ((flags & IPMGMT_APPEND) && (flags & IPMGMT_REMOVE))) {
      725 +                *errp = EINVAL;
      726 +                return (B_FALSE);
      727 +        }
      728 +
      729 +        if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES))
 575  730                  return (B_TRUE);
      731 +
      732 +        if (nvlist_exists(db_nvl, IPADM_NVP_IFCLASS) &&
      733 +            nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &db_ifname) == 0 &&
      734 +            nvlist_lookup_string(in_nvl, IPADM_NVP_GIFNAME, &gifname) == 0 &&
      735 +            nvlist_lookup_string(in_nvl, IPADM_NVP_MIFNAMES, &mifname) == 0 &&
      736 +            strcmp(db_ifname, mifname) == 0) {
      737 +                if (flags & IPMGMT_APPEND) {
      738 +                        if ((*errp = nvlist_add_string(db_nvl,
      739 +                            IPADM_NVP_GIFNAME, gifname)) != 0)
      740 +                                return (B_FALSE);
      741 +                } else {
      742 +                        if ((*errp = nvlist_remove(db_nvl, IPADM_NVP_GIFNAME,
      743 +                            DATA_TYPE_STRING)) != 0)
      744 +                                return (B_FALSE);
      745 +                }
      746 +                cb->dbw_flags &= ~IPMGMT_UPDATE_IPMP;
      747 +                goto done;
 576  748          }
 577      -        af = atoi(afstr);
 578      -        for (ifp = cbarg->cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next) {
 579      -                if (strcmp(ifp->ifi_name, intf) == 0)
 580      -                        break;
      749 +
      750 +        if (!ipmgmt_nvlist_intersects(db_nvl, in_nvl))
      751 +                return (B_TRUE);
      752 +
      753 +        for (nvp = nvlist_next_nvpair(in_nvl, NULL); nvp != NULL;
      754 +            nvp = nvlist_next_nvpair(in_nvl, nvp)) {
      755 +                name = nvpair_name(nvp);
      756 +                if (strcmp(name, IPADM_NVP_FAMILIES) != 0 &&
      757 +                    strcmp(name, IPADM_NVP_MIFNAMES) != 0)
      758 +                        continue;
      759 +
      760 +                updater = ipmgmt_find_if_field_updater(name);
      761 +                assert(updater != NULL);
      762 +                *errp = (*updater->func)(db_nvl, nvp, flags);
      763 +                if (*errp != 0)
      764 +                        return (B_FALSE);
 581  765          }
 582      -        if (ifp == NULL) {
 583      -                ipadm_if_info_t *new;
 584  766  
 585      -                if ((new = calloc(1, sizeof (*new))) == NULL) {
 586      -                        *errp = ENOMEM;
 587      -                        return (B_FALSE); /* don't continue the walk */
 588      -                }
 589      -                new->ifi_next = cbarg->cb_ifinfo;
 590      -                cbarg->cb_ifinfo = new;
 591      -                ifp = new;
 592      -                (void) strlcpy(ifp->ifi_name, intf, sizeof (ifp->ifi_name));
      767 +        cb->dbw_flags &= ~IPMGMT_UPDATE_IF;
      768 +
      769 +done:
      770 +        (void) memset(buf, 0, buflen);
      771 +        if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
      772 +                *errp = ENOBUFS;
      773 +                return (B_FALSE);
 593  774          }
 594  775  
 595      -        if (af == AF_INET) {
 596      -                ifp->ifi_pflags |= IFIF_IPV4;
 597      -        } else {
 598      -                assert(af == AF_INET6);
 599      -                ifp->ifi_pflags |= IFIF_IPV6;
      776 +        /* we finished all operations, so do not continue */
      777 +        if ((cb->dbw_flags & (IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP)) == 0)
      778 +                return (B_FALSE);
      779 +
      780 +        return (B_TRUE);
      781 +}
      782 +
      783 +/*
      784 + * For the given `cbarg->cb_ifname' interface retrieves
      785 + * the nvlist that represents the persistent interface information
      786 + * The nvlist contains:
      787 + *      IPADM_NVP_IFNAME
      788 + *      IPADM_NVP_FAMILIES
      789 + *      IPADM_NVP_IF_CLASS
      790 + *
      791 + * (used in 'ipadm show-if')
      792 + */
      793 +/* ARGSUSED */
      794 +boolean_t
      795 +ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
      796 +    int *errp)
      797 +{
      798 +        ipmgmt_get_cbarg_t *cbarg = arg;
      799 +        char            *ifname = cbarg->cb_ifname;
      800 +        nvpair_t        *nvp;
      801 +        char            *db_ifname = NULL;
      802 +        uint16_t        *db_families = NULL;
      803 +        uint_t          nelem = 0;
      804 +
      805 +        /* Parse db nvlist */
      806 +        for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL;
      807 +            nvp = nvlist_next_nvpair(db_nvl, nvp)) {
      808 +                if (strcmp(nvpair_name(nvp), IPADM_NVP_IFNAME) == 0) {
      809 +                        (void) nvpair_value_string(nvp, &db_ifname);
      810 +                } else if (strcmp(nvpair_name(nvp), IPADM_NVP_FAMILIES) == 0) {
      811 +                        (void) nvpair_value_uint16_array(nvp,
      812 +                            &db_families, &nelem);
      813 +                }
 600  814          }
 601  815  
 602      -        /* Terminate the walk if we found both v4 and v6 interfaces. */
 603      -        if (ifname[0] != '\0' && (ifp->ifi_pflags & IFIF_IPV4) &&
 604      -            (ifp->ifi_pflags & IFIF_IPV6))
      816 +        if (db_ifname == NULL || db_families == NULL)
      817 +                return (B_TRUE);
      818 +
      819 +        if (ifname != NULL && ifname[0] != '\0' &&
      820 +            strcmp(ifname, db_ifname) != 0)
      821 +                return (B_TRUE);
      822 +
      823 +        *errp = nvlist_add_nvlist(cbarg->cb_onvl, db_ifname, db_nvl);
      824 +        if (*errp == 0)
      825 +                cbarg->cb_ocnt++;
      826 +
      827 +        if (ifname != NULL && ifname[0] != '\0')
 605  828                  return (B_FALSE);
 606  829  
 607  830          return (B_TRUE);
 608  831  }
 609  832  
 610  833  /*
 611  834   * Deletes those entries from the database for which interface name
 612  835   * matches with the given `cbarg->cb_ifname'
 613  836   */
 614  837  /* ARGSUSED */
 615  838  boolean_t
 616  839  ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 617  840      int *errp)
 618  841  {
 619  842          ipmgmt_if_cbarg_t *cbarg = arg;
 620  843          boolean_t       isv6 = (cbarg->cb_family == AF_INET6);
 621  844          char            *ifname = cbarg->cb_ifname;
 622  845          char            *modstr = NULL;
 623      -        char            *afstr;
 624  846          char            *aobjname;
 625  847          uint_t          proto;
 626  848          ipmgmt_aobjmap_t *head;
 627  849          boolean_t       aobjfound = B_FALSE;
 628  850  
 629  851          *errp = 0;
 630  852  
 631  853          if (!ipmgmt_nvlist_contains(db_nvl, NULL, ifname, NULL))
 632  854                  return (B_TRUE);
 633  855  
 634      -        if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) == 0) {
 635      -                if (atoi(afstr) == cbarg->cb_family)
      856 +        if (nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) {
      857 +
      858 +                if ((*errp = ipmgmt_update_family_nvp(db_nvl, cbarg->cb_family,
      859 +                    IPMGMT_REMOVE)) != 0) {
      860 +                        return (B_FALSE);
      861 +                }
      862 +
      863 +                if (cbarg->cb_family == AF_INET) {
      864 +                        cbarg->cb_ipv4exists = B_FALSE;
      865 +                } else {
      866 +                        assert(cbarg->cb_family == AF_INET6);
      867 +                        cbarg->cb_ipv6exists = B_FALSE;
      868 +                }
      869 +                if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) {
      870 +                        cbarg->cb_ipv4exists = B_FALSE;
      871 +                        cbarg->cb_ipv6exists = B_FALSE;
 636  872                          goto delete;
      873 +                }
      874 +                /* Otherwise need to reconstruct this string */
      875 +                (void) memset(buf, 0, buflen);
      876 +                if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
      877 +                        /* buffer overflow */
      878 +                        *errp = ENOBUFS;
      879 +                        return (B_FALSE);
      880 +                }
 637  881                  return (B_TRUE);
 638  882          }
 639  883  
 640  884          /* Reset all the interface configurations for 'ifname' */
 641  885          if (isv6 && (nvlist_exists(db_nvl, IPADM_NVP_IPV6ADDR) ||
 642  886              nvlist_exists(db_nvl, IPADM_NVP_INTFID))) {
 643  887                  goto delete;
 644  888          }
 645  889          if (!isv6 &&
 646  890              (nvlist_exists(db_nvl, IPADM_NVP_IPV4ADDR) ||
↓ open down ↓ 35 lines elided ↑ open up ↑
 682  926                  switch (proto) {
 683  927                  case MOD_PROTO_IPV6:
 684  928                          if (isv6)
 685  929                                  goto delete;
 686  930                          break;
 687  931                  case MOD_PROTO_IPV4:
 688  932                          if (!isv6)
 689  933                                  goto delete;
 690  934                          break;
 691  935                  case MOD_PROTO_IP:
 692      -                        /* this should never be the case, today */
 693      -                        assert(0);
      936 +                        if (!cbarg->cb_ipv4exists && !cbarg->cb_ipv6exists)
      937 +                                goto delete;
 694  938                          break;
 695  939                  }
 696  940          }
 697  941          /* Not found a match yet. Continue processing the db */
 698  942          return (B_TRUE);
 699  943  delete:
 700  944          /* delete the line from the db */
 701  945          buf[0] = '\0';
 702  946          return (B_TRUE);
 703  947  }
↓ open down ↓ 179 lines elided ↑ open up ↑
 883 1127   * (b) ADDROBJ_DELETE: delete address object from `aobjmap'
 884 1128   * (c) ADDROBJ_LOOKUPADD: place a stub address object in `aobjmap'
 885 1129   * (d) ADDROBJ_SETLIFNUM: Sets the lifnum for an address object in `aobjmap'
 886 1130   */
 887 1131  int
 888 1132  ipmgmt_aobjmap_op(ipmgmt_aobjmap_t *nodep, uint32_t op)
 889 1133  {
 890 1134          ipmgmt_aobjmap_t        *head, *prev, *matched = NULL;
 891 1135          boolean_t               update = B_TRUE;
 892 1136          int                     err = 0;
 893      -        ipadm_db_op_t           db_op;
     1137 +        ipadm_db_op_t           db_op = IPADM_DB_READ;
 894 1138  
 895 1139          (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock);
 896 1140  
 897 1141          head = aobjmap.aobjmap_head;
 898 1142          switch (op) {
 899 1143          case ADDROBJ_ADD:
 900 1144                  /*
 901 1145                   * check for stub nodes (added by ADDROBJ_LOOKUPADD) and
 902 1146                   * update, else add the new node.
 903 1147                   */
↓ open down ↓ 455 lines elided ↑ open up ↑
1359 1603   *
1360 1604   * Walk through the DB and apply all the global module properties. We plow
1361 1605   * through the DB even if we fail to apply property.
1362 1606   */
1363 1607  /* ARGSUSED */
1364 1608  static boolean_t
1365 1609  ipmgmt_db_init(void *cbarg, nvlist_t *db_nvl, char *buf, size_t buflen,
1366 1610      int *errp)
1367 1611  {
1368 1612          ipadm_handle_t  iph = cbarg;
1369      -        nvpair_t        *nvp, *pnvp;
     1613 +        nvpair_t        *nvp, *pnvp = NULL;
1370 1614          char            *strval = NULL, *name, *mod = NULL, *pname;
1371 1615          char            tmpstr[IPMGMT_STRSIZE];
1372 1616          uint_t          proto;
1373 1617  
1374 1618          /*
1375 1619           * We could have used nvl_exists() directly, however we need several
1376 1620           * calls to it and each call traverses the list. Since this codepath
1377 1621           * is exercised during boot, let's traverse the list ourselves and do
1378 1622           * the necessary checks.
1379 1623           */
↓ open down ↓ 6 lines elided ↑ open up ↑
1386 1630                                  return (B_TRUE);
1387 1631                          else if (strcmp(name, IPADM_NVP_PROTONAME) == 0 &&
1388 1632                              nvpair_value_string(nvp, &mod) != 0)
1389 1633                                  return (B_TRUE);
1390 1634                  } else {
1391 1635                          /* possible a property */
1392 1636                          pnvp = nvp;
1393 1637                  }
1394 1638          }
1395 1639  
1396      -        /* if we are here than we found a global property */
     1640 +        /* If we are here then we have found a global property */
1397 1641          assert(mod != NULL);
1398 1642          assert(nvpair_type(pnvp) == DATA_TYPE_STRING);
1399 1643  
1400 1644          proto = ipadm_str2proto(mod);
1401 1645          name = nvpair_name(pnvp);
1402 1646          if (nvpair_value_string(pnvp, &strval) == 0) {
1403 1647                  if (strncmp(name, IPADM_PERSIST_PRIVPROP_PREFIX,
1404 1648                      strlen(IPADM_PERSIST_PRIVPROP_PREFIX)) == 0) {
1405 1649                          /* private protocol property */
1406 1650                          pname = &name[1];
↓ open down ↓ 168 lines elided ↑ open up ↑
1575 1819          numvals = scf_simple_prop_numvalues(prop);
1576 1820          if (numvals <= 0)
1577 1821                  goto ret;
1578 1822          switch (ptype) {
1579 1823          case SCF_TYPE_INTEGER:
1580 1824                  *(int64_t **)pval = scf_simple_prop_next_integer(prop);
1581 1825                  break;
1582 1826          case SCF_TYPE_ASTRING:
1583 1827                  *(char **)pval = scf_simple_prop_next_astring(prop);
1584 1828                  break;
     1829 +        default:
     1830 +                break;
1585 1831          }
1586 1832  ret:
1587 1833          scf_simple_prop_free(prop);
1588 1834          return (numvals);
1589 1835  }
1590 1836  
1591 1837  /*
1592 1838   * It stores the `pval' for given `pgname'/`pname' property group in SCF.
1593 1839   */
1594 1840  static int
↓ open down ↓ 102 lines elided ↑ open up ↑
1697 1943   * the data-store upgraded to recent version we don't have to do anything on
1698 1944   * subsequent reboots.
1699 1945   */
1700 1946  void
1701 1947  ipmgmt_update_dbver(scf_resources_t *res)
1702 1948  {
1703 1949          int64_t         version = IPADM_DB_VERSION;
1704 1950  
1705 1951          (void) ipmgmt_set_scfprop(res, IPMGMTD_APP_PG,
1706 1952              IPMGMTD_PROP_DBVER, &version, SCF_TYPE_INTEGER);
     1953 +}
     1954 +
     1955 +/*
     1956 + * Return TRUE if `ifname' has persistent configuration for the `af' address
     1957 + * family in the datastore.
     1958 + * It is possible to call the function with af == AF_UNSPEC, so in this case
     1959 + * the function returns TRUE if either AF_INET or AF_INET6 interface exists
     1960 + */
     1961 +boolean_t
     1962 +ipmgmt_persist_if_exists(const char *ifname, sa_family_t af)
     1963 +{
     1964 +        boolean_t exists = B_FALSE;
     1965 +        nvlist_t    *if_info_nvl;
     1966 +        uint16_t    *families = NULL;
     1967 +        sa_family_t af_db;
     1968 +        uint_t  nelem = 0;
     1969 +
     1970 +        if (ipmgmt_get_ifinfo_nvl(ifname, &if_info_nvl) != 0)
     1971 +                goto done;
     1972 +
     1973 +        if (nvlist_lookup_uint16_array(if_info_nvl, IPADM_NVP_FAMILIES,
     1974 +            &families, &nelem) != 0)
     1975 +                goto done;
     1976 +
     1977 +        while (nelem-- > 0) {
     1978 +                af_db = families[nelem];
     1979 +                if (af_db == af || (af == AF_UNSPEC &&
     1980 +                    (af_db == AF_INET || af_db == AF_INET6))) {
     1981 +                        exists = B_TRUE;
     1982 +                        break;
     1983 +                }
     1984 +        }
     1985 +
     1986 +done:
     1987 +        if (if_info_nvl != NULL)
     1988 +                nvlist_free(if_info_nvl);
     1989 +
     1990 +        return (exists);
     1991 +}
     1992 +
     1993 +/*
     1994 + * Retrieves the membership information for the requested mif_name
     1995 + * if mif_name is a memeber of a IPMP group, then gif_name will contain
     1996 + * the name of IPMP group interface, otherwise the variable will be empty
     1997 + */
     1998 +void
     1999 +ipmgmt_get_group_interface(const char *mif_name, char *gif_name, size_t size)
     2000 +{
     2001 +        char    *gif_name_from_nvl;
     2002 +        nvlist_t        *if_info_nvl;
     2003 +
     2004 +        gif_name[0] = '\0';
     2005 +
     2006 +        if (ipmgmt_get_ifinfo_nvl(mif_name, &if_info_nvl) != 0)
     2007 +                goto done;
     2008 +
     2009 +        if (nvlist_lookup_string(if_info_nvl, IPADM_NVP_GIFNAME,
     2010 +            &gif_name_from_nvl) != 0)
     2011 +                goto done;
     2012 +
     2013 +        (void) strlcpy(gif_name, gif_name_from_nvl, size);
     2014 +
     2015 +done:
     2016 +        if (if_info_nvl != NULL)
     2017 +                nvlist_free(if_info_nvl);
     2018 +}
     2019 +
     2020 +static int
     2021 +ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl)
     2022 +{
     2023 +        ipmgmt_get_cbarg_t cbarg;
     2024 +        nvpair_t    *nvp;
     2025 +        nvlist_t    *nvl;
     2026 +        int     err;
     2027 +
     2028 +        cbarg.cb_ifname = NULL;
     2029 +        cbarg.cb_aobjname = NULL;
     2030 +        cbarg.cb_ocnt = 0;
     2031 +
     2032 +        if ((err = nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0)) != 0)
     2033 +                goto done;
     2034 +
     2035 +        err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
     2036 +        if (err == ENOENT && cbarg.cb_ocnt > 0)
     2037 +                err = 0;
     2038 +
     2039 +        if (err != 0)
     2040 +                goto done;
     2041 +
     2042 +        for (nvp = nvlist_next_nvpair(cbarg.cb_onvl, NULL); nvp != NULL;
     2043 +            nvp = nvlist_next_nvpair(cbarg.cb_onvl, nvp)) {
     2044 +
     2045 +                if (strcmp(nvpair_name(nvp), ifname) != 0)
     2046 +                        continue;
     2047 +
     2048 +                if ((err = nvpair_value_nvlist(nvp, &nvl)) != 0 ||
     2049 +                    (err = nvlist_dup(nvl, if_info_nvl, NV_UNIQUE_NAME)) != 0)
     2050 +                        *if_info_nvl = NULL;
     2051 +
     2052 +                break;
     2053 +        }
     2054 +
     2055 +done:
     2056 +        nvlist_free(cbarg.cb_onvl);
     2057 +
     2058 +        return (err);
1707 2059  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX