Print this page
Commit 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 2014 Nexenta Systems, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Main door handler functions used by ipmgmtd to process the different door
  28   29   * call requests, issued by the library libipadm.so.
  29   30   */
  30   31  
  31   32  #include <alloca.h>
  32   33  #include <pwd.h>
  33   34  #include <auth_attr.h>
  34   35  #include <secdb.h>
  35   36  #include <stdlib.h>
  36   37  #include <stdio.h>
  37   38  #include <string.h>
  38   39  #include <strings.h>
  39   40  #include <errno.h>
  40   41  #include <assert.h>
  41   42  #include <libnvpair.h>
  42   43  #include "ipmgmt_impl.h"
  43   44  
       45 +
       46 +static void ipmgmt_common_handler(char *, char *, db_wfunc_t *);
       47 +
  44   48  /* Handler declaration for each door command */
  45   49  typedef void ipmgmt_door_handler_t(void *argp);
  46   50  
  47   51  static ipmgmt_door_handler_t    ipmgmt_getaddr_handler,
  48   52                                  ipmgmt_getprop_handler,
  49   53                                  ipmgmt_getif_handler,
  50   54                                  ipmgmt_initif_handler,
  51   55                                  ipmgmt_aobjop_handler,
  52   56                                  ipmgmt_resetaddr_handler,
  53   57                                  ipmgmt_setif_handler,
  54   58                                  ipmgmt_resetif_handler,
  55   59                                  ipmgmt_resetprop_handler,
  56   60                                  ipmgmt_setaddr_handler,
  57      -                                ipmgmt_setprop_handler;
       61 +                                ipmgmt_setprop_handler,
       62 +                                ipmgmt_ipmp_update_handler;
  58   63  
  59   64  typedef struct ipmgmt_door_info_s {
  60   65          uint_t                  idi_cmd;
  61   66          boolean_t               idi_set;
  62   67          ipmgmt_door_handler_t   *idi_handler;
  63   68  } ipmgmt_door_info_t;
  64   69  
  65   70  /* maps door commands to door handler functions */
  66   71  static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
  67   72          { IPMGMT_CMD_SETPROP,           B_TRUE,  ipmgmt_setprop_handler },
↓ open down ↓ 4 lines elided ↑ open up ↑
  72   77          { IPMGMT_CMD_GETADDR,           B_FALSE, ipmgmt_getaddr_handler },
  73   78          { IPMGMT_CMD_RESETIF,           B_TRUE,  ipmgmt_resetif_handler },
  74   79          { IPMGMT_CMD_RESETADDR,         B_TRUE,  ipmgmt_resetaddr_handler },
  75   80          { IPMGMT_CMD_RESETPROP,         B_TRUE,  ipmgmt_resetprop_handler },
  76   81          { IPMGMT_CMD_INITIF,            B_TRUE,  ipmgmt_initif_handler },
  77   82          { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE,  ipmgmt_aobjop_handler },
  78   83          { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE,  ipmgmt_aobjop_handler },
  79   84          { IPMGMT_CMD_ADDROBJ_ADD,       B_TRUE,  ipmgmt_aobjop_handler },
  80   85          { IPMGMT_CMD_AOBJNAME2ADDROBJ,  B_FALSE, ipmgmt_aobjop_handler },
  81   86          { IPMGMT_CMD_LIF2ADDROBJ,       B_FALSE, ipmgmt_aobjop_handler },
       87 +        { IPMGMT_CMD_IPMP_UPDATE,       B_FALSE, ipmgmt_ipmp_update_handler},
  82   88          { 0, 0, NULL },
  83   89  };
  84   90  
  85   91  /*
  86   92   * The main server procedure function that gets invoked for any of the incoming
  87   93   * door commands. Inside this function we identify the incoming command and
  88   94   * invoke the right door handler function.
  89   95   */
  90   96  /* ARGSUSED */
  91   97  void
↓ open down ↓ 477 lines elided ↑ open up ↑
 569  575  ipmgmt_resetif_handler(void *argp)
 570  576  {
 571  577          ipmgmt_if_arg_t         *rargp = argp;
 572  578          ipmgmt_retval_t         rval;
 573  579          ipmgmt_if_cbarg_t       cbarg;
 574  580          uint32_t                flags = rargp->ia_flags;
 575  581          int                     err = 0;
 576  582  
 577  583          cbarg.cb_family = rargp->ia_family;
 578  584          cbarg.cb_ifname = rargp->ia_ifname;
      585 +
      586 +        cbarg.cb_ipv4exists = B_TRUE;
      587 +        cbarg.cb_ipv6exists = B_TRUE;
      588 +
 579  589          if (flags & IPMGMT_PERSIST)
 580  590                  err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
 581  591                      IPADM_DB_DELETE);
 582  592  
 583  593          if (flags & IPMGMT_ACTIVE)
 584  594                  i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
 585  595                      flags);
 586  596  
 587  597          rval.ir_err = err;
 588  598          (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
↓ open down ↓ 41 lines elided ↑ open up ↑
 630  640  /*
 631  641   * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
 632  642   * address for a given `gargp->ia_aobjname'. If it is not defined then it
 633  643   * retrieves all the addresses configured on `gargp->ia_ifname'. The
 634  644   * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
 635  645   * handler through library.
 636  646   */
 637  647  static void
 638  648  ipmgmt_getaddr_handler(void *argp)
 639  649  {
 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;
      650 +        ipmgmt_getaddr_arg_t    *gargp = argp;
 646  651  
 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);
      652 +        ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname,
      653 +            ipmgmt_db_getaddr);
 689  654  }
 690  655  
 691  656  /*
 692  657   * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
 693  658   * from the DB.
 694  659   */
 695  660  static void
 696  661  ipmgmt_resetprop_handler(void *argp)
 697  662  {
 698  663          ipmgmt_prop_arg_t       *pargp = argp;
↓ open down ↓ 1 lines elided ↑ open up ↑
 700  665  
 701  666          assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
 702  667  
 703  668          rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
 704  669              IPADM_DB_DELETE);
 705  670          (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
 706  671  }
 707  672  
 708  673  /*
 709  674   * 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.
      675 + * persisted interfaces and the IP protocols (IPv4 or IPv6) they support and
      676 + * returns the info as a nvlist
 711  677   */
 712  678  static void
 713  679  ipmgmt_getif_handler(void *argp)
 714  680  {
 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;
      681 +        ipmgmt_getif_arg_t  *getif = argp;
 722  682  
 723  683          assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
 724  684  
 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);
      685 +        ipmgmt_common_handler(getif->ia_ifname, NULL,
      686 +            ipmgmt_db_getif);
 767  687  }
 768  688  
 769  689  /*
 770  690   * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
 771  691   * interface configuration (interface properties and addresses), for all those
 772  692   * interfaces that need to be initialized.
 773  693   */
 774  694  static void
 775  695  ipmgmt_initif_handler(void *argp)
 776  696  {
↓ open down ↓ 13 lines elided ↑ open up ↑
 790  710          if (err != 0)
 791  711                  goto fail;
 792  712  
 793  713          cbarg.cb_family = initif->ia_family;
 794  714          if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
 795  715                  goto fail;
 796  716  
 797  717          err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
 798  718          if (err == ENOENT && cbarg.cb_ocnt > 0) {
 799  719                  /*
 800      -                 * If there is atleast one entry in the nvlist,
      720 +                 * If there is at least one entry in the nvlist,
 801  721                   * do not return error.
 802  722                   */
 803  723                  err = 0;
 804  724          }
 805  725          if (err != 0)
 806  726                  goto fail;
 807  727  
 808  728          if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
 809  729                  goto fail;
 810  730          buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
↓ open down ↓ 19 lines elided ↑ open up ↑
 830  750          nvlist_free(cbarg.cb_invl);
 831  751          nvlist_free(cbarg.cb_onvl);
 832  752          rvalp->ir_err = err;
 833  753          (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
 834  754  }
 835  755  
 836  756  int
 837  757  ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
 838  758  {
 839  759          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];
      760 +        uint32_t        flags = sargp->ia_flags;
      761 +        nvlist_t        *nvl = NULL;
      762 +        char    strval[IPMGMT_STRSIZE];
      763 +        int     err = 0;
 844  764  
 845  765          if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
 846  766              sargp->ia_ifname[0] == '\0') {
 847  767                  err = EINVAL;
 848  768                  goto ret;
 849  769          }
 850  770          if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 851  771                  goto ret;
      772 +
 852  773          if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
 853  774              sargp->ia_ifname)) != 0)
 854  775                  goto ret;
 855      -        (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
 856      -        if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
      776 +
      777 +        if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family,
      778 +            IPMGMT_APPEND)) != 0)
 857  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 +
 858  785          cb.dbw_nvl = nvl;
 859      -        cb.dbw_flags = 0;
 860      -        err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
      786 +        cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF;
      787 +        err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE);
 861  788  ret:
 862  789          nvlist_free(nvl);
 863  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);
 864  927  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX