summaryrefslogtreecommitdiff
path: root/usr/src/lib/libipadm/common/libipadm.c
diff options
context:
space:
mode:
authorDan McDonald <danmcd@joyent.com>2021-11-22 17:10:57 -0500
committerDan McDonald <danmcd@joyent.com>2021-11-22 17:10:57 -0500
commit4384c8ad8dbbd88a368729dac65c5c7715bece40 (patch)
treee872cefca5da7b7ebe5ef846a8e445ce2d8a152b /usr/src/lib/libipadm/common/libipadm.c
parenta9abe3f2aacb7ff5172ef7d55241b1d9b969c359 (diff)
parenta73be61a80f7331c35adfa540bcf8f1546ff1e33 (diff)
downloadillumos-joyent-4384c8ad8dbbd88a368729dac65c5c7715bece40.tar.gz
[illumos-gate merge]
commit a73be61a80f7331c35adfa540bcf8f1546ff1e33 2554 ipadm needs IPMP configuration support commit f81209f5137586c57e31f7d74b929149299d9b3c 14247 SMF seed databases contain build paths commit 671e12f2cf68dbd241dfc08296dc05fecc27127c 14235 pcitool doesn't properly handle AMD Type 1 I/O space access commit b15548ab7300ec8625be47442fd92b71ed91c2cd 14245 sed regression tests 7.1 and 7.7 are locale sensitive commit 0153d828c132fdb1a17c11b99386a3d1b87994cf 13896 bhyve VM interfaces should be better fit 13981 bhyve emulation should set dirty bits commit d8f839f91e21bea2f5200f95df55608cbecdeeb9 14223 Add change key zfs channel program commit 705b6680745618ebbf67feb254ce9a62511084a5 4450 pointless condfree in libfmnotify Conflicts: usr/src/cmd/cmd-inet/lib/ipmgmtd/Makefile usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_main.c usr/src/cmd/svc/milestone/net-physical usr/src/lib/libipadm/common/libipadm.c usr/src/uts/common/fs/zfs/zfs_ioctl.c
Diffstat (limited to 'usr/src/lib/libipadm/common/libipadm.c')
-rw-r--r--usr/src/lib/libipadm/common/libipadm.c164
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 9ef32f35c1..005d86fc0c 100644
--- a/usr/src/lib/libipadm/common/libipadm.c
+++ b/usr/src/lib/libipadm/common/libipadm.c
@@ -22,8 +22,8 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Joyent, Inc.
- * 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>
@@ -537,39 +537,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.
*/
@@ -702,40 +669,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
@@ -746,10 +755,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
@@ -760,15 +771,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);
}
@@ -788,8 +801,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) {
@@ -981,6 +995,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).