Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.
@@ -19,10 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
*/
/*
* Main door handler functions used by ipmgmtd to process the different door
* call requests, issued by the library libipadm.so.
@@ -223,12 +224,10 @@
i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
{
char *aobjname = NULL, *ifname = NULL;
int32_t lnum;
nvlist_t *nvladdr;
- struct sockaddr_storage addr;
- uint_t n;
sa_family_t af = AF_UNSPEC;
ipadm_addr_type_t addrtype = IPADM_ADDR_NONE;
int err = 0;
/*
@@ -242,20 +241,46 @@
return (err);
}
if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
af = AF_INET;
addrtype = IPADM_ADDR_STATIC;
- } else if (nvlist_exists(nvl, IPADM_NVP_DHCP)) {
+ } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvladdr) == 0) {
+ char *reqhost;
+ boolean_t primary;
+
af = AF_INET;
addrtype = IPADM_ADDR_DHCP;
+
+ if (nvlist_lookup_boolean_value(nvladdr, IPADM_NVP_PRIMARY,
+ &primary) != 0)
+ return (EINVAL);
+ nodep->ipmgmt_am_primary = primary;
+
+ /*
+ * ipmgmt_am_reqhost comes through in `nvl' for purposes of updating
+ * the cached representation, but it is persisted as a stand-alone
+ * DB line; so remove it after copying it.
+ */
+ if (!nvlist_exists(nvl, IPADM_NVP_REQHOST)) {
+ *nodep->ipmgmt_am_reqhost = '\0';
+ } else {
+ if ((err = nvlist_lookup_string(nvl, IPADM_NVP_REQHOST,
+ &reqhost)) != 0)
+ return (err);
+
+ (void) strlcpy(nodep->ipmgmt_am_reqhost, reqhost,
+ sizeof (nodep->ipmgmt_am_reqhost));
+ (void) nvlist_remove(nvl, IPADM_NVP_REQHOST, DATA_TYPE_STRING);
+ }
} else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
af = AF_INET6;
addrtype = IPADM_ADDR_STATIC;
} else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ struct sockaddr_in6 sin6 = {0};
uint8_t *addr6;
uint32_t plen;
+ uint_t n;
af = AF_INET6;
addrtype = IPADM_ADDR_IPV6_ADDRCONF;
if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
&plen) != 0)
@@ -262,29 +287,26 @@
return (EINVAL);
if (plen != 0) {
if (nvlist_lookup_uint8_array(nvladdr,
IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
return (EINVAL);
- bcopy(addr6, &sin6->sin6_addr, n);
- } else {
- bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
+ bcopy(addr6, &sin6.sin6_addr, n);
}
+
+ nodep->ipmgmt_am_linklocal = B_TRUE;
+ nodep->ipmgmt_am_ifid = sin6;
}
/*
- * populate the `*nodep' with retrieved values.
+ * populate the non-addrtype-specific `*nodep' with retrieved values.
*/
(void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
(void) strlcpy(nodep->am_aobjname, aobjname,
sizeof (nodep->am_aobjname));
nodep->am_lnum = lnum;
nodep->am_family = af;
nodep->am_atype = addrtype;
- if (addrtype == IPADM_ADDR_IPV6_ADDRCONF) {
- nodep->am_linklocal = B_TRUE;
- nodep->am_ifid = addr;
- }
nodep->am_next = NULL;
/*
* Do not store logical interface number in persistent store as it
* takes different value on reboot. So remove it from `nvl'.
@@ -295,19 +317,19 @@
return (0);
}
/*
* Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
- * node to the list `aobjmap' and then persists the address information in the
- * DB.
+ * node to the list `aobjmap' and optionally persists the address
+ * information in the DB.
*/
static void
ipmgmt_setaddr_handler(void *argp)
{
ipmgmt_setaddr_arg_t *sargp = argp;
ipmgmt_retval_t rval;
- ipmgmt_aobjmap_t node;
+ ipmgmt_aobjmap_t node = {0};
nvlist_t *nvl = NULL;
char *nvlbuf;
size_t nvlsize = sargp->ia_nvlsize;
uint32_t flags = sargp->ia_flags;
int err = 0;
@@ -319,15 +341,15 @@
if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0)
goto ret;
if (flags & IPMGMT_INIT)
node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST);
else
- node.am_flags = flags;
+ node.am_flags = flags & ~IPMGMT_PROPS_ONLY;
if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0)
goto ret;
}
- if (flags & IPMGMT_PERSIST) {
+ if ((flags & IPMGMT_PERSIST) && !(flags & IPMGMT_PROPS_ONLY)) {
ipadm_dbwrite_cbarg_t cb;
cb.dbw_nvl = nvl;
cb.dbw_flags = 0;
err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
@@ -337,11 +359,11 @@
rval.ir_err = err;
(void) door_return((char *)&rval, sizeof (rval), NULL, 0);
}
/*
- * Handles the door commands that modify the `aobjmap' structure.
+ * Handles the door commands that read or modify the `aobjmap' structure.
*
* IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
* after ensuring that the namespace is not taken. If required, also
* generates an `aobjname' for address object for the library to use.
* IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
@@ -439,11 +461,11 @@
* Other logical interfaces were created for
* prefixes and dhcpv6 addresses and do not
* have am_ifid set.
*/
if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
- head->am_linklocal) {
+ head->ipmgmt_am_linklocal) {
break;
}
}
if (head == NULL) {
err = ENOENT;
@@ -454,13 +476,12 @@
sizeof (aobjrval.ir_ifname));
aobjrval.ir_lnum = head->am_lnum;
aobjrval.ir_family = head->am_family;
aobjrval.ir_flags = head->am_flags;
aobjrval.ir_atype = head->am_atype;
- if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF &&
- head->am_linklocal)
- aobjrval.ir_ifid = head->am_ifid;
+ (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
+ sizeof (aobjrval.ir_atype_cache));
(void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
break;
case IPMGMT_CMD_LIF2ADDROBJ:
rsize = sizeof (ipmgmt_aobjop_rval_t);
rvalp = &aobjrval;
@@ -485,10 +506,12 @@
}
(void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname,
sizeof (aobjrval.ir_aobjname));
aobjrval.ir_atype = head->am_atype;
aobjrval.ir_flags = head->am_flags;
+ (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
+ sizeof (aobjrval.ir_atype_cache));
(void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
break;
default:
rsize = sizeof (ipmgmt_retval_t);
rvalp = &rval;