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

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
          +++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2016 Nexenta Systems, Inc.
  24   25   * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>.
  25   26   */
  26   27  
  27   28  /*
  28   29   * Main door handler functions used by ipmgmtd to process the different door
  29   30   * call requests, issued by the library libipadm.so.
  30   31   */
  31   32  
  32   33  #include <alloca.h>
  33   34  #include <pwd.h>
↓ open down ↓ 1 lines elided ↑ open up ↑
  35   36  #include <secdb.h>
  36   37  #include <stdlib.h>
  37   38  #include <stdio.h>
  38   39  #include <string.h>
  39   40  #include <strings.h>
  40   41  #include <errno.h>
  41   42  #include <assert.h>
  42   43  #include <libnvpair.h>
  43   44  #include "ipmgmt_impl.h"
  44   45  
       46 +
       47 +static void ipmgmt_common_handler(char *, char *, db_wfunc_t *);
       48 +
  45   49  /* Handler declaration for each door command */
  46   50  typedef void ipmgmt_door_handler_t(void *argp);
  47   51  
  48   52  static ipmgmt_door_handler_t    ipmgmt_getaddr_handler,
  49   53                                  ipmgmt_getprop_handler,
  50   54                                  ipmgmt_getif_handler,
  51   55                                  ipmgmt_initif_handler,
  52   56                                  ipmgmt_aobjop_handler,
  53   57                                  ipmgmt_resetaddr_handler,
  54   58                                  ipmgmt_setif_handler,
  55   59                                  ipmgmt_resetif_handler,
  56   60                                  ipmgmt_resetprop_handler,
  57   61                                  ipmgmt_setaddr_handler,
  58      -                                ipmgmt_setprop_handler;
       62 +                                ipmgmt_setprop_handler,
       63 +                                ipmgmt_ipmp_update_handler;
  59   64  
  60   65  typedef struct ipmgmt_door_info_s {
  61   66          uint_t                  idi_cmd;
  62   67          boolean_t               idi_set;
  63   68          ipmgmt_door_handler_t   *idi_handler;
  64   69  } ipmgmt_door_info_t;
  65   70  
  66   71  /* maps door commands to door handler functions */
  67   72  static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
  68   73          { IPMGMT_CMD_SETPROP,           B_TRUE,  ipmgmt_setprop_handler },
↓ open down ↓ 4 lines elided ↑ open up ↑
  73   78          { IPMGMT_CMD_GETADDR,           B_FALSE, ipmgmt_getaddr_handler },
  74   79          { IPMGMT_CMD_RESETIF,           B_TRUE,  ipmgmt_resetif_handler },
  75   80          { IPMGMT_CMD_RESETADDR,         B_TRUE,  ipmgmt_resetaddr_handler },
  76   81          { IPMGMT_CMD_RESETPROP,         B_TRUE,  ipmgmt_resetprop_handler },
  77   82          { IPMGMT_CMD_INITIF,            B_TRUE,  ipmgmt_initif_handler },
  78   83          { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE,  ipmgmt_aobjop_handler },
  79   84          { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE,  ipmgmt_aobjop_handler },
  80   85          { IPMGMT_CMD_ADDROBJ_ADD,       B_TRUE,  ipmgmt_aobjop_handler },
  81   86          { IPMGMT_CMD_AOBJNAME2ADDROBJ,  B_FALSE, ipmgmt_aobjop_handler },
  82   87          { IPMGMT_CMD_LIF2ADDROBJ,       B_FALSE, ipmgmt_aobjop_handler },
       88 +        { IPMGMT_CMD_IPMP_UPDATE,       B_FALSE, ipmgmt_ipmp_update_handler},
  83   89          { 0, 0, NULL },
  84   90  };
  85   91  
  86   92  /*
  87   93   * The main server procedure function that gets invoked for any of the incoming
  88   94   * door commands. Inside this function we identify the incoming command and
  89   95   * invoke the right door handler function.
  90   96   */
  91   97  /* ARGSUSED */
  92   98  void
↓ open down ↓ 492 lines elided ↑ open up ↑
 585  591  ipmgmt_resetif_handler(void *argp)
 586  592  {
 587  593          ipmgmt_if_arg_t         *rargp = argp;
 588  594          ipmgmt_retval_t         rval;
 589  595          ipmgmt_if_cbarg_t       cbarg;
 590  596          uint32_t                flags = rargp->ia_flags;
 591  597          int                     err = 0;
 592  598  
 593  599          cbarg.cb_family = rargp->ia_family;
 594  600          cbarg.cb_ifname = rargp->ia_ifname;
      601 +
      602 +        cbarg.cb_ipv4exists = B_TRUE;
      603 +        cbarg.cb_ipv6exists = B_TRUE;
      604 +
 595  605          if (flags & IPMGMT_PERSIST)
 596  606                  err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 597  607                      IPADM_DB_DELETE);
 598  608  
 599  609          if (flags & IPMGMT_ACTIVE)
 600  610                  i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 601  611                      flags);
 602  612  
 603  613          rval.ir_err = err;
 604  614          (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
↓ open down ↓ 41 lines elided ↑ open up ↑
 646  656  /*
 647  657   * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
 648  658   * address for a given `gargp->ia_aobjname'. If it is not defined then it
 649  659   * retrieves all the addresses configured on `gargp->ia_ifname'. The
 650  660   * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
 651  661   * handler through library.
 652  662   */
 653  663  static void
 654  664  ipmgmt_getaddr_handler(void *argp)
 655  665  {
 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;
      666 +        ipmgmt_getaddr_arg_t    *gargp = argp;
 662  667  
 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);
      668 +        ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname,
      669 +            ipmgmt_db_getaddr);
 705  670  }
 706  671  
 707  672  /*
 708  673   * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
 709  674   * from the DB.
 710  675   */
 711  676  static void
 712  677  ipmgmt_resetprop_handler(void *argp)
 713  678  {
 714  679          ipmgmt_prop_arg_t       *pargp = argp;
 715  680          ipmgmt_retval_t         rval;
 716  681  
 717  682          assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
 718  683  
 719  684          rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
 720  685              IPADM_DB_DELETE);
 721  686          (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 722  687  }
 723  688  
 724  689  /*
 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.
      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().
 727  694   */
 728  695  static void
 729  696  ipmgmt_getif_handler(void *argp)
 730  697  {
 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;
      698 +        ipmgmt_getif_arg_t  *getif = argp;
 738  699  
 739  700          assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
 740  701  
 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);
      702 +        ipmgmt_common_handler(getif->ia_ifname, NULL,
      703 +            ipmgmt_db_getif);
 783  704  }
 784  705  
 785  706  /*
 786  707   * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
 787  708   * interface configuration (interface properties and addresses), for all those
 788  709   * interfaces that need to be initialized.
 789  710   */
 790  711  static void
 791  712  ipmgmt_initif_handler(void *argp)
 792  713  {
↓ open down ↓ 13 lines elided ↑ open up ↑
 806  727          if (err != 0)
 807  728                  goto fail;
 808  729  
 809  730          cbarg.cb_family = initif->ia_family;
 810  731          if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 811  732                  goto fail;
 812  733  
 813  734          err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
 814  735          if (err == ENOENT && cbarg.cb_ocnt > 0) {
 815  736                  /*
 816      -                 * If there is atleast one entry in the nvlist,
      737 +                 * If there is at least one entry in the nvlist,
 817  738                   * do not return error.
 818  739                   */
 819  740                  err = 0;
 820  741          }
 821  742          if (err != 0)
 822  743                  goto fail;
 823  744  
 824  745          if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
 825  746                  goto fail;
 826  747          buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
↓ open down ↓ 19 lines elided ↑ open up ↑
 846  767          nvlist_free(cbarg.cb_invl);
 847  768          nvlist_free(cbarg.cb_onvl);
 848  769          rvalp->ir_err = err;
 849  770          (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 850  771  }
 851  772  
 852  773  int
 853  774  ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 854  775  {
 855  776          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];
      777 +        uint32_t        flags = sargp->ia_flags;
      778 +        nvlist_t        *nvl = NULL;
      779 +        char    strval[IPMGMT_STRSIZE];
      780 +        int     err = 0;
 860  781  
 861  782          if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
 862  783              sargp->ia_ifname[0] == '\0') {
 863  784                  err = EINVAL;
 864  785                  goto ret;
 865  786          }
 866  787          if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 867  788                  goto ret;
      789 +
 868  790          if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 869  791              sargp->ia_ifname)) != 0)
 870  792                  goto ret;
 871      -        (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
 872      -        if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
      793 +
      794 +        if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family,
      795 +            IPMGMT_APPEND)) != 0)
 873  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 +
 874  802          cb.dbw_nvl = nvl;
 875      -        cb.dbw_flags = 0;
 876      -        err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
      803 +        cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF;
      804 +        err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
 877  805  ret:
 878  806          nvlist_free(nvl);
 879  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);
 880  942  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX