Print this page
NEX-7823 ipmgmtd can't properly remove interface from the old ipadm.conf format
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
OS-161: Integrate 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  * Copyright (c) 2016-2017, 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 



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

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

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


 575         rval.ir_err = ipmgmt_persist_if(argp);
 576         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 577 }
 578 
 579 /*
 580  * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
 581  * deletes all the persisted interface configuration. It also deletes, from
 582  * `aobjmap', all the address objects configured on the given interface.
 583  */
 584 static void
 585 ipmgmt_resetif_handler(void *argp)
 586 {
 587         ipmgmt_if_arg_t         *rargp = argp;
 588         ipmgmt_retval_t         rval;
 589         ipmgmt_if_cbarg_t       cbarg;
 590         uint32_t                flags = rargp->ia_flags;
 591         int                     err = 0;
 592 
 593         cbarg.cb_family = rargp->ia_family;
 594         cbarg.cb_ifname = rargp->ia_ifname;




 595         if (flags & IPMGMT_PERSIST)
 596                 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 597                     IPADM_DB_DELETE);
 598 
 599         if (flags & IPMGMT_ACTIVE)
 600                 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 601                     flags);
 602 
 603         rval.ir_err = err;
 604         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 605 }
 606 
 607 /*
 608  * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
 609  * deletes all the persisted addrobj configuration. It also deletes the
 610  * corresponding node, from `aobjmap'.
 611  */
 612 static void
 613 ipmgmt_resetaddr_handler(void *argp)
 614 {


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


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


 838         nvlist_free(cbarg.cb_onvl);
 839         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 840         rvalp->ir_err = 0;
 841         rvalp->ir_nvlsize = nvlsize;
 842 
 843         (void) door_return(buf, buflen, NULL, 0);
 844         return;
 845 fail:
 846         nvlist_free(cbarg.cb_invl);
 847         nvlist_free(cbarg.cb_onvl);
 848         rvalp->ir_err = err;
 849         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 850 }
 851 
 852 int
 853 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 854 {
 855         ipadm_dbwrite_cbarg_t   cb;
 856         uint32_t                flags = sargp->ia_flags;
 857         nvlist_t                *nvl = NULL;
 858         int                     err = 0;
 859         char                    strval[IPMGMT_STRSIZE];

 860 
 861         if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
 862             sargp->ia_ifname[0] == '\0') {
 863                 err = EINVAL;
 864                 goto ret;
 865         }
 866         if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 867                 goto ret;

 868         if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 869             sargp->ia_ifname)) != 0)
 870                 goto ret;
 871         (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
 872         if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)

 873                 goto ret;





 874         cb.dbw_nvl = nvl;
 875         cb.dbw_flags = 0;
 876         err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
 877 ret:
 878         nvlist_free(nvl);
 879         return (err);






































































































































 880 }


   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 2016 Nexenta Systems, Inc.
  25  * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
  26  */
  27 
  28 /*
  29  * Main door handler functions used by ipmgmtd to process the different door
  30  * call requests, issued by the library libipadm.so.
  31  */
  32 
  33 #include <alloca.h>
  34 #include <pwd.h>
  35 #include <auth_attr.h>
  36 #include <secdb.h>
  37 #include <stdlib.h>
  38 #include <stdio.h>
  39 #include <string.h>
  40 #include <strings.h>
  41 #include <errno.h>
  42 #include <assert.h>
  43 #include <libnvpair.h>
  44 #include "ipmgmt_impl.h"
  45 
  46 
  47 static void ipmgmt_common_handler(char *, char *, db_wfunc_t *);
  48 
  49 /* Handler declaration for each door command */
  50 typedef void ipmgmt_door_handler_t(void *argp);
  51 
  52 static ipmgmt_door_handler_t    ipmgmt_getaddr_handler,
  53                                 ipmgmt_getprop_handler,
  54                                 ipmgmt_getif_handler,
  55                                 ipmgmt_initif_handler,
  56                                 ipmgmt_aobjop_handler,
  57                                 ipmgmt_resetaddr_handler,
  58                                 ipmgmt_setif_handler,
  59                                 ipmgmt_resetif_handler,
  60                                 ipmgmt_resetprop_handler,
  61                                 ipmgmt_setaddr_handler,
  62                                 ipmgmt_setprop_handler,
  63                                 ipmgmt_ipmp_update_handler;
  64 
  65 typedef struct ipmgmt_door_info_s {
  66         uint_t                  idi_cmd;
  67         boolean_t               idi_set;
  68         ipmgmt_door_handler_t   *idi_handler;
  69 } ipmgmt_door_info_t;
  70 
  71 /* maps door commands to door handler functions */
  72 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
  73         { IPMGMT_CMD_SETPROP,           B_TRUE,  ipmgmt_setprop_handler },
  74         { IPMGMT_CMD_SETIF,             B_TRUE,  ipmgmt_setif_handler },
  75         { IPMGMT_CMD_SETADDR,           B_TRUE,  ipmgmt_setaddr_handler },
  76         { IPMGMT_CMD_GETPROP,           B_FALSE, ipmgmt_getprop_handler },
  77         { IPMGMT_CMD_GETIF,             B_FALSE, ipmgmt_getif_handler },
  78         { IPMGMT_CMD_GETADDR,           B_FALSE, ipmgmt_getaddr_handler },
  79         { IPMGMT_CMD_RESETIF,           B_TRUE,  ipmgmt_resetif_handler },
  80         { IPMGMT_CMD_RESETADDR,         B_TRUE,  ipmgmt_resetaddr_handler },
  81         { IPMGMT_CMD_RESETPROP,         B_TRUE,  ipmgmt_resetprop_handler },
  82         { IPMGMT_CMD_INITIF,            B_TRUE,  ipmgmt_initif_handler },
  83         { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE,  ipmgmt_aobjop_handler },
  84         { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE,  ipmgmt_aobjop_handler },
  85         { IPMGMT_CMD_ADDROBJ_ADD,       B_TRUE,  ipmgmt_aobjop_handler },
  86         { IPMGMT_CMD_AOBJNAME2ADDROBJ,  B_FALSE, ipmgmt_aobjop_handler },
  87         { IPMGMT_CMD_LIF2ADDROBJ,       B_FALSE, ipmgmt_aobjop_handler },
  88         { IPMGMT_CMD_IPMP_UPDATE,       B_FALSE, ipmgmt_ipmp_update_handler},
  89         { 0, 0, NULL },
  90 };
  91 
  92 /*
  93  * The main server procedure function that gets invoked for any of the incoming
  94  * door commands. Inside this function we identify the incoming command and
  95  * invoke the right door handler function.
  96  */
  97 /* ARGSUSED */
  98 void
  99 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
 100     uint_t n_desc)
 101 {
 102         ipmgmt_door_info_t      *infop = NULL;
 103         ipmgmt_retval_t         retval;
 104         int                     i;
 105         uint_t                  err;
 106         ucred_t                 *cred = NULL;
 107 
 108         for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {


 581         rval.ir_err = ipmgmt_persist_if(argp);
 582         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 583 }
 584 
 585 /*
 586  * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
 587  * deletes all the persisted interface configuration. It also deletes, from
 588  * `aobjmap', all the address objects configured on the given interface.
 589  */
 590 static void
 591 ipmgmt_resetif_handler(void *argp)
 592 {
 593         ipmgmt_if_arg_t         *rargp = argp;
 594         ipmgmt_retval_t         rval;
 595         ipmgmt_if_cbarg_t       cbarg;
 596         uint32_t                flags = rargp->ia_flags;
 597         int                     err = 0;
 598 
 599         cbarg.cb_family = rargp->ia_family;
 600         cbarg.cb_ifname = rargp->ia_ifname;
 601 
 602         cbarg.cb_ipv4exists = B_TRUE;
 603         cbarg.cb_ipv6exists = B_TRUE;
 604 
 605         if (flags & IPMGMT_PERSIST)
 606                 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 607                     IPADM_DB_DELETE);
 608 
 609         if (flags & IPMGMT_ACTIVE)
 610                 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 611                     flags);
 612 
 613         rval.ir_err = err;
 614         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 615 }
 616 
 617 /*
 618  * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
 619  * deletes all the persisted addrobj configuration. It also deletes the
 620  * corresponding node, from `aobjmap'.
 621  */
 622 static void
 623 ipmgmt_resetaddr_handler(void *argp)
 624 {


 646                  */
 647                 node.am_lnum = rargp->ia_lnum;
 648                 node.am_flags = flags;
 649                 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
 650         }
 651 
 652         rval.ir_err = err;
 653         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 654 }
 655 
 656 /*
 657  * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
 658  * address for a given `gargp->ia_aobjname'. If it is not defined then it
 659  * retrieves all the addresses configured on `gargp->ia_ifname'. The
 660  * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
 661  * handler through library.
 662  */
 663 static void
 664 ipmgmt_getaddr_handler(void *argp)
 665 {


 666         ipmgmt_getaddr_arg_t    *gargp = argp;



 667 
 668         ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname,
 669             ipmgmt_db_getaddr);








































 670 }
 671 
 672 /*
 673  * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
 674  * from the DB.
 675  */
 676 static void
 677 ipmgmt_resetprop_handler(void *argp)
 678 {
 679         ipmgmt_prop_arg_t       *pargp = argp;
 680         ipmgmt_retval_t         rval;
 681 
 682         assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
 683 
 684         rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
 685             IPADM_DB_DELETE);
 686         (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 687 }
 688 
 689 /*
 690  * Handles the door command IPMGMT_CMD_GETIF. It retrieves names of all
 691  * persisted interfaces and the IP protocol families (IPv4 or IPv6) they
 692  * support. Returns the info as a nvlist using door_return() from
 693  * ipmgmt_common_handler().
 694  */
 695 static void
 696 ipmgmt_getif_handler(void *argp)
 697 {
 698         ipmgmt_getif_arg_t  *getif = argp;






 699 
 700         assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
 701 
 702         ipmgmt_common_handler(getif->ia_ifname, NULL,
 703             ipmgmt_db_getif);








































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


 759         nvlist_free(cbarg.cb_onvl);
 760         rvalp = (ipmgmt_get_rval_t *)(void *)buf;
 761         rvalp->ir_err = 0;
 762         rvalp->ir_nvlsize = nvlsize;
 763 
 764         (void) door_return(buf, buflen, NULL, 0);
 765         return;
 766 fail:
 767         nvlist_free(cbarg.cb_invl);
 768         nvlist_free(cbarg.cb_onvl);
 769         rvalp->ir_err = err;
 770         (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 771 }
 772 
 773 int
 774 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 775 {
 776         ipadm_dbwrite_cbarg_t   cb;
 777         uint32_t        flags = sargp->ia_flags;
 778         nvlist_t        *nvl = NULL;

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