16e91bba0SGirish Moodalbail /* 26e91bba0SGirish Moodalbail * CDDL HEADER START 36e91bba0SGirish Moodalbail * 46e91bba0SGirish Moodalbail * The contents of this file are subject to the terms of the 56e91bba0SGirish Moodalbail * Common Development and Distribution License (the "License"). 66e91bba0SGirish Moodalbail * You may not use this file except in compliance with the License. 76e91bba0SGirish Moodalbail * 86e91bba0SGirish Moodalbail * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96e91bba0SGirish Moodalbail * or http://www.opensolaris.org/os/licensing. 106e91bba0SGirish Moodalbail * See the License for the specific language governing permissions 116e91bba0SGirish Moodalbail * and limitations under the License. 126e91bba0SGirish Moodalbail * 136e91bba0SGirish Moodalbail * When distributing Covered Code, include this CDDL HEADER in each 146e91bba0SGirish Moodalbail * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156e91bba0SGirish Moodalbail * If applicable, add the following below this CDDL HEADER, with the 166e91bba0SGirish Moodalbail * fields enclosed by brackets "[]" replaced with your own identifying 176e91bba0SGirish Moodalbail * information: Portions Copyright [yyyy] [name of copyright owner] 186e91bba0SGirish Moodalbail * 196e91bba0SGirish Moodalbail * CDDL HEADER END 206e91bba0SGirish Moodalbail */ 216e91bba0SGirish Moodalbail 226e91bba0SGirish Moodalbail /* 23ec3706caSVasumathi Sundaram * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24b31320a7SChris Fraire * Copyright (c) 2016-2017, Chris Fraire <cfraire@me.com>. 250a8fc1cbSHans Rosenfeld * Copyright 2021, Tintri by DDN. All rights reserved. 266e91bba0SGirish Moodalbail */ 276e91bba0SGirish Moodalbail 286e91bba0SGirish Moodalbail /* 296e91bba0SGirish Moodalbail * Main door handler functions used by ipmgmtd to process the different door 306e91bba0SGirish Moodalbail * call requests, issued by the library libipadm.so. 316e91bba0SGirish Moodalbail */ 326e91bba0SGirish Moodalbail 336e91bba0SGirish Moodalbail #include <alloca.h> 346e91bba0SGirish Moodalbail #include <pwd.h> 356e91bba0SGirish Moodalbail #include <auth_attr.h> 366e91bba0SGirish Moodalbail #include <secdb.h> 376e91bba0SGirish Moodalbail #include <stdlib.h> 386e91bba0SGirish Moodalbail #include <stdio.h> 396e91bba0SGirish Moodalbail #include <string.h> 406e91bba0SGirish Moodalbail #include <strings.h> 416e91bba0SGirish Moodalbail #include <errno.h> 426e91bba0SGirish Moodalbail #include <assert.h> 436e91bba0SGirish Moodalbail #include <libnvpair.h> 446e91bba0SGirish Moodalbail #include "ipmgmt_impl.h" 456e91bba0SGirish Moodalbail 46*a73be61aSHans Rosenfeld 47*a73be61aSHans Rosenfeld static void ipmgmt_common_handler(char *, char *, db_wfunc_t *); 48*a73be61aSHans Rosenfeld 496e91bba0SGirish Moodalbail /* Handler declaration for each door command */ 506e91bba0SGirish Moodalbail typedef void ipmgmt_door_handler_t(void *argp); 516e91bba0SGirish Moodalbail 526e91bba0SGirish Moodalbail static ipmgmt_door_handler_t ipmgmt_getaddr_handler, 536e91bba0SGirish Moodalbail ipmgmt_getprop_handler, 546e91bba0SGirish Moodalbail ipmgmt_getif_handler, 556e91bba0SGirish Moodalbail ipmgmt_initif_handler, 566e91bba0SGirish Moodalbail ipmgmt_aobjop_handler, 576e91bba0SGirish Moodalbail ipmgmt_resetaddr_handler, 586e91bba0SGirish Moodalbail ipmgmt_setif_handler, 596e91bba0SGirish Moodalbail ipmgmt_resetif_handler, 606e91bba0SGirish Moodalbail ipmgmt_resetprop_handler, 616e91bba0SGirish Moodalbail ipmgmt_setaddr_handler, 62*a73be61aSHans Rosenfeld ipmgmt_setprop_handler, 63*a73be61aSHans Rosenfeld ipmgmt_ipmp_update_handler; 646e91bba0SGirish Moodalbail 656e91bba0SGirish Moodalbail typedef struct ipmgmt_door_info_s { 666e91bba0SGirish Moodalbail uint_t idi_cmd; 676e91bba0SGirish Moodalbail boolean_t idi_set; 686e91bba0SGirish Moodalbail ipmgmt_door_handler_t *idi_handler; 696e91bba0SGirish Moodalbail } ipmgmt_door_info_t; 706e91bba0SGirish Moodalbail 716e91bba0SGirish Moodalbail /* maps door commands to door handler functions */ 726e91bba0SGirish Moodalbail static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = { 736e91bba0SGirish Moodalbail { IPMGMT_CMD_SETPROP, B_TRUE, ipmgmt_setprop_handler }, 746e91bba0SGirish Moodalbail { IPMGMT_CMD_SETIF, B_TRUE, ipmgmt_setif_handler }, 756e91bba0SGirish Moodalbail { IPMGMT_CMD_SETADDR, B_TRUE, ipmgmt_setaddr_handler }, 766e91bba0SGirish Moodalbail { IPMGMT_CMD_GETPROP, B_FALSE, ipmgmt_getprop_handler }, 776e91bba0SGirish Moodalbail { IPMGMT_CMD_GETIF, B_FALSE, ipmgmt_getif_handler }, 786e91bba0SGirish Moodalbail { IPMGMT_CMD_GETADDR, B_FALSE, ipmgmt_getaddr_handler }, 796e91bba0SGirish Moodalbail { IPMGMT_CMD_RESETIF, B_TRUE, ipmgmt_resetif_handler }, 806e91bba0SGirish Moodalbail { IPMGMT_CMD_RESETADDR, B_TRUE, ipmgmt_resetaddr_handler }, 816e91bba0SGirish Moodalbail { IPMGMT_CMD_RESETPROP, B_TRUE, ipmgmt_resetprop_handler }, 826e91bba0SGirish Moodalbail { IPMGMT_CMD_INITIF, B_TRUE, ipmgmt_initif_handler }, 836e91bba0SGirish Moodalbail { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE, ipmgmt_aobjop_handler }, 84ec3706caSVasumathi Sundaram { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE, ipmgmt_aobjop_handler }, 856e91bba0SGirish Moodalbail { IPMGMT_CMD_ADDROBJ_ADD, B_TRUE, ipmgmt_aobjop_handler }, 866e91bba0SGirish Moodalbail { IPMGMT_CMD_AOBJNAME2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler }, 876e91bba0SGirish Moodalbail { IPMGMT_CMD_LIF2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler }, 88*a73be61aSHans Rosenfeld { IPMGMT_CMD_IPMP_UPDATE, B_FALSE, ipmgmt_ipmp_update_handler}, 896e91bba0SGirish Moodalbail { 0, 0, NULL }, 906e91bba0SGirish Moodalbail }; 916e91bba0SGirish Moodalbail 926e91bba0SGirish Moodalbail /* 936e91bba0SGirish Moodalbail * The main server procedure function that gets invoked for any of the incoming 946e91bba0SGirish Moodalbail * door commands. Inside this function we identify the incoming command and 956e91bba0SGirish Moodalbail * invoke the right door handler function. 966e91bba0SGirish Moodalbail */ 976e91bba0SGirish Moodalbail /* ARGSUSED */ 986e91bba0SGirish Moodalbail void 996e91bba0SGirish Moodalbail ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp, 1006e91bba0SGirish Moodalbail uint_t n_desc) 1016e91bba0SGirish Moodalbail { 1026e91bba0SGirish Moodalbail ipmgmt_door_info_t *infop = NULL; 1036e91bba0SGirish Moodalbail ipmgmt_retval_t retval; 1046e91bba0SGirish Moodalbail int i; 1056e91bba0SGirish Moodalbail uint_t err; 1066e91bba0SGirish Moodalbail ucred_t *cred = NULL; 1076e91bba0SGirish Moodalbail 1086e91bba0SGirish Moodalbail for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) { 1096e91bba0SGirish Moodalbail if (i_ipmgmt_door_info_tbl[i].idi_cmd == 1106e91bba0SGirish Moodalbail ((ipmgmt_arg_t *)(void *)argp)->ia_cmd) { 1116e91bba0SGirish Moodalbail infop = &i_ipmgmt_door_info_tbl[i]; 1126e91bba0SGirish Moodalbail break; 1136e91bba0SGirish Moodalbail } 1146e91bba0SGirish Moodalbail } 1156e91bba0SGirish Moodalbail 1166e91bba0SGirish Moodalbail if (infop == NULL) { 1176e91bba0SGirish Moodalbail ipmgmt_log(LOG_ERR, "Invalid door command specified"); 1186e91bba0SGirish Moodalbail err = EINVAL; 1196e91bba0SGirish Moodalbail goto fail; 1206e91bba0SGirish Moodalbail } 1216e91bba0SGirish Moodalbail 1226e91bba0SGirish Moodalbail /* check for solaris.network.interface.config authorization */ 1236e91bba0SGirish Moodalbail if (infop->idi_set) { 1246e91bba0SGirish Moodalbail uid_t uid; 1256e91bba0SGirish Moodalbail struct passwd pwd; 1266e91bba0SGirish Moodalbail char buf[1024]; 1276e91bba0SGirish Moodalbail 1286e91bba0SGirish Moodalbail if (door_ucred(&cred) != 0) { 1296e91bba0SGirish Moodalbail err = errno; 1306e91bba0SGirish Moodalbail ipmgmt_log(LOG_ERR, "Could not get user credentials."); 1316e91bba0SGirish Moodalbail goto fail; 1326e91bba0SGirish Moodalbail } 1336e91bba0SGirish Moodalbail uid = ucred_getruid(cred); 1346e91bba0SGirish Moodalbail if ((int)uid < 0) { 1356e91bba0SGirish Moodalbail err = errno; 1366e91bba0SGirish Moodalbail ipmgmt_log(LOG_ERR, "Could not get user id."); 1376e91bba0SGirish Moodalbail goto fail; 1386e91bba0SGirish Moodalbail } 1396e91bba0SGirish Moodalbail if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) == 1406e91bba0SGirish Moodalbail NULL) { 1416e91bba0SGirish Moodalbail err = errno; 1426e91bba0SGirish Moodalbail ipmgmt_log(LOG_ERR, "Could not get password entry."); 1436e91bba0SGirish Moodalbail goto fail; 1446e91bba0SGirish Moodalbail } 1456e91bba0SGirish Moodalbail if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH, 1466e91bba0SGirish Moodalbail pwd.pw_name) != 1) { 1476e91bba0SGirish Moodalbail err = EPERM; 1486e91bba0SGirish Moodalbail ipmgmt_log(LOG_ERR, "Not authorized for operation."); 1496e91bba0SGirish Moodalbail goto fail; 1506e91bba0SGirish Moodalbail } 1516e91bba0SGirish Moodalbail ucred_free(cred); 1526e91bba0SGirish Moodalbail } 1536e91bba0SGirish Moodalbail 1546e91bba0SGirish Moodalbail /* individual handlers take care of calling door_return */ 1556e91bba0SGirish Moodalbail infop->idi_handler((void *)argp); 1566e91bba0SGirish Moodalbail return; 1576e91bba0SGirish Moodalbail fail: 1586e91bba0SGirish Moodalbail ucred_free(cred); 1596e91bba0SGirish Moodalbail retval.ir_err = err; 1606e91bba0SGirish Moodalbail (void) door_return((char *)&retval, sizeof (retval), NULL, 0); 1616e91bba0SGirish Moodalbail } 1626e91bba0SGirish Moodalbail 1636e91bba0SGirish Moodalbail /* 1646e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_GETPROP. It retrieves the persisted 1656e91bba0SGirish Moodalbail * property value for the given property. 1666e91bba0SGirish Moodalbail */ 1676e91bba0SGirish Moodalbail static void 1686e91bba0SGirish Moodalbail ipmgmt_getprop_handler(void *argp) 1696e91bba0SGirish Moodalbail { 1706e91bba0SGirish Moodalbail ipmgmt_prop_arg_t *pargp = argp; 1716e91bba0SGirish Moodalbail ipmgmt_getprop_rval_t rval, *rvalp = &rval; 1726e91bba0SGirish Moodalbail 1736e91bba0SGirish Moodalbail assert(pargp->ia_cmd == IPMGMT_CMD_GETPROP); 1746e91bba0SGirish Moodalbail 1756e91bba0SGirish Moodalbail rvalp->ir_err = ipmgmt_db_walk(ipmgmt_db_getprop, pargp, IPADM_DB_READ); 1766e91bba0SGirish Moodalbail if (rvalp->ir_err == 0) 1776e91bba0SGirish Moodalbail (void) strlcpy(rvalp->ir_pval, pargp->ia_pval, 1786e91bba0SGirish Moodalbail sizeof (rvalp->ir_pval)); 1796e91bba0SGirish Moodalbail (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); 1806e91bba0SGirish Moodalbail } 1816e91bba0SGirish Moodalbail 1826e91bba0SGirish Moodalbail /* 1836e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_SETPROP. It persists the property value 1846e91bba0SGirish Moodalbail * for the given property in the DB. 1856e91bba0SGirish Moodalbail */ 1866e91bba0SGirish Moodalbail static void 1876e91bba0SGirish Moodalbail ipmgmt_setprop_handler(void *argp) 1886e91bba0SGirish Moodalbail { 1896e91bba0SGirish Moodalbail ipmgmt_prop_arg_t *pargp = argp; 1906e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 1916e91bba0SGirish Moodalbail ipadm_dbwrite_cbarg_t cb; 1926e91bba0SGirish Moodalbail nvlist_t *nvl = NULL; 1936e91bba0SGirish Moodalbail int err; 1946e91bba0SGirish Moodalbail 1956e91bba0SGirish Moodalbail assert(pargp->ia_cmd == IPMGMT_CMD_SETPROP); 1966e91bba0SGirish Moodalbail 1976e91bba0SGirish Moodalbail if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) 1986e91bba0SGirish Moodalbail goto fail; 1996e91bba0SGirish Moodalbail if (pargp->ia_module[0] != '\0' && 2006e91bba0SGirish Moodalbail (err = nvlist_add_string(nvl, IPADM_NVP_PROTONAME, 2016e91bba0SGirish Moodalbail pargp->ia_module)) != 0) { 2026e91bba0SGirish Moodalbail goto fail; 2036e91bba0SGirish Moodalbail } 2046e91bba0SGirish Moodalbail if (pargp->ia_ifname[0] != '\0' && 2056e91bba0SGirish Moodalbail (err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, 2066e91bba0SGirish Moodalbail pargp->ia_ifname)) != 0) 2076e91bba0SGirish Moodalbail goto fail; 2086e91bba0SGirish Moodalbail if (pargp->ia_aobjname[0] != '\0' && 2096e91bba0SGirish Moodalbail (err = nvlist_add_string(nvl, IPADM_NVP_AOBJNAME, 2106e91bba0SGirish Moodalbail pargp->ia_aobjname)) != 0) 2116e91bba0SGirish Moodalbail goto fail; 2126e91bba0SGirish Moodalbail if ((err = nvlist_add_string(nvl, pargp->ia_pname, 2136e91bba0SGirish Moodalbail pargp->ia_pval)) != 0) 2146e91bba0SGirish Moodalbail goto fail; 2156e91bba0SGirish Moodalbail 2166e91bba0SGirish Moodalbail cb.dbw_nvl = nvl; 2176e91bba0SGirish Moodalbail cb.dbw_flags = pargp->ia_flags; 2186e91bba0SGirish Moodalbail err = ipmgmt_db_walk(ipmgmt_db_update, &cb, IPADM_DB_WRITE); 2196e91bba0SGirish Moodalbail fail: 2206e91bba0SGirish Moodalbail nvlist_free(nvl); 2216e91bba0SGirish Moodalbail rval.ir_err = err; 2226e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 2236e91bba0SGirish Moodalbail } 2246e91bba0SGirish Moodalbail 2256e91bba0SGirish Moodalbail /* 2266e91bba0SGirish Moodalbail * Helper function for ipmgmt_setaddr_handler(). 2276e91bba0SGirish Moodalbail * It converts the nvlist_t, `nvl', to aobjmap node `nodep'. 2286e91bba0SGirish Moodalbail */ 2296e91bba0SGirish Moodalbail static int 2306e91bba0SGirish Moodalbail i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep) 2316e91bba0SGirish Moodalbail { 2326e91bba0SGirish Moodalbail char *aobjname = NULL, *ifname = NULL; 2336e91bba0SGirish Moodalbail int32_t lnum; 2346e91bba0SGirish Moodalbail nvlist_t *nvladdr; 2356e91bba0SGirish Moodalbail sa_family_t af = AF_UNSPEC; 2366e91bba0SGirish Moodalbail ipadm_addr_type_t addrtype = IPADM_ADDR_NONE; 2376e91bba0SGirish Moodalbail int err = 0; 2386e91bba0SGirish Moodalbail 2396e91bba0SGirish Moodalbail /* 2406e91bba0SGirish Moodalbail * Retrieve all the information needed to build '*nodep' from 2416e91bba0SGirish Moodalbail * nvlist_t nvl. 2426e91bba0SGirish Moodalbail */ 2436e91bba0SGirish Moodalbail if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME, 2446e91bba0SGirish Moodalbail &aobjname)) != 0 || 2456e91bba0SGirish Moodalbail (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 || 2466e91bba0SGirish Moodalbail (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) { 2476e91bba0SGirish Moodalbail return (err); 2486e91bba0SGirish Moodalbail } 2496e91bba0SGirish Moodalbail if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) { 2506e91bba0SGirish Moodalbail af = AF_INET; 2516e91bba0SGirish Moodalbail addrtype = IPADM_ADDR_STATIC; 252b31320a7SChris Fraire } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvladdr) == 0) { 253b31320a7SChris Fraire char *reqhost; 254b31320a7SChris Fraire 2556e91bba0SGirish Moodalbail af = AF_INET; 2566e91bba0SGirish Moodalbail addrtype = IPADM_ADDR_DHCP; 257b31320a7SChris Fraire 258b31320a7SChris Fraire /* 259b31320a7SChris Fraire * ipmgmt_am_reqhost comes through in `nvl' for purposes of 260b31320a7SChris Fraire * updating the cached representation, but it is persisted as 261b31320a7SChris Fraire * a stand-alone DB line; so remove it after copying it. 262b31320a7SChris Fraire */ 263b31320a7SChris Fraire if (!nvlist_exists(nvl, IPADM_NVP_REQHOST)) { 264b31320a7SChris Fraire *nodep->ipmgmt_am_reqhost = '\0'; 265b31320a7SChris Fraire } else { 266b31320a7SChris Fraire if ((err = nvlist_lookup_string(nvl, IPADM_NVP_REQHOST, 267b31320a7SChris Fraire &reqhost)) != 0) 268b31320a7SChris Fraire return (err); 269b31320a7SChris Fraire 270b31320a7SChris Fraire (void) strlcpy(nodep->ipmgmt_am_reqhost, reqhost, 271b31320a7SChris Fraire sizeof (nodep->ipmgmt_am_reqhost)); 272b31320a7SChris Fraire (void) nvlist_remove(nvl, IPADM_NVP_REQHOST, 273b31320a7SChris Fraire DATA_TYPE_STRING); 274b31320a7SChris Fraire } 2756e91bba0SGirish Moodalbail } else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) { 2766e91bba0SGirish Moodalbail af = AF_INET6; 2776e91bba0SGirish Moodalbail addrtype = IPADM_ADDR_STATIC; 2786e91bba0SGirish Moodalbail } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) { 279b31320a7SChris Fraire struct sockaddr_in6 sin6 = {0}; 2806e91bba0SGirish Moodalbail uint8_t *addr6; 2816e91bba0SGirish Moodalbail uint32_t plen; 282b31320a7SChris Fraire uint_t n; 2836e91bba0SGirish Moodalbail 2846e91bba0SGirish Moodalbail af = AF_INET6; 2856e91bba0SGirish Moodalbail addrtype = IPADM_ADDR_IPV6_ADDRCONF; 2866e91bba0SGirish Moodalbail if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN, 2876e91bba0SGirish Moodalbail &plen) != 0) 2886e91bba0SGirish Moodalbail return (EINVAL); 2896e91bba0SGirish Moodalbail if (plen != 0) { 2906e91bba0SGirish Moodalbail if (nvlist_lookup_uint8_array(nvladdr, 2916e91bba0SGirish Moodalbail IPADM_NVP_IPNUMADDR, &addr6, &n) != 0) 2926e91bba0SGirish Moodalbail return (EINVAL); 293b31320a7SChris Fraire bcopy(addr6, &sin6.sin6_addr, n); 2946e91bba0SGirish Moodalbail } 295b31320a7SChris Fraire 296b31320a7SChris Fraire nodep->ipmgmt_am_linklocal = B_TRUE; 297b31320a7SChris Fraire nodep->ipmgmt_am_ifid = sin6; 2986e91bba0SGirish Moodalbail } 2996e91bba0SGirish Moodalbail 3006e91bba0SGirish Moodalbail /* 301b31320a7SChris Fraire * populate the non-addrtype-specific `*nodep' with retrieved values. 3026e91bba0SGirish Moodalbail */ 3036e91bba0SGirish Moodalbail (void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname)); 3046e91bba0SGirish Moodalbail (void) strlcpy(nodep->am_aobjname, aobjname, 3056e91bba0SGirish Moodalbail sizeof (nodep->am_aobjname)); 3066e91bba0SGirish Moodalbail nodep->am_lnum = lnum; 3076e91bba0SGirish Moodalbail nodep->am_family = af; 3086e91bba0SGirish Moodalbail nodep->am_atype = addrtype; 3096e91bba0SGirish Moodalbail nodep->am_next = NULL; 3106e91bba0SGirish Moodalbail 3116e91bba0SGirish Moodalbail /* 3126e91bba0SGirish Moodalbail * Do not store logical interface number in persistent store as it 3136e91bba0SGirish Moodalbail * takes different value on reboot. So remove it from `nvl'. 3146e91bba0SGirish Moodalbail */ 3156e91bba0SGirish Moodalbail if (nvlist_exists(nvl, IPADM_NVP_LIFNUM)) 3166e91bba0SGirish Moodalbail (void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32); 3176e91bba0SGirish Moodalbail 3186e91bba0SGirish Moodalbail return (0); 3196e91bba0SGirish Moodalbail } 3206e91bba0SGirish Moodalbail 3216e91bba0SGirish Moodalbail /* 3226e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object 323b31320a7SChris Fraire * node to the list `aobjmap' and optionally persists the address 324b31320a7SChris Fraire * information in the DB. 3256e91bba0SGirish Moodalbail */ 3266e91bba0SGirish Moodalbail static void 3276e91bba0SGirish Moodalbail ipmgmt_setaddr_handler(void *argp) 3286e91bba0SGirish Moodalbail { 3296e91bba0SGirish Moodalbail ipmgmt_setaddr_arg_t *sargp = argp; 3306e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 331b31320a7SChris Fraire ipmgmt_aobjmap_t node = {0}; 3326e91bba0SGirish Moodalbail nvlist_t *nvl = NULL; 3336e91bba0SGirish Moodalbail char *nvlbuf; 3346e91bba0SGirish Moodalbail size_t nvlsize = sargp->ia_nvlsize; 3356e91bba0SGirish Moodalbail uint32_t flags = sargp->ia_flags; 3366e91bba0SGirish Moodalbail int err = 0; 3376e91bba0SGirish Moodalbail 3386e91bba0SGirish Moodalbail nvlbuf = (char *)argp + sizeof (ipmgmt_setaddr_arg_t); 3390d1087e8SHans Rosenfeld if ((err = nvlist_unpack(nvlbuf, nvlsize, &nvl, 0)) != 0) 3406e91bba0SGirish Moodalbail goto ret; 3416e91bba0SGirish Moodalbail if (flags & (IPMGMT_ACTIVE|IPMGMT_INIT)) { 3426e91bba0SGirish Moodalbail if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0) 3436e91bba0SGirish Moodalbail goto ret; 3446e91bba0SGirish Moodalbail if (flags & IPMGMT_INIT) 3456e91bba0SGirish Moodalbail node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST); 3466e91bba0SGirish Moodalbail else 347b31320a7SChris Fraire node.am_flags = flags & ~IPMGMT_PROPS_ONLY; 3486e91bba0SGirish Moodalbail if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0) 3496e91bba0SGirish Moodalbail goto ret; 3506e91bba0SGirish Moodalbail } 351b31320a7SChris Fraire if ((flags & IPMGMT_PERSIST) && !(flags & IPMGMT_PROPS_ONLY)) { 3526e91bba0SGirish Moodalbail ipadm_dbwrite_cbarg_t cb; 3536e91bba0SGirish Moodalbail 3546e91bba0SGirish Moodalbail cb.dbw_nvl = nvl; 3556e91bba0SGirish Moodalbail cb.dbw_flags = 0; 3566e91bba0SGirish Moodalbail err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE); 3576e91bba0SGirish Moodalbail } 3586e91bba0SGirish Moodalbail ret: 3596e91bba0SGirish Moodalbail nvlist_free(nvl); 3606e91bba0SGirish Moodalbail rval.ir_err = err; 3616e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 3626e91bba0SGirish Moodalbail } 3636e91bba0SGirish Moodalbail 3646e91bba0SGirish Moodalbail /* 365b31320a7SChris Fraire * Handles the door commands that read or modify the `aobjmap' structure. 3666e91bba0SGirish Moodalbail * 3676e91bba0SGirish Moodalbail * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap' 3686e91bba0SGirish Moodalbail * after ensuring that the namespace is not taken. If required, also 3696e91bba0SGirish Moodalbail * generates an `aobjname' for address object for the library to use. 3706e91bba0SGirish Moodalbail * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap' 3716e91bba0SGirish Moodalbail * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object 3726e91bba0SGirish Moodalbail * associated with that logical interface. 3736e91bba0SGirish Moodalbail * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical 3746e91bba0SGirish Moodalbail * interface associated with that address object. 3756e91bba0SGirish Moodalbail */ 3766e91bba0SGirish Moodalbail static void 3776e91bba0SGirish Moodalbail ipmgmt_aobjop_handler(void *argp) 3786e91bba0SGirish Moodalbail { 3796e91bba0SGirish Moodalbail ipmgmt_aobjop_arg_t *largp = argp; 3806e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 3816e91bba0SGirish Moodalbail ipmgmt_aobjop_rval_t aobjrval; 3826e91bba0SGirish Moodalbail void *rvalp; 3836e91bba0SGirish Moodalbail size_t rsize; 3846e91bba0SGirish Moodalbail ipmgmt_aobjmap_t node; 3856e91bba0SGirish Moodalbail int err = 0; 3866e91bba0SGirish Moodalbail char *ifname = largp->ia_ifname; 3876e91bba0SGirish Moodalbail char *aobjname = largp->ia_aobjname; 3886e91bba0SGirish Moodalbail int32_t lnum = largp->ia_lnum; 3896e91bba0SGirish Moodalbail sa_family_t af = largp->ia_family; 3906e91bba0SGirish Moodalbail ipadm_addr_type_t atype = largp->ia_atype; 3916e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *head; 3926e91bba0SGirish Moodalbail 3936e91bba0SGirish Moodalbail switch (largp->ia_cmd) { 3946e91bba0SGirish Moodalbail case IPMGMT_CMD_ADDROBJ_LOOKUPADD: 3956e91bba0SGirish Moodalbail rsize = sizeof (ipmgmt_aobjop_rval_t); 3966e91bba0SGirish Moodalbail rvalp = &aobjrval; 3976e91bba0SGirish Moodalbail bzero(&node, sizeof (node)); 3986e91bba0SGirish Moodalbail (void) strlcpy(node.am_aobjname, aobjname, 3996e91bba0SGirish Moodalbail sizeof (node.am_aobjname)); 4006e91bba0SGirish Moodalbail (void) strlcpy(node.am_ifname, ifname, 4016e91bba0SGirish Moodalbail sizeof (node.am_ifname)); 4026e91bba0SGirish Moodalbail node.am_family = af; 403ec3706caSVasumathi Sundaram node.am_atype = atype; 4046e91bba0SGirish Moodalbail /* no logical number is associated with this addrobj yet */ 4056e91bba0SGirish Moodalbail node.am_lnum = -1; 4066e91bba0SGirish Moodalbail /* The address object is not persisted yet. */ 4076e91bba0SGirish Moodalbail node.am_flags = IPMGMT_ACTIVE; 4086e91bba0SGirish Moodalbail err = ipmgmt_aobjmap_op(&node, ADDROBJ_LOOKUPADD); 4096e91bba0SGirish Moodalbail if (err == 0) { 4106e91bba0SGirish Moodalbail (void) strlcpy(aobjrval.ir_aobjname, node.am_aobjname, 4116e91bba0SGirish Moodalbail sizeof (aobjrval.ir_aobjname)); 4126e91bba0SGirish Moodalbail } 4136e91bba0SGirish Moodalbail break; 414ec3706caSVasumathi Sundaram case IPMGMT_CMD_ADDROBJ_SETLIFNUM: 415ec3706caSVasumathi Sundaram rsize = sizeof (ipmgmt_retval_t); 416ec3706caSVasumathi Sundaram rvalp = &rval; 417ec3706caSVasumathi Sundaram bzero(&node, sizeof (node)); 418ec3706caSVasumathi Sundaram (void) strlcpy(node.am_aobjname, aobjname, 419ec3706caSVasumathi Sundaram sizeof (node.am_aobjname)); 420ec3706caSVasumathi Sundaram (void) strlcpy(node.am_ifname, ifname, 421ec3706caSVasumathi Sundaram sizeof (node.am_ifname)); 422ec3706caSVasumathi Sundaram node.am_family = af; 423ec3706caSVasumathi Sundaram node.am_lnum = lnum; 424ec3706caSVasumathi Sundaram err = ipmgmt_aobjmap_op(&node, ADDROBJ_SETLIFNUM); 425ec3706caSVasumathi Sundaram break; 4266e91bba0SGirish Moodalbail case IPMGMT_CMD_ADDROBJ_ADD: 4276e91bba0SGirish Moodalbail rsize = sizeof (ipmgmt_retval_t); 4286e91bba0SGirish Moodalbail rvalp = &rval; 4296e91bba0SGirish Moodalbail if (aobjname[0] == '\0' || ifname[0] == '\0' || lnum == -1 || 4306e91bba0SGirish Moodalbail af == AF_UNSPEC) { 4316e91bba0SGirish Moodalbail err = EINVAL; 4326e91bba0SGirish Moodalbail break; 4336e91bba0SGirish Moodalbail } 4346e91bba0SGirish Moodalbail bzero(&node, sizeof (node)); 4356e91bba0SGirish Moodalbail (void) strlcpy(node.am_aobjname, aobjname, 4366e91bba0SGirish Moodalbail sizeof (node.am_aobjname)); 4376e91bba0SGirish Moodalbail (void) strlcpy(node.am_ifname, ifname, 4386e91bba0SGirish Moodalbail sizeof (node.am_ifname)); 4396e91bba0SGirish Moodalbail node.am_atype = atype; 4406e91bba0SGirish Moodalbail node.am_lnum = lnum; 4416e91bba0SGirish Moodalbail node.am_family = af; 4426e91bba0SGirish Moodalbail /* The address object is not persisted. */ 4436e91bba0SGirish Moodalbail node.am_flags = IPMGMT_ACTIVE; 4446e91bba0SGirish Moodalbail err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD); 4456e91bba0SGirish Moodalbail break; 4466e91bba0SGirish Moodalbail case IPMGMT_CMD_AOBJNAME2ADDROBJ: 4476e91bba0SGirish Moodalbail rsize = sizeof (ipmgmt_aobjop_rval_t); 4486e91bba0SGirish Moodalbail rvalp = &aobjrval; 4496e91bba0SGirish Moodalbail bzero(&aobjrval, sizeof (aobjrval)); 4506e91bba0SGirish Moodalbail if (aobjname[0] == '\0') { 4516e91bba0SGirish Moodalbail err = EINVAL; 4526e91bba0SGirish Moodalbail break; 4536e91bba0SGirish Moodalbail } 4546e91bba0SGirish Moodalbail (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock); 4556e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 4566e91bba0SGirish Moodalbail for (; head; head = head->am_next) { 4576e91bba0SGirish Moodalbail if (strcmp(head->am_aobjname, aobjname) != 0) 4586e91bba0SGirish Moodalbail continue; 4596e91bba0SGirish Moodalbail /* 4606e91bba0SGirish Moodalbail * For an auto-configured interface, return 4616e91bba0SGirish Moodalbail * the lifnum that has the link-local on it. 4626e91bba0SGirish Moodalbail * Other logical interfaces were created for 4636e91bba0SGirish Moodalbail * prefixes and dhcpv6 addresses and do not 4646e91bba0SGirish Moodalbail * have am_ifid set. 4656e91bba0SGirish Moodalbail */ 4666e91bba0SGirish Moodalbail if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF || 467b31320a7SChris Fraire head->ipmgmt_am_linklocal) { 4686e91bba0SGirish Moodalbail break; 4696e91bba0SGirish Moodalbail } 4706e91bba0SGirish Moodalbail } 4716e91bba0SGirish Moodalbail if (head == NULL) { 4726e91bba0SGirish Moodalbail err = ENOENT; 4736e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 4746e91bba0SGirish Moodalbail break; 4756e91bba0SGirish Moodalbail } 4766e91bba0SGirish Moodalbail (void) strlcpy(aobjrval.ir_ifname, head->am_ifname, 4776e91bba0SGirish Moodalbail sizeof (aobjrval.ir_ifname)); 4786e91bba0SGirish Moodalbail aobjrval.ir_lnum = head->am_lnum; 4796e91bba0SGirish Moodalbail aobjrval.ir_family = head->am_family; 4806e91bba0SGirish Moodalbail aobjrval.ir_flags = head->am_flags; 4816e91bba0SGirish Moodalbail aobjrval.ir_atype = head->am_atype; 482b31320a7SChris Fraire aobjrval.ir_atype_cache = head->am_atype_cache; 4836e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 4846e91bba0SGirish Moodalbail break; 4856e91bba0SGirish Moodalbail case IPMGMT_CMD_LIF2ADDROBJ: 4866e91bba0SGirish Moodalbail rsize = sizeof (ipmgmt_aobjop_rval_t); 4876e91bba0SGirish Moodalbail rvalp = &aobjrval; 4886e91bba0SGirish Moodalbail bzero(&aobjrval, sizeof (aobjrval)); 4896e91bba0SGirish Moodalbail if (ifname[0] == '\0') { 4906e91bba0SGirish Moodalbail err = EINVAL; 4916e91bba0SGirish Moodalbail break; 4926e91bba0SGirish Moodalbail } 4936e91bba0SGirish Moodalbail (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock); 4946e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 4956e91bba0SGirish Moodalbail for (; head; head = head->am_next) { 4966e91bba0SGirish Moodalbail if (strcmp(head->am_ifname, ifname) == 0 && 4976e91bba0SGirish Moodalbail head->am_lnum == lnum && 4986e91bba0SGirish Moodalbail head->am_family == af) { 4996e91bba0SGirish Moodalbail break; 5006e91bba0SGirish Moodalbail } 5016e91bba0SGirish Moodalbail } 5026e91bba0SGirish Moodalbail if (head == NULL) { 5036e91bba0SGirish Moodalbail err = ENOENT; 5046e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 5056e91bba0SGirish Moodalbail break; 5066e91bba0SGirish Moodalbail } 5076e91bba0SGirish Moodalbail (void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname, 5086e91bba0SGirish Moodalbail sizeof (aobjrval.ir_aobjname)); 5096e91bba0SGirish Moodalbail aobjrval.ir_atype = head->am_atype; 5106e91bba0SGirish Moodalbail aobjrval.ir_flags = head->am_flags; 511b31320a7SChris Fraire aobjrval.ir_atype_cache = head->am_atype_cache; 5126e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 5136e91bba0SGirish Moodalbail break; 5146e91bba0SGirish Moodalbail default: 5156e91bba0SGirish Moodalbail rsize = sizeof (ipmgmt_retval_t); 5166e91bba0SGirish Moodalbail rvalp = &rval; 5176e91bba0SGirish Moodalbail err = EINVAL; 5186e91bba0SGirish Moodalbail } 5196e91bba0SGirish Moodalbail ((ipmgmt_retval_t *)rvalp)->ir_err = err; 5206e91bba0SGirish Moodalbail (void) door_return((char *)rvalp, rsize, NULL, 0); 5216e91bba0SGirish Moodalbail } 5226e91bba0SGirish Moodalbail 5236e91bba0SGirish Moodalbail /* 5246e91bba0SGirish Moodalbail * Given an interface name and family, deletes all the address objects 5256e91bba0SGirish Moodalbail * associated with it. 5266e91bba0SGirish Moodalbail */ 5276e91bba0SGirish Moodalbail void 5286e91bba0SGirish Moodalbail i_ipmgmt_delif_aobjs(char *ifname, sa_family_t af, uint32_t flags) 5296e91bba0SGirish Moodalbail { 5306e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *head, *next, *prev; 5316e91bba0SGirish Moodalbail ipadm_db_op_t db_op; 5326e91bba0SGirish Moodalbail 5336e91bba0SGirish Moodalbail prev = NULL; 5346e91bba0SGirish Moodalbail 5356e91bba0SGirish Moodalbail (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock); 5366e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 5376e91bba0SGirish Moodalbail for (; head; head = next) { 5386e91bba0SGirish Moodalbail next = head->am_next; 5396e91bba0SGirish Moodalbail if (strcmp(head->am_ifname, ifname) != 0 || 5406e91bba0SGirish Moodalbail head->am_family != af) { 5416e91bba0SGirish Moodalbail prev = head; 5426e91bba0SGirish Moodalbail continue; 5436e91bba0SGirish Moodalbail } 5446e91bba0SGirish Moodalbail 5456e91bba0SGirish Moodalbail if (head->am_flags == (IPMGMT_ACTIVE|IPMGMT_PERSIST) && 5466e91bba0SGirish Moodalbail flags == IPMGMT_ACTIVE) { 5476e91bba0SGirish Moodalbail /* 5486e91bba0SGirish Moodalbail * If the addres is present in both active and 5496e91bba0SGirish Moodalbail * persistent store, and if we are performing 5506e91bba0SGirish Moodalbail * a temporary delete, we update the node to 5516e91bba0SGirish Moodalbail * indicate that the address is only present in 5526e91bba0SGirish Moodalbail * persistent store and we proceed. Otherwise 5536e91bba0SGirish Moodalbail * we always delete the node from aobjmap. 5546e91bba0SGirish Moodalbail */ 5556e91bba0SGirish Moodalbail head->am_flags &= ~IPMGMT_ACTIVE; 5566e91bba0SGirish Moodalbail head->am_lnum = -1; 5576e91bba0SGirish Moodalbail db_op = IPADM_DB_WRITE; 5586e91bba0SGirish Moodalbail } else { 5596e91bba0SGirish Moodalbail db_op = IPADM_DB_DELETE; 5606e91bba0SGirish Moodalbail if (prev == NULL) 5616e91bba0SGirish Moodalbail aobjmap.aobjmap_head = next; 5626e91bba0SGirish Moodalbail else 5636e91bba0SGirish Moodalbail prev->am_next = next; 5646e91bba0SGirish Moodalbail } 5656e91bba0SGirish Moodalbail (void) ipmgmt_persist_aobjmap(head, db_op); 5666e91bba0SGirish Moodalbail if (db_op == IPADM_DB_DELETE) 5676e91bba0SGirish Moodalbail free(head); 5686e91bba0SGirish Moodalbail } 5696e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 5706e91bba0SGirish Moodalbail } 5716e91bba0SGirish Moodalbail 5726e91bba0SGirish Moodalbail /* 5736e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_SETIF. It persists the interface 5746e91bba0SGirish Moodalbail * information in the DB. 5756e91bba0SGirish Moodalbail */ 5766e91bba0SGirish Moodalbail static void 5776e91bba0SGirish Moodalbail ipmgmt_setif_handler(void *argp) 5786e91bba0SGirish Moodalbail { 5796e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 5806e91bba0SGirish Moodalbail 581550b6e40SSowmini Varadhan rval.ir_err = ipmgmt_persist_if(argp); 5826e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 5836e91bba0SGirish Moodalbail } 5846e91bba0SGirish Moodalbail 5856e91bba0SGirish Moodalbail /* 5866e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_RESETIF. For the given interface, 5876e91bba0SGirish Moodalbail * deletes all the persisted interface configuration. It also deletes, from 5886e91bba0SGirish Moodalbail * `aobjmap', all the address objects configured on the given interface. 5896e91bba0SGirish Moodalbail */ 5906e91bba0SGirish Moodalbail static void 5916e91bba0SGirish Moodalbail ipmgmt_resetif_handler(void *argp) 5926e91bba0SGirish Moodalbail { 5936e91bba0SGirish Moodalbail ipmgmt_if_arg_t *rargp = argp; 5946e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 5956e91bba0SGirish Moodalbail ipmgmt_if_cbarg_t cbarg; 5966e91bba0SGirish Moodalbail uint32_t flags = rargp->ia_flags; 5976e91bba0SGirish Moodalbail int err = 0; 5986e91bba0SGirish Moodalbail 5996e91bba0SGirish Moodalbail cbarg.cb_family = rargp->ia_family; 6006e91bba0SGirish Moodalbail cbarg.cb_ifname = rargp->ia_ifname; 601*a73be61aSHans Rosenfeld 602*a73be61aSHans Rosenfeld cbarg.cb_ipv4exists = B_TRUE; 603*a73be61aSHans Rosenfeld cbarg.cb_ipv6exists = B_TRUE; 604*a73be61aSHans Rosenfeld 6056e91bba0SGirish Moodalbail if (flags & IPMGMT_PERSIST) 6066e91bba0SGirish Moodalbail err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg, 6076e91bba0SGirish Moodalbail IPADM_DB_DELETE); 6086e91bba0SGirish Moodalbail 6096e91bba0SGirish Moodalbail if (flags & IPMGMT_ACTIVE) 6106e91bba0SGirish Moodalbail i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family, 6116e91bba0SGirish Moodalbail flags); 6126e91bba0SGirish Moodalbail 6136e91bba0SGirish Moodalbail rval.ir_err = err; 6146e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 6156e91bba0SGirish Moodalbail } 6166e91bba0SGirish Moodalbail 6176e91bba0SGirish Moodalbail /* 6186e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj 6196e91bba0SGirish Moodalbail * deletes all the persisted addrobj configuration. It also deletes the 6206e91bba0SGirish Moodalbail * corresponding node, from `aobjmap'. 6216e91bba0SGirish Moodalbail */ 6226e91bba0SGirish Moodalbail static void 6236e91bba0SGirish Moodalbail ipmgmt_resetaddr_handler(void *argp) 6246e91bba0SGirish Moodalbail { 6256e91bba0SGirish Moodalbail ipmgmt_addr_arg_t *rargp = argp; 6266e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 6276e91bba0SGirish Moodalbail ipmgmt_aobjmap_t node; 6286e91bba0SGirish Moodalbail uint32_t flags = rargp->ia_flags; 6296e91bba0SGirish Moodalbail int err = 0; 6306e91bba0SGirish Moodalbail ipmgmt_resetaddr_cbarg_t cbarg; 6316e91bba0SGirish Moodalbail 6326e91bba0SGirish Moodalbail cbarg.cb_aobjname = rargp->ia_aobjname; 6336e91bba0SGirish Moodalbail 6346e91bba0SGirish Moodalbail if (flags & IPMGMT_PERSIST) 6356e91bba0SGirish Moodalbail err = ipmgmt_db_walk(ipmgmt_db_resetaddr, &cbarg, 6366e91bba0SGirish Moodalbail IPADM_DB_DELETE); 6376e91bba0SGirish Moodalbail 6386e91bba0SGirish Moodalbail if (flags & IPMGMT_ACTIVE) { 6396e91bba0SGirish Moodalbail bzero(&node, sizeof (node)); 6406e91bba0SGirish Moodalbail (void) strlcpy(node.am_aobjname, rargp->ia_aobjname, 6416e91bba0SGirish Moodalbail sizeof (node.am_aobjname)); 6426e91bba0SGirish Moodalbail 6436e91bba0SGirish Moodalbail /* 6446e91bba0SGirish Moodalbail * am_lnum is used only for IPv6 autoconf case, since there 6456e91bba0SGirish Moodalbail * can be multiple nodes with the same aobjname. 6466e91bba0SGirish Moodalbail */ 6476e91bba0SGirish Moodalbail node.am_lnum = rargp->ia_lnum; 6486e91bba0SGirish Moodalbail node.am_flags = flags; 6496e91bba0SGirish Moodalbail (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE); 6506e91bba0SGirish Moodalbail } 6516e91bba0SGirish Moodalbail 6526e91bba0SGirish Moodalbail rval.ir_err = err; 6536e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 6546e91bba0SGirish Moodalbail } 6556e91bba0SGirish Moodalbail 6566e91bba0SGirish Moodalbail /* 6576e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted 6586e91bba0SGirish Moodalbail * address for a given `gargp->ia_aobjname'. If it is not defined then it 6596e91bba0SGirish Moodalbail * retrieves all the addresses configured on `gargp->ia_ifname'. The 6606e91bba0SGirish Moodalbail * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this 6616e91bba0SGirish Moodalbail * handler through library. 6626e91bba0SGirish Moodalbail */ 6636e91bba0SGirish Moodalbail static void 6646e91bba0SGirish Moodalbail ipmgmt_getaddr_handler(void *argp) 6656e91bba0SGirish Moodalbail { 6666e91bba0SGirish Moodalbail ipmgmt_getaddr_arg_t *gargp = argp; 6676e91bba0SGirish Moodalbail 668*a73be61aSHans Rosenfeld ipmgmt_common_handler(gargp->ia_ifname, gargp->ia_aobjname, 669*a73be61aSHans Rosenfeld ipmgmt_db_getaddr); 6706e91bba0SGirish Moodalbail } 6716e91bba0SGirish Moodalbail 6726e91bba0SGirish Moodalbail /* 6736e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line 6746e91bba0SGirish Moodalbail * from the DB. 6756e91bba0SGirish Moodalbail */ 6766e91bba0SGirish Moodalbail static void 6776e91bba0SGirish Moodalbail ipmgmt_resetprop_handler(void *argp) 6786e91bba0SGirish Moodalbail { 6796e91bba0SGirish Moodalbail ipmgmt_prop_arg_t *pargp = argp; 6806e91bba0SGirish Moodalbail ipmgmt_retval_t rval; 6816e91bba0SGirish Moodalbail 6826e91bba0SGirish Moodalbail assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP); 6836e91bba0SGirish Moodalbail 6846e91bba0SGirish Moodalbail rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp, 6856e91bba0SGirish Moodalbail IPADM_DB_DELETE); 6866e91bba0SGirish Moodalbail (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 6876e91bba0SGirish Moodalbail } 6886e91bba0SGirish Moodalbail 6896e91bba0SGirish Moodalbail /* 690*a73be61aSHans Rosenfeld * Handles the door command IPMGMT_CMD_GETIF. It retrieves the names of all 691*a73be61aSHans Rosenfeld * persisted interfaces and the IP protocol families (IPv4 or IPv6) they 692*a73be61aSHans Rosenfeld * support. Returns the info as a nvlist using door_return() from 693*a73be61aSHans Rosenfeld * ipmgmt_common_handler(). 6946e91bba0SGirish Moodalbail */ 6956e91bba0SGirish Moodalbail static void 6966e91bba0SGirish Moodalbail ipmgmt_getif_handler(void *argp) 6976e91bba0SGirish Moodalbail { 6986e91bba0SGirish Moodalbail ipmgmt_getif_arg_t *getif = argp; 6996e91bba0SGirish Moodalbail 7006e91bba0SGirish Moodalbail assert(getif->ia_cmd == IPMGMT_CMD_GETIF); 7016e91bba0SGirish Moodalbail 702*a73be61aSHans Rosenfeld ipmgmt_common_handler(getif->ia_ifname, NULL, 703*a73be61aSHans Rosenfeld ipmgmt_db_getif); 7046e91bba0SGirish Moodalbail } 7056e91bba0SGirish Moodalbail 7066e91bba0SGirish Moodalbail /* 7076e91bba0SGirish Moodalbail * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted 7086e91bba0SGirish Moodalbail * interface configuration (interface properties and addresses), for all those 7096e91bba0SGirish Moodalbail * interfaces that need to be initialized. 7106e91bba0SGirish Moodalbail */ 7116e91bba0SGirish Moodalbail static void 7126e91bba0SGirish Moodalbail ipmgmt_initif_handler(void *argp) 7136e91bba0SGirish Moodalbail { 7146e91bba0SGirish Moodalbail ipmgmt_initif_arg_t *initif = argp; 7156e91bba0SGirish Moodalbail size_t buflen, nvlsize; 7166e91bba0SGirish Moodalbail char *buf = NULL, *onvlbuf, *invlbuf; 7176e91bba0SGirish Moodalbail ipmgmt_get_rval_t rval, *rvalp = &rval; 7186e91bba0SGirish Moodalbail ipmgmt_initif_cbarg_t cbarg; 7196e91bba0SGirish Moodalbail int err; 7206e91bba0SGirish Moodalbail 7216e91bba0SGirish Moodalbail assert(initif->ia_cmd == IPMGMT_CMD_INITIF); 7226e91bba0SGirish Moodalbail 7236e91bba0SGirish Moodalbail bzero(&cbarg, sizeof (cbarg)); 7246e91bba0SGirish Moodalbail invlbuf = (char *)argp + sizeof (ipmgmt_initif_arg_t); 7256e91bba0SGirish Moodalbail nvlsize = initif->ia_nvlsize; 7260d1087e8SHans Rosenfeld err = nvlist_unpack(invlbuf, nvlsize, &cbarg.cb_invl, 0); 7276e91bba0SGirish Moodalbail if (err != 0) 7286e91bba0SGirish Moodalbail goto fail; 7296e91bba0SGirish Moodalbail 7306e91bba0SGirish Moodalbail cbarg.cb_family = initif->ia_family; 7316e91bba0SGirish Moodalbail if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) 7326e91bba0SGirish Moodalbail goto fail; 7336e91bba0SGirish Moodalbail 7346e91bba0SGirish Moodalbail err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ); 7356e91bba0SGirish Moodalbail if (err == ENOENT && cbarg.cb_ocnt > 0) { 7366e91bba0SGirish Moodalbail /* 7376e91bba0SGirish Moodalbail * If there is at least one entry in the nvlist, 7386e91bba0SGirish Moodalbail * do not return error. 7396e91bba0SGirish Moodalbail */ 7406e91bba0SGirish Moodalbail err = 0; 7416e91bba0SGirish Moodalbail } 7426e91bba0SGirish Moodalbail if (err != 0) 7436e91bba0SGirish Moodalbail goto fail; 7446e91bba0SGirish Moodalbail 7456e91bba0SGirish Moodalbail if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0) 7466e91bba0SGirish Moodalbail goto fail; 7470a8fc1cbSHans Rosenfeld 7480a8fc1cbSHans Rosenfeld if (nvlsize > (UINT32_MAX - sizeof (ipmgmt_get_rval_t))) 7490a8fc1cbSHans Rosenfeld goto fail; 7500a8fc1cbSHans Rosenfeld 7516e91bba0SGirish Moodalbail buflen = nvlsize + sizeof (ipmgmt_get_rval_t); 7526e91bba0SGirish Moodalbail /* 7536e91bba0SGirish Moodalbail * We cannot use malloc() here because door_return never returns, and 7546e91bba0SGirish Moodalbail * memory allocated by malloc() would get leaked. Use alloca() instead. 7556e91bba0SGirish Moodalbail */ 7566e91bba0SGirish Moodalbail buf = alloca(buflen); 7576e91bba0SGirish Moodalbail onvlbuf = buf + sizeof (ipmgmt_get_rval_t); 7586e91bba0SGirish Moodalbail if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &nvlsize, 7596e91bba0SGirish Moodalbail NV_ENCODE_NATIVE, 0)) != 0) { 7606e91bba0SGirish Moodalbail goto fail; 7616e91bba0SGirish Moodalbail } 7626e91bba0SGirish Moodalbail nvlist_free(cbarg.cb_invl); 7636e91bba0SGirish Moodalbail nvlist_free(cbarg.cb_onvl); 7646e91bba0SGirish Moodalbail rvalp = (ipmgmt_get_rval_t *)(void *)buf; 7656e91bba0SGirish Moodalbail rvalp->ir_err = 0; 7666e91bba0SGirish Moodalbail rvalp->ir_nvlsize = nvlsize; 7676e91bba0SGirish Moodalbail 7686e91bba0SGirish Moodalbail (void) door_return(buf, buflen, NULL, 0); 7696e91bba0SGirish Moodalbail return; 7706e91bba0SGirish Moodalbail fail: 7716e91bba0SGirish Moodalbail nvlist_free(cbarg.cb_invl); 7726e91bba0SGirish Moodalbail nvlist_free(cbarg.cb_onvl); 7736e91bba0SGirish Moodalbail rvalp->ir_err = err; 7746e91bba0SGirish Moodalbail (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); 7756e91bba0SGirish Moodalbail } 776550b6e40SSowmini Varadhan 777550b6e40SSowmini Varadhan int 778550b6e40SSowmini Varadhan ipmgmt_persist_if(ipmgmt_if_arg_t *sargp) 779550b6e40SSowmini Varadhan { 780550b6e40SSowmini Varadhan ipadm_dbwrite_cbarg_t cb; 781550b6e40SSowmini Varadhan uint32_t flags = sargp->ia_flags; 782550b6e40SSowmini Varadhan nvlist_t *nvl = NULL; 783550b6e40SSowmini Varadhan char strval[IPMGMT_STRSIZE]; 784*a73be61aSHans Rosenfeld int err = 0; 785550b6e40SSowmini Varadhan 786550b6e40SSowmini Varadhan if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC || 787550b6e40SSowmini Varadhan sargp->ia_ifname[0] == '\0') { 788550b6e40SSowmini Varadhan err = EINVAL; 789550b6e40SSowmini Varadhan goto ret; 790550b6e40SSowmini Varadhan } 791550b6e40SSowmini Varadhan if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) 792550b6e40SSowmini Varadhan goto ret; 793*a73be61aSHans Rosenfeld 794550b6e40SSowmini Varadhan if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, 795550b6e40SSowmini Varadhan sargp->ia_ifname)) != 0) 796550b6e40SSowmini Varadhan goto ret; 797*a73be61aSHans Rosenfeld 798*a73be61aSHans Rosenfeld if ((err = ipmgmt_update_family_nvp(nvl, sargp->ia_family, 799*a73be61aSHans Rosenfeld IPMGMT_APPEND)) != 0) 800550b6e40SSowmini Varadhan goto ret; 801*a73be61aSHans Rosenfeld 802*a73be61aSHans Rosenfeld (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_ifclass); 803*a73be61aSHans Rosenfeld if ((err = nvlist_add_string(nvl, IPADM_NVP_IFCLASS, strval)) != 0) 804*a73be61aSHans Rosenfeld goto ret; 805*a73be61aSHans Rosenfeld 806550b6e40SSowmini Varadhan cb.dbw_nvl = nvl; 807*a73be61aSHans Rosenfeld cb.dbw_flags = IPMGMT_APPEND | IPMGMT_UPDATE_IF; 808*a73be61aSHans Rosenfeld err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE); 809550b6e40SSowmini Varadhan ret: 810550b6e40SSowmini Varadhan nvlist_free(nvl); 811550b6e40SSowmini Varadhan return (err); 812550b6e40SSowmini Varadhan } 813*a73be61aSHans Rosenfeld 814*a73be61aSHans Rosenfeld /* 815*a73be61aSHans Rosenfeld * The helper for ipmgmt_getif_handler and ipmgmt_getaddr_handler 816*a73be61aSHans Rosenfeld */ 817*a73be61aSHans Rosenfeld static void 818*a73be61aSHans Rosenfeld ipmgmt_common_handler(char *if_name, char *aobj_name, db_wfunc_t worker) 819*a73be61aSHans Rosenfeld { 820*a73be61aSHans Rosenfeld size_t buflen, onvlsize; 821*a73be61aSHans Rosenfeld char *buf, *onvlbuf; 822*a73be61aSHans Rosenfeld ipmgmt_get_cbarg_t cbarg; 823*a73be61aSHans Rosenfeld ipmgmt_get_rval_t rval, *rvalp = &rval; 824*a73be61aSHans Rosenfeld int err = 0; 825*a73be61aSHans Rosenfeld 826*a73be61aSHans Rosenfeld cbarg.cb_ifname = if_name; 827*a73be61aSHans Rosenfeld cbarg.cb_aobjname = aobj_name; 828*a73be61aSHans Rosenfeld cbarg.cb_ocnt = 0; 829*a73be61aSHans Rosenfeld 830*a73be61aSHans Rosenfeld if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0) 831*a73be61aSHans Rosenfeld goto fail; 832*a73be61aSHans Rosenfeld 833*a73be61aSHans Rosenfeld err = ipmgmt_db_walk(worker, &cbarg, IPADM_DB_READ); 834*a73be61aSHans Rosenfeld if (err == ENOENT && cbarg.cb_ocnt > 0) { 835*a73be61aSHans Rosenfeld /* 836*a73be61aSHans Rosenfeld * If there is at least one entry in the nvlist, 837*a73be61aSHans Rosenfeld * do not return error. 838*a73be61aSHans Rosenfeld */ 839*a73be61aSHans Rosenfeld err = 0; 840*a73be61aSHans Rosenfeld } 841*a73be61aSHans Rosenfeld if (err != 0) 842*a73be61aSHans Rosenfeld goto fail; 843*a73be61aSHans Rosenfeld 844*a73be61aSHans Rosenfeld if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize, 845*a73be61aSHans Rosenfeld NV_ENCODE_NATIVE)) != 0) 846*a73be61aSHans Rosenfeld goto fail; 847*a73be61aSHans Rosenfeld 848*a73be61aSHans Rosenfeld if (onvlsize > (UINT32_MAX - sizeof (ipmgmt_get_rval_t))) 849*a73be61aSHans Rosenfeld goto fail; 850*a73be61aSHans Rosenfeld 851*a73be61aSHans Rosenfeld buflen = onvlsize + sizeof (ipmgmt_get_rval_t); 852*a73be61aSHans Rosenfeld /* 853*a73be61aSHans Rosenfeld * We cannot use malloc() here because door_return never returns, and 854*a73be61aSHans Rosenfeld * memory allocated by malloc() would get leaked. Use alloca() instead. 855*a73be61aSHans Rosenfeld */ 856*a73be61aSHans Rosenfeld buf = alloca(buflen); 857*a73be61aSHans Rosenfeld onvlbuf = buf + sizeof (ipmgmt_get_rval_t); 858*a73be61aSHans Rosenfeld if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, 859*a73be61aSHans Rosenfeld &onvlsize, NV_ENCODE_NATIVE, 0)) != 0) 860*a73be61aSHans Rosenfeld goto fail; 861*a73be61aSHans Rosenfeld 862*a73be61aSHans Rosenfeld nvlist_free(cbarg.cb_onvl); 863*a73be61aSHans Rosenfeld rvalp = (ipmgmt_get_rval_t *)(void *)buf; 864*a73be61aSHans Rosenfeld rvalp->ir_err = 0; 865*a73be61aSHans Rosenfeld rvalp->ir_nvlsize = onvlsize; 866*a73be61aSHans Rosenfeld 867*a73be61aSHans Rosenfeld (void) door_return(buf, buflen, NULL, 0); 868*a73be61aSHans Rosenfeld 869*a73be61aSHans Rosenfeld fail: 870*a73be61aSHans Rosenfeld nvlist_free(cbarg.cb_onvl); 871*a73be61aSHans Rosenfeld rvalp->ir_err = err; 872*a73be61aSHans Rosenfeld (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0); 873*a73be61aSHans Rosenfeld } 874*a73be61aSHans Rosenfeld 875*a73be61aSHans Rosenfeld /* 876*a73be61aSHans Rosenfeld * Handles the door command IPMGMT_CMD_IPMP_UPDATE 877*a73be61aSHans Rosenfeld */ 878*a73be61aSHans Rosenfeld static void 879*a73be61aSHans Rosenfeld ipmgmt_ipmp_update_handler(void *argp) 880*a73be61aSHans Rosenfeld { 881*a73be61aSHans Rosenfeld ipmgmt_ipmp_update_arg_t *uargp = argp; 882*a73be61aSHans Rosenfeld ipmgmt_retval_t rval; 883*a73be61aSHans Rosenfeld ipadm_dbwrite_cbarg_t cb; 884*a73be61aSHans Rosenfeld 885*a73be61aSHans Rosenfeld boolean_t gif_exists; 886*a73be61aSHans Rosenfeld char gifname[LIFNAMSIZ]; 887*a73be61aSHans Rosenfeld nvlist_t *nvl = NULL; 888*a73be61aSHans Rosenfeld uint32_t flags = uargp->ia_flags; 889*a73be61aSHans Rosenfeld int err = 0; 890*a73be61aSHans Rosenfeld 891*a73be61aSHans Rosenfeld assert(uargp->ia_cmd == IPMGMT_CMD_IPMP_UPDATE); 892*a73be61aSHans Rosenfeld 893*a73be61aSHans Rosenfeld gif_exists = ipmgmt_persist_if_exists(uargp->ia_gifname, 894*a73be61aSHans Rosenfeld AF_UNSPEC); 895*a73be61aSHans Rosenfeld 896*a73be61aSHans Rosenfeld if (!ipmgmt_persist_if_exists(uargp->ia_mifname, AF_UNSPEC)) { 897*a73be61aSHans Rosenfeld err = EINVAL; 898*a73be61aSHans Rosenfeld goto ret; 899*a73be61aSHans Rosenfeld } 900*a73be61aSHans Rosenfeld 901*a73be61aSHans Rosenfeld ipmgmt_get_group_interface(uargp->ia_mifname, gifname, LIFNAMSIZ); 902*a73be61aSHans Rosenfeld 903*a73be61aSHans Rosenfeld if (flags & IPMGMT_APPEND) { 904*a73be61aSHans Rosenfeld /* Group interface should be available in the DB */ 905*a73be61aSHans Rosenfeld if (!gif_exists) { 906*a73be61aSHans Rosenfeld err = ENOENT; 907*a73be61aSHans Rosenfeld goto ret; 908*a73be61aSHans Rosenfeld } 909*a73be61aSHans Rosenfeld 910*a73be61aSHans Rosenfeld if (gifname[0] != '\0') { 911*a73be61aSHans Rosenfeld err = EEXIST; 912*a73be61aSHans Rosenfeld goto ret; 913*a73be61aSHans Rosenfeld } 914*a73be61aSHans Rosenfeld } 915*a73be61aSHans Rosenfeld 916*a73be61aSHans Rosenfeld if (flags & IPMGMT_REMOVE) { 917*a73be61aSHans Rosenfeld /* We cannot remove something that does not exist */ 918*a73be61aSHans Rosenfeld if (!gif_exists || gifname[0] == '\0') { 919*a73be61aSHans Rosenfeld err = ENOENT; 920*a73be61aSHans Rosenfeld goto ret; 921*a73be61aSHans Rosenfeld } 922*a73be61aSHans Rosenfeld if (strcmp(uargp->ia_gifname, gifname) != 0) { 923*a73be61aSHans Rosenfeld err = EINVAL; 924*a73be61aSHans Rosenfeld goto ret; 925*a73be61aSHans Rosenfeld } 926*a73be61aSHans Rosenfeld } 927*a73be61aSHans Rosenfeld 928*a73be61aSHans Rosenfeld if (flags & IPMGMT_PERSIST) { 929*a73be61aSHans Rosenfeld if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) 930*a73be61aSHans Rosenfeld goto ret; 931*a73be61aSHans Rosenfeld 932*a73be61aSHans Rosenfeld if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, 933*a73be61aSHans Rosenfeld uargp->ia_gifname)) != 0) 934*a73be61aSHans Rosenfeld goto ret; 935*a73be61aSHans Rosenfeld 936*a73be61aSHans Rosenfeld if ((err = nvlist_add_string(nvl, IPADM_NVP_MIFNAMES, 937*a73be61aSHans Rosenfeld uargp->ia_mifname)) != 0) 938*a73be61aSHans Rosenfeld goto ret; 939*a73be61aSHans Rosenfeld 940*a73be61aSHans Rosenfeld if ((err = nvlist_add_string(nvl, IPADM_NVP_GIFNAME, 941*a73be61aSHans Rosenfeld uargp->ia_gifname)) != 0) 942*a73be61aSHans Rosenfeld goto ret; 943*a73be61aSHans Rosenfeld 944*a73be61aSHans Rosenfeld cb.dbw_nvl = nvl; 945*a73be61aSHans Rosenfeld cb.dbw_flags = flags | IPMGMT_UPDATE_IF | IPMGMT_UPDATE_IPMP; 946*a73be61aSHans Rosenfeld err = ipmgmt_db_walk(ipmgmt_db_update_if, &cb, IPADM_DB_WRITE); 947*a73be61aSHans Rosenfeld } 948*a73be61aSHans Rosenfeld ret: 949*a73be61aSHans Rosenfeld nvlist_free(nvl); 950*a73be61aSHans Rosenfeld rval.ir_err = err; 951*a73be61aSHans Rosenfeld (void) door_return((char *)&rval, sizeof (rval), NULL, 0); 952*a73be61aSHans Rosenfeld } 953