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. 246e91bba0SGirish Moodalbail */ 256e91bba0SGirish Moodalbail 266e91bba0SGirish Moodalbail /* 276e91bba0SGirish Moodalbail * Contains DB walker functions, which are of type `db_wfunc_t'; 286e91bba0SGirish Moodalbail * 296e91bba0SGirish Moodalbail * typedef boolean_t db_wfunc_t(void *cbarg, nvlist_t *db_nvl, char *buf, 306e91bba0SGirish Moodalbail * size_t bufsize, int *errp); 316e91bba0SGirish Moodalbail * 326e91bba0SGirish Moodalbail * ipadm_rw_db() walks through the data store, one line at a time and calls 336e91bba0SGirish Moodalbail * these call back functions with: 346e91bba0SGirish Moodalbail * `cbarg' - callback argument 356e91bba0SGirish Moodalbail * `db_nvl' - representing a line from DB in nvlist_t form 366e91bba0SGirish Moodalbail * `buf' - character buffer to hold modified line 376e91bba0SGirish Moodalbail * `bufsize'- size of the buffer 386e91bba0SGirish Moodalbail * `errp' - captures any error inside the walker function. 396e91bba0SGirish Moodalbail * 406e91bba0SGirish Moodalbail * All the 'write' callback functions modify `db_nvl' based on `cbarg' and 416e91bba0SGirish Moodalbail * copy string representation of `db_nvl' (using ipadm_nvlist2str()) into `buf'. 426e91bba0SGirish Moodalbail * To delete a line from the DB, buf[0] is set to `\0'. Inside ipadm_rw_db(), 436e91bba0SGirish Moodalbail * the modified `buf' is written back into DB. 446e91bba0SGirish Moodalbail * 456e91bba0SGirish Moodalbail * All the 'read' callback functions, retrieve the information from the DB, by 466e91bba0SGirish Moodalbail * reading `db_nvl' and then populate the `cbarg'. 476e91bba0SGirish Moodalbail */ 486e91bba0SGirish Moodalbail 496e91bba0SGirish Moodalbail #include <stdlib.h> 506e91bba0SGirish Moodalbail #include <strings.h> 516e91bba0SGirish Moodalbail #include <errno.h> 526e91bba0SGirish Moodalbail #include <assert.h> 536e91bba0SGirish Moodalbail #include <sys/types.h> 546e91bba0SGirish Moodalbail #include <sys/socket.h> 556e91bba0SGirish Moodalbail #include <netinet/in.h> 566e91bba0SGirish Moodalbail #include <arpa/inet.h> 576e91bba0SGirish Moodalbail #include <unistd.h> 586e91bba0SGirish Moodalbail #include "ipmgmt_impl.h" 59*8887b57dSGirish Moodalbail 60*8887b57dSGirish Moodalbail /* SCF related property group names and property names */ 61*8887b57dSGirish Moodalbail #define IPMGMTD_APP_PG "ipmgmtd" 62*8887b57dSGirish Moodalbail #define IPMGMTD_PROP_FBD "first_boot_done" 63*8887b57dSGirish Moodalbail #define IPMGMTD_PROP_DBVER "datastore_version" 64*8887b57dSGirish Moodalbail #define IPMGMTD_TRUESTR "true" 656e91bba0SGirish Moodalbail 666e91bba0SGirish Moodalbail #define ATYPE "_atype" /* name of the address type nvpair */ 676e91bba0SGirish Moodalbail #define FLAGS "_flags" /* name of the flags nvpair */ 686e91bba0SGirish Moodalbail 696e91bba0SGirish Moodalbail /* 706e91bba0SGirish Moodalbail * flag used by ipmgmt_persist_aobjmap() to indicate address type is 716e91bba0SGirish Moodalbail * IPADM_ADDR_IPV6_ADDRCONF. 726e91bba0SGirish Moodalbail */ 736e91bba0SGirish Moodalbail #define IPMGMT_ATYPE_V6ACONF 0x1 746e91bba0SGirish Moodalbail 756e91bba0SGirish Moodalbail extern pthread_rwlock_t ipmgmt_dbconf_lock; 766e91bba0SGirish Moodalbail 779b5bf10aSMark Haywood /* signifies whether volatile copy of data store is in use */ 789b5bf10aSMark Haywood static boolean_t ipmgmt_rdonly_root = B_FALSE; 799b5bf10aSMark Haywood 806e91bba0SGirish Moodalbail /* 816e91bba0SGirish Moodalbail * Checks if the database nvl, `db_nvl' contains and matches ALL of the passed 826e91bba0SGirish Moodalbail * in private nvpairs `proto', `ifname' & `aobjname'. 836e91bba0SGirish Moodalbail */ 846e91bba0SGirish Moodalbail static boolean_t 856e91bba0SGirish Moodalbail ipmgmt_nvlist_match(nvlist_t *db_nvl, const char *proto, const char *ifname, 866e91bba0SGirish Moodalbail const char *aobjname) 876e91bba0SGirish Moodalbail { 886e91bba0SGirish Moodalbail char *db_proto = NULL, *db_ifname = NULL; 896e91bba0SGirish Moodalbail char *db_aobjname = NULL; 906e91bba0SGirish Moodalbail nvpair_t *nvp; 916e91bba0SGirish Moodalbail char *name; 926e91bba0SGirish Moodalbail 936e91bba0SGirish Moodalbail /* walk through db_nvl and retrieve all its private nvpairs */ 946e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 956e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 966e91bba0SGirish Moodalbail name = nvpair_name(nvp); 976e91bba0SGirish Moodalbail if (strcmp(IPADM_NVP_PROTONAME, name) == 0) 986e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_proto); 996e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_IFNAME, name) == 0) 1006e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_ifname); 1016e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) 1026e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_aobjname); 1036e91bba0SGirish Moodalbail } 1046e91bba0SGirish Moodalbail 1056e91bba0SGirish Moodalbail if (proto != NULL && proto[0] == '\0') 1066e91bba0SGirish Moodalbail proto = NULL; 1076e91bba0SGirish Moodalbail if (ifname != NULL && ifname[0] == '\0') 1086e91bba0SGirish Moodalbail ifname = NULL; 1096e91bba0SGirish Moodalbail if (aobjname != NULL && aobjname[0] == '\0') 1106e91bba0SGirish Moodalbail aobjname = NULL; 1116e91bba0SGirish Moodalbail 1126e91bba0SGirish Moodalbail if ((proto == NULL && db_proto != NULL) || 1136e91bba0SGirish Moodalbail (proto != NULL && db_proto == NULL) || 1146e91bba0SGirish Moodalbail strcmp(proto, db_proto) != 0) { 1156e91bba0SGirish Moodalbail /* no intersection - different protocols. */ 1166e91bba0SGirish Moodalbail return (B_FALSE); 1176e91bba0SGirish Moodalbail } 1186e91bba0SGirish Moodalbail if ((ifname == NULL && db_ifname != NULL) || 1196e91bba0SGirish Moodalbail (ifname != NULL && db_ifname == NULL) || 1206e91bba0SGirish Moodalbail strcmp(ifname, db_ifname) != 0) { 1216e91bba0SGirish Moodalbail /* no intersection - different interfaces. */ 1226e91bba0SGirish Moodalbail return (B_FALSE); 1236e91bba0SGirish Moodalbail } 1246e91bba0SGirish Moodalbail if ((aobjname == NULL && db_aobjname != NULL) || 1256e91bba0SGirish Moodalbail (aobjname != NULL && db_aobjname == NULL) || 1266e91bba0SGirish Moodalbail strcmp(aobjname, db_aobjname) != 0) { 1276e91bba0SGirish Moodalbail /* no intersection - different address objects */ 1286e91bba0SGirish Moodalbail return (B_FALSE); 1296e91bba0SGirish Moodalbail } 1306e91bba0SGirish Moodalbail 1316e91bba0SGirish Moodalbail return (B_TRUE); 1326e91bba0SGirish Moodalbail } 1336e91bba0SGirish Moodalbail 1346e91bba0SGirish Moodalbail /* 1356e91bba0SGirish Moodalbail * Checks if the database nvl, `db_nvl' and the input nvl, `in_nvl' intersects. 1366e91bba0SGirish Moodalbail */ 1376e91bba0SGirish Moodalbail static boolean_t 1386e91bba0SGirish Moodalbail ipmgmt_nvlist_intersects(nvlist_t *db_nvl, nvlist_t *in_nvl) 1396e91bba0SGirish Moodalbail { 1406e91bba0SGirish Moodalbail nvpair_t *nvp; 1416e91bba0SGirish Moodalbail char *name; 1426e91bba0SGirish Moodalbail char *proto = NULL, *ifname = NULL, *aobjname = NULL; 1436e91bba0SGirish Moodalbail 1446e91bba0SGirish Moodalbail /* walk through in_nvl and retrieve all its private nvpairs */ 1456e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(in_nvl, NULL); nvp != NULL; 1466e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(in_nvl, nvp)) { 1476e91bba0SGirish Moodalbail name = nvpair_name(nvp); 1486e91bba0SGirish Moodalbail if (strcmp(IPADM_NVP_PROTONAME, name) == 0) 1496e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &proto); 1506e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_IFNAME, name) == 0) 1516e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &ifname); 1526e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) 1536e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &aobjname); 1546e91bba0SGirish Moodalbail } 1556e91bba0SGirish Moodalbail 1566e91bba0SGirish Moodalbail return (ipmgmt_nvlist_match(db_nvl, proto, ifname, aobjname)); 1576e91bba0SGirish Moodalbail } 1586e91bba0SGirish Moodalbail 1596e91bba0SGirish Moodalbail /* 1606e91bba0SGirish Moodalbail * Checks if the database nvl, `db_nvl', contains and matches ANY of the passed 1616e91bba0SGirish Moodalbail * in private nvpairs `proto', `ifname' & `aobjname'. 1626e91bba0SGirish Moodalbail */ 1636e91bba0SGirish Moodalbail static boolean_t 1646e91bba0SGirish Moodalbail ipmgmt_nvlist_contains(nvlist_t *db_nvl, const char *proto, 1656e91bba0SGirish Moodalbail const char *ifname, char *aobjname) 1666e91bba0SGirish Moodalbail { 1676e91bba0SGirish Moodalbail char *db_ifname = NULL, *db_proto = NULL; 1686e91bba0SGirish Moodalbail char *db_aobjname = NULL; 1696e91bba0SGirish Moodalbail nvpair_t *nvp; 1706e91bba0SGirish Moodalbail char *name; 1716e91bba0SGirish Moodalbail 1726e91bba0SGirish Moodalbail /* walk through db_nvl and retrieve all private nvpairs */ 1736e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 1746e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 1756e91bba0SGirish Moodalbail name = nvpair_name(nvp); 1766e91bba0SGirish Moodalbail if (strcmp(IPADM_NVP_PROTONAME, name) == 0) 1776e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_proto); 1786e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_IFNAME, name) == 0) 1796e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_ifname); 1806e91bba0SGirish Moodalbail else if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) 1816e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_aobjname); 1826e91bba0SGirish Moodalbail } 1836e91bba0SGirish Moodalbail 1846e91bba0SGirish Moodalbail if (proto != NULL && proto[0] != '\0') { 1856e91bba0SGirish Moodalbail if ((db_proto == NULL || strcmp(proto, db_proto) != 0)) 1866e91bba0SGirish Moodalbail return (B_FALSE); 1876e91bba0SGirish Moodalbail } 1886e91bba0SGirish Moodalbail if (ifname != NULL && ifname[0] != '\0') { 1896e91bba0SGirish Moodalbail if ((db_ifname == NULL || strcmp(ifname, db_ifname) != 0)) 1906e91bba0SGirish Moodalbail return (B_FALSE); 1916e91bba0SGirish Moodalbail } 1926e91bba0SGirish Moodalbail if (aobjname != NULL && aobjname[0] != '\0') { 1936e91bba0SGirish Moodalbail if ((db_aobjname == NULL || strcmp(aobjname, db_aobjname) != 0)) 1946e91bba0SGirish Moodalbail return (B_FALSE); 1956e91bba0SGirish Moodalbail } 1966e91bba0SGirish Moodalbail 1976e91bba0SGirish Moodalbail return (B_TRUE); 1986e91bba0SGirish Moodalbail } 1996e91bba0SGirish Moodalbail 2006e91bba0SGirish Moodalbail /* 2016e91bba0SGirish Moodalbail * Retrieves the property value from the DB. The property whose value is to be 2026e91bba0SGirish Moodalbail * retrieved is in `pargp->ia_pname'. 2036e91bba0SGirish Moodalbail */ 2046e91bba0SGirish Moodalbail /* ARGSUSED */ 2056e91bba0SGirish Moodalbail boolean_t 2066e91bba0SGirish Moodalbail ipmgmt_db_getprop(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 2076e91bba0SGirish Moodalbail int *errp) 2086e91bba0SGirish Moodalbail { 2096e91bba0SGirish Moodalbail ipmgmt_prop_arg_t *pargp = arg; 2106e91bba0SGirish Moodalbail boolean_t cont = B_TRUE; 2116e91bba0SGirish Moodalbail char *pval; 2126e91bba0SGirish Moodalbail int err = 0; 2136e91bba0SGirish Moodalbail 2146e91bba0SGirish Moodalbail *errp = 0; 2156e91bba0SGirish Moodalbail 2166e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_match(db_nvl, pargp->ia_module, 2176e91bba0SGirish Moodalbail pargp->ia_ifname, pargp->ia_aobjname)) 2186e91bba0SGirish Moodalbail return (B_TRUE); 2196e91bba0SGirish Moodalbail 2206e91bba0SGirish Moodalbail if ((err = nvlist_lookup_string(db_nvl, pargp->ia_pname, 2216e91bba0SGirish Moodalbail &pval)) == 0) { 2226e91bba0SGirish Moodalbail (void) strlcpy(pargp->ia_pval, pval, sizeof (pargp->ia_pval)); 2236e91bba0SGirish Moodalbail /* 2246e91bba0SGirish Moodalbail * We have retrieved what we are looking for. 2256e91bba0SGirish Moodalbail * Stop the walker. 2266e91bba0SGirish Moodalbail */ 2276e91bba0SGirish Moodalbail cont = B_FALSE; 2286e91bba0SGirish Moodalbail } else { 2296e91bba0SGirish Moodalbail if (err == ENOENT) 2306e91bba0SGirish Moodalbail err = 0; 2316e91bba0SGirish Moodalbail *errp = err; 2326e91bba0SGirish Moodalbail } 2336e91bba0SGirish Moodalbail 2346e91bba0SGirish Moodalbail return (cont); 2356e91bba0SGirish Moodalbail } 2366e91bba0SGirish Moodalbail 2376e91bba0SGirish Moodalbail /* 2386e91bba0SGirish Moodalbail * Removes the property value from the DB. The property whose value is to be 2396e91bba0SGirish Moodalbail * removed is in `pargp->ia_pname'. 2406e91bba0SGirish Moodalbail */ 2416e91bba0SGirish Moodalbail /* ARGSUSED */ 2426e91bba0SGirish Moodalbail boolean_t 2436e91bba0SGirish Moodalbail ipmgmt_db_resetprop(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 2446e91bba0SGirish Moodalbail int *errp) 2456e91bba0SGirish Moodalbail { 2466e91bba0SGirish Moodalbail ipmgmt_prop_arg_t *pargp = arg; 2476e91bba0SGirish Moodalbail 2486e91bba0SGirish Moodalbail *errp = 0; 2496e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_match(db_nvl, pargp->ia_module, 2506e91bba0SGirish Moodalbail pargp->ia_ifname, pargp->ia_aobjname)) 2516e91bba0SGirish Moodalbail return (B_TRUE); 2526e91bba0SGirish Moodalbail 2536e91bba0SGirish Moodalbail if (!nvlist_exists(db_nvl, pargp->ia_pname)) 2546e91bba0SGirish Moodalbail return (B_TRUE); 2556e91bba0SGirish Moodalbail 2566e91bba0SGirish Moodalbail /* 2576e91bba0SGirish Moodalbail * We found the property in the DB. If IPMGMT_REMOVE is not set then 2586e91bba0SGirish Moodalbail * delete the entry from the db. If it is set, then the property is a 2596e91bba0SGirish Moodalbail * multi-valued property so just remove the specified values from DB. 2606e91bba0SGirish Moodalbail */ 2616e91bba0SGirish Moodalbail if (pargp->ia_flags & IPMGMT_REMOVE) { 2626e91bba0SGirish Moodalbail char *dbpval = NULL; 2636e91bba0SGirish Moodalbail char *inpval = pargp->ia_pval; 2646e91bba0SGirish Moodalbail char pval[MAXPROPVALLEN]; 2656e91bba0SGirish Moodalbail char *val, *lasts; 2666e91bba0SGirish Moodalbail 2676e91bba0SGirish Moodalbail *errp = nvlist_lookup_string(db_nvl, pargp->ia_pname, &dbpval); 2686e91bba0SGirish Moodalbail if (*errp != 0) 2696e91bba0SGirish Moodalbail return (B_FALSE); 2706e91bba0SGirish Moodalbail 2716e91bba0SGirish Moodalbail /* 2726e91bba0SGirish Moodalbail * multi-valued properties are represented as comma separated 2736e91bba0SGirish Moodalbail * values. Use string tokenizer functions to split them and 2746e91bba0SGirish Moodalbail * search for the value to be removed. 2756e91bba0SGirish Moodalbail */ 2766e91bba0SGirish Moodalbail bzero(pval, sizeof (pval)); 2776e91bba0SGirish Moodalbail if ((val = strtok_r(dbpval, ",", &lasts)) != NULL) { 2786e91bba0SGirish Moodalbail if (strcmp(val, inpval) != 0) 2796e91bba0SGirish Moodalbail (void) strlcat(pval, val, MAXPROPVALLEN); 2806e91bba0SGirish Moodalbail while ((val = strtok_r(NULL, ",", &lasts)) != NULL) { 2816e91bba0SGirish Moodalbail if (strcmp(val, inpval) != 0) { 2826e91bba0SGirish Moodalbail if (pval[0] != '\0') 2836e91bba0SGirish Moodalbail (void) strlcat(pval, ",", 2846e91bba0SGirish Moodalbail MAXPROPVALLEN); 2856e91bba0SGirish Moodalbail (void) strlcat(pval, val, 2866e91bba0SGirish Moodalbail MAXPROPVALLEN); 2876e91bba0SGirish Moodalbail } 2886e91bba0SGirish Moodalbail } 2896e91bba0SGirish Moodalbail } else { 2906e91bba0SGirish Moodalbail if (strcmp(dbpval, inpval) != 0) 2916e91bba0SGirish Moodalbail *errp = ENOENT; 2926e91bba0SGirish Moodalbail else 2936e91bba0SGirish Moodalbail buf[0] = '\0'; 2946e91bba0SGirish Moodalbail return (B_FALSE); 2956e91bba0SGirish Moodalbail } 2966e91bba0SGirish Moodalbail *errp = nvlist_add_string(db_nvl, pargp->ia_pname, pval); 2976e91bba0SGirish Moodalbail if (*errp != 0) 2986e91bba0SGirish Moodalbail return (B_FALSE); 2996e91bba0SGirish Moodalbail 3006e91bba0SGirish Moodalbail (void) memset(buf, 0, buflen); 3016e91bba0SGirish Moodalbail if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) { 3026e91bba0SGirish Moodalbail /* buffer overflow */ 3036e91bba0SGirish Moodalbail *errp = ENOBUFS; 3046e91bba0SGirish Moodalbail } 3056e91bba0SGirish Moodalbail } else { 3066e91bba0SGirish Moodalbail buf[0] = '\0'; 3076e91bba0SGirish Moodalbail } 3086e91bba0SGirish Moodalbail 3096e91bba0SGirish Moodalbail /* stop the search */ 3106e91bba0SGirish Moodalbail return (B_FALSE); 3116e91bba0SGirish Moodalbail } 3126e91bba0SGirish Moodalbail 3136e91bba0SGirish Moodalbail /* 3146e91bba0SGirish Moodalbail * Input arguments can have IPADM_NVP_AOBJNAME or IPADM_NVP_IFNAME. A match is 3156e91bba0SGirish Moodalbail * found, when one of the following occurs first. 3166e91bba0SGirish Moodalbail * - the input aobjname matches the db aobjname. Return the db address. 3176e91bba0SGirish Moodalbail * - the input interface matches the db interface. Return all the 3186e91bba0SGirish Moodalbail * matching db lines with addresses. 3196e91bba0SGirish Moodalbail */ 3206e91bba0SGirish Moodalbail /* ARGSUSED */ 3216e91bba0SGirish Moodalbail boolean_t 3226e91bba0SGirish Moodalbail ipmgmt_db_getaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 3236e91bba0SGirish Moodalbail int *errp) 3246e91bba0SGirish Moodalbail { 3256e91bba0SGirish Moodalbail ipmgmt_getaddr_cbarg_t *cbarg = arg; 3266e91bba0SGirish Moodalbail char *db_aobjname = NULL; 3276e91bba0SGirish Moodalbail char *db_ifname = NULL; 3286e91bba0SGirish Moodalbail nvlist_t *db_addr = NULL; 3296e91bba0SGirish Moodalbail char name[IPMGMT_STRSIZE]; 3306e91bba0SGirish Moodalbail nvpair_t *nvp; 3316e91bba0SGirish Moodalbail boolean_t add_nvl = B_FALSE; 3326e91bba0SGirish Moodalbail 3336e91bba0SGirish Moodalbail /* Parse db nvlist */ 3346e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 3356e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 3366e91bba0SGirish Moodalbail if (nvpair_type(nvp) == DATA_TYPE_NVLIST) 3376e91bba0SGirish Moodalbail (void) nvpair_value_nvlist(nvp, &db_addr); 3386e91bba0SGirish Moodalbail else if (strcmp(nvpair_name(nvp), IPADM_NVP_IFNAME) == 0) 3396e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_ifname); 3406e91bba0SGirish Moodalbail else if (strcmp(nvpair_name(nvp), IPADM_NVP_AOBJNAME) == 0) 3416e91bba0SGirish Moodalbail (void) nvpair_value_string(nvp, &db_aobjname); 3426e91bba0SGirish Moodalbail } 3436e91bba0SGirish Moodalbail 3446e91bba0SGirish Moodalbail if (db_aobjname == NULL) /* Not an address */ 3456e91bba0SGirish Moodalbail return (B_TRUE); 3466e91bba0SGirish Moodalbail 3476e91bba0SGirish Moodalbail /* Check for a match between the aobjnames or the interface name */ 3486e91bba0SGirish Moodalbail if (cbarg->cb_aobjname[0] != '\0') { 3496e91bba0SGirish Moodalbail if (strcmp(cbarg->cb_aobjname, db_aobjname) == 0) 3506e91bba0SGirish Moodalbail add_nvl = B_TRUE; 3516e91bba0SGirish Moodalbail } else if (cbarg->cb_ifname[0] != '\0') { 3526e91bba0SGirish Moodalbail if (strcmp(cbarg->cb_ifname, db_ifname) == 0) 3536e91bba0SGirish Moodalbail add_nvl = B_TRUE; 3546e91bba0SGirish Moodalbail } else { 3556e91bba0SGirish Moodalbail add_nvl = B_TRUE; 3566e91bba0SGirish Moodalbail } 3576e91bba0SGirish Moodalbail 3586e91bba0SGirish Moodalbail if (add_nvl) { 3596e91bba0SGirish Moodalbail (void) snprintf(name, sizeof (name), "%s_%d", db_ifname, 3606e91bba0SGirish Moodalbail cbarg->cb_ocnt); 3616e91bba0SGirish Moodalbail *errp = nvlist_add_nvlist(cbarg->cb_onvl, name, db_nvl); 3626e91bba0SGirish Moodalbail if (*errp == 0) 3636e91bba0SGirish Moodalbail cbarg->cb_ocnt++; 3646e91bba0SGirish Moodalbail } 3656e91bba0SGirish Moodalbail return (B_TRUE); 3666e91bba0SGirish Moodalbail } 3676e91bba0SGirish Moodalbail 3686e91bba0SGirish Moodalbail /* 3699b5bf10aSMark Haywood * This function only gets called if a volatile filesystem version 3709b5bf10aSMark Haywood * of the configuration file has been created. This only happens in the 3719b5bf10aSMark Haywood * extremely rare case that a request has been made to update the configuration 3729b5bf10aSMark Haywood * file at boottime while the root filesystem was read-only. This is 3739b5bf10aSMark Haywood * really a rare occurrence now that we don't support UFS root filesystems 3749b5bf10aSMark Haywood * any longer. This function will periodically attempt to write the 3759b5bf10aSMark Haywood * configuration back to its location on the root filesystem. Success 3769b5bf10aSMark Haywood * will indicate that the filesystem is no longer read-only. 3779b5bf10aSMark Haywood */ 3789b5bf10aSMark Haywood /* ARGSUSED */ 3799b5bf10aSMark Haywood static void * 3809b5bf10aSMark Haywood ipmgmt_db_restore_thread(void *arg) 3819b5bf10aSMark Haywood { 3829b5bf10aSMark Haywood int err; 3839b5bf10aSMark Haywood 3849b5bf10aSMark Haywood for (;;) { 3859b5bf10aSMark Haywood (void) sleep(5); 3869b5bf10aSMark Haywood (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); 3879b5bf10aSMark Haywood if (!ipmgmt_rdonly_root) 3889b5bf10aSMark Haywood break; 3899b5bf10aSMark Haywood err = ipmgmt_cpfile(IPADM_VOL_DB_FILE, IPADM_DB_FILE, B_FALSE); 3909b5bf10aSMark Haywood if (err == 0) { 3919b5bf10aSMark Haywood ipmgmt_rdonly_root = B_FALSE; 3929b5bf10aSMark Haywood break; 3939b5bf10aSMark Haywood } 3949b5bf10aSMark Haywood (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); 3959b5bf10aSMark Haywood } 3969b5bf10aSMark Haywood (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); 3979b5bf10aSMark Haywood return (NULL); 3989b5bf10aSMark Haywood } 3999b5bf10aSMark Haywood 4009b5bf10aSMark Haywood /* 4016e91bba0SGirish Moodalbail * This function takes the appropriate lock, read or write, based on the 4029b5bf10aSMark Haywood * `db_op' and then calls DB walker ipadm_rw_db(). The code is complicated 4039b5bf10aSMark Haywood * by the fact that we are not always guaranteed to have a writable root 4049b5bf10aSMark Haywood * filesystem since it is possible that we are reading or writing during 4059b5bf10aSMark Haywood * bootime while the root filesystem is still read-only. This is, by far, 4069b5bf10aSMark Haywood * the exception case. Normally, this function will be called when the 4079b5bf10aSMark Haywood * root filesystem is writable. In the unusual case where this is not 4089b5bf10aSMark Haywood * true, the configuration file is copied to the volatile file system 4099b5bf10aSMark Haywood * and is updated there until the root filesystem becomes writable. At 4109b5bf10aSMark Haywood * that time the file will be moved back to its proper location by 4119b5bf10aSMark Haywood * ipmgmt_db_restore_thread(). 4126e91bba0SGirish Moodalbail */ 4136e91bba0SGirish Moodalbail extern int 4146e91bba0SGirish Moodalbail ipmgmt_db_walk(db_wfunc_t *db_walk_func, void *db_warg, ipadm_db_op_t db_op) 4156e91bba0SGirish Moodalbail { 4166e91bba0SGirish Moodalbail int err; 4176e91bba0SGirish Moodalbail boolean_t writeop; 4186e91bba0SGirish Moodalbail mode_t mode; 4199b5bf10aSMark Haywood pthread_t tid; 420*8887b57dSGirish Moodalbail pthread_attr_t attr; 4216e91bba0SGirish Moodalbail 4226e91bba0SGirish Moodalbail writeop = (db_op != IPADM_DB_READ); 4236e91bba0SGirish Moodalbail if (writeop) { 4246e91bba0SGirish Moodalbail (void) pthread_rwlock_wrlock(&ipmgmt_dbconf_lock); 4256e91bba0SGirish Moodalbail mode = IPADM_FILE_MODE; 4266e91bba0SGirish Moodalbail } else { 4276e91bba0SGirish Moodalbail (void) pthread_rwlock_rdlock(&ipmgmt_dbconf_lock); 4286e91bba0SGirish Moodalbail mode = 0; 4296e91bba0SGirish Moodalbail } 4306e91bba0SGirish Moodalbail 4319b5bf10aSMark Haywood /* 4329b5bf10aSMark Haywood * Did a previous write attempt fail? If so, don't even try to 4339b5bf10aSMark Haywood * read/write to IPADM_DB_FILE. 4349b5bf10aSMark Haywood */ 4359b5bf10aSMark Haywood if (!ipmgmt_rdonly_root) { 4369b5bf10aSMark Haywood err = ipadm_rw_db(db_walk_func, db_warg, IPADM_DB_FILE, 4379b5bf10aSMark Haywood mode, db_op); 4389b5bf10aSMark Haywood if (err != EROFS) 4399b5bf10aSMark Haywood goto done; 4409b5bf10aSMark Haywood } 4419b5bf10aSMark Haywood 4429b5bf10aSMark Haywood /* 4439b5bf10aSMark Haywood * If we haven't already copied the file to the volatile 4449b5bf10aSMark Haywood * file system, do so. This should only happen on a failed 4459b5bf10aSMark Haywood * writeop(i.e., we have acquired the write lock above). 4469b5bf10aSMark Haywood */ 4479b5bf10aSMark Haywood if (access(IPADM_VOL_DB_FILE, F_OK) != 0) { 4489b5bf10aSMark Haywood assert(writeop); 4499b5bf10aSMark Haywood err = ipmgmt_cpfile(IPADM_DB_FILE, IPADM_VOL_DB_FILE, B_TRUE); 4509b5bf10aSMark Haywood if (err != 0) 4519b5bf10aSMark Haywood goto done; 452*8887b57dSGirish Moodalbail (void) pthread_attr_init(&attr); 453*8887b57dSGirish Moodalbail (void) pthread_attr_setdetachstate(&attr, 454*8887b57dSGirish Moodalbail PTHREAD_CREATE_DETACHED); 455*8887b57dSGirish Moodalbail err = pthread_create(&tid, &attr, ipmgmt_db_restore_thread, 4569b5bf10aSMark Haywood NULL); 457*8887b57dSGirish Moodalbail (void) pthread_attr_destroy(&attr); 4589b5bf10aSMark Haywood if (err != 0) { 4599b5bf10aSMark Haywood (void) unlink(IPADM_VOL_DB_FILE); 4609b5bf10aSMark Haywood goto done; 4619b5bf10aSMark Haywood } 4629b5bf10aSMark Haywood ipmgmt_rdonly_root = B_TRUE; 4639b5bf10aSMark Haywood } 4649b5bf10aSMark Haywood 4659b5bf10aSMark Haywood /* 4669b5bf10aSMark Haywood * Read/write from the volatile copy. 4679b5bf10aSMark Haywood */ 4689b5bf10aSMark Haywood err = ipadm_rw_db(db_walk_func, db_warg, IPADM_VOL_DB_FILE, 4699b5bf10aSMark Haywood mode, db_op); 4709b5bf10aSMark Haywood done: 4716e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&ipmgmt_dbconf_lock); 4726e91bba0SGirish Moodalbail return (err); 4736e91bba0SGirish Moodalbail } 4746e91bba0SGirish Moodalbail 4756e91bba0SGirish Moodalbail /* 4766e91bba0SGirish Moodalbail * Used to add an entry towards the end of DB. It just returns B_TRUE for 4776e91bba0SGirish Moodalbail * every line of the DB. When we reach the end, ipadm_rw_db() adds the 4786e91bba0SGirish Moodalbail * line at the end. 4796e91bba0SGirish Moodalbail */ 4806e91bba0SGirish Moodalbail /* ARGSUSED */ 4816e91bba0SGirish Moodalbail boolean_t 4826e91bba0SGirish Moodalbail ipmgmt_db_add(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, int *errp) 4836e91bba0SGirish Moodalbail { 4846e91bba0SGirish Moodalbail return (B_TRUE); 4856e91bba0SGirish Moodalbail } 4866e91bba0SGirish Moodalbail 4876e91bba0SGirish Moodalbail /* 4886e91bba0SGirish Moodalbail * This function is used to update or create an entry in DB. The nvlist_t, 4896e91bba0SGirish Moodalbail * `in_nvl', represents the line we are looking for. Once we ensure the right 4906e91bba0SGirish Moodalbail * line from DB, we update that entry. 4916e91bba0SGirish Moodalbail */ 4926e91bba0SGirish Moodalbail boolean_t 4936e91bba0SGirish Moodalbail ipmgmt_db_update(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 4946e91bba0SGirish Moodalbail int *errp) 4956e91bba0SGirish Moodalbail { 4966e91bba0SGirish Moodalbail ipadm_dbwrite_cbarg_t *cb = arg; 4976e91bba0SGirish Moodalbail uint_t flags = cb->dbw_flags; 4986e91bba0SGirish Moodalbail nvlist_t *in_nvl = cb->dbw_nvl; 4996e91bba0SGirish Moodalbail nvpair_t *nvp; 5006e91bba0SGirish Moodalbail char *name, *instrval = NULL, *dbstrval = NULL; 5016e91bba0SGirish Moodalbail char pval[MAXPROPVALLEN]; 5026e91bba0SGirish Moodalbail 503*8887b57dSGirish Moodalbail *errp = 0; 5046e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_intersects(db_nvl, in_nvl)) 5056e91bba0SGirish Moodalbail return (B_TRUE); 5066e91bba0SGirish Moodalbail 5076e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(in_nvl, NULL); nvp != NULL; 5086e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(in_nvl, nvp)) { 5096e91bba0SGirish Moodalbail name = nvpair_name(nvp); 5106e91bba0SGirish Moodalbail if (!IPADM_PRIV_NVP(name) && nvlist_exists(db_nvl, name)) 5116e91bba0SGirish Moodalbail break; 5126e91bba0SGirish Moodalbail } 5136e91bba0SGirish Moodalbail 5146e91bba0SGirish Moodalbail if (nvp == NULL) 5156e91bba0SGirish Moodalbail return (B_TRUE); 5166e91bba0SGirish Moodalbail 5176e91bba0SGirish Moodalbail assert(nvpair_type(nvp) == DATA_TYPE_STRING); 5186e91bba0SGirish Moodalbail 5196e91bba0SGirish Moodalbail if ((*errp = nvpair_value_string(nvp, &instrval)) != 0) 5206e91bba0SGirish Moodalbail return (B_FALSE); 5216e91bba0SGirish Moodalbail 5226e91bba0SGirish Moodalbail /* 5236e91bba0SGirish Moodalbail * If IPMGMT_APPEND is set then we are dealing with multi-valued 5246e91bba0SGirish Moodalbail * properties. We append to the entry from the db, with the new value. 5256e91bba0SGirish Moodalbail */ 5266e91bba0SGirish Moodalbail if (flags & IPMGMT_APPEND) { 5276e91bba0SGirish Moodalbail if ((*errp = nvlist_lookup_string(db_nvl, name, 5286e91bba0SGirish Moodalbail &dbstrval)) != 0) 5296e91bba0SGirish Moodalbail return (B_FALSE); 5306e91bba0SGirish Moodalbail (void) snprintf(pval, MAXPROPVALLEN, "%s,%s", dbstrval, 5316e91bba0SGirish Moodalbail instrval); 5326e91bba0SGirish Moodalbail if ((*errp = nvlist_add_string(db_nvl, name, pval)) != 0) 5336e91bba0SGirish Moodalbail return (B_FALSE); 5346e91bba0SGirish Moodalbail } else { 5356e91bba0SGirish Moodalbail /* case of in-line update of a db entry */ 5366e91bba0SGirish Moodalbail if ((*errp = nvlist_add_string(db_nvl, name, instrval)) != 0) 5376e91bba0SGirish Moodalbail return (B_FALSE); 5386e91bba0SGirish Moodalbail } 5396e91bba0SGirish Moodalbail 5406e91bba0SGirish Moodalbail (void) memset(buf, 0, buflen); 5416e91bba0SGirish Moodalbail if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) { 5426e91bba0SGirish Moodalbail /* buffer overflow */ 5436e91bba0SGirish Moodalbail *errp = ENOBUFS; 5446e91bba0SGirish Moodalbail } 5456e91bba0SGirish Moodalbail 5466e91bba0SGirish Moodalbail /* we updated the DB entry, so do not continue */ 5476e91bba0SGirish Moodalbail return (B_FALSE); 5486e91bba0SGirish Moodalbail } 5496e91bba0SGirish Moodalbail 5506e91bba0SGirish Moodalbail /* 5516e91bba0SGirish Moodalbail * For the given `cbarg->cb_ifname' interface, retrieves any persistent 5526e91bba0SGirish Moodalbail * interface information (used in 'ipadm show-if') 5536e91bba0SGirish Moodalbail */ 5546e91bba0SGirish Moodalbail /* ARGSUSED */ 5556e91bba0SGirish Moodalbail boolean_t 5566e91bba0SGirish Moodalbail ipmgmt_db_getif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 5576e91bba0SGirish Moodalbail int *errp) 5586e91bba0SGirish Moodalbail { 5596e91bba0SGirish Moodalbail ipmgmt_getif_cbarg_t *cbarg = arg; 5606e91bba0SGirish Moodalbail char *ifname = cbarg->cb_ifname; 5616e91bba0SGirish Moodalbail char *intf = NULL; 5626e91bba0SGirish Moodalbail ipadm_if_info_t *ifp = NULL; 5636e91bba0SGirish Moodalbail sa_family_t af; 5646e91bba0SGirish Moodalbail char *afstr; 5656e91bba0SGirish Moodalbail 5666e91bba0SGirish Moodalbail *errp = 0; 5676e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) != 0 || 5686e91bba0SGirish Moodalbail nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &intf) != 0 || 5696e91bba0SGirish Moodalbail (ifname[0] != '\0' && strcmp(ifname, intf) != 0)) { 5706e91bba0SGirish Moodalbail return (B_TRUE); 5716e91bba0SGirish Moodalbail } 5726e91bba0SGirish Moodalbail af = atoi(afstr); 5736e91bba0SGirish Moodalbail for (ifp = cbarg->cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next) { 5746e91bba0SGirish Moodalbail if (strcmp(ifp->ifi_name, intf) == 0) 5756e91bba0SGirish Moodalbail break; 5766e91bba0SGirish Moodalbail } 5776e91bba0SGirish Moodalbail if (ifp == NULL) { 5786e91bba0SGirish Moodalbail ipadm_if_info_t *new; 5796e91bba0SGirish Moodalbail 5806e91bba0SGirish Moodalbail if ((new = calloc(1, sizeof (*new))) == NULL) { 5816e91bba0SGirish Moodalbail *errp = ENOMEM; 5826e91bba0SGirish Moodalbail return (B_FALSE); /* don't continue the walk */ 5836e91bba0SGirish Moodalbail } 5846e91bba0SGirish Moodalbail new->ifi_next = cbarg->cb_ifinfo; 5856e91bba0SGirish Moodalbail cbarg->cb_ifinfo = new; 5866e91bba0SGirish Moodalbail ifp = new; 5876e91bba0SGirish Moodalbail (void) strlcpy(ifp->ifi_name, intf, sizeof (ifp->ifi_name)); 5886e91bba0SGirish Moodalbail } 5896e91bba0SGirish Moodalbail 5906e91bba0SGirish Moodalbail if (af == AF_INET) { 5916e91bba0SGirish Moodalbail ifp->ifi_pflags |= IFIF_IPV4; 5926e91bba0SGirish Moodalbail } else { 5936e91bba0SGirish Moodalbail assert(af == AF_INET6); 5946e91bba0SGirish Moodalbail ifp->ifi_pflags |= IFIF_IPV6; 5956e91bba0SGirish Moodalbail } 5966e91bba0SGirish Moodalbail 5976e91bba0SGirish Moodalbail /* Terminate the walk if we found both v4 and v6 interfaces. */ 5986e91bba0SGirish Moodalbail if (ifname[0] != '\0' && (ifp->ifi_pflags & IFIF_IPV4) && 5996e91bba0SGirish Moodalbail (ifp->ifi_pflags & IFIF_IPV6)) 6006e91bba0SGirish Moodalbail return (B_FALSE); 6016e91bba0SGirish Moodalbail 6026e91bba0SGirish Moodalbail return (B_TRUE); 6036e91bba0SGirish Moodalbail } 6046e91bba0SGirish Moodalbail 6056e91bba0SGirish Moodalbail /* 6066e91bba0SGirish Moodalbail * Deletes those entries from the database for which interface name 6076e91bba0SGirish Moodalbail * matches with the given `cbarg->cb_ifname' 6086e91bba0SGirish Moodalbail */ 6096e91bba0SGirish Moodalbail /* ARGSUSED */ 6106e91bba0SGirish Moodalbail boolean_t 6116e91bba0SGirish Moodalbail ipmgmt_db_resetif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 6126e91bba0SGirish Moodalbail int *errp) 6136e91bba0SGirish Moodalbail { 6146e91bba0SGirish Moodalbail ipmgmt_if_cbarg_t *cbarg = arg; 6156e91bba0SGirish Moodalbail boolean_t isv6 = (cbarg->cb_family == AF_INET6); 6166e91bba0SGirish Moodalbail char *ifname = cbarg->cb_ifname; 6176e91bba0SGirish Moodalbail char *modstr = NULL; 6186e91bba0SGirish Moodalbail char *afstr; 6196e91bba0SGirish Moodalbail char *aobjname; 6206e91bba0SGirish Moodalbail uint_t proto; 6216e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *head; 6226e91bba0SGirish Moodalbail boolean_t aobjfound = B_FALSE; 6236e91bba0SGirish Moodalbail 6246e91bba0SGirish Moodalbail *errp = 0; 6256e91bba0SGirish Moodalbail 6266e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_contains(db_nvl, NULL, ifname, NULL)) 6276e91bba0SGirish Moodalbail return (B_TRUE); 6286e91bba0SGirish Moodalbail 6296e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_FAMILY, &afstr) == 0) { 6306e91bba0SGirish Moodalbail if (atoi(afstr) == cbarg->cb_family) 6316e91bba0SGirish Moodalbail goto delete; 6326e91bba0SGirish Moodalbail return (B_TRUE); 6336e91bba0SGirish Moodalbail } 6346e91bba0SGirish Moodalbail 6356e91bba0SGirish Moodalbail /* Reset all the interface configurations for 'ifname' */ 6366e91bba0SGirish Moodalbail if (isv6 && (nvlist_exists(db_nvl, IPADM_NVP_IPV6ADDR) || 6376e91bba0SGirish Moodalbail nvlist_exists(db_nvl, IPADM_NVP_INTFID))) { 6386e91bba0SGirish Moodalbail goto delete; 6396e91bba0SGirish Moodalbail } 6406e91bba0SGirish Moodalbail if (!isv6 && 6416e91bba0SGirish Moodalbail (nvlist_exists(db_nvl, IPADM_NVP_IPV4ADDR) || 6426e91bba0SGirish Moodalbail nvlist_exists(db_nvl, IPADM_NVP_DHCP))) { 6436e91bba0SGirish Moodalbail goto delete; 6446e91bba0SGirish Moodalbail } 6456e91bba0SGirish Moodalbail 6466e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_AOBJNAME, &aobjname) == 0) { 6476e91bba0SGirish Moodalbail /* 6486e91bba0SGirish Moodalbail * This must be an address property. Delete this 6496e91bba0SGirish Moodalbail * line if there is a match in the address family. 6506e91bba0SGirish Moodalbail */ 6516e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 6526e91bba0SGirish Moodalbail while (head != NULL) { 6536e91bba0SGirish Moodalbail if (strcmp(head->am_aobjname, aobjname) == 0) { 6546e91bba0SGirish Moodalbail aobjfound = B_TRUE; 6556e91bba0SGirish Moodalbail if (head->am_family == cbarg->cb_family) 6566e91bba0SGirish Moodalbail goto delete; 6576e91bba0SGirish Moodalbail } 6586e91bba0SGirish Moodalbail head = head->am_next; 6596e91bba0SGirish Moodalbail } 6606e91bba0SGirish Moodalbail /* 6616e91bba0SGirish Moodalbail * If aobjfound = B_FALSE, then this address is not 6626e91bba0SGirish Moodalbail * available in active configuration. We should go ahead 6636e91bba0SGirish Moodalbail * and delete it. 6646e91bba0SGirish Moodalbail */ 6656e91bba0SGirish Moodalbail if (!aobjfound) 6666e91bba0SGirish Moodalbail goto delete; 6676e91bba0SGirish Moodalbail } 6686e91bba0SGirish Moodalbail 6696e91bba0SGirish Moodalbail /* 6706e91bba0SGirish Moodalbail * If we are removing both v4 and v6 interface, then we get rid of 6716e91bba0SGirish Moodalbail * all the properties for that interface. On the other hand, if we 6726e91bba0SGirish Moodalbail * are deleting only v4 instance of an interface, then we delete v4 6736e91bba0SGirish Moodalbail * properties only. 6746e91bba0SGirish Moodalbail */ 6756e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_PROTONAME, &modstr) == 0) { 6766e91bba0SGirish Moodalbail proto = ipadm_str2proto(modstr); 6776e91bba0SGirish Moodalbail switch (proto) { 6786e91bba0SGirish Moodalbail case MOD_PROTO_IPV6: 6796e91bba0SGirish Moodalbail if (isv6) 6806e91bba0SGirish Moodalbail goto delete; 6816e91bba0SGirish Moodalbail break; 6826e91bba0SGirish Moodalbail case MOD_PROTO_IPV4: 6836e91bba0SGirish Moodalbail if (!isv6) 6846e91bba0SGirish Moodalbail goto delete; 6856e91bba0SGirish Moodalbail break; 6866e91bba0SGirish Moodalbail case MOD_PROTO_IP: 6876e91bba0SGirish Moodalbail /* this should never be the case, today */ 6886e91bba0SGirish Moodalbail assert(0); 6896e91bba0SGirish Moodalbail break; 6906e91bba0SGirish Moodalbail } 6916e91bba0SGirish Moodalbail } 6926e91bba0SGirish Moodalbail /* Not found a match yet. Continue processing the db */ 6936e91bba0SGirish Moodalbail return (B_TRUE); 6946e91bba0SGirish Moodalbail delete: 6956e91bba0SGirish Moodalbail /* delete the line from the db */ 6966e91bba0SGirish Moodalbail buf[0] = '\0'; 6976e91bba0SGirish Moodalbail return (B_TRUE); 6986e91bba0SGirish Moodalbail } 6996e91bba0SGirish Moodalbail 7006e91bba0SGirish Moodalbail /* 7016e91bba0SGirish Moodalbail * Deletes those entries from the database for which address object name 7026e91bba0SGirish Moodalbail * matches with the given `cbarg->cb_aobjname' 7036e91bba0SGirish Moodalbail */ 7046e91bba0SGirish Moodalbail /* ARGSUSED */ 7056e91bba0SGirish Moodalbail boolean_t 7066e91bba0SGirish Moodalbail ipmgmt_db_resetaddr(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 7076e91bba0SGirish Moodalbail int *errp) 7086e91bba0SGirish Moodalbail { 7096e91bba0SGirish Moodalbail ipmgmt_resetaddr_cbarg_t *cbarg = arg; 7106e91bba0SGirish Moodalbail char *aobjname = cbarg->cb_aobjname; 7116e91bba0SGirish Moodalbail 7126e91bba0SGirish Moodalbail *errp = 0; 7136e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_contains(db_nvl, NULL, NULL, aobjname)) 7146e91bba0SGirish Moodalbail return (B_TRUE); 7156e91bba0SGirish Moodalbail 7166e91bba0SGirish Moodalbail /* delete the line from the db */ 7176e91bba0SGirish Moodalbail buf[0] = '\0'; 7186e91bba0SGirish Moodalbail return (B_TRUE); 7196e91bba0SGirish Moodalbail } 7206e91bba0SGirish Moodalbail 7216e91bba0SGirish Moodalbail /* 7226e91bba0SGirish Moodalbail * Retrieves all interface props, including addresses, for given interface(s). 7236e91bba0SGirish Moodalbail * `invl' contains the list of interfaces, for which information need to be 7246e91bba0SGirish Moodalbail * retrieved. 7256e91bba0SGirish Moodalbail */ 7266e91bba0SGirish Moodalbail /* ARGSUSED */ 7276e91bba0SGirish Moodalbail boolean_t 7286e91bba0SGirish Moodalbail ipmgmt_db_initif(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 7296e91bba0SGirish Moodalbail int *errp) 7306e91bba0SGirish Moodalbail { 7316e91bba0SGirish Moodalbail ipmgmt_initif_cbarg_t *cbarg = arg; 7326e91bba0SGirish Moodalbail nvlist_t *onvl = cbarg->cb_onvl; 7336e91bba0SGirish Moodalbail nvlist_t *invl = cbarg->cb_invl; 7346e91bba0SGirish Moodalbail sa_family_t in_af = cbarg->cb_family; 7356e91bba0SGirish Moodalbail char *db_ifname; 7366e91bba0SGirish Moodalbail 7376e91bba0SGirish Moodalbail *errp = 0; 7386e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_IFNAME, &db_ifname) == 0 && 7396e91bba0SGirish Moodalbail nvlist_exists(invl, db_ifname)) { 7406e91bba0SGirish Moodalbail char name[IPMGMT_STRSIZE]; 7416e91bba0SGirish Moodalbail sa_family_t db_af = in_af; 7426e91bba0SGirish Moodalbail uint_t proto; 7436e91bba0SGirish Moodalbail char *pstr; 7446e91bba0SGirish Moodalbail 7456e91bba0SGirish Moodalbail if (in_af != AF_UNSPEC) { 7466e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_PROTONAME, 7476e91bba0SGirish Moodalbail &pstr) == 0) { 7486e91bba0SGirish Moodalbail proto = ipadm_str2proto(pstr); 7496e91bba0SGirish Moodalbail if (proto == MOD_PROTO_IPV4) 7506e91bba0SGirish Moodalbail db_af = AF_INET; 7516e91bba0SGirish Moodalbail else if (proto == MOD_PROTO_IPV6) 7526e91bba0SGirish Moodalbail db_af = AF_INET6; 7536e91bba0SGirish Moodalbail else 7546e91bba0SGirish Moodalbail db_af = in_af; 7556e91bba0SGirish Moodalbail } else { 7566e91bba0SGirish Moodalbail if (nvlist_exists(db_nvl, IPADM_NVP_IPV4ADDR) || 7576e91bba0SGirish Moodalbail nvlist_exists(db_nvl, IPADM_NVP_DHCP)) 7586e91bba0SGirish Moodalbail db_af = AF_INET; 7596e91bba0SGirish Moodalbail else 7606e91bba0SGirish Moodalbail db_af = AF_INET6; 7616e91bba0SGirish Moodalbail } 7626e91bba0SGirish Moodalbail } 7636e91bba0SGirish Moodalbail if (in_af == db_af) { 7646e91bba0SGirish Moodalbail (void) snprintf(name, sizeof (name), "%s_%d", db_ifname, 7656e91bba0SGirish Moodalbail cbarg->cb_ocnt); 7666e91bba0SGirish Moodalbail *errp = nvlist_add_nvlist(onvl, name, db_nvl); 7676e91bba0SGirish Moodalbail if (*errp == 0) 7686e91bba0SGirish Moodalbail cbarg->cb_ocnt++; 7696e91bba0SGirish Moodalbail } 7706e91bba0SGirish Moodalbail } 7716e91bba0SGirish Moodalbail return (B_TRUE); 7726e91bba0SGirish Moodalbail } 7736e91bba0SGirish Moodalbail 7746e91bba0SGirish Moodalbail /* 7756e91bba0SGirish Moodalbail * helper function for ipmgmt_aobjmap_op(). Adds the node pointed by `nodep' 7766e91bba0SGirish Moodalbail * into `aobjmap' structure. 7776e91bba0SGirish Moodalbail */ 7786e91bba0SGirish Moodalbail static int 7796e91bba0SGirish Moodalbail i_ipmgmt_add_amnode(ipmgmt_aobjmap_t *nodep) 7806e91bba0SGirish Moodalbail { 7816e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *new, *head; 7826e91bba0SGirish Moodalbail 7836e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 7846e91bba0SGirish Moodalbail if ((new = malloc(sizeof (ipmgmt_aobjmap_t))) == NULL) 7856e91bba0SGirish Moodalbail return (ENOMEM); 7866e91bba0SGirish Moodalbail *new = *nodep; 7876e91bba0SGirish Moodalbail new->am_next = NULL; 7886e91bba0SGirish Moodalbail 7896e91bba0SGirish Moodalbail /* Add the node at the beginning of the list */ 7906e91bba0SGirish Moodalbail if (head == NULL) { 7916e91bba0SGirish Moodalbail aobjmap.aobjmap_head = new; 7926e91bba0SGirish Moodalbail } else { 7936e91bba0SGirish Moodalbail new->am_next = aobjmap.aobjmap_head; 7946e91bba0SGirish Moodalbail aobjmap.aobjmap_head = new; 7956e91bba0SGirish Moodalbail } 7966e91bba0SGirish Moodalbail return (0); 7976e91bba0SGirish Moodalbail } 7986e91bba0SGirish Moodalbail 7996e91bba0SGirish Moodalbail /* 8006e91bba0SGirish Moodalbail * A recursive function to generate alphabetized number given a decimal number. 8016e91bba0SGirish Moodalbail * Decimal 0 to 25 maps to 'a' to 'z' and then the counting continues with 'aa', 8026e91bba0SGirish Moodalbail * 'ab', 'ac', et al. 8036e91bba0SGirish Moodalbail */ 8046e91bba0SGirish Moodalbail static void 8056e91bba0SGirish Moodalbail i_ipmgmt_num2priv_aobjname(uint32_t num, char **cp, char *endp) 8066e91bba0SGirish Moodalbail { 8076e91bba0SGirish Moodalbail if (num >= 26) 8086e91bba0SGirish Moodalbail i_ipmgmt_num2priv_aobjname(num / 26 - 1, cp, endp); 8096e91bba0SGirish Moodalbail if (*cp != endp) { 8106e91bba0SGirish Moodalbail *cp[0] = 'a' + (num % 26); 8116e91bba0SGirish Moodalbail (*cp)++; 8126e91bba0SGirish Moodalbail } 8136e91bba0SGirish Moodalbail } 8146e91bba0SGirish Moodalbail 8156e91bba0SGirish Moodalbail /* 8166e91bba0SGirish Moodalbail * This function generates an `aobjname', when required, and then does 8176e91bba0SGirish Moodalbail * lookup-add. If `nodep->am_aobjname' is not an empty string, then it walks 8186e91bba0SGirish Moodalbail * through the `aobjmap' to check if an address object with the same 8196e91bba0SGirish Moodalbail * `nodep->am_aobjname' exists. If it exists, EEXIST is returned as duplicate 8206e91bba0SGirish Moodalbail * `aobjname's are not allowed. 8216e91bba0SGirish Moodalbail * 8226e91bba0SGirish Moodalbail * If `nodep->am_aobjname' is an empty string then the daemon generates an 8236e91bba0SGirish Moodalbail * `aobjname' using the `am_nextnum', which contains the next number to be 8246e91bba0SGirish Moodalbail * used to generate `aobjname'. `am_nextnum' is converted to base26 using 8256e91bba0SGirish Moodalbail * `a-z' alphabets in i_ipmgmt_num2priv_aobjname(). 8266e91bba0SGirish Moodalbail * 8276e91bba0SGirish Moodalbail * `am_nextnum' will be 0 to begin with. Every time an address object that 8286e91bba0SGirish Moodalbail * needs `aobjname' is added it's incremented by 1. So for the first address 8296e91bba0SGirish Moodalbail * object on net0 the `am_aobjname' will be net0/_a and `am_nextnum' will be 1. 8306e91bba0SGirish Moodalbail * For the second address object on that interface `am_aobjname' will be net0/_b 8316e91bba0SGirish Moodalbail * and `am_nextnum' will incremented to 2. 8326e91bba0SGirish Moodalbail */ 8336e91bba0SGirish Moodalbail static int 8346e91bba0SGirish Moodalbail i_ipmgmt_lookupadd_amnode(ipmgmt_aobjmap_t *nodep) 8356e91bba0SGirish Moodalbail { 8366e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *head; 8376e91bba0SGirish Moodalbail uint32_t nextnum; 8386e91bba0SGirish Moodalbail 8396e91bba0SGirish Moodalbail for (head = aobjmap.aobjmap_head; head != NULL; head = head->am_next) 8406e91bba0SGirish Moodalbail if (strcmp(head->am_ifname, nodep->am_ifname) == 0) 8416e91bba0SGirish Moodalbail break; 8426e91bba0SGirish Moodalbail nextnum = (head == NULL ? 0 : head->am_nextnum); 8436e91bba0SGirish Moodalbail 8446e91bba0SGirish Moodalbail /* 8456e91bba0SGirish Moodalbail * if `aobjname' is empty, then the daemon has to generate the 8466e91bba0SGirish Moodalbail * next `aobjname' for the given interface and family. 8476e91bba0SGirish Moodalbail */ 8486e91bba0SGirish Moodalbail if (nodep->am_aobjname[0] == '\0') { 8496e91bba0SGirish Moodalbail char tmpstr[IPADM_AOBJ_USTRSIZ - 1]; /* 1 for leading '_' */ 8506e91bba0SGirish Moodalbail char *cp = tmpstr; 8516e91bba0SGirish Moodalbail char *endp = tmpstr + sizeof (tmpstr); 8526e91bba0SGirish Moodalbail 8536e91bba0SGirish Moodalbail i_ipmgmt_num2priv_aobjname(nextnum, &cp, endp); 8546e91bba0SGirish Moodalbail 8556e91bba0SGirish Moodalbail if (cp == endp) 8566e91bba0SGirish Moodalbail return (EINVAL); 8576e91bba0SGirish Moodalbail cp[0] = '\0'; 8586e91bba0SGirish Moodalbail 8596e91bba0SGirish Moodalbail if (snprintf(nodep->am_aobjname, IPADM_AOBJSIZ, "%s/_%s", 8606e91bba0SGirish Moodalbail nodep->am_ifname, tmpstr) >= IPADM_AOBJSIZ) { 8616e91bba0SGirish Moodalbail return (EINVAL); 8626e91bba0SGirish Moodalbail } 8636e91bba0SGirish Moodalbail nodep->am_nextnum = ++nextnum; 8646e91bba0SGirish Moodalbail } else { 8656e91bba0SGirish Moodalbail for (head = aobjmap.aobjmap_head; head != NULL; 8666e91bba0SGirish Moodalbail head = head->am_next) { 8676e91bba0SGirish Moodalbail if (strcmp(head->am_aobjname, nodep->am_aobjname) == 0) 8686e91bba0SGirish Moodalbail return (EEXIST); 8696e91bba0SGirish Moodalbail } 8706e91bba0SGirish Moodalbail nodep->am_nextnum = nextnum; 8716e91bba0SGirish Moodalbail } 8726e91bba0SGirish Moodalbail return (i_ipmgmt_add_amnode(nodep)); 8736e91bba0SGirish Moodalbail } 8746e91bba0SGirish Moodalbail 8756e91bba0SGirish Moodalbail /* 8766e91bba0SGirish Moodalbail * Performs following operations on the global `aobjmap' linked list. 8776e91bba0SGirish Moodalbail * (a) ADDROBJ_ADD: add or update address object in `aobjmap' 8786e91bba0SGirish Moodalbail * (b) ADDROBJ_DELETE: delete address object from `aobjmap' 8796e91bba0SGirish Moodalbail * (c) ADDROBJ_LOOKUPADD: place a stub address object in `aobjmap' 880ec3706caSVasumathi Sundaram * (d) ADDROBJ_SETLIFNUM: Sets the lifnum for an address object in `aobjmap' 8816e91bba0SGirish Moodalbail */ 8826e91bba0SGirish Moodalbail int 8836e91bba0SGirish Moodalbail ipmgmt_aobjmap_op(ipmgmt_aobjmap_t *nodep, uint32_t op) 8846e91bba0SGirish Moodalbail { 885ec3706caSVasumathi Sundaram ipmgmt_aobjmap_t *head, *prev, *matched = NULL; 8866e91bba0SGirish Moodalbail boolean_t update = B_TRUE; 8876e91bba0SGirish Moodalbail int err = 0; 8886e91bba0SGirish Moodalbail ipadm_db_op_t db_op; 8896e91bba0SGirish Moodalbail 8906e91bba0SGirish Moodalbail (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock); 8916e91bba0SGirish Moodalbail 8926e91bba0SGirish Moodalbail head = aobjmap.aobjmap_head; 8936e91bba0SGirish Moodalbail switch (op) { 8946e91bba0SGirish Moodalbail case ADDROBJ_ADD: 8956e91bba0SGirish Moodalbail /* 8966e91bba0SGirish Moodalbail * check for stub nodes (added by ADDROBJ_LOOKUPADD) and 8976e91bba0SGirish Moodalbail * update, else add the new node. 8986e91bba0SGirish Moodalbail */ 8996e91bba0SGirish Moodalbail for (; head != NULL; head = head->am_next) { 900ec3706caSVasumathi Sundaram /* 901ec3706caSVasumathi Sundaram * For IPv6, we need to distinguish between the 902ec3706caSVasumathi Sundaram * linklocal and non-linklocal nodes 903ec3706caSVasumathi Sundaram */ 9046e91bba0SGirish Moodalbail if (strcmp(head->am_aobjname, 905ec3706caSVasumathi Sundaram nodep->am_aobjname) == 0 && 906ec3706caSVasumathi Sundaram (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF || 907ec3706caSVasumathi Sundaram head->am_linklocal == nodep->am_linklocal)) 9086e91bba0SGirish Moodalbail break; 9096e91bba0SGirish Moodalbail } 9106e91bba0SGirish Moodalbail 9116e91bba0SGirish Moodalbail if (head != NULL) { 9126e91bba0SGirish Moodalbail /* update the node */ 9136e91bba0SGirish Moodalbail (void) strlcpy(head->am_ifname, nodep->am_ifname, 9146e91bba0SGirish Moodalbail sizeof (head->am_ifname)); 9156e91bba0SGirish Moodalbail head->am_lnum = nodep->am_lnum; 9166e91bba0SGirish Moodalbail head->am_family = nodep->am_family; 9176e91bba0SGirish Moodalbail head->am_flags = nodep->am_flags; 9186e91bba0SGirish Moodalbail head->am_atype = nodep->am_atype; 9196e91bba0SGirish Moodalbail if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF) { 9206e91bba0SGirish Moodalbail head->am_ifid = nodep->am_ifid; 9216e91bba0SGirish Moodalbail head->am_linklocal = nodep->am_linklocal; 9226e91bba0SGirish Moodalbail } 9236e91bba0SGirish Moodalbail } else { 9246e91bba0SGirish Moodalbail for (head = aobjmap.aobjmap_head; head != NULL; 9256e91bba0SGirish Moodalbail head = head->am_next) { 9266e91bba0SGirish Moodalbail if (strcmp(head->am_ifname, 9276e91bba0SGirish Moodalbail nodep->am_ifname) == 0) 9286e91bba0SGirish Moodalbail break; 9296e91bba0SGirish Moodalbail } 9306e91bba0SGirish Moodalbail nodep->am_nextnum = (head == NULL ? 0 : 9316e91bba0SGirish Moodalbail head->am_nextnum); 9326e91bba0SGirish Moodalbail err = i_ipmgmt_add_amnode(nodep); 9336e91bba0SGirish Moodalbail } 9346e91bba0SGirish Moodalbail db_op = IPADM_DB_WRITE; 9356e91bba0SGirish Moodalbail break; 9366e91bba0SGirish Moodalbail case ADDROBJ_DELETE: 9376e91bba0SGirish Moodalbail prev = head; 9386e91bba0SGirish Moodalbail while (head != NULL) { 9396e91bba0SGirish Moodalbail if (strcmp(head->am_aobjname, 9406e91bba0SGirish Moodalbail nodep->am_aobjname) == 0) { 9416e91bba0SGirish Moodalbail nodep->am_atype = head->am_atype; 9426e91bba0SGirish Moodalbail /* 9436e91bba0SGirish Moodalbail * There could be multiple IPV6_ADDRCONF nodes, 9446e91bba0SGirish Moodalbail * with same address object name, so check for 9456e91bba0SGirish Moodalbail * logical number also. 9466e91bba0SGirish Moodalbail */ 9476e91bba0SGirish Moodalbail if (head->am_atype != 9486e91bba0SGirish Moodalbail IPADM_ADDR_IPV6_ADDRCONF || 9496e91bba0SGirish Moodalbail nodep->am_lnum == head->am_lnum) 9506e91bba0SGirish Moodalbail break; 9516e91bba0SGirish Moodalbail } 9526e91bba0SGirish Moodalbail prev = head; 9536e91bba0SGirish Moodalbail head = head->am_next; 9546e91bba0SGirish Moodalbail } 9556e91bba0SGirish Moodalbail if (head != NULL) { 9566e91bba0SGirish Moodalbail /* 9576e91bba0SGirish Moodalbail * If the address object is in both active and 9586e91bba0SGirish Moodalbail * persistent configuration and the user is deleting it 9596e91bba0SGirish Moodalbail * only from active configuration then mark this node 9606e91bba0SGirish Moodalbail * for deletion by reseting IPMGMT_ACTIVE bit. 9616e91bba0SGirish Moodalbail * With this the same address object name cannot 9626e91bba0SGirish Moodalbail * be reused until it is permanently removed. 9636e91bba0SGirish Moodalbail */ 9646e91bba0SGirish Moodalbail if (head->am_flags == (IPMGMT_ACTIVE|IPMGMT_PERSIST) && 9656e91bba0SGirish Moodalbail nodep->am_flags == IPMGMT_ACTIVE) { 9666e91bba0SGirish Moodalbail /* Update flags in the in-memory map. */ 9676e91bba0SGirish Moodalbail head->am_flags &= ~IPMGMT_ACTIVE; 9686e91bba0SGirish Moodalbail head->am_lnum = -1; 9696e91bba0SGirish Moodalbail 9706e91bba0SGirish Moodalbail /* Update info in file. */ 9716e91bba0SGirish Moodalbail db_op = IPADM_DB_WRITE; 9726e91bba0SGirish Moodalbail *nodep = *head; 9736e91bba0SGirish Moodalbail } else { 9746e91bba0SGirish Moodalbail (void) strlcpy(nodep->am_ifname, 9756e91bba0SGirish Moodalbail head->am_ifname, 9766e91bba0SGirish Moodalbail sizeof (nodep->am_ifname)); 9776e91bba0SGirish Moodalbail /* otherwise delete the node */ 9786e91bba0SGirish Moodalbail if (head == aobjmap.aobjmap_head) 9796e91bba0SGirish Moodalbail aobjmap.aobjmap_head = head->am_next; 9806e91bba0SGirish Moodalbail else 9816e91bba0SGirish Moodalbail prev->am_next = head->am_next; 9826e91bba0SGirish Moodalbail free(head); 9836e91bba0SGirish Moodalbail db_op = IPADM_DB_DELETE; 9846e91bba0SGirish Moodalbail } 9856e91bba0SGirish Moodalbail } else { 9866e91bba0SGirish Moodalbail err = ENOENT; 9876e91bba0SGirish Moodalbail } 9886e91bba0SGirish Moodalbail break; 9896e91bba0SGirish Moodalbail case ADDROBJ_LOOKUPADD: 9906e91bba0SGirish Moodalbail err = i_ipmgmt_lookupadd_amnode(nodep); 9916e91bba0SGirish Moodalbail update = B_FALSE; 9926e91bba0SGirish Moodalbail break; 993ec3706caSVasumathi Sundaram case ADDROBJ_SETLIFNUM: 994ec3706caSVasumathi Sundaram update = B_FALSE; 995ec3706caSVasumathi Sundaram for (; head != NULL; head = head->am_next) { 996ec3706caSVasumathi Sundaram if (strcmp(head->am_ifname, 997ec3706caSVasumathi Sundaram nodep->am_ifname) == 0 && 998ec3706caSVasumathi Sundaram head->am_family == nodep->am_family && 999ec3706caSVasumathi Sundaram head->am_lnum == nodep->am_lnum) { 1000ec3706caSVasumathi Sundaram err = EEXIST; 1001ec3706caSVasumathi Sundaram break; 1002ec3706caSVasumathi Sundaram } 1003ec3706caSVasumathi Sundaram if (strcmp(head->am_aobjname, 1004ec3706caSVasumathi Sundaram nodep->am_aobjname) == 0) { 1005ec3706caSVasumathi Sundaram matched = head; 1006ec3706caSVasumathi Sundaram } 1007ec3706caSVasumathi Sundaram } 1008ec3706caSVasumathi Sundaram if (err == EEXIST) 1009ec3706caSVasumathi Sundaram break; 1010ec3706caSVasumathi Sundaram if (matched != NULL) { 1011ec3706caSVasumathi Sundaram /* update the lifnum */ 1012ec3706caSVasumathi Sundaram matched->am_lnum = nodep->am_lnum; 1013ec3706caSVasumathi Sundaram } else { 1014ec3706caSVasumathi Sundaram err = ENOENT; 1015ec3706caSVasumathi Sundaram } 1016ec3706caSVasumathi Sundaram break; 10176e91bba0SGirish Moodalbail default: 10186e91bba0SGirish Moodalbail assert(0); 10196e91bba0SGirish Moodalbail } 10206e91bba0SGirish Moodalbail 10216e91bba0SGirish Moodalbail if (err == 0 && update) 10226e91bba0SGirish Moodalbail err = ipmgmt_persist_aobjmap(nodep, db_op); 10236e91bba0SGirish Moodalbail 10246e91bba0SGirish Moodalbail (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock); 10256e91bba0SGirish Moodalbail 10266e91bba0SGirish Moodalbail return (err); 10276e91bba0SGirish Moodalbail } 10286e91bba0SGirish Moodalbail 10296e91bba0SGirish Moodalbail /* 10306e91bba0SGirish Moodalbail * Given a node in `aobjmap', this function converts it into nvlist_t structure. 10316e91bba0SGirish Moodalbail * The content to be written to DB must be represented as nvlist_t. 10326e91bba0SGirish Moodalbail */ 10336e91bba0SGirish Moodalbail static int 10346e91bba0SGirish Moodalbail i_ipmgmt_node2nvl(nvlist_t **nvl, ipmgmt_aobjmap_t *np) 10356e91bba0SGirish Moodalbail { 10366e91bba0SGirish Moodalbail int err; 10376e91bba0SGirish Moodalbail char strval[IPMGMT_STRSIZE]; 10386e91bba0SGirish Moodalbail 10396e91bba0SGirish Moodalbail *nvl = NULL; 10406e91bba0SGirish Moodalbail if ((err = nvlist_alloc(nvl, NV_UNIQUE_NAME, 0)) != 0) 10416e91bba0SGirish Moodalbail goto fail; 10426e91bba0SGirish Moodalbail 10436e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_AOBJNAME, 10446e91bba0SGirish Moodalbail np->am_aobjname)) != 0) 10456e91bba0SGirish Moodalbail goto fail; 10466e91bba0SGirish Moodalbail 10476e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_IFNAME, 10486e91bba0SGirish Moodalbail np->am_ifname)) != 0) 10496e91bba0SGirish Moodalbail goto fail; 10506e91bba0SGirish Moodalbail 10516e91bba0SGirish Moodalbail (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_lnum); 10526e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_LIFNUM, strval)) != 0) 10536e91bba0SGirish Moodalbail goto fail; 10546e91bba0SGirish Moodalbail 10556e91bba0SGirish Moodalbail (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_family); 10566e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_FAMILY, strval)) != 0) 10576e91bba0SGirish Moodalbail goto fail; 10586e91bba0SGirish Moodalbail 10596e91bba0SGirish Moodalbail (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_flags); 10606e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, FLAGS, strval)) != 0) 10616e91bba0SGirish Moodalbail goto fail; 10626e91bba0SGirish Moodalbail 10636e91bba0SGirish Moodalbail (void) snprintf(strval, IPMGMT_STRSIZE, "%d", np->am_atype); 10646e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, ATYPE, strval)) != 0) 10656e91bba0SGirish Moodalbail goto fail; 10666e91bba0SGirish Moodalbail 10676e91bba0SGirish Moodalbail if (np->am_atype == IPADM_ADDR_IPV6_ADDRCONF) { 10686e91bba0SGirish Moodalbail struct sockaddr_in6 *in6; 10696e91bba0SGirish Moodalbail 10706e91bba0SGirish Moodalbail in6 = (struct sockaddr_in6 *)&np->am_ifid; 10716e91bba0SGirish Moodalbail if (np->am_linklocal && 10726e91bba0SGirish Moodalbail IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)) { 10736e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR, 10746e91bba0SGirish Moodalbail "default")) != 0) 10756e91bba0SGirish Moodalbail goto fail; 10766e91bba0SGirish Moodalbail } else { 10776e91bba0SGirish Moodalbail if (inet_ntop(AF_INET6, &in6->sin6_addr, strval, 10786e91bba0SGirish Moodalbail IPMGMT_STRSIZE) == NULL) { 10796e91bba0SGirish Moodalbail err = errno; 10806e91bba0SGirish Moodalbail goto fail; 10816e91bba0SGirish Moodalbail } 10826e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR, 10836e91bba0SGirish Moodalbail strval)) != 0) 10846e91bba0SGirish Moodalbail goto fail; 10856e91bba0SGirish Moodalbail } 10866e91bba0SGirish Moodalbail } else { 10876e91bba0SGirish Moodalbail if ((err = nvlist_add_string(*nvl, IPADM_NVP_IPNUMADDR, 10886e91bba0SGirish Moodalbail "")) != 0) 10896e91bba0SGirish Moodalbail goto fail; 10906e91bba0SGirish Moodalbail } 10916e91bba0SGirish Moodalbail return (err); 10926e91bba0SGirish Moodalbail fail: 10936e91bba0SGirish Moodalbail nvlist_free(*nvl); 10946e91bba0SGirish Moodalbail return (err); 10956e91bba0SGirish Moodalbail } 10966e91bba0SGirish Moodalbail 10976e91bba0SGirish Moodalbail /* 10986e91bba0SGirish Moodalbail * Read the aobjmap data store and build the in-memory representation 10996e91bba0SGirish Moodalbail * of the aobjmap. We don't need to hold any locks while building this as 11006e91bba0SGirish Moodalbail * we do this in very early stage of daemon coming up, even before the door 11016e91bba0SGirish Moodalbail * is opened. 11026e91bba0SGirish Moodalbail */ 11036e91bba0SGirish Moodalbail /* ARGSUSED */ 11046e91bba0SGirish Moodalbail extern boolean_t 11056e91bba0SGirish Moodalbail ipmgmt_aobjmap_init(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 11066e91bba0SGirish Moodalbail int *errp) 11076e91bba0SGirish Moodalbail { 11086e91bba0SGirish Moodalbail nvpair_t *nvp = NULL; 11096e91bba0SGirish Moodalbail char *name, *strval = NULL; 11106e91bba0SGirish Moodalbail ipmgmt_aobjmap_t node; 11116e91bba0SGirish Moodalbail struct sockaddr_in6 *in6; 11126e91bba0SGirish Moodalbail 11136e91bba0SGirish Moodalbail *errp = 0; 11146e91bba0SGirish Moodalbail node.am_next = NULL; 11156e91bba0SGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 11166e91bba0SGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 11176e91bba0SGirish Moodalbail name = nvpair_name(nvp); 11186e91bba0SGirish Moodalbail 11196e91bba0SGirish Moodalbail if ((*errp = nvpair_value_string(nvp, &strval)) != 0) 11206e91bba0SGirish Moodalbail return (B_TRUE); 11216e91bba0SGirish Moodalbail if (strcmp(IPADM_NVP_AOBJNAME, name) == 0) { 11226e91bba0SGirish Moodalbail (void) strlcpy(node.am_aobjname, strval, 11236e91bba0SGirish Moodalbail sizeof (node.am_aobjname)); 11246e91bba0SGirish Moodalbail } else if (strcmp(IPADM_NVP_IFNAME, name) == 0) { 11256e91bba0SGirish Moodalbail (void) strlcpy(node.am_ifname, strval, 11266e91bba0SGirish Moodalbail sizeof (node.am_ifname)); 11276e91bba0SGirish Moodalbail } else if (strcmp(IPADM_NVP_LIFNUM, name) == 0) { 11286e91bba0SGirish Moodalbail node.am_lnum = atoi(strval); 11296e91bba0SGirish Moodalbail } else if (strcmp(IPADM_NVP_FAMILY, name) == 0) { 11306e91bba0SGirish Moodalbail node.am_family = (sa_family_t)atoi(strval); 11316e91bba0SGirish Moodalbail } else if (strcmp(FLAGS, name) == 0) { 11326e91bba0SGirish Moodalbail node.am_flags = atoi(strval); 11336e91bba0SGirish Moodalbail } else if (strcmp(ATYPE, name) == 0) { 11346e91bba0SGirish Moodalbail node.am_atype = (ipadm_addr_type_t)atoi(strval); 11356e91bba0SGirish Moodalbail } else if (strcmp(IPADM_NVP_IPNUMADDR, name) == 0) { 11366e91bba0SGirish Moodalbail if (node.am_atype == IPADM_ADDR_IPV6_ADDRCONF) { 11376e91bba0SGirish Moodalbail in6 = (struct sockaddr_in6 *)&node.am_ifid; 11386e91bba0SGirish Moodalbail if (strcmp(strval, "default") == 0) { 11396e91bba0SGirish Moodalbail bzero(in6, sizeof (node.am_ifid)); 11406e91bba0SGirish Moodalbail node.am_linklocal = B_TRUE; 11416e91bba0SGirish Moodalbail } else { 11426e91bba0SGirish Moodalbail (void) inet_pton(AF_INET6, strval, 11436e91bba0SGirish Moodalbail &in6->sin6_addr); 11446e91bba0SGirish Moodalbail if (IN6_IS_ADDR_UNSPECIFIED( 11456e91bba0SGirish Moodalbail &in6->sin6_addr)) 11466e91bba0SGirish Moodalbail node.am_linklocal = B_TRUE; 11476e91bba0SGirish Moodalbail } 11486e91bba0SGirish Moodalbail } 11496e91bba0SGirish Moodalbail } 11506e91bba0SGirish Moodalbail } 11516e91bba0SGirish Moodalbail 11526e91bba0SGirish Moodalbail /* we have all the information we need, add the node */ 11536e91bba0SGirish Moodalbail *errp = i_ipmgmt_add_amnode(&node); 11546e91bba0SGirish Moodalbail 11556e91bba0SGirish Moodalbail return (B_TRUE); 11566e91bba0SGirish Moodalbail } 11576e91bba0SGirish Moodalbail 11586e91bba0SGirish Moodalbail /* 11596e91bba0SGirish Moodalbail * Updates an entry from the temporary cache file, which matches the given 11606e91bba0SGirish Moodalbail * address object name. 11616e91bba0SGirish Moodalbail */ 11626e91bba0SGirish Moodalbail /* ARGSUSED */ 11636e91bba0SGirish Moodalbail static boolean_t 11646e91bba0SGirish Moodalbail ipmgmt_update_aobjmap(void *arg, nvlist_t *db_nvl, char *buf, 11656e91bba0SGirish Moodalbail size_t buflen, int *errp) 11666e91bba0SGirish Moodalbail { 11676e91bba0SGirish Moodalbail ipadm_dbwrite_cbarg_t *cb = arg; 11686e91bba0SGirish Moodalbail nvlist_t *in_nvl = cb->dbw_nvl; 11696e91bba0SGirish Moodalbail uint32_t flags = cb->dbw_flags; 11706e91bba0SGirish Moodalbail char *db_lifnumstr = NULL, *in_lifnumstr = NULL; 11716e91bba0SGirish Moodalbail 11726e91bba0SGirish Moodalbail *errp = 0; 11736e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_intersects(db_nvl, in_nvl)) 11746e91bba0SGirish Moodalbail return (B_TRUE); 11756e91bba0SGirish Moodalbail 11766e91bba0SGirish Moodalbail if (flags & IPMGMT_ATYPE_V6ACONF) { 11776e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_LIFNUM, 11786e91bba0SGirish Moodalbail &db_lifnumstr) != 0 || 11796e91bba0SGirish Moodalbail nvlist_lookup_string(in_nvl, IPADM_NVP_LIFNUM, 11806e91bba0SGirish Moodalbail &in_lifnumstr) != 0 || 11816e91bba0SGirish Moodalbail (atoi(db_lifnumstr) != -1 && atoi(in_lifnumstr) != -1 && 11826e91bba0SGirish Moodalbail strcmp(db_lifnumstr, in_lifnumstr) != 0)) 11836e91bba0SGirish Moodalbail return (B_TRUE); 11846e91bba0SGirish Moodalbail } 11856e91bba0SGirish Moodalbail 11866e91bba0SGirish Moodalbail /* we found the match */ 11876e91bba0SGirish Moodalbail (void) memset(buf, 0, buflen); 11886e91bba0SGirish Moodalbail if (ipadm_nvlist2str(in_nvl, buf, buflen) == 0) { 11896e91bba0SGirish Moodalbail /* buffer overflow */ 11906e91bba0SGirish Moodalbail *errp = ENOBUFS; 11916e91bba0SGirish Moodalbail } 11926e91bba0SGirish Moodalbail 11936e91bba0SGirish Moodalbail /* stop the walker */ 11946e91bba0SGirish Moodalbail return (B_FALSE); 11956e91bba0SGirish Moodalbail } 11966e91bba0SGirish Moodalbail 11976e91bba0SGirish Moodalbail /* 11986e91bba0SGirish Moodalbail * Deletes an entry from the temporary cache file, which matches the given 11996e91bba0SGirish Moodalbail * address object name. 12006e91bba0SGirish Moodalbail */ 12016e91bba0SGirish Moodalbail /* ARGSUSED */ 12026e91bba0SGirish Moodalbail static boolean_t 12036e91bba0SGirish Moodalbail ipmgmt_delete_aobjmap(void *arg, nvlist_t *db_nvl, char *buf, 12046e91bba0SGirish Moodalbail size_t buflen, int *errp) 12056e91bba0SGirish Moodalbail { 12066e91bba0SGirish Moodalbail ipmgmt_aobjmap_t *nodep = arg; 12076e91bba0SGirish Moodalbail char *db_lifnumstr = NULL; 12086e91bba0SGirish Moodalbail 12096e91bba0SGirish Moodalbail *errp = 0; 12106e91bba0SGirish Moodalbail if (!ipmgmt_nvlist_match(db_nvl, NULL, nodep->am_ifname, 12116e91bba0SGirish Moodalbail nodep->am_aobjname)) 12126e91bba0SGirish Moodalbail return (B_TRUE); 12136e91bba0SGirish Moodalbail 12146e91bba0SGirish Moodalbail if (nodep->am_atype == IPADM_ADDR_IPV6_ADDRCONF) { 12156e91bba0SGirish Moodalbail if (nvlist_lookup_string(db_nvl, IPADM_NVP_LIFNUM, 12166e91bba0SGirish Moodalbail &db_lifnumstr) != 0 || atoi(db_lifnumstr) != nodep->am_lnum) 12176e91bba0SGirish Moodalbail return (B_TRUE); 12186e91bba0SGirish Moodalbail } 12196e91bba0SGirish Moodalbail 12206e91bba0SGirish Moodalbail /* we found the match, delete the line from the db */ 12216e91bba0SGirish Moodalbail buf[0] = '\0'; 12226e91bba0SGirish Moodalbail 12236e91bba0SGirish Moodalbail /* stop the walker */ 12246e91bba0SGirish Moodalbail return (B_FALSE); 12256e91bba0SGirish Moodalbail } 12266e91bba0SGirish Moodalbail 12276e91bba0SGirish Moodalbail /* 12286e91bba0SGirish Moodalbail * Adds or deletes aobjmap node information into a temporary cache file. 12296e91bba0SGirish Moodalbail */ 12306e91bba0SGirish Moodalbail extern int 12316e91bba0SGirish Moodalbail ipmgmt_persist_aobjmap(ipmgmt_aobjmap_t *nodep, ipadm_db_op_t op) 12326e91bba0SGirish Moodalbail { 12336e91bba0SGirish Moodalbail int err; 12346e91bba0SGirish Moodalbail ipadm_dbwrite_cbarg_t cb; 12356e91bba0SGirish Moodalbail nvlist_t *nvl = NULL; 12366e91bba0SGirish Moodalbail 12376e91bba0SGirish Moodalbail if (op == IPADM_DB_WRITE) { 12386e91bba0SGirish Moodalbail if ((err = i_ipmgmt_node2nvl(&nvl, nodep)) != 0) 12396e91bba0SGirish Moodalbail return (err); 12406e91bba0SGirish Moodalbail cb.dbw_nvl = nvl; 12416e91bba0SGirish Moodalbail if (nodep->am_atype == IPADM_ADDR_IPV6_ADDRCONF) 12426e91bba0SGirish Moodalbail cb.dbw_flags = IPMGMT_ATYPE_V6ACONF; 12436e91bba0SGirish Moodalbail else 12446e91bba0SGirish Moodalbail cb.dbw_flags = 0; 12456e91bba0SGirish Moodalbail 12466e91bba0SGirish Moodalbail err = ipadm_rw_db(ipmgmt_update_aobjmap, &cb, 12476e91bba0SGirish Moodalbail ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_WRITE); 12486e91bba0SGirish Moodalbail nvlist_free(nvl); 12496e91bba0SGirish Moodalbail } else { 12506e91bba0SGirish Moodalbail assert(op == IPADM_DB_DELETE); 12516e91bba0SGirish Moodalbail 12526e91bba0SGirish Moodalbail err = ipadm_rw_db(ipmgmt_delete_aobjmap, nodep, 12536e91bba0SGirish Moodalbail ADDROBJ_MAPPING_DB_FILE, IPADM_FILE_MODE, IPADM_DB_DELETE); 12546e91bba0SGirish Moodalbail } 12556e91bba0SGirish Moodalbail return (err); 12566e91bba0SGirish Moodalbail } 1257550b6e40SSowmini Varadhan 1258*8887b57dSGirish Moodalbail /* 1259*8887b57dSGirish Moodalbail * upgrades the ipadm data-store. It renames all the old private protocol 1260*8887b57dSGirish Moodalbail * property names which start with leading protocol names to begin with 1261*8887b57dSGirish Moodalbail * IPADM_PRIV_PROP_PREFIX. 1262*8887b57dSGirish Moodalbail */ 1263*8887b57dSGirish Moodalbail /* ARGSUSED */ 1264*8887b57dSGirish Moodalbail boolean_t 1265*8887b57dSGirish Moodalbail ipmgmt_db_upgrade(void *arg, nvlist_t *db_nvl, char *buf, size_t buflen, 1266*8887b57dSGirish Moodalbail int *errp) 1267*8887b57dSGirish Moodalbail { 1268*8887b57dSGirish Moodalbail nvpair_t *nvp; 1269*8887b57dSGirish Moodalbail char *name, *pname = NULL, *protostr = NULL, *pval = NULL; 1270*8887b57dSGirish Moodalbail uint_t proto, nproto; 1271*8887b57dSGirish Moodalbail char nname[IPMGMT_STRSIZE], tmpstr[IPMGMT_STRSIZE]; 1272*8887b57dSGirish Moodalbail 1273*8887b57dSGirish Moodalbail *errp = 0; 1274*8887b57dSGirish Moodalbail /* 1275*8887b57dSGirish Moodalbail * We are interested in lines which contain protocol properties. We 1276*8887b57dSGirish Moodalbail * walk through other lines in the DB. 1277*8887b57dSGirish Moodalbail */ 1278*8887b57dSGirish Moodalbail if (nvlist_exists(db_nvl, IPADM_NVP_IFNAME) || 1279*8887b57dSGirish Moodalbail nvlist_exists(db_nvl, IPADM_NVP_AOBJNAME)) { 1280*8887b57dSGirish Moodalbail return (B_TRUE); 1281*8887b57dSGirish Moodalbail } 1282*8887b57dSGirish Moodalbail assert(nvlist_exists(db_nvl, IPADM_NVP_PROTONAME)); 1283550b6e40SSowmini Varadhan 1284550b6e40SSowmini Varadhan /* 1285*8887b57dSGirish Moodalbail * extract the propname from the `db_nvl' and also extract the 1286*8887b57dSGirish Moodalbail * protocol from the `db_nvl'. 1287550b6e40SSowmini Varadhan */ 1288*8887b57dSGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 1289*8887b57dSGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 1290*8887b57dSGirish Moodalbail name = nvpair_name(nvp); 1291*8887b57dSGirish Moodalbail if (strcmp(name, IPADM_NVP_PROTONAME) == 0) { 1292*8887b57dSGirish Moodalbail if (nvpair_value_string(nvp, &protostr) != 0) 1293*8887b57dSGirish Moodalbail return (B_TRUE); 1294*8887b57dSGirish Moodalbail } else { 1295*8887b57dSGirish Moodalbail assert(!IPADM_PRIV_NVP(name)); 1296*8887b57dSGirish Moodalbail pname = name; 1297*8887b57dSGirish Moodalbail if (nvpair_value_string(nvp, &pval) != 0) 1298*8887b57dSGirish Moodalbail return (B_TRUE); 1299*8887b57dSGirish Moodalbail } 1300*8887b57dSGirish Moodalbail } 1301*8887b57dSGirish Moodalbail 1302*8887b57dSGirish Moodalbail /* if the private property is in the right format return */ 1303*8887b57dSGirish Moodalbail if (strncmp(pname, IPADM_PERSIST_PRIVPROP_PREFIX, 1304*8887b57dSGirish Moodalbail strlen(IPADM_PERSIST_PRIVPROP_PREFIX)) == 0) { 1305*8887b57dSGirish Moodalbail return (B_TRUE); 1306*8887b57dSGirish Moodalbail } 1307*8887b57dSGirish Moodalbail /* if it's a public property move onto the next property */ 1308*8887b57dSGirish Moodalbail nproto = proto = ipadm_str2proto(protostr); 1309*8887b57dSGirish Moodalbail if (ipadm_legacy2new_propname(pname, nname, sizeof (nname), 1310*8887b57dSGirish Moodalbail &nproto) != 0) { 1311*8887b57dSGirish Moodalbail return (B_TRUE); 1312*8887b57dSGirish Moodalbail } 1313*8887b57dSGirish Moodalbail 1314*8887b57dSGirish Moodalbail /* replace the old protocol with new protocol, if required */ 1315*8887b57dSGirish Moodalbail if (nproto != proto) { 1316*8887b57dSGirish Moodalbail protostr = ipadm_proto2str(nproto); 1317*8887b57dSGirish Moodalbail if (nvlist_add_string(db_nvl, IPADM_NVP_PROTONAME, 1318*8887b57dSGirish Moodalbail protostr) != 0) { 1319*8887b57dSGirish Moodalbail return (B_TRUE); 1320*8887b57dSGirish Moodalbail } 1321*8887b57dSGirish Moodalbail } 1322*8887b57dSGirish Moodalbail 1323*8887b57dSGirish Moodalbail /* replace the old property name with new property name, if required */ 1324*8887b57dSGirish Moodalbail /* add the prefix to property name */ 1325*8887b57dSGirish Moodalbail (void) snprintf(tmpstr, sizeof (tmpstr), "_%s", nname); 1326*8887b57dSGirish Moodalbail if (nvlist_add_string(db_nvl, tmpstr, pval) != 0 || 1327*8887b57dSGirish Moodalbail nvlist_remove(db_nvl, pname, DATA_TYPE_STRING) != 0) { 1328*8887b57dSGirish Moodalbail return (B_TRUE); 1329*8887b57dSGirish Moodalbail } 1330*8887b57dSGirish Moodalbail (void) memset(buf, 0, buflen); 1331*8887b57dSGirish Moodalbail if (ipadm_nvlist2str(db_nvl, buf, buflen) == 0) { 1332*8887b57dSGirish Moodalbail /* buffer overflow */ 1333*8887b57dSGirish Moodalbail *errp = ENOBUFS; 1334*8887b57dSGirish Moodalbail } 1335*8887b57dSGirish Moodalbail return (B_TRUE); 1336*8887b57dSGirish Moodalbail } 1337*8887b57dSGirish Moodalbail 1338*8887b57dSGirish Moodalbail /* 1339*8887b57dSGirish Moodalbail * Called during boot. 1340*8887b57dSGirish Moodalbail * 1341*8887b57dSGirish Moodalbail * Walk through the DB and apply all the global module properties. We plow 1342*8887b57dSGirish Moodalbail * through the DB even if we fail to apply property. 1343*8887b57dSGirish Moodalbail */ 1344*8887b57dSGirish Moodalbail /* ARGSUSED */ 1345*8887b57dSGirish Moodalbail static boolean_t 1346*8887b57dSGirish Moodalbail ipmgmt_db_init(void *cbarg, nvlist_t *db_nvl, char *buf, size_t buflen, 1347*8887b57dSGirish Moodalbail int *errp) 1348*8887b57dSGirish Moodalbail { 1349*8887b57dSGirish Moodalbail ipadm_handle_t iph = cbarg; 1350*8887b57dSGirish Moodalbail nvpair_t *nvp, *pnvp; 1351*8887b57dSGirish Moodalbail char *strval = NULL, *name, *mod = NULL, *pname; 1352*8887b57dSGirish Moodalbail char tmpstr[IPMGMT_STRSIZE]; 1353*8887b57dSGirish Moodalbail uint_t proto; 1354*8887b57dSGirish Moodalbail 1355*8887b57dSGirish Moodalbail /* 1356*8887b57dSGirish Moodalbail * We could have used nvl_exists() directly, however we need several 1357*8887b57dSGirish Moodalbail * calls to it and each call traverses the list. Since this codepath 1358*8887b57dSGirish Moodalbail * is exercised during boot, let's traverse the list ourselves and do 1359*8887b57dSGirish Moodalbail * the necessary checks. 1360*8887b57dSGirish Moodalbail */ 1361*8887b57dSGirish Moodalbail for (nvp = nvlist_next_nvpair(db_nvl, NULL); nvp != NULL; 1362*8887b57dSGirish Moodalbail nvp = nvlist_next_nvpair(db_nvl, nvp)) { 1363*8887b57dSGirish Moodalbail name = nvpair_name(nvp); 1364*8887b57dSGirish Moodalbail if (IPADM_PRIV_NVP(name)) { 1365*8887b57dSGirish Moodalbail if (strcmp(name, IPADM_NVP_IFNAME) == 0 || 1366*8887b57dSGirish Moodalbail strcmp(name, IPADM_NVP_AOBJNAME) == 0) 1367*8887b57dSGirish Moodalbail return (B_TRUE); 1368*8887b57dSGirish Moodalbail else if (strcmp(name, IPADM_NVP_PROTONAME) == 0 && 1369*8887b57dSGirish Moodalbail nvpair_value_string(nvp, &mod) != 0) 1370*8887b57dSGirish Moodalbail return (B_TRUE); 1371*8887b57dSGirish Moodalbail } else { 1372*8887b57dSGirish Moodalbail /* possible a property */ 1373*8887b57dSGirish Moodalbail pnvp = nvp; 1374*8887b57dSGirish Moodalbail } 1375*8887b57dSGirish Moodalbail } 1376*8887b57dSGirish Moodalbail 1377*8887b57dSGirish Moodalbail /* if we are here than we found a global property */ 1378*8887b57dSGirish Moodalbail assert(mod != NULL); 1379*8887b57dSGirish Moodalbail assert(nvpair_type(pnvp) == DATA_TYPE_STRING); 1380*8887b57dSGirish Moodalbail 1381*8887b57dSGirish Moodalbail proto = ipadm_str2proto(mod); 1382*8887b57dSGirish Moodalbail name = nvpair_name(pnvp); 1383*8887b57dSGirish Moodalbail if (nvpair_value_string(pnvp, &strval) == 0) { 1384*8887b57dSGirish Moodalbail if (strncmp(name, IPADM_PERSIST_PRIVPROP_PREFIX, 1385*8887b57dSGirish Moodalbail strlen(IPADM_PERSIST_PRIVPROP_PREFIX)) == 0) { 1386*8887b57dSGirish Moodalbail /* private protocol property */ 1387*8887b57dSGirish Moodalbail pname = &name[1]; 1388*8887b57dSGirish Moodalbail } else if (ipadm_legacy2new_propname(name, tmpstr, 1389*8887b57dSGirish Moodalbail sizeof (tmpstr), &proto) == 0) { 1390*8887b57dSGirish Moodalbail pname = tmpstr; 1391*8887b57dSGirish Moodalbail } else { 1392*8887b57dSGirish Moodalbail pname = name; 1393*8887b57dSGirish Moodalbail } 1394*8887b57dSGirish Moodalbail if (ipadm_set_prop(iph, pname, strval, proto, 1395*8887b57dSGirish Moodalbail IPADM_OPT_ACTIVE) != IPADM_SUCCESS) { 1396*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "Failed to reapply property %s", 1397*8887b57dSGirish Moodalbail pname); 1398*8887b57dSGirish Moodalbail } 1399*8887b57dSGirish Moodalbail } 1400*8887b57dSGirish Moodalbail 1401*8887b57dSGirish Moodalbail return (B_TRUE); 1402*8887b57dSGirish Moodalbail } 1403*8887b57dSGirish Moodalbail 1404*8887b57dSGirish Moodalbail /* initialize global module properties */ 1405*8887b57dSGirish Moodalbail void 1406*8887b57dSGirish Moodalbail ipmgmt_init_prop() 1407*8887b57dSGirish Moodalbail { 1408*8887b57dSGirish Moodalbail ipadm_handle_t iph = NULL; 1409*8887b57dSGirish Moodalbail 1410*8887b57dSGirish Moodalbail if (ipadm_open(&iph, IPH_INIT) != IPADM_SUCCESS) { 1411*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "Could not reapply any of the " 1412*8887b57dSGirish Moodalbail "persisted protocol properties"); 1413*8887b57dSGirish Moodalbail return; 1414*8887b57dSGirish Moodalbail } 1415*8887b57dSGirish Moodalbail /* ipmgmt_db_init() logs warnings if there are any issues */ 1416*8887b57dSGirish Moodalbail (void) ipmgmt_db_walk(ipmgmt_db_init, iph, IPADM_DB_READ); 1417*8887b57dSGirish Moodalbail ipadm_close(iph); 1418*8887b57dSGirish Moodalbail } 1419*8887b57dSGirish Moodalbail 1420*8887b57dSGirish Moodalbail void 1421550b6e40SSowmini Varadhan ipmgmt_release_scf_resources(scf_resources_t *res) 1422550b6e40SSowmini Varadhan { 1423550b6e40SSowmini Varadhan scf_entry_destroy(res->sr_ent); 1424550b6e40SSowmini Varadhan scf_transaction_destroy(res->sr_tx); 1425550b6e40SSowmini Varadhan scf_value_destroy(res->sr_val); 1426550b6e40SSowmini Varadhan scf_property_destroy(res->sr_prop); 1427550b6e40SSowmini Varadhan scf_pg_destroy(res->sr_pg); 1428550b6e40SSowmini Varadhan scf_instance_destroy(res->sr_inst); 1429550b6e40SSowmini Varadhan (void) scf_handle_unbind(res->sr_handle); 1430550b6e40SSowmini Varadhan scf_handle_destroy(res->sr_handle); 1431550b6e40SSowmini Varadhan } 1432550b6e40SSowmini Varadhan 1433550b6e40SSowmini Varadhan /* 1434*8887b57dSGirish Moodalbail * It creates the necessary SCF handles and binds the given `fmri' to an 1435*8887b57dSGirish Moodalbail * instance. These resources are required for retrieving property value, 1436*8887b57dSGirish Moodalbail * creating property groups and modifying property values. 1437550b6e40SSowmini Varadhan */ 1438*8887b57dSGirish Moodalbail int 1439550b6e40SSowmini Varadhan ipmgmt_create_scf_resources(const char *fmri, scf_resources_t *res) 1440550b6e40SSowmini Varadhan { 1441550b6e40SSowmini Varadhan res->sr_tx = NULL; 1442550b6e40SSowmini Varadhan res->sr_ent = NULL; 1443550b6e40SSowmini Varadhan res->sr_inst = NULL; 1444550b6e40SSowmini Varadhan res->sr_pg = NULL; 1445550b6e40SSowmini Varadhan res->sr_prop = NULL; 1446550b6e40SSowmini Varadhan res->sr_val = NULL; 1447550b6e40SSowmini Varadhan 1448*8887b57dSGirish Moodalbail if ((res->sr_handle = scf_handle_create(SCF_VERSION)) == NULL) 1449550b6e40SSowmini Varadhan return (-1); 1450550b6e40SSowmini Varadhan 1451550b6e40SSowmini Varadhan if (scf_handle_bind(res->sr_handle) != 0) { 1452550b6e40SSowmini Varadhan scf_handle_destroy(res->sr_handle); 1453550b6e40SSowmini Varadhan return (-1); 1454550b6e40SSowmini Varadhan } 1455*8887b57dSGirish Moodalbail if ((res->sr_inst = scf_instance_create(res->sr_handle)) == NULL) 1456550b6e40SSowmini Varadhan goto failure; 1457550b6e40SSowmini Varadhan if (scf_handle_decode_fmri(res->sr_handle, fmri, NULL, NULL, 1458550b6e40SSowmini Varadhan res->sr_inst, NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) != 0) { 1459550b6e40SSowmini Varadhan goto failure; 1460550b6e40SSowmini Varadhan } 1461*8887b57dSGirish Moodalbail /* we will create the rest of the resources on demand */ 1462550b6e40SSowmini Varadhan return (0); 1463550b6e40SSowmini Varadhan 1464550b6e40SSowmini Varadhan failure: 1465*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "failed to create scf resources: %s", 1466*8887b57dSGirish Moodalbail scf_strerror(scf_error())); 1467550b6e40SSowmini Varadhan ipmgmt_release_scf_resources(res); 1468550b6e40SSowmini Varadhan return (-1); 1469550b6e40SSowmini Varadhan } 1470550b6e40SSowmini Varadhan 1471*8887b57dSGirish Moodalbail /* 1472*8887b57dSGirish Moodalbail * persists the `pval' for a given property `pname' in SCF. The only supported 1473*8887b57dSGirish Moodalbail * SCF property types are INTEGER and ASTRING. 1474*8887b57dSGirish Moodalbail */ 1475550b6e40SSowmini Varadhan static int 1476*8887b57dSGirish Moodalbail ipmgmt_set_scfprop_value(scf_resources_t *res, const char *pname, void *pval, 1477*8887b57dSGirish Moodalbail scf_type_t ptype) 1478550b6e40SSowmini Varadhan { 1479550b6e40SSowmini Varadhan int result = -1; 1480550b6e40SSowmini Varadhan boolean_t new; 1481550b6e40SSowmini Varadhan 1482*8887b57dSGirish Moodalbail if ((res->sr_val = scf_value_create(res->sr_handle)) == NULL) 1483*8887b57dSGirish Moodalbail goto failure; 1484*8887b57dSGirish Moodalbail switch (ptype) { 1485*8887b57dSGirish Moodalbail case SCF_TYPE_INTEGER: 1486*8887b57dSGirish Moodalbail scf_value_set_integer(res->sr_val, *(int64_t *)pval); 1487*8887b57dSGirish Moodalbail break; 1488*8887b57dSGirish Moodalbail case SCF_TYPE_ASTRING: 1489*8887b57dSGirish Moodalbail if (scf_value_set_astring(res->sr_val, (char *)pval) != 0) { 1490*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "Error setting string value %s " 1491*8887b57dSGirish Moodalbail "for property %s: %s", pval, pname, 1492*8887b57dSGirish Moodalbail scf_strerror(scf_error())); 1493550b6e40SSowmini Varadhan goto failure; 1494550b6e40SSowmini Varadhan } 1495*8887b57dSGirish Moodalbail break; 1496*8887b57dSGirish Moodalbail default: 1497*8887b57dSGirish Moodalbail goto failure; 1498*8887b57dSGirish Moodalbail } 1499*8887b57dSGirish Moodalbail 1500*8887b57dSGirish Moodalbail if ((res->sr_tx = scf_transaction_create(res->sr_handle)) == NULL) 1501*8887b57dSGirish Moodalbail goto failure; 1502*8887b57dSGirish Moodalbail if ((res->sr_ent = scf_entry_create(res->sr_handle)) == NULL) 1503*8887b57dSGirish Moodalbail goto failure; 1504*8887b57dSGirish Moodalbail if ((res->sr_prop = scf_property_create(res->sr_handle)) == NULL) 1505*8887b57dSGirish Moodalbail goto failure; 1506*8887b57dSGirish Moodalbail 1507*8887b57dSGirish Moodalbail retry: 1508*8887b57dSGirish Moodalbail new = (scf_pg_get_property(res->sr_pg, pname, res->sr_prop) != 0); 1509*8887b57dSGirish Moodalbail if (scf_transaction_start(res->sr_tx, res->sr_pg) == -1) 1510*8887b57dSGirish Moodalbail goto failure; 1511550b6e40SSowmini Varadhan if (new) { 1512550b6e40SSowmini Varadhan if (scf_transaction_property_new(res->sr_tx, res->sr_ent, 1513*8887b57dSGirish Moodalbail pname, ptype) == -1) { 1514550b6e40SSowmini Varadhan goto failure; 1515550b6e40SSowmini Varadhan } 1516550b6e40SSowmini Varadhan } else { 1517550b6e40SSowmini Varadhan if (scf_transaction_property_change(res->sr_tx, res->sr_ent, 1518*8887b57dSGirish Moodalbail pname, ptype) == -1) { 1519550b6e40SSowmini Varadhan goto failure; 1520550b6e40SSowmini Varadhan } 1521550b6e40SSowmini Varadhan } 1522550b6e40SSowmini Varadhan 1523*8887b57dSGirish Moodalbail if (scf_entry_add_value(res->sr_ent, res->sr_val) != 0) 1524550b6e40SSowmini Varadhan goto failure; 1525550b6e40SSowmini Varadhan 1526550b6e40SSowmini Varadhan result = scf_transaction_commit(res->sr_tx); 1527550b6e40SSowmini Varadhan if (result == 0) { 1528550b6e40SSowmini Varadhan scf_transaction_reset(res->sr_tx); 1529550b6e40SSowmini Varadhan if (scf_pg_update(res->sr_pg) == -1) { 1530550b6e40SSowmini Varadhan goto failure; 1531550b6e40SSowmini Varadhan } 1532550b6e40SSowmini Varadhan goto retry; 1533550b6e40SSowmini Varadhan } 1534550b6e40SSowmini Varadhan if (result == -1) 1535550b6e40SSowmini Varadhan goto failure; 1536550b6e40SSowmini Varadhan return (0); 1537550b6e40SSowmini Varadhan 1538550b6e40SSowmini Varadhan failure: 1539*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "failed to save the data in SCF: %s", 1540*8887b57dSGirish Moodalbail scf_strerror(scf_error())); 1541550b6e40SSowmini Varadhan return (-1); 1542550b6e40SSowmini Varadhan } 1543550b6e40SSowmini Varadhan 1544550b6e40SSowmini Varadhan /* 1545*8887b57dSGirish Moodalbail * Given a `pgname'/`pname', it retrieves the value based on `ptype' and 1546*8887b57dSGirish Moodalbail * places it in `pval'. 1547550b6e40SSowmini Varadhan */ 1548*8887b57dSGirish Moodalbail static int 1549*8887b57dSGirish Moodalbail ipmgmt_get_scfprop(scf_resources_t *res, const char *pgname, const char *pname, 1550*8887b57dSGirish Moodalbail void *pval, scf_type_t ptype) 1551550b6e40SSowmini Varadhan { 1552550b6e40SSowmini Varadhan ssize_t numvals; 1553*8887b57dSGirish Moodalbail scf_simple_prop_t *prop; 1554*8887b57dSGirish Moodalbail 1555*8887b57dSGirish Moodalbail prop = scf_simple_prop_get(res->sr_handle, IPMGMTD_FMRI, pgname, pname); 1556*8887b57dSGirish Moodalbail numvals = scf_simple_prop_numvalues(prop); 1557*8887b57dSGirish Moodalbail if (numvals <= 0) 1558*8887b57dSGirish Moodalbail goto ret; 1559*8887b57dSGirish Moodalbail switch (ptype) { 1560*8887b57dSGirish Moodalbail case SCF_TYPE_INTEGER: 1561*8887b57dSGirish Moodalbail *(int64_t **)pval = scf_simple_prop_next_integer(prop); 1562*8887b57dSGirish Moodalbail break; 1563*8887b57dSGirish Moodalbail case SCF_TYPE_ASTRING: 1564*8887b57dSGirish Moodalbail *(char **)pval = scf_simple_prop_next_astring(prop); 1565*8887b57dSGirish Moodalbail break; 1566*8887b57dSGirish Moodalbail } 1567*8887b57dSGirish Moodalbail ret: 1568*8887b57dSGirish Moodalbail scf_simple_prop_free(prop); 1569*8887b57dSGirish Moodalbail return (numvals); 1570*8887b57dSGirish Moodalbail } 1571*8887b57dSGirish Moodalbail 1572*8887b57dSGirish Moodalbail /* 1573*8887b57dSGirish Moodalbail * It stores the `pval' for given `pgname'/`pname' property group in SCF. 1574*8887b57dSGirish Moodalbail */ 1575*8887b57dSGirish Moodalbail static int 1576*8887b57dSGirish Moodalbail ipmgmt_set_scfprop(scf_resources_t *res, const char *pgname, const char *pname, 1577*8887b57dSGirish Moodalbail void *pval, scf_type_t ptype) 1578*8887b57dSGirish Moodalbail { 1579550b6e40SSowmini Varadhan scf_error_t err; 1580550b6e40SSowmini Varadhan 1581*8887b57dSGirish Moodalbail if ((res->sr_pg = scf_pg_create(res->sr_handle)) == NULL) { 1582*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "failed to create property group: %s", 1583*8887b57dSGirish Moodalbail scf_strerror(scf_error())); 1584*8887b57dSGirish Moodalbail return (-1); 1585550b6e40SSowmini Varadhan } 1586550b6e40SSowmini Varadhan 1587*8887b57dSGirish Moodalbail if (scf_instance_add_pg(res->sr_inst, pgname, SCF_GROUP_APPLICATION, 1588*8887b57dSGirish Moodalbail 0, res->sr_pg) != 0) { 1589*8887b57dSGirish Moodalbail if ((err = scf_error()) != SCF_ERROR_EXISTS) { 1590550b6e40SSowmini Varadhan ipmgmt_log(LOG_WARNING, 1591*8887b57dSGirish Moodalbail "Error adding property group '%s/%s': %s", 1592*8887b57dSGirish Moodalbail pgname, pname, scf_strerror(err)); 1593*8887b57dSGirish Moodalbail return (-1); 1594*8887b57dSGirish Moodalbail } 1595*8887b57dSGirish Moodalbail /* 1596*8887b57dSGirish Moodalbail * if the property group already exists, then we get the 1597*8887b57dSGirish Moodalbail * composed view of the property group for the given instance. 1598*8887b57dSGirish Moodalbail */ 1599*8887b57dSGirish Moodalbail if (scf_instance_get_pg_composed(res->sr_inst, NULL, pgname, 1600*8887b57dSGirish Moodalbail res->sr_pg) != 0) { 1601*8887b57dSGirish Moodalbail ipmgmt_log(LOG_WARNING, "Error getting composed view " 1602*8887b57dSGirish Moodalbail "of the property group '%s/%s': %s", pgname, pname, 1603*8887b57dSGirish Moodalbail scf_strerror(scf_error())); 1604*8887b57dSGirish Moodalbail return (-1); 1605*8887b57dSGirish Moodalbail } 1606550b6e40SSowmini Varadhan } 1607550b6e40SSowmini Varadhan 1608*8887b57dSGirish Moodalbail return (ipmgmt_set_scfprop_value(res, pname, pval, ptype)); 1609*8887b57dSGirish Moodalbail } 1610*8887b57dSGirish Moodalbail 1611*8887b57dSGirish Moodalbail /* 1612*8887b57dSGirish Moodalbail * Returns B_TRUE, if the non-global zone is being booted for the first time 1613*8887b57dSGirish Moodalbail * after being installed. This is required to setup the ipadm data-store for 1614*8887b57dSGirish Moodalbail * the first boot of the non-global zone. Please see, PSARC 2010/166, 1615*8887b57dSGirish Moodalbail * for more info. 1616*8887b57dSGirish Moodalbail * 1617*8887b57dSGirish Moodalbail * Note that, this API cannot be used to determine first boot post image-update. 1618*8887b57dSGirish Moodalbail * 'pkg image-update' clones the current BE and the existing value of 1619*8887b57dSGirish Moodalbail * ipmgmtd/first_boot_done will be carried forward and obviously it will be set 1620*8887b57dSGirish Moodalbail * to B_TRUE. 1621*8887b57dSGirish Moodalbail */ 1622*8887b57dSGirish Moodalbail boolean_t 1623*8887b57dSGirish Moodalbail ipmgmt_ngz_firstboot_postinstall() 1624*8887b57dSGirish Moodalbail { 1625*8887b57dSGirish Moodalbail scf_resources_t res; 1626*8887b57dSGirish Moodalbail boolean_t bval = B_TRUE; 1627*8887b57dSGirish Moodalbail char *strval; 1628*8887b57dSGirish Moodalbail 1629*8887b57dSGirish Moodalbail /* we always err on the side of caution */ 1630*8887b57dSGirish Moodalbail if (ipmgmt_create_scf_resources(IPMGMTD_FMRI, &res) != 0) 1631*8887b57dSGirish Moodalbail return (bval); 1632*8887b57dSGirish Moodalbail 1633*8887b57dSGirish Moodalbail if (ipmgmt_get_scfprop(&res, IPMGMTD_APP_PG, IPMGMTD_PROP_FBD, &strval, 1634*8887b57dSGirish Moodalbail SCF_TYPE_ASTRING) > 0) { 1635*8887b57dSGirish Moodalbail bval = (strcmp(strval, IPMGMTD_TRUESTR) == 0 ? 1636*8887b57dSGirish Moodalbail B_FALSE : B_TRUE); 1637*8887b57dSGirish Moodalbail } else { 1638*8887b57dSGirish Moodalbail /* 1639*8887b57dSGirish Moodalbail * IPMGMTD_PROP_FBD does not exist in the SCF. Lets create it. 1640*8887b57dSGirish Moodalbail * Since we err on the side of caution, we ignore the return 1641*8887b57dSGirish Moodalbail * error and return B_TRUE. 1642*8887b57dSGirish Moodalbail */ 1643*8887b57dSGirish Moodalbail (void) ipmgmt_set_scfprop(&res, IPMGMTD_APP_PG, 1644*8887b57dSGirish Moodalbail IPMGMTD_PROP_FBD, IPMGMTD_TRUESTR, SCF_TYPE_ASTRING); 1645*8887b57dSGirish Moodalbail } 1646550b6e40SSowmini Varadhan ipmgmt_release_scf_resources(&res); 1647*8887b57dSGirish Moodalbail return (bval); 1648*8887b57dSGirish Moodalbail } 1649*8887b57dSGirish Moodalbail 1650*8887b57dSGirish Moodalbail /* 1651*8887b57dSGirish Moodalbail * Returns B_TRUE, if the data-store needs upgrade otherwise returns B_FALSE. 1652*8887b57dSGirish Moodalbail * Today we have to take care of, one case of, upgrading from version 0 to 1653*8887b57dSGirish Moodalbail * version 1, so we will use boolean_t as means to decide if upgrade is needed 1654*8887b57dSGirish Moodalbail * or not. Further, the upcoming projects might completely move the flatfile 1655*8887b57dSGirish Moodalbail * data-store into SCF and hence we shall keep this interface simple. 1656*8887b57dSGirish Moodalbail */ 1657*8887b57dSGirish Moodalbail boolean_t 1658*8887b57dSGirish Moodalbail ipmgmt_needs_upgrade(scf_resources_t *res) 1659*8887b57dSGirish Moodalbail { 1660*8887b57dSGirish Moodalbail boolean_t bval = B_TRUE; 1661*8887b57dSGirish Moodalbail int64_t *verp; 1662*8887b57dSGirish Moodalbail 1663*8887b57dSGirish Moodalbail if (ipmgmt_get_scfprop(res, IPMGMTD_APP_PG, IPMGMTD_PROP_DBVER, 1664*8887b57dSGirish Moodalbail &verp, SCF_TYPE_INTEGER) > 0) { 1665*8887b57dSGirish Moodalbail if (*verp == IPADM_DB_VERSION) 1666*8887b57dSGirish Moodalbail bval = B_FALSE; 1667*8887b57dSGirish Moodalbail } 1668*8887b57dSGirish Moodalbail /* 1669*8887b57dSGirish Moodalbail * 'datastore_version' doesn't exist. Which means that we need to 1670*8887b57dSGirish Moodalbail * upgrade the datastore. We will create 'datastore_version' and set 1671*8887b57dSGirish Moodalbail * the version value to IPADM_DB_VERSION, after we upgrade the file. 1672*8887b57dSGirish Moodalbail */ 1673*8887b57dSGirish Moodalbail return (bval); 1674*8887b57dSGirish Moodalbail } 1675*8887b57dSGirish Moodalbail 1676*8887b57dSGirish Moodalbail /* 1677*8887b57dSGirish Moodalbail * This is called after the successful upgrade of the local data-store. With 1678*8887b57dSGirish Moodalbail * the data-store upgraded to recent version we don't have to do anything on 1679*8887b57dSGirish Moodalbail * subsequent reboots. 1680*8887b57dSGirish Moodalbail */ 1681*8887b57dSGirish Moodalbail void 1682*8887b57dSGirish Moodalbail ipmgmt_update_dbver(scf_resources_t *res) 1683*8887b57dSGirish Moodalbail { 1684*8887b57dSGirish Moodalbail int64_t version = IPADM_DB_VERSION; 1685*8887b57dSGirish Moodalbail 1686*8887b57dSGirish Moodalbail (void) ipmgmt_set_scfprop(res, IPMGMTD_APP_PG, 1687*8887b57dSGirish Moodalbail IPMGMTD_PROP_DBVER, &version, SCF_TYPE_INTEGER); 1688550b6e40SSowmini Varadhan } 1689