Print this page
Commit IPMP changes


   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 



  44 /* Handler declaration for each door command */
  45 typedef void ipmgmt_door_handler_t(void *argp);
  46 
  47 static ipmgmt_door_handler_t    ipmgmt_getaddr_handler,
  48                                 ipmgmt_getprop_handler,
  49                                 ipmgmt_getif_handler,
  50                                 ipmgmt_initif_handler,
  51                                 ipmgmt_aobjop_handler,
  52                                 ipmgmt_resetaddr_handler,
  53                                 ipmgmt_setif_handler,
  54                                 ipmgmt_resetif_handler,
  55                                 ipmgmt_resetprop_handler,
  56                                 ipmgmt_setaddr_handler,
  57                                 ipmgmt_setprop_handler;

  58 
  59 typedef struct ipmgmt_door_info_s {
  60         uint_t                  idi_cmd;
  61         boolean_t               idi_set;
  62         ipmgmt_door_handler_t   *idi_handler;
  63 } ipmgmt_door_info_t;
  64 
  65 /* maps door commands to door handler functions */
  66 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
  67         { IPMGMT_CMD_SETPROP,           B_TRUE,  ipmgmt_setprop_handler },
  68         { IPMGMT_CMD_SETIF,             B_TRUE,  ipmgmt_setif_handler },
  69         { IPMGMT_CMD_SETADDR,           B_TRUE,  ipmgmt_setaddr_handler },
  70         { IPMGMT_CMD_GETPROP,           B_FALSE, ipmgmt_getprop_handler },
  71         { IPMGMT_CMD_GETIF,             B_FALSE, ipmgmt_getif_handler },
  72         { IPMGMT_CMD_GETADDR,           B_FALSE, ipmgmt_getaddr_handler },
  73         { IPMGMT_CMD_RESETIF,           B_TRUE,  ipmgmt_resetif_handler },
  74         { IPMGMT_CMD_RESETADDR,         B_TRUE,  ipmgmt_resetaddr_handler },
  75         { IPMGMT_CMD_RESETPROP,         B_TRUE,  ipmgmt_resetprop_handler },
  76         { IPMGMT_CMD_INITIF,            B_TRUE,  ipmgmt_initif_handler },
  77         { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE,  ipmgmt_aobjop_handler },
  78         { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE,  ipmgmt_aobjop_handler },
  79         { IPMGMT_CMD_ADDROBJ_ADD,       B_TRUE,  ipmgmt_aobjop_handler },
  80         { IPMGMT_CMD_AOBJNAME2ADDROBJ,  B_FALSE, ipmgmt_aobjop_handler },
  81         { IPMGMT_CMD_LIF2ADDROBJ,       B_FALSE, ipmgmt_aobjop_handler },

  82         { 0, 0, NULL },
  83 };
  84 
  85 /*
  86  * The main server procedure function that gets invoked for any of the incoming
  87  * door commands. Inside this function we identify the incoming command and
  88  * invoke the right door handler function.
  89  */
  90 /* ARGSUSED */
  91 void
  92 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
  93     uint_t n_desc)
  94 {
  95         ipmgmt_door_info_t      *infop = NULL;
  96         ipmgmt_retval_t         retval;
  97         int                     i;
  98         uint_t                  err;
  99         ucred_t                 *cred = NULL;
 100 
 101         for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {


 559         rval.ir_err = ipmgmt_persist_if(argp);
 560         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 561 }
 562 
 563 /*
 564  * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
 565  * deletes all the persisted interface configuration. It also deletes, from
 566  * `aobjmap', all the address objects configured on the given interface.
 567  */
 568 static void
 569 ipmgmt_resetif_handler(void *argp)
 570 {
 571         ipmgmt_if_arg_t         *rargp = argp;
 572         ipmgmt_retval_t         rval;
 573         ipmgmt_if_cbarg_t       cbarg;
 574         uint32_t                flags = rargp->ia_flags;
 575         int                     err = 0;
 576 
 577         cbarg.cb_family = rargp->ia_family;
 578         cbarg.cb_ifname = rargp->ia_ifname;




 579         if (flags & IPMGMT_PERSIST)
 580                 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 581                     IPADM_DB_DELETE);
 582 
 583         if (flags & IPMGMT_ACTIVE)
 584                 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 585                     flags);
 586 
 587         rval.ir_err = err;
 588         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 589 }
 590 
 591 /*
 592  * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
 593  * deletes all the persisted addrobj configuration. It also deletes the
 594  * corresponding node, from `aobjmap'.
 595  */
 596 static void
 597 ipmgmt_resetaddr_handler(void *argp)
 598 {


 620                  */
 621                 node.am_lnum = rargp->ia_lnum;
 622                 node.am_flags = flags;
 623                 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
 624         }
 625 
 626         rval.ir_err = err;
 627         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 628 }
 629 
 630 /*
 631  * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
 632  * address for a given `gargp->ia_aobjname'. If it is not defined then it
 633  * retrieves all the addresses configured on `gargp->ia_ifname'. The
 634  * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
 635  * handler through library.
 636  */
 637 static void
 638 ipmgmt_getaddr_handler(void *argp)
 639 {
 640         size_t                  buflen, onvlsize;
 641         char                    *buf, *onvlbuf;
 642         ipmgmt_getaddr_arg_t    *gargp = argp;
 643         ipmgmt_getaddr_cbarg_t  cbarg;
 644         ipmgmt_get_rval_t       rval, *rvalp = &rval;
 645         int                     err = 0;
 646 
 647         cbarg.cb_ifname = gargp->ia_ifname;
 648         cbarg.cb_aobjname = gargp->ia_aobjname;
 649         cbarg.cb_ocnt = 0;
 650         if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 651                 goto fail;
 652         err = ipmgmt_db_walk(ipmgmt_db_getaddr, &cbarg, IPADM_DB_READ);
 653         if (err == ENOENT && cbarg.cb_ocnt > 0) {
 654                 /*
 655                  * If there is atleast one entry in the nvlist,
 656                  * do not return error.
 657                  */
 658                 err = 0;
 659         }
 660         if (err != 0)
 661                 goto fail;
 662 
 663         if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize,
 664             NV_ENCODE_NATIVE)) != 0) {
 665                 goto fail;
 666         }
 667         buflen = onvlsize + sizeof (ipmgmt_get_rval_t);
 668         /*
 669          * We cannot use malloc() here because door_return never returns, and
 670          * memory allocated by malloc() would get leaked. Use alloca() instead.
 671          */
 672         buf = alloca(buflen);
 673         onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
 674         if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &onvlsize,
 675             NV_ENCODE_NATIVE, 0)) != 0) {
 676                 goto fail;
 677         }
 678         nvlist_free(cbarg.cb_onvl);
 679         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 680         rvalp->ir_err = 0;
 681         rvalp->ir_nvlsize = onvlsize;
 682 
 683         (void) door_return(buf, buflen, NULL, 0);
 684         return;
 685 fail:
 686         nvlist_free(cbarg.cb_onvl);
 687         rvalp->ir_err = err;
 688         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 689 }
 690 
 691 /*
 692  * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
 693  * from the DB.
 694  */
 695 static void
 696 ipmgmt_resetprop_handler(void *argp)
 697 {
 698         ipmgmt_prop_arg_t       *pargp = argp;
 699         ipmgmt_retval_t         rval;
 700 
 701         assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
 702 
 703         rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
 704             IPADM_DB_DELETE);
 705         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 706 }
 707 
 708 /*
 709  * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
 710  * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.

 711  */
 712 static void
 713 ipmgmt_getif_handler(void *argp)
 714 {
 715         ipmgmt_getif_arg_t      *getif = argp;
 716         ipmgmt_getif_rval_t     *rvalp;
 717         ipmgmt_retval_t         rval;
 718         ipmgmt_getif_cbarg_t    cbarg;
 719         ipadm_if_info_t         *ifp, *rifp, *curifp;
 720         int                     i, err = 0, count = 0;
 721         size_t                  rbufsize;
 722 
 723         assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
 724 
 725         bzero(&cbarg, sizeof (cbarg));
 726         cbarg.cb_ifname = getif->ia_ifname;
 727         err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
 728         if (err == ENOENT && cbarg.cb_ifinfo) {
 729                 /*
 730                  * If there is atleast one entry in the nvlist,
 731                  * do not return error.
 732                  */
 733                 err = 0;
 734         }
 735         if (err != 0) {
 736                 rval.ir_err = err;
 737                 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 738                 return;
 739         }
 740 
 741         /* allocate sufficient buffer to return the interface info */
 742         for (ifp = cbarg.cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next)
 743                 ++count;
 744         rbufsize = sizeof (*rvalp) + count * sizeof (*ifp);
 745         rvalp = alloca(rbufsize);
 746         bzero(rvalp, rbufsize);
 747 
 748         rvalp->ir_ifcnt = count;
 749         rifp = rvalp->ir_ifinfo;
 750         ifp = cbarg.cb_ifinfo;
 751 
 752         /*
 753          * copy the interface info to buffer allocated on stack. The reason
 754          * we do this is to avoid memory leak, as door_return() would never
 755          * return
 756          */
 757         for (i = 0; i < count; i++) {
 758                 rifp = rvalp->ir_ifinfo + i;
 759                 (void) bcopy(ifp, rifp, sizeof (*rifp));
 760                 rifp->ifi_next = NULL;
 761                 curifp = ifp->ifi_next;
 762                 free(ifp);
 763                 ifp = curifp;
 764         }
 765         rvalp->ir_err = err;
 766         (void) door_return((char *)rvalp, rbufsize, NULL, 0);
 767 }
 768 
 769 /*
 770  * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
 771  * interface configuration (interface properties and addresses), for all those
 772  * interfaces that need to be initialized.
 773  */
 774 static void
 775 ipmgmt_initif_handler(void *argp)
 776 {
 777         ipmgmt_initif_arg_t     *initif = argp;
 778         size_t                  buflen, nvlsize;
 779         char                    *buf = NULL, *onvlbuf, *invlbuf;
 780         ipmgmt_get_rval_t       rval, *rvalp = &rval;
 781         ipmgmt_initif_cbarg_t   cbarg;
 782         int                     err;
 783 
 784         assert(initif->ia_cmd == IPMGMT_CMD_INITIF);
 785 
 786         bzero(&cbarg, sizeof (cbarg));
 787         invlbuf = (char *)argp + sizeof (ipmgmt_initif_arg_t);
 788         nvlsize = initif->ia_nvlsize;
 789         err = nvlist_unpack(invlbuf, nvlsize, &cbarg.cb_invl, NV_ENCODE_NATIVE);
 790         if (err != 0)
 791                 goto fail;
 792 
 793         cbarg.cb_family = initif->ia_family;
 794         if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 795                 goto fail;
 796 
 797         err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
 798         if (err == ENOENT && cbarg.cb_ocnt > 0) {
 799                 /*
 800                  * If there is atleast one entry in the nvlist,
 801                  * do not return error.
 802                  */
 803                 err = 0;
 804         }
 805         if (err != 0)
 806                 goto fail;
 807 
 808         if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
 809                 goto fail;
 810         buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
 811         /*
 812          * We cannot use malloc() here because door_return never returns, and
 813          * memory allocated by malloc() would get leaked. Use alloca() instead.
 814          */
 815         buf = alloca(buflen);
 816         onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
 817         if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &nvlsize,
 818             NV_ENCODE_NATIVE, 0)) != 0) {
 819                 goto fail;
 820         }


 822         nvlist_free(cbarg.cb_onvl);
 823         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 824         rvalp->ir_err = 0;
 825         rvalp->ir_nvlsize = nvlsize;
 826 
 827         (void) door_return(buf, buflen, NULL, 0);
 828         return;
 829 fail:
 830         nvlist_free(cbarg.cb_invl);
 831         nvlist_free(cbarg.cb_onvl);
 832         rvalp->ir_err = err;
 833         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 834 }
 835 
 836 int
 837 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 838 {
 839         ipadm_dbwrite_cbarg_t   cb;
 840         uint32_t                flags = sargp->ia_flags;
 841         nvlist_t                *nvl = NULL;
 842         int                     err = 0;
 843         char                    strval[IPMGMT_STRSIZE];

 844 
 845         if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
 846             sargp->ia_ifname[0] == '\0') {
 847                 err = EINVAL;
 848                 goto ret;
 849         }
 850         if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 851                 goto ret;

 852         if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 853             sargp->ia_ifname)) != 0)
 854                 goto ret;
 855         (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
 856         if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)

 857                 goto ret;





 858         cb.dbw_nvl = nvl;
 859         cb.dbw_flags = 0;
 860         err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
 861 ret:
 862         nvlist_free(nvl);
 863         return (err);








































































































































 864 }


   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 2014 Nexenta Systems, Inc. All rights reserved.
  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 
  45 
  46 static void ipmgmt_common_handler(char *, char *, db_wfunc_t *);
  47 
  48 /* Handler declaration for each door command */
  49 typedef void ipmgmt_door_handler_t(void *argp);
  50 
  51 static ipmgmt_door_handler_t    ipmgmt_getaddr_handler,
  52                                 ipmgmt_getprop_handler,
  53                                 ipmgmt_getif_handler,
  54                                 ipmgmt_initif_handler,
  55                                 ipmgmt_aobjop_handler,
  56                                 ipmgmt_resetaddr_handler,
  57                                 ipmgmt_setif_handler,
  58                                 ipmgmt_resetif_handler,
  59                                 ipmgmt_resetprop_handler,
  60                                 ipmgmt_setaddr_handler,
  61                                 ipmgmt_setprop_handler,
  62                                 ipmgmt_ipmp_update_handler;
  63 
  64 typedef struct ipmgmt_door_info_s {
  65         uint_t                  idi_cmd;
  66         boolean_t               idi_set;
  67         ipmgmt_door_handler_t   *idi_handler;
  68 } ipmgmt_door_info_t;
  69 
  70 /* maps door commands to door handler functions */
  71 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
  72         { IPMGMT_CMD_SETPROP,           B_TRUE,  ipmgmt_setprop_handler },
  73         { IPMGMT_CMD_SETIF,             B_TRUE,  ipmgmt_setif_handler },
  74         { IPMGMT_CMD_SETADDR,           B_TRUE,  ipmgmt_setaddr_handler },
  75         { IPMGMT_CMD_GETPROP,           B_FALSE, ipmgmt_getprop_handler },
  76         { IPMGMT_CMD_GETIF,             B_FALSE, ipmgmt_getif_handler },
  77         { IPMGMT_CMD_GETADDR,           B_FALSE, ipmgmt_getaddr_handler },
  78         { IPMGMT_CMD_RESETIF,           B_TRUE,  ipmgmt_resetif_handler },
  79         { IPMGMT_CMD_RESETADDR,         B_TRUE,  ipmgmt_resetaddr_handler },
  80         { IPMGMT_CMD_RESETPROP,         B_TRUE,  ipmgmt_resetprop_handler },
  81         { IPMGMT_CMD_INITIF,            B_TRUE,  ipmgmt_initif_handler },
  82         { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE,  ipmgmt_aobjop_handler },
  83         { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE,  ipmgmt_aobjop_handler },
  84         { IPMGMT_CMD_ADDROBJ_ADD,       B_TRUE,  ipmgmt_aobjop_handler },
  85         { IPMGMT_CMD_AOBJNAME2ADDROBJ,  B_FALSE, ipmgmt_aobjop_handler },
  86         { IPMGMT_CMD_LIF2ADDROBJ,       B_FALSE, ipmgmt_aobjop_handler },
  87         { IPMGMT_CMD_IPMP_UPDATE,       B_FALSE, ipmgmt_ipmp_update_handler},
  88         { 0, 0, NULL },
  89 };
  90 
  91 /*
  92  * The main server procedure function that gets invoked for any of the incoming
  93  * door commands. Inside this function we identify the incoming command and
  94  * invoke the right door handler function.
  95  */
  96 /* ARGSUSED */
  97 void
  98 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
  99     uint_t n_desc)
 100 {
 101         ipmgmt_door_info_t      *infop = NULL;
 102         ipmgmt_retval_t         retval;
 103         int                     i;
 104         uint_t                  err;
 105         ucred_t                 *cred = NULL;
 106 
 107         for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {


 565         rval.ir_err = ipmgmt_persist_if(argp);
 566         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 567 }
 568 
 569 /*
 570  * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
 571  * deletes all the persisted interface configuration. It also deletes, from
 572  * `aobjmap', all the address objects configured on the given interface.
 573  */
 574 static void
 575 ipmgmt_resetif_handler(void *argp)
 576 {
 577         ipmgmt_if_arg_t         *rargp = argp;
 578         ipmgmt_retval_t         rval;
 579         ipmgmt_if_cbarg_t       cbarg;
 580         uint32_t                flags = rargp->ia_flags;
 581         int                     err = 0;
 582 
 583         cbarg.cb_family = rargp->ia_family;
 584         cbarg.cb_ifname = rargp->ia_ifname;
 585 
 586         cbarg.cb_ipv4exists = B_TRUE;
 587         cbarg.cb_ipv6exists = B_TRUE;
 588 
 589         if (flags & IPMGMT_PERSIST)
 590                 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 591                     IPADM_DB_DELETE);
 592 
 593         if (flags & IPMGMT_ACTIVE)
 594                 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 595                     flags);
 596 
 597         rval.ir_err = err;
 598         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 599 }
 600 
 601 /*
 602  * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
 603  * deletes all the persisted addrobj configuration. It also deletes the
 604  * corresponding node, from `aobjmap'.
 605  */
 606 static void
 607 ipmgmt_resetaddr_handler(void *argp)
 608 {


 630                  */
 631                 node.am_lnum = rargp->ia_lnum;
 632                 node.am_flags = flags;
 633                 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
 634         }
 635 
 636         rval.ir_err = err;
 637         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 638 }
 639 
 640 /*
 641  * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
 642  * address for a given `gargp->ia_aobjname'. If it is not defined then it
 643  * retrieves all the addresses configured on `gargp->ia_ifname'. The
 644  * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
 645  * handler through library.
 646  */
 647 static void
 648 ipmgmt_getaddr_handler(void *argp)
 649 {


 650         ipmgmt_getaddr_arg_t    *gargp = argp;



 651 
 652         ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname,
 653             ipmgmt_db_getaddr);








































 654 }
 655 
 656 /*
 657  * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
 658  * from the DB.
 659  */
 660 static void
 661 ipmgmt_resetprop_handler(void *argp)
 662 {
 663         ipmgmt_prop_arg_t       *pargp = argp;
 664         ipmgmt_retval_t         rval;
 665 
 666         assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
 667 
 668         rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
 669             IPADM_DB_DELETE);
 670         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 671 }
 672 
 673 /*
 674  * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
 675  * persisted interfaces and the IP protocols (IPv4 or IPv6) they support and
 676  * returns the info as a nvlist
 677  */
 678 static void
 679 ipmgmt_getif_handler(void *argp)
 680 {
 681         ipmgmt_getif_arg_t  *getif = argp;






 682 
 683         assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
 684 
 685         ipmgmt_common_handler(getif->ia_ifname, NULL,
 686             ipmgmt_db_getif);








































 687 }
 688 
 689 /*
 690  * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
 691  * interface configuration (interface properties and addresses), for all those
 692  * interfaces that need to be initialized.
 693  */
 694 static void
 695 ipmgmt_initif_handler(void *argp)
 696 {
 697         ipmgmt_initif_arg_t     *initif = argp;
 698         size_t                  buflen, nvlsize;
 699         char                    *buf = NULL, *onvlbuf, *invlbuf;
 700         ipmgmt_get_rval_t       rval, *rvalp = &rval;
 701         ipmgmt_initif_cbarg_t   cbarg;
 702         int                     err;
 703 
 704         assert(initif->ia_cmd == IPMGMT_CMD_INITIF);
 705 
 706         bzero(&cbarg, sizeof (cbarg));
 707         invlbuf = (char *)argp + sizeof (ipmgmt_initif_arg_t);
 708         nvlsize = initif->ia_nvlsize;
 709         err = nvlist_unpack(invlbuf, nvlsize, &cbarg.cb_invl, NV_ENCODE_NATIVE);
 710         if (err != 0)
 711                 goto fail;
 712 
 713         cbarg.cb_family = initif->ia_family;
 714         if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 715                 goto fail;
 716 
 717         err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
 718         if (err == ENOENT && cbarg.cb_ocnt > 0) {
 719                 /*
 720                  * If there is at least one entry in the nvlist,
 721                  * do not return error.
 722                  */
 723                 err = 0;
 724         }
 725         if (err != 0)
 726                 goto fail;
 727 
 728         if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
 729                 goto fail;
 730         buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
 731         /*
 732          * We cannot use malloc() here because door_return never returns, and
 733          * memory allocated by malloc() would get leaked. Use alloca() instead.
 734          */
 735         buf = alloca(buflen);
 736         onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
 737         if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &nvlsize,
 738             NV_ENCODE_NATIVE, 0)) != 0) {
 739                 goto fail;
 740         }


 742         nvlist_free(cbarg.cb_onvl);
 743         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 744         rvalp->ir_err = 0;
 745         rvalp->ir_nvlsize = nvlsize;
 746 
 747         (void) door_return(buf, buflen, NULL, 0);
 748         return;
 749 fail:
 750         nvlist_free(cbarg.cb_invl);
 751         nvlist_free(cbarg.cb_onvl);
 752         rvalp->ir_err = err;
 753         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 754 }
 755 
 756 int
 757 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 758 {
 759         ipadm_dbwrite_cbarg_t   cb;
 760         uint32_t        flags = sargp->ia_flags;
 761         nvlist_t        *nvl = NULL;

 762         char    strval[IPMGMT_STRSIZE];
 763         int     err = 0;
 764 
 765         if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
 766             sargp->ia_ifname[0] == '\0') {
 767                 err = EINVAL;
 768                 goto ret;
 769         }
 770         if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 771                 goto ret;
 772 
 773         if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 774             sargp->ia_ifname)) != 0)
 775                 goto ret;
 776 
 777         if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family,
 778             IPMGMT_APPEND)) != 0)
 779                 goto ret;
 780 
 781         (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_ifclass);
 782         if ((err = nvlist_add_string(nvl, IPADM_NVP_IFCLASS, strval)) != 0)
 783                 goto ret;
 784 
 785         cb.dbw_nvl = nvl;
 786         cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF;
 787         err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
 788 ret:
 789         nvlist_free(nvl);
 790         return (err);
 791 }
 792 
 793 /*
 794  * The helper for ipmgmt_getif_handler and ipmgmt_getaddr_handler
 795  */
 796 static void
 797 ipmgmt_common_handler(char *if_name, char *aobj_name, db_wfunc_t worker)
 798 {
 799         ipmgmt_get_rval_t   rval, *rvalp = &rval;
 800         ipmgmt_get_cbarg_t    cbarg;
 801         int     err = 0;
 802         size_t  buflen, onvlsize;
 803         char    *buf, *onvlbuf;
 804 
 805         cbarg.cb_ifname = if_name;
 806         cbarg.cb_aobjname = aobj_name;
 807         cbarg.cb_ocnt = 0;
 808 
 809         if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 810                 goto fail;
 811 
 812         err = ipmgmt_db_walk(worker, &cbarg, IPADM_DB_READ);
 813         if (err == ENOENT && cbarg.cb_ocnt > 0) {
 814                 /*
 815                  * If there is atleast one entry in the nvlist,
 816                  * do not return error.
 817                  */
 818                 err = 0;
 819         }
 820         if (err != 0)
 821                 goto fail;
 822 
 823         if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize,
 824             NV_ENCODE_NATIVE)) != 0)
 825                 goto fail;
 826 
 827         buflen = onvlsize + sizeof (ipmgmt_get_rval_t);
 828         /* We cannot use malloc() here because door_return never returns */
 829         buf = alloca(buflen);
 830         onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
 831         if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf,
 832             &onvlsize, NV_ENCODE_NATIVE, 0)) != 0)
 833                 goto fail;
 834 
 835         nvlist_free(cbarg.cb_onvl);
 836         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 837         rvalp->ir_err = 0;
 838         rvalp->ir_nvlsize = onvlsize;
 839 
 840         (void) door_return(buf, buflen, NULL, 0);
 841         return;
 842 
 843 fail:
 844         nvlist_free(cbarg.cb_onvl);
 845         rvalp->ir_err = err;
 846         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 847 }
 848 
 849 /*
 850  * Handles the door command IPMGMT_CMD_IPMP_UPDATE
 851  */
 852 static void
 853 ipmgmt_ipmp_update_handler(void *argp)
 854 {
 855         ipmgmt_ipmp_update_arg_t *uargp = argp;
 856         ipmgmt_retval_t rval;
 857         ipadm_dbwrite_cbarg_t   cb;
 858 
 859         boolean_t       gif_exists;
 860         char            gifname[LIFNAMSIZ];
 861         nvlist_t        *nvl = NULL;
 862         uint32_t        flags = uargp->ia_flags;
 863         int             err = 0;
 864 
 865         assert(uargp->ia_cmd == IPMGMT_CMD_IPMP_UPDATE);
 866 
 867         gif_exists = ipmgmt_persist_if_exists(uargp->ia_gifname,
 868             AF_UNSPEC);
 869 
 870         if (!ipmgmt_persist_if_exists(uargp->ia_mifname, AF_UNSPEC)) {
 871                 err = EINVAL;
 872                 goto ret;
 873         }
 874 
 875         ipmgmt_get_group_interface(uargp->ia_mifname, gifname, LIFNAMSIZ);
 876 
 877         if (flags & IPMGMT_APPEND) {
 878                 /* group interface should be available in the DB */
 879                 if (!gif_exists) {
 880                         err = ENOENT;
 881                         goto ret;
 882                 }
 883 
 884                 if (gifname[0] != '\0') {
 885                         err = EEXIST;
 886                         goto ret;
 887                 }
 888         }
 889 
 890         if (flags & IPMGMT_REMOVE) {
 891                 /* We cannot remove something that does not exist */
 892                 if (!gif_exists || gifname[0] == '\0') {
 893                         err = ENOENT;
 894                         goto ret;
 895                 }
 896                 if (strcmp(uargp->ia_gifname, gifname) != 0) {
 897                         err = EINVAL;
 898                         goto ret;
 899                 }
 900         }
 901 
 902         if (flags & IPMGMT_PERSIST) {
 903 
 904                 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 905                         goto ret;
 906 
 907                 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 908                     uargp->ia_gifname)) != 0)
 909                         goto ret;
 910 
 911                 if ((err = nvlist_add_string(nvl, IPADM_NVP_MIFNAMES,
 912                     uargp->ia_mifname)) != 0)
 913                         goto ret;
 914 
 915                 if ((err = nvlist_add_string(nvl, IPADM_NVP_GIFNAME,
 916                     uargp->ia_gifname)) != 0)
 917                         goto ret;
 918 
 919                 cb.dbw_nvl = nvl;
 920                 cb.dbw_flags = flags | IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP;
 921                 err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
 922         }
 923 ret:
 924         nvlist_free(nvl);
 925         rval.ir_err = err;
 926         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 927 }