diff options
Diffstat (limited to 'usr/src/lib/libipadm/common/libipadm.c')
-rw-r--r-- | usr/src/lib/libipadm/common/libipadm.c | 164 |
1 files changed, 104 insertions, 60 deletions
diff --git a/usr/src/lib/libipadm/common/libipadm.c b/usr/src/lib/libipadm/common/libipadm.c index 5d72275f34..972c45630b 100644 --- a/usr/src/lib/libipadm/common/libipadm.c +++ b/usr/src/lib/libipadm/common/libipadm.c @@ -21,8 +21,8 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016, Chris Fraire <cfraire@me.com>. + * Copyright 2021 Tintri by DDN, Inc. All rights reserved. */ #include <stdio.h> @@ -528,39 +528,6 @@ i_ipadm_is_6to4(ipadm_handle_t iph, char *ifname) } /* - * Returns B_TRUE if `ifname' represents an IPMP underlying interface. - */ -boolean_t -i_ipadm_is_under_ipmp(ipadm_handle_t iph, const char *ifname) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); - if (ioctl(iph->iph_sock, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) { - if (ioctl(iph->iph_sock6, SIOCGLIFGROUPNAME, - (caddr_t)&lifr) < 0) { - return (B_FALSE); - } - } - return (lifr.lifr_groupname[0] != '\0'); -} - -/* - * Returns B_TRUE if `ifname' represents an IPMP meta-interface. - */ -boolean_t -i_ipadm_is_ipmp(ipadm_handle_t iph, const char *ifname) -{ - uint64_t flags; - - if (i_ipadm_get_flags(iph, ifname, AF_INET, &flags) != IPADM_SUCCESS && - i_ipadm_get_flags(iph, ifname, AF_INET6, &flags) != IPADM_SUCCESS) - return (B_FALSE); - - return ((flags & IFF_IPMP) != 0); -} - -/* * For a given interface name, ipadm_if_enabled() checks if v4 * or v6 or both IP interfaces exist in the active configuration. */ @@ -693,40 +660,82 @@ i_ipadm_init_ifobj(ipadm_handle_t iph, const char *ifname, nvlist_t *ifnvl) { nvlist_t *nvl = NULL; nvpair_t *nvp; - char *afstr; - ipadm_status_t status; + ipadm_status_t status = IPADM_ENXIO; ipadm_status_t ret_status = IPADM_SUCCESS; char newifname[LIFNAMSIZ]; char *aobjstr; - sa_family_t af = AF_UNSPEC; - boolean_t is_ngz = (iph->iph_zoneid != GLOBAL_ZONEID); + uint16_t *afs; + char *gifname; + uint_t nelem = 0; + boolean_t init_from_gz = B_FALSE; + boolean_t move_to_group = B_FALSE; (void) strlcpy(newifname, ifname, sizeof (newifname)); + /* - * First plumb the given interface and then apply all the persistent - * interface properties and then instantiate any persistent addresses - * objects on that interface. + * First go through the ifnvl nvlist looking for nested nvlist + * containing interface class and address families. */ for (nvp = nvlist_next_nvpair(ifnvl, NULL); nvp != NULL; nvp = nvlist_next_nvpair(ifnvl, nvp)) { - if (nvpair_value_nvlist(nvp, &nvl) != 0) + char *icstr; + char **mifnames; + uint32_t ipadm_flags = IPADM_OPT_ACTIVE; + + if (nvpair_value_nvlist(nvp, &nvl) != 0 || + nvlist_lookup_uint16_array(nvl, IPADM_NVP_FAMILIES, + &afs, &nelem) != 0) continue; - if (nvlist_lookup_string(nvl, IPADM_NVP_FAMILY, &afstr) == 0) { - status = i_ipadm_plumb_if(iph, newifname, atoi(afstr), - IPADM_OPT_ACTIVE); - /* - * If the interface is already plumbed, we should - * ignore this error because there might be address - * address objects on that interface that needs to - * be enabled again. - */ + /* Check if this is IPMP group interface */ + if (nvlist_lookup_string(nvl, IPADM_NVP_IFCLASS, + &icstr) == 0 && atoi(icstr) == IPADM_IF_CLASS_IPMP) + ipadm_flags |= IPADM_OPT_IPMP; + + /* Create interfaces for address families specified */ + while (nelem-- > 0) { + uint16_t af = afs[nelem]; + + assert(af == AF_INET || af == AF_INET6); + + status = i_ipadm_plumb_if(iph, newifname, af, + ipadm_flags); if (status == IPADM_IF_EXISTS) status = IPADM_SUCCESS; + if (status != IPADM_SUCCESS) + return (status); + } + if (nvlist_lookup_string(nvl, IPADM_NVP_GIFNAME, + &gifname) == 0) { + /* + * IPMP underlying interface. Move to the + * specified IPMP group. + */ + move_to_group = B_TRUE; + } else if ((ipadm_flags & IPADM_OPT_IPMP) && + nvlist_lookup_string_array(nvl, IPADM_NVP_MIFNAMES, + &mifnames, &nelem) == 0) { + /* Non-empty IPMP group interface */ + while (nelem-- > 0) { + (void) ipadm_add_ipmp_member(iph, newifname, + mifnames[nelem], IPADM_OPT_ACTIVE); + } + } + if (iph->iph_zoneid != GLOBAL_ZONEID) + init_from_gz = B_TRUE; + } - if (is_ngz) - af = atoi(afstr); - } else if (nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME, + if (status != IPADM_SUCCESS) + return (status); + + /* + * Go through the ifnvl nvlist again, applying persistent configuration. + */ + for (nvp = nvlist_next_nvpair(ifnvl, NULL); nvp != NULL; + nvp = nvlist_next_nvpair(ifnvl, nvp)) { + if (nvpair_value_nvlist(nvp, &nvl) != 0) + continue; + if (nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME, &aobjstr) == 0) { /* * For addresses, we need to relocate addrprops from the @@ -737,10 +746,12 @@ i_ipadm_init_ifobj(ipadm_handle_t iph, const char *ifname, nvlist_t *ifnvl) nvlist_exists(nvl, IPADM_NVP_DHCP)) { status = i_ipadm_merge_addrprops_from_nvl(ifnvl, nvl, aobjstr); + if (status != IPADM_SUCCESS) continue; } status = i_ipadm_init_addrobj(iph, nvl); + /* * If this address is in use on some other interface, * we want to record an error to be returned as @@ -751,15 +762,17 @@ i_ipadm_init_ifobj(ipadm_handle_t iph, const char *ifname, nvlist_t *ifnvl) ret_status = IPADM_ALL_ADDRS_NOT_ENABLED; status = IPADM_SUCCESS; } - } else { - assert(nvlist_exists(nvl, IPADM_NVP_PROTONAME)); + } else if (nvlist_exists(nvl, IPADM_NVP_PROTONAME) == B_TRUE) { status = i_ipadm_init_ifprop(iph, nvl); } if (status != IPADM_SUCCESS) return (status); } - - if (is_ngz && af != AF_UNSPEC) + if (move_to_group) { + (void) ipadm_add_ipmp_member(iph, gifname, newifname, + IPADM_OPT_ACTIVE); + } + if (init_from_gz) ret_status = ipadm_init_net_from_gz(iph, newifname, NULL); return (ret_status); } @@ -779,8 +792,9 @@ i_ipadm_init_ifs(ipadm_handle_t iph, const char *ifs, nvlist_t **allifs) int err; ipadm_status_t status = IPADM_SUCCESS; - if ((err = ipadm_str2nvlist(ifs, &nvl, IPADM_NORVAL)) != 0) - return (ipadm_errno2status(err)); + status = ipadm_str2nvlist(ifs, &nvl, IPADM_NORVAL); + if (status != IPADM_SUCCESS) + return (status); err = nvlist_pack(nvl, &nvlbuf, &nvlsize, NV_ENCODE_NATIVE, 0); if (err != 0) { @@ -960,6 +974,36 @@ reopen: } /* + * A helper that is used by i_ipadm_get_db_addr and i_ipadm_get_db_if + * to do a door_call to ipmgmtd, that should return persistent information + * about interfaces or/and addresses from ipadm DB + */ +ipadm_status_t +i_ipadm_call_ipmgmtd(ipadm_handle_t iph, void *garg, size_t garg_size, + nvlist_t **onvl) +{ + ipmgmt_get_rval_t *rvalp; + int err; + size_t nvlsize; + char *nvlbuf; + + rvalp = malloc(sizeof (ipmgmt_get_rval_t)); + if (rvalp == NULL) + return (IPADM_NO_MEMORY); + + err = ipadm_door_call(iph, garg, garg_size, (void **)&rvalp, + sizeof (*rvalp), B_TRUE); + if (err == 0) { + nvlsize = rvalp->ir_nvlsize; + nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t); + err = nvlist_unpack(nvlbuf, nvlsize, onvl, 0); + } + free(rvalp); + + return (ipadm_errno2status(err)); +} + +/* * ipadm_is_nil_hostname() : Determine if the `hostname' is nil: i.e., * NULL, empty, or a single space (e.g., as returned by * domainname(1M)/sysinfo). |