Print this page
Commit IPMP changes

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 Nexenta Systems, Inc. All rights reserved. */ /* * Main door handler functions used by ipmgmtd to process the different door * call requests, issued by the library libipadm.so.
*** 39,48 **** --- 40,52 ---- #include <errno.h> #include <assert.h> #include <libnvpair.h> #include "ipmgmt_impl.h" + + static void ipmgmt_common_handler(char *, char *, db_wfunc_t *); + /* Handler declaration for each door command */ typedef void ipmgmt_door_handler_t(void *argp); static ipmgmt_door_handler_t ipmgmt_getaddr_handler, ipmgmt_getprop_handler,
*** 52,62 **** ipmgmt_resetaddr_handler, ipmgmt_setif_handler, ipmgmt_resetif_handler, ipmgmt_resetprop_handler, ipmgmt_setaddr_handler, ! ipmgmt_setprop_handler; typedef struct ipmgmt_door_info_s { uint_t idi_cmd; boolean_t idi_set; ipmgmt_door_handler_t *idi_handler; --- 56,67 ---- ipmgmt_resetaddr_handler, ipmgmt_setif_handler, ipmgmt_resetif_handler, ipmgmt_resetprop_handler, ipmgmt_setaddr_handler, ! ipmgmt_setprop_handler, ! ipmgmt_ipmp_update_handler; typedef struct ipmgmt_door_info_s { uint_t idi_cmd; boolean_t idi_set; ipmgmt_door_handler_t *idi_handler;
*** 77,86 **** --- 82,92 ---- { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE, ipmgmt_aobjop_handler }, { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE, ipmgmt_aobjop_handler }, { IPMGMT_CMD_ADDROBJ_ADD, B_TRUE, ipmgmt_aobjop_handler }, { IPMGMT_CMD_AOBJNAME2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler }, { IPMGMT_CMD_LIF2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler }, + { IPMGMT_CMD_IPMP_UPDATE, B_FALSE, ipmgmt_ipmp_update_handler}, { 0, 0, NULL }, }; /* * The main server procedure function that gets invoked for any of the incoming
*** 574,583 **** --- 580,593 ---- uint32_t flags = rargp->ia_flags; int err = 0; cbarg.cb_family = rargp->ia_family; cbarg.cb_ifname = rargp->ia_ifname; + + cbarg.cb_ipv4exists = B_TRUE; + cbarg.cb_ipv6exists = B_TRUE; + if (flags & IPMGMT_PERSIST) err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg, IPADM_DB_DELETE); if (flags & IPMGMT_ACTIVE)
*** 635,693 **** * handler through library. */ static void ipmgmt_getaddr_handler(void *argp) { - size_t buflen, onvlsize; - char *buf, *onvlbuf; ipmgmt_getaddr_arg_t *gargp = argp; - ipmgmt_getaddr_cbarg_t cbarg; - ipmgmt_get_rval_t rval, *rvalp = &rval; - int err = 0; ! cbarg.cb_ifname = gargp->ia_ifname; ! cbarg.cb_aobjname = gargp->ia_aobjname; ! cbarg.cb_ocnt = 0; ! if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) ! goto fail; ! err = ipmgmt_db_walk(ipmgmt_db_getaddr, &cbarg, IPADM_DB_READ); ! if (err == ENOENT && cbarg.cb_ocnt > 0) { ! /* ! * If there is atleast one entry in the nvlist, ! * do not return error. ! */ ! err = 0; ! } ! if (err != 0) ! goto fail; ! ! if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize, ! NV_ENCODE_NATIVE)) != 0) { ! goto fail; ! } ! buflen = onvlsize + sizeof (ipmgmt_get_rval_t); ! /* ! * We cannot use malloc() here because door_return never returns, and ! * memory allocated by malloc() would get leaked. Use alloca() instead. ! */ ! buf = alloca(buflen); ! onvlbuf = buf + sizeof (ipmgmt_get_rval_t); ! if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &onvlsize, ! NV_ENCODE_NATIVE, 0)) != 0) { ! goto fail; ! } ! nvlist_free(cbarg.cb_onvl); ! rvalp = (ipmgmt_get_rval_t *)(void *)buf; ! rvalp->ir_err = 0; ! rvalp->ir_nvlsize = onvlsize; ! ! (void) door_return(buf, buflen, NULL, 0); ! return; ! fail: ! nvlist_free(cbarg.cb_onvl); ! rvalp->ir_err = err; ! (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); } /* * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line * from the DB. --- 645,658 ---- * handler through library. */ static void ipmgmt_getaddr_handler(void *argp) { ipmgmt_getaddr_arg_t *gargp = argp; ! ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname, ! ipmgmt_db_getaddr); } /* * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line * from the DB.
*** 705,771 **** (void) door_return((char *)&rval, sizeof (rval), NULL, 0); } /* * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the ! * persisted interfaces and the IP protocols (IPv4 or IPv6) they support. */ static void ipmgmt_getif_handler(void *argp) { ipmgmt_getif_arg_t *getif = argp; - ipmgmt_getif_rval_t *rvalp; - ipmgmt_retval_t rval; - ipmgmt_getif_cbarg_t cbarg; - ipadm_if_info_t *ifp, *rifp, *curifp; - int i, err = 0, count = 0; - size_t rbufsize; assert(getif->ia_cmd == IPMGMT_CMD_GETIF); ! bzero(&cbarg, sizeof (cbarg)); ! cbarg.cb_ifname = getif->ia_ifname; ! err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ); ! if (err == ENOENT && cbarg.cb_ifinfo) { ! /* ! * If there is atleast one entry in the nvlist, ! * do not return error. ! */ ! err = 0; ! } ! if (err != 0) { ! rval.ir_err = err; ! (void) door_return((char *)&rval, sizeof (rval), NULL, 0); ! return; ! } ! ! /* allocate sufficient buffer to return the interface info */ ! for (ifp = cbarg.cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next) ! ++count; ! rbufsize = sizeof (*rvalp) + count * sizeof (*ifp); ! rvalp = alloca(rbufsize); ! bzero(rvalp, rbufsize); ! ! rvalp->ir_ifcnt = count; ! rifp = rvalp->ir_ifinfo; ! ifp = cbarg.cb_ifinfo; ! ! /* ! * copy the interface info to buffer allocated on stack. The reason ! * we do this is to avoid memory leak, as door_return() would never ! * return ! */ ! for (i = 0; i < count; i++) { ! rifp = rvalp->ir_ifinfo + i; ! (void) bcopy(ifp, rifp, sizeof (*rifp)); ! rifp->ifi_next = NULL; ! curifp = ifp->ifi_next; ! free(ifp); ! ifp = curifp; ! } ! rvalp->ir_err = err; ! (void) door_return((char *)rvalp, rbufsize, NULL, 0); } /* * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted * interface configuration (interface properties and addresses), for all those --- 670,691 ---- (void) door_return((char *)&rval, sizeof (rval), NULL, 0); } /* * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the ! * persisted interfaces and the IP protocols (IPv4 or IPv6) they support and ! * returns the info as a nvlist */ static void ipmgmt_getif_handler(void *argp) { ipmgmt_getif_arg_t *getif = argp; assert(getif->ia_cmd == IPMGMT_CMD_GETIF); ! ipmgmt_common_handler(getif->ia_ifname, NULL, ! ipmgmt_db_getif); } /* * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted * interface configuration (interface properties and addresses), for all those
*** 795,805 **** goto fail; err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ); if (err == ENOENT && cbarg.cb_ocnt > 0) { /* ! * If there is atleast one entry in the nvlist, * do not return error. */ err = 0; } if (err != 0) --- 715,725 ---- goto fail; err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ); if (err == ENOENT && cbarg.cb_ocnt > 0) { /* ! * If there is at least one entry in the nvlist, * do not return error. */ err = 0; } if (err != 0)
*** 837,864 **** ipmgmt_persist_if(ipmgmt_if_arg_t *sargp) { ipadm_dbwrite_cbarg_t cb; uint32_t flags = sargp->ia_flags; nvlist_t *nvl = NULL; - int err = 0; char strval[IPMGMT_STRSIZE]; if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC || sargp->ia_ifname[0] == '\0') { err = EINVAL; goto ret; } if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) goto ret; if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, sargp->ia_ifname)) != 0) goto ret; ! (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family); ! if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0) goto ret; cb.dbw_nvl = nvl; ! cb.dbw_flags = 0; ! err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE); ret: nvlist_free(nvl); return (err); } --- 757,927 ---- ipmgmt_persist_if(ipmgmt_if_arg_t *sargp) { ipadm_dbwrite_cbarg_t cb; uint32_t flags = sargp->ia_flags; nvlist_t *nvl = NULL; char strval[IPMGMT_STRSIZE]; + int err = 0; if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC || sargp->ia_ifname[0] == '\0') { err = EINVAL; goto ret; } if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) goto ret; + if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, sargp->ia_ifname)) != 0) goto ret; ! ! if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family, ! IPMGMT_APPEND)) != 0) goto ret; + + (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_ifclass); + if ((err = nvlist_add_string(nvl, IPADM_NVP_IFCLASS, strval)) != 0) + goto ret; + cb.dbw_nvl = nvl; ! cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF; ! err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE); ret: nvlist_free(nvl); return (err); + } + + /* + * The helper for ipmgmt_getif_handler and ipmgmt_getaddr_handler + */ + static void + ipmgmt_common_handler(char *if_name, char *aobj_name, db_wfunc_t worker) + { + ipmgmt_get_rval_t rval, *rvalp = &rval; + ipmgmt_get_cbarg_t cbarg; + int err = 0; + size_t buflen, onvlsize; + char *buf, *onvlbuf; + + cbarg.cb_ifname = if_name; + cbarg.cb_aobjname = aobj_name; + cbarg.cb_ocnt = 0; + + if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) + goto fail; + + err = ipmgmt_db_walk(worker, &cbarg, IPADM_DB_READ); + if (err == ENOENT && cbarg.cb_ocnt > 0) { + /* + * If there is atleast one entry in the nvlist, + * do not return error. + */ + err = 0; + } + if (err != 0) + goto fail; + + if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize, + NV_ENCODE_NATIVE)) != 0) + goto fail; + + buflen = onvlsize + sizeof (ipmgmt_get_rval_t); + /* We cannot use malloc() here because door_return never returns */ + buf = alloca(buflen); + onvlbuf = buf + sizeof (ipmgmt_get_rval_t); + if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, + &onvlsize, NV_ENCODE_NATIVE, 0)) != 0) + goto fail; + + nvlist_free(cbarg.cb_onvl); + rvalp = (ipmgmt_get_rval_t *)(void *)buf; + rvalp->ir_err = 0; + rvalp->ir_nvlsize = onvlsize; + + (void) door_return(buf, buflen, NULL, 0); + return; + + fail: + nvlist_free(cbarg.cb_onvl); + rvalp->ir_err = err; + (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); + } + + /* + * Handles the door command IPMGMT_CMD_IPMP_UPDATE + */ + static void + ipmgmt_ipmp_update_handler(void *argp) + { + ipmgmt_ipmp_update_arg_t *uargp = argp; + ipmgmt_retval_t rval; + ipadm_dbwrite_cbarg_t cb; + + boolean_t gif_exists; + char gifname[LIFNAMSIZ]; + nvlist_t *nvl = NULL; + uint32_t flags = uargp->ia_flags; + int err = 0; + + assert(uargp->ia_cmd == IPMGMT_CMD_IPMP_UPDATE); + + gif_exists = ipmgmt_persist_if_exists(uargp->ia_gifname, + AF_UNSPEC); + + if (!ipmgmt_persist_if_exists(uargp->ia_mifname, AF_UNSPEC)) { + err = EINVAL; + goto ret; + } + + ipmgmt_get_group_interface(uargp->ia_mifname, gifname, LIFNAMSIZ); + + if (flags & IPMGMT_APPEND) { + /* group interface should be available in the DB */ + if (!gif_exists) { + err = ENOENT; + goto ret; + } + + if (gifname[0] != '\0') { + err = EEXIST; + goto ret; + } + } + + if (flags & IPMGMT_REMOVE) { + /* We cannot remove something that does not exist */ + if (!gif_exists || gifname[0] == '\0') { + err = ENOENT; + goto ret; + } + if (strcmp(uargp->ia_gifname, gifname) != 0) { + err = EINVAL; + goto ret; + } + } + + if (flags & IPMGMT_PERSIST) { + + if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) + goto ret; + + if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, + uargp->ia_gifname)) != 0) + goto ret; + + if ((err = nvlist_add_string(nvl, IPADM_NVP_MIFNAMES, + uargp->ia_mifname)) != 0) + goto ret; + + if ((err = nvlist_add_string(nvl, IPADM_NVP_GIFNAME, + uargp->ia_gifname)) != 0) + goto ret; + + cb.dbw_nvl = nvl; + cb.dbw_flags = flags | IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP; + err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE); + } + ret: + nvlist_free(nvl); + rval.ir_err = err; + (void) door_return((char *)&rval, sizeof (rval), NULL, 0); }