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);
}