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;