Print this page
Commit 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 2014 Nexenta Systems, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Contains DB walker functions, which are of type `db_wfunc_t';
  28   29   *
  29   30   * typedef boolean_t db_wfunc_t(void *cbarg, nvlist_t *db_nvl, char *buf,
  30   31   *                              size_t bufsize, int *errp);
  31   32   *
  32   33   * ipadm_rw_db() walks through the data store, one line at a time and calls
  33   34   * these call back functions with:
↓ open down ↓ 36 lines elided ↑ open up ↑
  70   71   * flag used by ipmgmt_persist_aobjmap() to indicate address type is
  71   72   * IPADM_ADDR_IPV6_ADDRCONF.
  72   73   */
  73   74  #define IPMGMT_ATYPE_V6ACONF    0x1
  74   75  
  75   76  extern pthread_rwlock_t ipmgmt_dbconf_lock;
  76   77  
  77   78  /* signifies whether volatile copy of data store is in use */
  78   79  static boolean_t ipmgmt_rdonly_root = B_FALSE;
  79   80  
       81 +typedef int ipmgmt_if_updater_func_t(nvlist_t *, nvpair_t *, uint_t);
       82 +
       83 +static ipmgmt_if_updater_func_t ipmgmt_if_family_updater;
       84 +static ipmgmt_if_updater_func_t ipmgmt_if_groupmembers_updater;
       85 +
       86 +static int ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl);
       87 +
       88 +typedef struct {
       89 +        const char      *name;
       90 +        ipmgmt_if_updater_func_t        *func;
       91 +} ipmgmt_if_updater_ent_t;
       92 +
       93 +static ipmgmt_if_updater_ent_t ipmgmt_if_updater_ent[] = {
       94 +        {IPADM_NVP_FAMILIES, ipmgmt_if_family_updater},
       95 +        {IPADM_NVP_MIFNAMES, ipmgmt_if_groupmembers_updater},
       96 +        {NULL, NULL}
       97 +};
       98 +
       99 +static ipmgmt_if_updater_ent_t *
      100 +ipmgmt_find_if_field_updater(const char *field_name)
      101 +{
      102 +        int i;
      103 +
      104 +        for (i = 0; ipmgmt_if_updater_ent[i].name != NULL; i++) {
      105 +                if (strcmp(field_name, ipmgmt_if_updater_ent[i].name) == 0) {
      106 +                        break;
      107 +                }
      108 +        }
      109 +
      110 +        return (&ipmgmt_if_updater_ent[i]);
      111 +}
      112 +
      113 +static int
      114 +ipmgmt_if_groupmembers_updater(nvlist_t *db_nvl, nvpair_t *member_nvp,
      115 +        uint_t flags)
      116 +{
      117 +        char    **members;
      118 +        char    *member;
      119 +        char    *out_memebers[256];
      120 +        uint_t  nelem = 0, cnt = 0;
      121 +        int     err;
      122 +
      123 +        if ((err = nvpair_value_string(member_nvp, &member)) != 0)
      124 +                return (err);
      125 +
      126 +        err = nvlist_lookup_string_array(db_nvl, IPADM_NVP_MIFNAMES,
      127 +            &members, &nelem);
      128 +
      129 +        if (err != 0 && (flags & IPMGMT_REMOVE))
      130 +                return (ENOENT);
      131 +
      132 +        while (nelem--) {
      133 +                if ((flags & IPMGMT_REMOVE) &&
      134 +                    (strcmp(member, members[nelem]) == 0))
      135 +                        continue;
      136 +
      137 +                if ((out_memebers[cnt] = strdup(members[nelem])) == NULL) {
      138 +                        err = ENOMEM;
      139 +                        goto fail;
      140 +                }
      141 +
      142 +                cnt++;
      143 +        }
      144 +
      145 +        if (flags & IPMGMT_APPEND) {
      146 +                if ((out_memebers[cnt] = strdup(member)) == NULL) {
      147 +                        err = ENOMEM;
      148 +                        goto fail;
      149 +                }
      150 +                cnt++;
      151 +        }
      152 +
      153 +        if (cnt == 0) {
      154 +                err = nvlist_remove(db_nvl, IPADM_NVP_MIFNAMES,
      155 +                    DATA_TYPE_STRING_ARRAY);
      156 +        } else {
      157 +                err = nvlist_add_string_array(db_nvl, IPADM_NVP_MIFNAMES,
      158 +                    out_memebers, cnt);
      159 +        }
      160 +
      161 +fail:
      162 +        while (cnt--)
      163 +                free(out_memebers[cnt]);
      164 +
      165 +        return (err);
      166 +}
      167 +
      168 +static int
      169 +ipmgmt_if_family_updater(nvlist_t *db_nvl, nvpair_t *families_nvp, uint_t flags)
      170 +{
      171 +        uint16_t *families;
      172 +        uint_t  nelem = 0;
      173 +        int     err;
      174 +
      175 +        if ((err = nvpair_value_uint16_array(families_nvp, &families,
      176 +            &nelem)) != 0)
      177 +                return (err);
      178 +
      179 +        return (ipmgmt_update_family_nvp(db_nvl, families[0], flags));
      180 +}
      181 +
      182 +int
      183 +ipmgmt_update_family_nvp(nvlist_t *nvl, sa_family_t af, uint_t flags)
      184 +{
      185 +        uint16_t        *families = NULL;
      186 +        uint16_t        out_families[2];
      187 +        uint_t  nelem = 0, cnt;
      188 +        int     err;
      189 +
      190 +        err = nvlist_lookup_uint16_array(nvl, IPADM_NVP_FAMILIES,
      191 +            &families, &nelem);
      192 +        if (err != 0 && (flags & IPMGMT_REMOVE)) {
      193 +                return (ENOENT);
      194 +        }
      195 +
      196 +        if (flags & IPMGMT_APPEND) {
      197 +                if (families != NULL) {
      198 +                        if (nelem == 2 || families[0] == af) {
      199 +                                return (EEXIST);
      200 +                        }
      201 +                        out_families[0] = families[0];
      202 +                        out_families[1] = af;
      203 +                        cnt = 2;
      204 +                } else {
      205 +                        out_families[0] = af;
      206 +                        cnt = 1;
      207 +                }
      208 +        } else {
      209 +                assert(nelem == 1 || nelem == 2);
      210 +                cnt = 0;
      211 +                while (nelem--) {
      212 +                        if (families[nelem] != af) {
      213 +                                out_families[cnt] = families[nelem];
      214 +                                cnt++;
      215 +                        }
      216 +                }
      217 +        }
      218 +
      219 +        if (cnt != 0) {
      220 +                return (nvlist_add_uint16_array(nvl, IPADM_NVP_FAMILIES,
      221 +                    out_families, cnt));
      222 +        }
      223 +        return (nvlist_remove(nvl, IPADM_NVP_FAMILIES, DATA_TYPE_UINT16_ARRAY));
      224 +}
      225 +
  80  226  /*
  81  227   * Checks if the database nvl, `db_nvl' contains and matches ALL of the passed
  82  228   * in private nvpairs `proto', `ifname' & `aobjname'.
  83  229   */
  84  230  static boolean_t
  85  231  ipmgmt_nvlist_match(nvlist_t *db_nvl, const char *proto, const char *ifname,
  86  232      const char *aobjname)
  87  233  {
  88  234          char            *db_proto = NULL, *db_ifname = NULL;
  89  235          char            *db_aobjname = NULL;
↓ open down ↓ 225 lines elided ↑ open up ↑
 315  461   * found, when one of the following occurs first.
 316  462   * - the input aobjname matches the db aobjname. Return the db address.
 317  463   * - the input interface matches the db interface. Return all the
 318  464   *   matching db lines with addresses.
 319  465   */
 320  466  /* ARGSUSED */
 321  467  boolean_t
 322  468  ipmgmt_db_getaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 323  469      int *errp)
 324  470  {
 325      -        ipmgmt_getaddr_cbarg_t  *cbarg = arg;
      471 +        ipmgmt_get_cbarg_t      *cbarg = arg;
 326  472          char            *db_aobjname = NULL;
 327  473          char            *db_ifname = NULL;
 328  474          nvlist_t        *db_addr = NULL;
 329  475          char            name[IPMGMT_STRSIZE];
 330  476          nvpair_t        *nvp;
 331  477          boolean_t       add_nvl = B_FALSE;
 332  478  
 333  479          /* Parse db nvlist */
 334  480          for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL;
 335  481              nvp = nvlist_next_nvpair(db_nvl, nvp)) {
↓ open down ↓ 205 lines elided ↑ open up ↑
 541  687          if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
 542  688                  /* buffer overflow */
 543  689                  *errp = ENOBUFS;
 544  690          }
 545  691  
 546  692          /* we updated the DB entry, so do not continue */
 547  693          return (B_FALSE);
 548  694  }
 549  695  
 550  696  /*
 551      - * For the given `cbarg->cb_ifname' interface, retrieves any persistent
 552      - * interface information (used in 'ipadm show-if')
      697 + * This function is used to update a DB line that describes
      698 + * an interface, its family and group interface
      699 + *
 553  700   */
 554      -/* ARGSUSED */
 555  701  boolean_t
 556      -ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 557      -    int *errp)
      702 +ipmgmt_db_update_if(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
      703 +                int *errp)
 558  704  {
 559      -        ipmgmt_getif_cbarg_t    *cbarg = arg;
 560      -        char                    *ifname = cbarg->cb_ifname;
 561      -        char                    *intf = NULL;
 562      -        ipadm_if_info_t         *ifp = NULL;
 563      -        sa_family_t             af;
 564      -        char                    *afstr;
      705 +        ipadm_dbwrite_cbarg_t   *cb = arg;
      706 +        nvlist_t        *in_nvl = cb->dbw_nvl;
      707 +        uint_t  flags = cb->dbw_flags;
      708 +        nvpair_t        *nvp;
      709 +        char    *name;
      710 +        ipmgmt_if_updater_ent_t *updater;
      711 +        char    *member = NULL;
      712 +        char    *gifname = NULL;
      713 +        char    *db_line_if_name;
 565  714  
      715 +
 566  716          *errp = 0;
 567      -        if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) != 0 ||
 568      -            nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &intf) != 0 ||
 569      -            (ifname[0] != '\0' && strcmp(ifname, intf) != 0)) {
      717 +
      718 +        /* Only one flag */
      719 +        if ((flags & (IPMGMT_APPEND | IPMGMT_REMOVE)) == 0 ||
      720 +            ((flags & IPMGMT_APPEND) && (flags & IPMGMT_REMOVE))) {
      721 +                *errp = EINVAL;
      722 +                return (B_FALSE);
      723 +        }
      724 +
      725 +        if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES))
 570  726                  return (B_TRUE);
      727 +
      728 +        if (nvlist_lookup_string(db_nvl,
      729 +            IPADM_NVP_IFNAME, &db_line_if_name) == 0 &&
      730 +            nvlist_lookup_string(in_nvl, IPADM_NVP_GIFNAME, &gifname) == 0 &&
      731 +            nvlist_lookup_string(in_nvl, IPADM_NVP_MIFNAMES, &member) == 0 &&
      732 +            strcmp(db_line_if_name, member) == 0) {
      733 +                if (flags & IPMGMT_APPEND) {
      734 +                        if ((*errp = nvlist_add_string(db_nvl,
      735 +                            IPADM_NVP_GIFNAME, gifname)) != 0)
      736 +                                return (B_FALSE);
      737 +                } else {
      738 +                        if ((*errp = nvlist_remove(db_nvl, IPADM_NVP_GIFNAME,
      739 +                            DATA_TYPE_STRING)) != 0)
      740 +                                return (B_FALSE);
      741 +                }
      742 +                cb->dbw_flags &= ~IPMGMT_UPDATE_IPMP;
      743 +                goto done;
 571  744          }
 572      -        af = atoi(afstr);
 573      -        for (ifp = cbarg->cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next) {
 574      -                if (strcmp(ifp->ifi_name, intf) == 0)
 575      -                        break;
      745 +
      746 +        if (!ipmgmt_nvlist_intersects(db_nvl, in_nvl))
      747 +                return (B_TRUE);
      748 +
      749 +
      750 +        for (nvp = nvlist_next_nvpair(in_nvl, NULL); nvp != NULL;
      751 +            nvp = nvlist_next_nvpair(in_nvl, nvp)) {
      752 +
      753 +                name = nvpair_name(nvp);
      754 +                if (strcmp(name, IPADM_NVP_FAMILIES) != 0 &&
      755 +                    strcmp(name, IPADM_NVP_MIFNAMES) != 0)
      756 +                        continue;
      757 +
      758 +                updater = ipmgmt_find_if_field_updater(name);
      759 +                assert(updater != NULL);
      760 +                *errp = (*updater->func)(db_nvl, nvp, flags);
      761 +                if (*errp != 0)
      762 +                        return (B_FALSE);
 576  763          }
 577      -        if (ifp == NULL) {
 578      -                ipadm_if_info_t *new;
 579  764  
 580      -                if ((new = calloc(1, sizeof (*new))) == NULL) {
 581      -                        *errp = ENOMEM;
 582      -                        return (B_FALSE); /* don't continue the walk */
 583      -                }
 584      -                new->ifi_next = cbarg->cb_ifinfo;
 585      -                cbarg->cb_ifinfo = new;
 586      -                ifp = new;
 587      -                (void) strlcpy(ifp->ifi_name, intf, sizeof (ifp->ifi_name));
      765 +        cb->dbw_flags &= ~IPMGMT_UPDATE_IF;
      766 +
      767 +done:
      768 +        (void) memset(buf, 0, buflen);
      769 +        if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
      770 +                *errp = ENOBUFS;
      771 +                return (B_FALSE);
 588  772          }
 589  773  
 590      -        if (af == AF_INET) {
 591      -                ifp->ifi_pflags |= IFIF_IPV4;
 592      -        } else {
 593      -                assert(af == AF_INET6);
 594      -                ifp->ifi_pflags |= IFIF_IPV6;
      774 +        /* we finished all operations ???, so do not continue */
      775 +        if ((cb->dbw_flags & (IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP)) == 0)
      776 +                return (B_FALSE);
      777 +
      778 +        return (B_TRUE);
      779 +}
      780 +
      781 +/*
      782 + * For the given `cbarg->cb_ifname' interface retrieves
      783 + * the nvlist that represents the persistent interface information
      784 + * The nvlist contains:
      785 + *      IPADM_NVP_IFNAME
      786 + *      IPADM_NVP_FAMILIES
      787 + *      IPADM_NVP_IF_CLASS
      788 + *
      789 + * (used in 'ipadm show-if')
      790 + */
      791 +/* ARGSUSED */
      792 +boolean_t
      793 +ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
      794 +    int *errp)
      795 +{
      796 +        ipmgmt_get_cbarg_t      *cbarg = arg;
      797 +        char    *ifname = cbarg->cb_ifname;
      798 +        nvpair_t        *nvp;
      799 +        char    *db_ifname = NULL;
      800 +        uint16_t        *db_families = NULL;
      801 +        uint_t  nelem = 0;
      802 +
      803 +        /* Parse db nvlist */
      804 +        for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL;
      805 +            nvp = nvlist_next_nvpair(db_nvl, nvp)) {
      806 +
      807 +                if (strcmp(nvpair_name(nvp), IPADM_NVP_IFNAME) == 0)
      808 +                        (void) nvpair_value_string(nvp, &db_ifname);
      809 +                else if (strcmp(nvpair_name(nvp), IPADM_NVP_FAMILIES) == 0)
      810 +                        (void) nvpair_value_uint16_array(nvp,
      811 +                            &db_families, &nelem);
 595  812          }
 596  813  
 597      -        /* Terminate the walk if we found both v4 and v6 interfaces. */
 598      -        if (ifname[0] != '\0' && (ifp->ifi_pflags & IFIF_IPV4) &&
 599      -            (ifp->ifi_pflags & IFIF_IPV6))
      814 +        if (db_ifname == NULL || db_families == NULL)
      815 +                return (B_TRUE);
      816 +
      817 +        if (ifname != NULL && ifname[0] != '\0' &&
      818 +            strcmp(ifname, db_ifname) != 0)
      819 +                return (B_TRUE);
      820 +
      821 +        *errp = nvlist_add_nvlist(cbarg->cb_onvl, db_ifname, db_nvl);
      822 +        if (*errp == 0)
      823 +                cbarg->cb_ocnt++;
      824 +
      825 +        if (ifname != NULL && ifname[0] != '\0')
 600  826                  return (B_FALSE);
 601  827  
 602  828          return (B_TRUE);
 603  829  }
 604  830  
 605  831  /*
 606  832   * Deletes those entries from the database for which interface name
 607  833   * matches with the given `cbarg->cb_ifname'
 608  834   */
 609  835  /* ARGSUSED */
 610  836  boolean_t
 611  837  ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen,
 612  838      int *errp)
 613  839  {
 614  840          ipmgmt_if_cbarg_t *cbarg = arg;
 615  841          boolean_t       isv6 = (cbarg->cb_family == AF_INET6);
 616  842          char            *ifname = cbarg->cb_ifname;
 617  843          char            *modstr = NULL;
 618      -        char            *afstr;
 619  844          char            *aobjname;
 620  845          uint_t          proto;
 621  846          ipmgmt_aobjmap_t *head;
 622  847          boolean_t       aobjfound = B_FALSE;
 623  848  
 624  849          *errp = 0;
 625  850  
 626  851          if (!ipmgmt_nvlist_contains(db_nvl, NULL, ifname, NULL))
 627  852                  return (B_TRUE);
 628  853  
 629      -        if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) == 0) {
 630      -                if (atoi(afstr) == cbarg->cb_family)
      854 +        if (nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) {
      855 +
      856 +                if ((*errp = ipmgmt_update_family_nvp(db_nvl, cbarg->cb_family,
      857 +                    IPMGMT_REMOVE)) != 0) {
      858 +                        return (B_FALSE);
      859 +                }
      860 +
      861 +                if (cbarg->cb_family == AF_INET) {
      862 +                        cbarg->cb_ipv4exists = B_FALSE;
      863 +                } else {
      864 +                        assert(cbarg->cb_family == AF_INET6);
      865 +                        cbarg->cb_ipv6exists = B_FALSE;
      866 +                }
      867 +                if (!nvlist_exists(db_nvl, IPADM_NVP_FAMILIES)) {
      868 +                        cbarg->cb_ipv4exists = B_FALSE;
      869 +                        cbarg->cb_ipv6exists = B_FALSE;
 631  870                          goto delete;
      871 +                }
      872 +                /* Otherwise need to reconstruct this string */
      873 +                (void) memset(buf, 0, buflen);
      874 +                if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) {
      875 +                        /* buffer overflow */
      876 +                        *errp = ENOBUFS;
      877 +                        return (B_FALSE);
      878 +                }
 632  879                  return (B_TRUE);
 633  880          }
 634  881  
 635  882          /* Reset all the interface configurations for 'ifname' */
 636  883          if (isv6 && (nvlist_exists(db_nvl, IPADM_NVP_IPV6ADDR) ||
 637  884              nvlist_exists(db_nvl, IPADM_NVP_INTFID))) {
 638  885                  goto delete;
 639  886          }
 640  887          if (!isv6 &&
 641  888              (nvlist_exists(db_nvl, IPADM_NVP_IPV4ADDR) ||
↓ open down ↓ 35 lines elided ↑ open up ↑
 677  924                  switch (proto) {
 678  925                  case MOD_PROTO_IPV6:
 679  926                          if (isv6)
 680  927                                  goto delete;
 681  928                          break;
 682  929                  case MOD_PROTO_IPV4:
 683  930                          if (!isv6)
 684  931                                  goto delete;
 685  932                          break;
 686  933                  case MOD_PROTO_IP:
 687      -                        /* this should never be the case, today */
 688      -                        assert(0);
      934 +                if (!cbarg->cb_ipv4exists && !cbarg->cb_ipv6exists)
      935 +                goto delete;
 689  936                          break;
 690  937                  }
 691  938          }
 692  939          /* Not found a match yet. Continue processing the db */
 693  940          return (B_TRUE);
 694  941  delete:
 695  942          /* delete the line from the db */
 696  943          buf[0] = '\0';
 697  944          return (B_TRUE);
 698  945  }
↓ open down ↓ 979 lines elided ↑ open up ↑
1678 1925   * the data-store upgraded to recent version we don't have to do anything on
1679 1926   * subsequent reboots.
1680 1927   */
1681 1928  void
1682 1929  ipmgmt_update_dbver(scf_resources_t *res)
1683 1930  {
1684 1931          int64_t         version = IPADM_DB_VERSION;
1685 1932  
1686 1933          (void) ipmgmt_set_scfprop(res, IPMGMTD_APP_PG,
1687 1934              IPMGMTD_PROP_DBVER, &version, SCF_TYPE_INTEGER);
     1935 +}
     1936 +
     1937 +/*
     1938 + * Return TRUE if `ifname' has persistent configuration for the `af' address
     1939 + * family in the datastore.
     1940 + * It is possible to call the function with af == AF_UNSPEC, so in this case
     1941 + * the function returns TRUE if either AF_INET or AF_INET6 interface exists
     1942 + */
     1943 +boolean_t
     1944 +ipmgmt_persist_if_exists(const char *ifname, sa_family_t af)
     1945 +{
     1946 +        boolean_t exists = B_FALSE;
     1947 +        nvlist_t    *if_info_nvl;
     1948 +        uint16_t    *families = NULL;
     1949 +        sa_family_t af_db;
     1950 +        uint_t  nelem = 0;
     1951 +
     1952 +        if (ipmgmt_get_ifinfo_nvl(ifname, &if_info_nvl) != 0)
     1953 +                goto done;
     1954 +
     1955 +        if (nvlist_lookup_uint16_array(if_info_nvl, IPADM_NVP_FAMILIES,
     1956 +            &families, &nelem) != 0)
     1957 +                goto done;
     1958 +
     1959 +        while (nelem--) {
     1960 +                af_db = families[nelem];
     1961 +                if (af_db == af || (af == AF_UNSPEC &&
     1962 +                    (af_db == AF_INET || af_db == AF_INET6))) {
     1963 +                        exists = B_TRUE;
     1964 +                        break;
     1965 +                }
     1966 +        }
     1967 +
     1968 +done:
     1969 +        if (if_info_nvl != NULL)
     1970 +                nvlist_free(if_info_nvl);
     1971 +
     1972 +        return (exists);
     1973 +}
     1974 +
     1975 +/*
     1976 + * Retrieves the membership information for the requested mif_name
     1977 + * if mif_name is a memeber of a IPMP group, then gif_name will contain
     1978 + * the name of IPMP group interface, otherwise the variable will be empty
     1979 + */
     1980 +void
     1981 +ipmgmt_get_group_interface(const char *mif_name, char *gif_name, size_t size)
     1982 +{
     1983 +        char    *gif_name_from_nvl;
     1984 +        nvlist_t        *if_info_nvl;
     1985 +
     1986 +        gif_name[0] = '\0';
     1987 +
     1988 +        if (ipmgmt_get_ifinfo_nvl(mif_name, &if_info_nvl) != 0)
     1989 +                goto done;
     1990 +
     1991 +        if (nvlist_lookup_string(if_info_nvl, IPADM_NVP_GIFNAME,
     1992 +            &gif_name_from_nvl) != 0)
     1993 +                goto done;
     1994 +
     1995 +        (void) strlcpy(gif_name, gif_name_from_nvl, size);
     1996 +
     1997 +done:
     1998 +        if (if_info_nvl != NULL)
     1999 +                nvlist_free(if_info_nvl);
     2000 +}
     2001 +
     2002 +static int
     2003 +ipmgmt_get_ifinfo_nvl(const char *ifname, nvlist_t **if_info_nvl)
     2004 +{
     2005 +        ipmgmt_get_cbarg_t cbarg;
     2006 +        nvpair_t    *nvp;
     2007 +        nvlist_t    *nvl;
     2008 +        int     err;
     2009 +
     2010 +        cbarg.cb_ifname = NULL;
     2011 +        cbarg.cb_aobjname = NULL;
     2012 +        cbarg.cb_ocnt = 0;
     2013 +
     2014 +        if ((err = nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0)) != 0)
     2015 +                goto done;
     2016 +
     2017 +        err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
     2018 +        if (err == ENOENT && cbarg.cb_ocnt > 0)
     2019 +                err = 0;
     2020 +
     2021 +        if (err != 0)
     2022 +                goto done;
     2023 +
     2024 +        for (nvp = nvlist_next_nvpair(cbarg.cb_onvl, NULL); nvp != NULL;
     2025 +            nvp = nvlist_next_nvpair(cbarg.cb_onvl, nvp)) {
     2026 +
     2027 +                if (strcmp(nvpair_name(nvp), ifname) != 0)
     2028 +                        continue;
     2029 +
     2030 +                if ((err = nvpair_value_nvlist(nvp, &nvl)) != 0 ||
     2031 +                    (err = nvlist_dup(nvl, if_info_nvl, NV_UNIQUE_NAME)) != 0)
     2032 +                        *if_info_nvl = NULL;
     2033 +
     2034 +                break;
     2035 +        }
     2036 +
     2037 +done:
     2038 +        nvlist_free(cbarg.cb_onvl);
     2039 +
     2040 +        return (err);
1688 2041  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX