Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  * Main door handler functions used by ipmgmtd to process the different door
  28  * call requests, issued by the library libipadm.so.
  29  */
  30 
  31 #include <alloca.h>
  32 #include <pwd.h>
  33 #include <auth_attr.h>
  34 #include <secdb.h>
  35 #include <stdlib.h>
  36 #include <stdio.h>
  37 #include <string.h>
  38 #include <strings.h>
  39 #include <errno.h>
  40 #include <assert.h>
  41 #include <libnvpair.h>
  42 #include "ipmgmt_impl.h"
  43 


 208 
 209         cb.dbw_nvl = nvl;
 210         cb.dbw_flags = pargp->ia_flags;
 211         err = ipmgmt_db_walk(ipmgmt_db_update, &cb, IPADM_DB_WRITE);
 212 fail:
 213         nvlist_free(nvl);
 214         rval.ir_err = err;
 215         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 216 }
 217 
 218 /*
 219  * Helper function for ipmgmt_setaddr_handler().
 220  * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
 221  */
 222 static int
 223 i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
 224 {
 225         char                    *aobjname = NULL, *ifname = NULL;
 226         int32_t                 lnum;
 227         nvlist_t                *nvladdr;
 228         struct sockaddr_storage addr;
 229         uint_t                  n;
 230         sa_family_t             af = AF_UNSPEC;
 231         ipadm_addr_type_t       addrtype = IPADM_ADDR_NONE;
 232         int                     err = 0;
 233 
 234         /*
 235          * Retrieve all the information needed to build '*nodep' from
 236          * nvlist_t nvl.
 237          */
 238         if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
 239             &aobjname)) != 0 ||
 240             (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 ||
 241             (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) {
 242                 return (err);
 243         }
 244         if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
 245                 af = AF_INET;
 246                 addrtype = IPADM_ADDR_STATIC;
 247         } else if (nvlist_exists(nvl, IPADM_NVP_DHCP)) {



 248                 af = AF_INET;
 249                 addrtype = IPADM_ADDR_DHCP;






















 250         } else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
 251                 af = AF_INET6;
 252                 addrtype = IPADM_ADDR_STATIC;
 253         } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
 254                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
 255                 uint8_t *addr6;
 256                 uint32_t plen;

 257 
 258                 af = AF_INET6;
 259                 addrtype = IPADM_ADDR_IPV6_ADDRCONF;
 260                 if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
 261                     &plen) != 0)
 262                         return (EINVAL);
 263                 if (plen != 0) {
 264                         if (nvlist_lookup_uint8_array(nvladdr,
 265                             IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
 266                                 return (EINVAL);
 267                         bcopy(addr6, &sin6->sin6_addr, n);
 268                 } else {
 269                         bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
 270                 }



 271         }
 272 
 273         /*
 274          * populate the `*nodep' with retrieved values.
 275          */
 276         (void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
 277         (void) strlcpy(nodep->am_aobjname, aobjname,
 278             sizeof (nodep->am_aobjname));
 279         nodep->am_lnum = lnum;
 280         nodep->am_family = af;
 281         nodep->am_atype = addrtype;
 282         if (addrtype == IPADM_ADDR_IPV6_ADDRCONF) {
 283                 nodep->am_linklocal = B_TRUE;
 284                 nodep->am_ifid = addr;
 285         }
 286         nodep->am_next = NULL;
 287 
 288         /*
 289          * Do not store logical interface number in persistent store as it
 290          * takes different value on reboot. So remove it from `nvl'.
 291          */
 292         if (nvlist_exists(nvl, IPADM_NVP_LIFNUM))
 293                 (void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32);
 294 
 295         return (0);
 296 }
 297 
 298 /*
 299  * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
 300  * node to the list `aobjmap' and then persists the address information in the
 301  * DB.
 302  */
 303 static void
 304 ipmgmt_setaddr_handler(void *argp)
 305 {
 306         ipmgmt_setaddr_arg_t    *sargp = argp;
 307         ipmgmt_retval_t         rval;
 308         ipmgmt_aobjmap_t        node;
 309         nvlist_t                *nvl = NULL;
 310         char                    *nvlbuf;
 311         size_t                  nvlsize = sargp->ia_nvlsize;
 312         uint32_t                flags = sargp->ia_flags;
 313         int                     err = 0;
 314 
 315         nvlbuf = (char *)argp + sizeof (ipmgmt_setaddr_arg_t);
 316         if ((err = nvlist_unpack(nvlbuf, nvlsize, &nvl, NV_ENCODE_NATIVE)) != 0)
 317                 goto ret;
 318         if (flags & (IPMGMT_ACTIVE|IPMGMT_INIT)) {
 319                 if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0)
 320                         goto ret;
 321                 if (flags & IPMGMT_INIT)
 322                         node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST);
 323                 else
 324                         node.am_flags = flags;
 325                 if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0)
 326                         goto ret;
 327         }
 328         if (flags & IPMGMT_PERSIST) {
 329                 ipadm_dbwrite_cbarg_t   cb;
 330 
 331                 cb.dbw_nvl = nvl;
 332                 cb.dbw_flags = 0;
 333                 err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
 334         }
 335 ret:
 336         nvlist_free(nvl);
 337         rval.ir_err = err;
 338         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 339 }
 340 
 341 /*
 342  * Handles the door commands that modify the `aobjmap' structure.
 343  *
 344  * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
 345  *      after ensuring that the namespace is not taken. If required, also
 346  *      generates an `aobjname' for address object for the library to use.
 347  * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
 348  * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
 349  *      associated with that logical interface.
 350  * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
 351  *      interface associated with that address object.
 352  */
 353 static void
 354 ipmgmt_aobjop_handler(void *argp)
 355 {
 356         ipmgmt_aobjop_arg_t     *largp = argp;
 357         ipmgmt_retval_t         rval;
 358         ipmgmt_aobjop_rval_t    aobjrval;
 359         void                    *rvalp;
 360         size_t                  rsize;
 361         ipmgmt_aobjmap_t        node;
 362         int                     err = 0;


 424                 rsize = sizeof (ipmgmt_aobjop_rval_t);
 425                 rvalp = &aobjrval;
 426                 bzero(&aobjrval, sizeof (aobjrval));
 427                 if (aobjname[0] == '\0') {
 428                         err = EINVAL;
 429                         break;
 430                 }
 431                 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
 432                 head = aobjmap.aobjmap_head;
 433                 for (; head; head = head->am_next) {
 434                         if (strcmp(head->am_aobjname, aobjname) != 0)
 435                                 continue;
 436                         /*
 437                          * For an auto-configured interface, return
 438                          * the lifnum that has the link-local on it.
 439                          * Other logical interfaces were created for
 440                          * prefixes and dhcpv6 addresses and do not
 441                          * have am_ifid set.
 442                          */
 443                         if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
 444                             head->am_linklocal) {
 445                                 break;
 446                         }
 447                 }
 448                 if (head == NULL) {
 449                         err = ENOENT;
 450                         (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 451                         break;
 452                 }
 453                 (void) strlcpy(aobjrval.ir_ifname, head->am_ifname,
 454                     sizeof (aobjrval.ir_ifname));
 455                 aobjrval.ir_lnum = head->am_lnum;
 456                 aobjrval.ir_family = head->am_family;
 457                 aobjrval.ir_flags = head->am_flags;
 458                 aobjrval.ir_atype = head->am_atype;
 459                 if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF &&
 460                     head->am_linklocal)
 461                         aobjrval.ir_ifid = head->am_ifid;
 462                 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 463                 break;
 464         case IPMGMT_CMD_LIF2ADDROBJ:
 465                 rsize = sizeof (ipmgmt_aobjop_rval_t);
 466                 rvalp = &aobjrval;
 467                 bzero(&aobjrval, sizeof (aobjrval));
 468                 if (ifname[0] == '\0') {
 469                         err = EINVAL;
 470                         break;
 471                 }
 472                 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
 473                 head = aobjmap.aobjmap_head;
 474                 for (; head; head = head->am_next) {
 475                         if (strcmp(head->am_ifname, ifname) == 0 &&
 476                             head->am_lnum == lnum &&
 477                             head->am_family == af) {
 478                                 break;
 479                         }
 480                 }
 481                 if (head == NULL) {
 482                         err = ENOENT;
 483                         (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 484                         break;
 485                 }
 486                 (void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname,
 487                     sizeof (aobjrval.ir_aobjname));
 488                 aobjrval.ir_atype = head->am_atype;
 489                 aobjrval.ir_flags = head->am_flags;


 490                 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 491                 break;
 492         default:
 493                 rsize = sizeof (ipmgmt_retval_t);
 494                 rvalp = &rval;
 495                 err = EINVAL;
 496         }
 497         ((ipmgmt_retval_t *)rvalp)->ir_err = err;
 498         (void) door_return((char *)rvalp, rsize, NULL, 0);
 499 }
 500 
 501 /*
 502  * Given an interface name and family, deletes all the address objects
 503  * associated with it.
 504  */
 505 void
 506 i_ipmgmt_delif_aobjs(char *ifname, sa_family_t af, uint32_t flags)
 507 {
 508         ipmgmt_aobjmap_t        *head, *next, *prev;
 509         ipadm_db_op_t           db_op;




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
  25  */
  26 
  27 /*
  28  * Main door handler functions used by ipmgmtd to process the different door
  29  * call requests, issued by the library libipadm.so.
  30  */
  31 
  32 #include <alloca.h>
  33 #include <pwd.h>
  34 #include <auth_attr.h>
  35 #include <secdb.h>
  36 #include <stdlib.h>
  37 #include <stdio.h>
  38 #include <string.h>
  39 #include <strings.h>
  40 #include <errno.h>
  41 #include <assert.h>
  42 #include <libnvpair.h>
  43 #include "ipmgmt_impl.h"
  44 


 209 
 210         cb.dbw_nvl = nvl;
 211         cb.dbw_flags = pargp->ia_flags;
 212         err = ipmgmt_db_walk(ipmgmt_db_update, &cb, IPADM_DB_WRITE);
 213 fail:
 214         nvlist_free(nvl);
 215         rval.ir_err = err;
 216         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 217 }
 218 
 219 /*
 220  * Helper function for ipmgmt_setaddr_handler().
 221  * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
 222  */
 223 static int
 224 i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
 225 {
 226         char                    *aobjname = NULL, *ifname = NULL;
 227         int32_t                 lnum;
 228         nvlist_t                *nvladdr;


 229         sa_family_t             af = AF_UNSPEC;
 230         ipadm_addr_type_t       addrtype = IPADM_ADDR_NONE;
 231         int                     err = 0;
 232 
 233         /*
 234          * Retrieve all the information needed to build '*nodep' from
 235          * nvlist_t nvl.
 236          */
 237         if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
 238             &aobjname)) != 0 ||
 239             (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 ||
 240             (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) {
 241                 return (err);
 242         }
 243         if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
 244                 af = AF_INET;
 245                 addrtype = IPADM_ADDR_STATIC;
 246         } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvladdr) == 0) {
 247                 char    *reqhost;
 248                 boolean_t       primary;
 249 
 250                 af = AF_INET;
 251                 addrtype = IPADM_ADDR_DHCP;
 252 
 253                 if (nvlist_lookup_boolean_value(nvladdr, IPADM_NVP_PRIMARY,
 254                     &primary) != 0)
 255                         return (EINVAL);
 256                 nodep->ipmgmt_am_primary = primary;
 257 
 258                 /*
 259                  * ipmgmt_am_reqhost comes through in `nvl' for purposes of updating
 260                  * the cached representation, but it is persisted as a stand-alone
 261                  * DB line; so remove it after copying it.
 262                  */
 263                 if (!nvlist_exists(nvl, IPADM_NVP_REQHOST)) {
 264                         *nodep->ipmgmt_am_reqhost = '\0';
 265                 } else {
 266                         if ((err = nvlist_lookup_string(nvl, IPADM_NVP_REQHOST,
 267                             &reqhost)) != 0)
 268                                 return (err);
 269 
 270                         (void) strlcpy(nodep->ipmgmt_am_reqhost, reqhost,
 271                             sizeof (nodep->ipmgmt_am_reqhost));
 272                         (void) nvlist_remove(nvl, IPADM_NVP_REQHOST, DATA_TYPE_STRING);
 273                 }
 274         } else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
 275                 af = AF_INET6;
 276                 addrtype = IPADM_ADDR_STATIC;
 277         } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
 278                 struct sockaddr_in6             sin6 = {0};
 279                 uint8_t *addr6;
 280                 uint32_t plen;
 281                 uint_t n;
 282 
 283                 af = AF_INET6;
 284                 addrtype = IPADM_ADDR_IPV6_ADDRCONF;
 285                 if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
 286                     &plen) != 0)
 287                         return (EINVAL);
 288                 if (plen != 0) {
 289                         if (nvlist_lookup_uint8_array(nvladdr,
 290                             IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
 291                                 return (EINVAL);
 292                         bcopy(addr6, &sin6.sin6_addr, n);


 293                 }
 294 
 295                 nodep->ipmgmt_am_linklocal = B_TRUE;
 296                 nodep->ipmgmt_am_ifid = sin6;
 297         }
 298 
 299         /*
 300          * populate the non-addrtype-specific `*nodep' with retrieved values.
 301          */
 302         (void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
 303         (void) strlcpy(nodep->am_aobjname, aobjname,
 304             sizeof (nodep->am_aobjname));
 305         nodep->am_lnum = lnum;
 306         nodep->am_family = af;
 307         nodep->am_atype = addrtype;




 308         nodep->am_next = NULL;
 309 
 310         /*
 311          * Do not store logical interface number in persistent store as it
 312          * takes different value on reboot. So remove it from `nvl'.
 313          */
 314         if (nvlist_exists(nvl, IPADM_NVP_LIFNUM))
 315                 (void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32);
 316 
 317         return (0);
 318 }
 319 
 320 /*
 321  * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
 322  * node to the list `aobjmap' and optionally persists the address
 323  * information in the DB.
 324  */
 325 static void
 326 ipmgmt_setaddr_handler(void *argp)
 327 {
 328         ipmgmt_setaddr_arg_t    *sargp = argp;
 329         ipmgmt_retval_t         rval;
 330         ipmgmt_aobjmap_t        node = {0};
 331         nvlist_t                *nvl = NULL;
 332         char                    *nvlbuf;
 333         size_t                  nvlsize = sargp->ia_nvlsize;
 334         uint32_t                flags = sargp->ia_flags;
 335         int                     err = 0;
 336 
 337         nvlbuf = (char *)argp + sizeof (ipmgmt_setaddr_arg_t);
 338         if ((err = nvlist_unpack(nvlbuf, nvlsize, &nvl, NV_ENCODE_NATIVE)) != 0)
 339                 goto ret;
 340         if (flags & (IPMGMT_ACTIVE|IPMGMT_INIT)) {
 341                 if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0)
 342                         goto ret;
 343                 if (flags & IPMGMT_INIT)
 344                         node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST);
 345                 else
 346                         node.am_flags = flags & ~IPMGMT_PROPS_ONLY;
 347                 if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0)
 348                         goto ret;
 349         }
 350         if ((flags & IPMGMT_PERSIST) && !(flags & IPMGMT_PROPS_ONLY)) {
 351                 ipadm_dbwrite_cbarg_t   cb;
 352 
 353                 cb.dbw_nvl = nvl;
 354                 cb.dbw_flags = 0;
 355                 err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
 356         }
 357 ret:
 358         nvlist_free(nvl);
 359         rval.ir_err = err;
 360         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 361 }
 362 
 363 /*
 364  * Handles the door commands that read or modify the `aobjmap' structure.
 365  *
 366  * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
 367  *      after ensuring that the namespace is not taken. If required, also
 368  *      generates an `aobjname' for address object for the library to use.
 369  * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
 370  * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
 371  *      associated with that logical interface.
 372  * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
 373  *      interface associated with that address object.
 374  */
 375 static void
 376 ipmgmt_aobjop_handler(void *argp)
 377 {
 378         ipmgmt_aobjop_arg_t     *largp = argp;
 379         ipmgmt_retval_t         rval;
 380         ipmgmt_aobjop_rval_t    aobjrval;
 381         void                    *rvalp;
 382         size_t                  rsize;
 383         ipmgmt_aobjmap_t        node;
 384         int                     err = 0;


 446                 rsize = sizeof (ipmgmt_aobjop_rval_t);
 447                 rvalp = &aobjrval;
 448                 bzero(&aobjrval, sizeof (aobjrval));
 449                 if (aobjname[0] == '\0') {
 450                         err = EINVAL;
 451                         break;
 452                 }
 453                 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
 454                 head = aobjmap.aobjmap_head;
 455                 for (; head; head = head->am_next) {
 456                         if (strcmp(head->am_aobjname, aobjname) != 0)
 457                                 continue;
 458                         /*
 459                          * For an auto-configured interface, return
 460                          * the lifnum that has the link-local on it.
 461                          * Other logical interfaces were created for
 462                          * prefixes and dhcpv6 addresses and do not
 463                          * have am_ifid set.
 464                          */
 465                         if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
 466                             head->ipmgmt_am_linklocal) {
 467                                 break;
 468                         }
 469                 }
 470                 if (head == NULL) {
 471                         err = ENOENT;
 472                         (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 473                         break;
 474                 }
 475                 (void) strlcpy(aobjrval.ir_ifname, head->am_ifname,
 476                     sizeof (aobjrval.ir_ifname));
 477                 aobjrval.ir_lnum = head->am_lnum;
 478                 aobjrval.ir_family = head->am_family;
 479                 aobjrval.ir_flags = head->am_flags;
 480                 aobjrval.ir_atype = head->am_atype;
 481                 (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
 482                     sizeof (aobjrval.ir_atype_cache));

 483                 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 484                 break;
 485         case IPMGMT_CMD_LIF2ADDROBJ:
 486                 rsize = sizeof (ipmgmt_aobjop_rval_t);
 487                 rvalp = &aobjrval;
 488                 bzero(&aobjrval, sizeof (aobjrval));
 489                 if (ifname[0] == '\0') {
 490                         err = EINVAL;
 491                         break;
 492                 }
 493                 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
 494                 head = aobjmap.aobjmap_head;
 495                 for (; head; head = head->am_next) {
 496                         if (strcmp(head->am_ifname, ifname) == 0 &&
 497                             head->am_lnum == lnum &&
 498                             head->am_family == af) {
 499                                 break;
 500                         }
 501                 }
 502                 if (head == NULL) {
 503                         err = ENOENT;
 504                         (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 505                         break;
 506                 }
 507                 (void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname,
 508                     sizeof (aobjrval.ir_aobjname));
 509                 aobjrval.ir_atype = head->am_atype;
 510                 aobjrval.ir_flags = head->am_flags;
 511                 (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
 512                     sizeof (aobjrval.ir_atype_cache));
 513                 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
 514                 break;
 515         default:
 516                 rsize = sizeof (ipmgmt_retval_t);
 517                 rvalp = &rval;
 518                 err = EINVAL;
 519         }
 520         ((ipmgmt_retval_t *)rvalp)->ir_err = err;
 521         (void) door_return((char *)rvalp, rsize, NULL, 0);
 522 }
 523 
 524 /*
 525  * Given an interface name and family, deletes all the address objects
 526  * associated with it.
 527  */
 528 void
 529 i_ipmgmt_delif_aobjs(char *ifname, sa_family_t af, uint32_t flags)
 530 {
 531         ipmgmt_aobjmap_t        *head, *next, *prev;
 532         ipadm_db_op_t           db_op;