13147Sxc151355 /* 23147Sxc151355 * CDDL HEADER START 33147Sxc151355 * 43147Sxc151355 * The contents of this file are subject to the terms of the 53147Sxc151355 * Common Development and Distribution License (the "License"). 63147Sxc151355 * You may not use this file except in compliance with the License. 73147Sxc151355 * 83147Sxc151355 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93147Sxc151355 * or http://www.opensolaris.org/os/licensing. 103147Sxc151355 * See the License for the specific language governing permissions 113147Sxc151355 * and limitations under the License. 123147Sxc151355 * 133147Sxc151355 * When distributing Covered Code, include this CDDL HEADER in each 143147Sxc151355 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153147Sxc151355 * If applicable, add the following below this CDDL HEADER, with the 163147Sxc151355 * fields enclosed by brackets "[]" replaced with your own identifying 173147Sxc151355 * information: Portions Copyright [yyyy] [name of copyright owner] 183147Sxc151355 * 193147Sxc151355 * CDDL HEADER END 203147Sxc151355 */ 213147Sxc151355 /* 22*3448Sdh155122 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233147Sxc151355 * Use is subject to license terms. 243147Sxc151355 */ 253147Sxc151355 263147Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 273147Sxc151355 283147Sxc151355 #include <stdlib.h> 293147Sxc151355 #include <strings.h> 303147Sxc151355 #include <errno.h> 313147Sxc151355 #include <ctype.h> 32*3448Sdh155122 #include <sys/types.h> 333147Sxc151355 #include <sys/stat.h> 34*3448Sdh155122 #include <sys/dld.h> 35*3448Sdh155122 #include <sys/zone.h> 36*3448Sdh155122 #include <fcntl.h> 37*3448Sdh155122 #include <unistd.h> 38*3448Sdh155122 #include <libdevinfo.h> 39*3448Sdh155122 #include <zone.h> 403147Sxc151355 #include <libwladm.h> 413147Sxc151355 #include <libdladm_impl.h> 423147Sxc151355 43*3448Sdh155122 #include <dlfcn.h> 44*3448Sdh155122 #include <link.h> 45*3448Sdh155122 463147Sxc151355 static dladm_status_t i_dladm_set_prop_db(const char *, const char *, 473147Sxc151355 char **, uint_t); 483147Sxc151355 static dladm_status_t i_dladm_get_prop_db(const char *, const char *, 493147Sxc151355 char **, uint_t *); 50*3448Sdh155122 static dladm_status_t i_dladm_get_prop_temp(const char *, dladm_prop_type_t, 51*3448Sdh155122 const char *, char **, uint_t *); 52*3448Sdh155122 static dladm_status_t i_dladm_set_prop_temp(const char *, const char *, 53*3448Sdh155122 char **, uint_t, uint_t, char **); 54*3448Sdh155122 static boolean_t i_dladm_is_prop_temponly(const char *prop_name, 55*3448Sdh155122 char **); 56*3448Sdh155122 57*3448Sdh155122 typedef struct val_desc { 58*3448Sdh155122 char *vd_name; 59*3448Sdh155122 void *vd_val; 60*3448Sdh155122 } val_desc_t; 61*3448Sdh155122 62*3448Sdh155122 struct prop_desc; 63*3448Sdh155122 64*3448Sdh155122 typedef dladm_status_t pd_getf_t(const char *, char **, uint_t *); 65*3448Sdh155122 typedef dladm_status_t pd_setf_t(const char *, val_desc_t *, uint_t); 66*3448Sdh155122 typedef dladm_status_t pd_checkf_t(struct prop_desc *, char **, 67*3448Sdh155122 uint_t, val_desc_t **); 68*3448Sdh155122 69*3448Sdh155122 static pd_getf_t do_get_zone; 70*3448Sdh155122 static pd_setf_t do_set_zone; 71*3448Sdh155122 static pd_checkf_t do_check_zone; 72*3448Sdh155122 73*3448Sdh155122 typedef struct prop_desc { 74*3448Sdh155122 char *pd_name; 75*3448Sdh155122 val_desc_t pd_defval; 76*3448Sdh155122 val_desc_t *pd_modval; 77*3448Sdh155122 uint_t pd_nmodval; 78*3448Sdh155122 boolean_t pd_temponly; 79*3448Sdh155122 pd_setf_t *pd_set; 80*3448Sdh155122 pd_getf_t *pd_getmod; 81*3448Sdh155122 pd_getf_t *pd_get; 82*3448Sdh155122 pd_checkf_t *pd_check; 83*3448Sdh155122 } prop_desc_t; 84*3448Sdh155122 85*3448Sdh155122 static prop_desc_t prop_table[] = { 86*3448Sdh155122 { "zone", { "", NULL }, NULL, 0, B_TRUE, 87*3448Sdh155122 do_set_zone, NULL, 88*3448Sdh155122 do_get_zone, do_check_zone} 89*3448Sdh155122 }; 90*3448Sdh155122 91*3448Sdh155122 #define MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 923147Sxc151355 933147Sxc151355 /* 943147Sxc151355 * Convert a wladm_status_t to a dladm_status_t. This is used by wrappers 953147Sxc151355 * to libwladm routines (e.g. dladm_set_prop()). Note that the mapping is 963147Sxc151355 * not 1-1; whenever possible we try to look for an error code with a 973147Sxc151355 * similar meaning. Error codes with no suitable counterpart in libdladm 983147Sxc151355 * will be mapped to DLADM_STATUS_FAILED. Clients who require clearer error 993147Sxc151355 * reporting should use libwladm directly. 1003147Sxc151355 */ 1013147Sxc151355 static dladm_status_t 1023147Sxc151355 dladm_wladmstatus2status(wladm_status_t wstatus) 1033147Sxc151355 { 1043147Sxc151355 switch (wstatus) { 1053147Sxc151355 case WLADM_STATUS_OK: 1063147Sxc151355 return (DLADM_STATUS_OK); 1073147Sxc151355 case WLADM_STATUS_FAILED: 1083147Sxc151355 return (DLADM_STATUS_FAILED); 1093147Sxc151355 case WLADM_STATUS_NOTSUP: 1103147Sxc151355 return (DLADM_STATUS_NOTSUP); 1113147Sxc151355 case WLADM_STATUS_BADARG: 1123147Sxc151355 return (DLADM_STATUS_BADARG); 1133147Sxc151355 case WLADM_STATUS_NOTFOUND: 1143147Sxc151355 return (DLADM_STATUS_NOTFOUND); 1153147Sxc151355 case WLADM_STATUS_BADVAL: 1163147Sxc151355 return (DLADM_STATUS_BADVAL); 1173147Sxc151355 case WLADM_STATUS_LINKINVAL: 1183147Sxc151355 return (DLADM_STATUS_LINKINVAL); 1193147Sxc151355 case WLADM_STATUS_NOMEM: 1203147Sxc151355 return (DLADM_STATUS_NOMEM); 1213147Sxc151355 case WLADM_STATUS_PROPRDONLY: 1223147Sxc151355 return (DLADM_STATUS_PROPRDONLY); 1233147Sxc151355 case WLADM_STATUS_TOOSMALL: 1243147Sxc151355 return (DLADM_STATUS_TOOSMALL); 1253147Sxc151355 case WLADM_STATUS_BADVALCNT: 1263147Sxc151355 return (DLADM_STATUS_BADVALCNT); 1273147Sxc151355 default: 1283147Sxc151355 return (DLADM_STATUS_FAILED); 1293147Sxc151355 } 1303147Sxc151355 } 1313147Sxc151355 1323147Sxc151355 dladm_status_t 1333147Sxc151355 dladm_set_prop(const char *link, const char *prop_name, char **prop_val, 134*3448Sdh155122 uint_t val_cnt, uint_t flags, char **errprop) 1353147Sxc151355 { 1363147Sxc151355 dladm_status_t status = DLADM_STATUS_BADARG; 1373147Sxc151355 1383147Sxc151355 if (link == NULL || (prop_val == NULL && val_cnt > 0) || 1393147Sxc151355 (prop_val != NULL && val_cnt == 0) || flags == 0) 1403147Sxc151355 return (DLADM_STATUS_BADARG); 1413147Sxc151355 1423147Sxc151355 if ((flags & DLADM_OPT_TEMP) != 0) { 143*3448Sdh155122 status = i_dladm_set_prop_temp(link, prop_name, prop_val, 144*3448Sdh155122 val_cnt, flags, errprop); 145*3448Sdh155122 if (status == DLADM_STATUS_TEMPONLY && 146*3448Sdh155122 (flags & DLADM_OPT_PERSIST) != 0) 147*3448Sdh155122 return (DLADM_STATUS_TEMPONLY); 148*3448Sdh155122 149*3448Sdh155122 if (status == DLADM_STATUS_NOTFOUND) { 150*3448Sdh155122 status = DLADM_STATUS_BADARG; 151*3448Sdh155122 if (wladm_is_valid(link)) { 152*3448Sdh155122 status = dladm_wladmstatus2status( 153*3448Sdh155122 wladm_set_prop(link, prop_name, 154*3448Sdh155122 prop_val, val_cnt, errprop)); 155*3448Sdh155122 } 1563147Sxc151355 } 1573147Sxc151355 if (status != DLADM_STATUS_OK) 1583147Sxc151355 return (status); 1593147Sxc151355 } 1603147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) { 161*3448Sdh155122 if (i_dladm_is_prop_temponly(prop_name, errprop)) 162*3448Sdh155122 return (DLADM_STATUS_TEMPONLY); 163*3448Sdh155122 1643147Sxc151355 status = i_dladm_set_prop_db(link, prop_name, 1653147Sxc151355 prop_val, val_cnt); 1663147Sxc151355 } 1673147Sxc151355 return (status); 1683147Sxc151355 } 1693147Sxc151355 1703147Sxc151355 dladm_status_t 1713147Sxc151355 dladm_walk_prop(const char *link, void *arg, 1723147Sxc151355 boolean_t (*func)(void *, const char *)) 1733147Sxc151355 { 174*3448Sdh155122 int i; 175*3448Sdh155122 1763147Sxc151355 if (link == NULL || func == NULL) 1773147Sxc151355 return (DLADM_STATUS_BADARG); 1783147Sxc151355 179*3448Sdh155122 /* For wifi links, show wifi properties first */ 1803147Sxc151355 if (wladm_is_valid(link)) { 181*3448Sdh155122 dladm_status_t status; 182*3448Sdh155122 183*3448Sdh155122 status = dladm_wladmstatus2status( 184*3448Sdh155122 wladm_walk_prop(link, arg, func)); 185*3448Sdh155122 if (status != DLADM_STATUS_OK) 186*3448Sdh155122 return (status); 1873147Sxc151355 } 188*3448Sdh155122 189*3448Sdh155122 /* Then show data-link properties if there are any */ 190*3448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 191*3448Sdh155122 if (!func(arg, prop_table[i].pd_name)) 192*3448Sdh155122 break; 193*3448Sdh155122 } 194*3448Sdh155122 return (DLADM_STATUS_OK); 1953147Sxc151355 } 1963147Sxc151355 1973147Sxc151355 dladm_status_t 1983147Sxc151355 dladm_get_prop(const char *link, dladm_prop_type_t type, 1993147Sxc151355 const char *prop_name, char **prop_val, uint_t *val_cntp) 2003147Sxc151355 { 201*3448Sdh155122 dladm_status_t status; 202*3448Sdh155122 2033147Sxc151355 if (link == NULL || prop_name == NULL || prop_val == NULL || 2043147Sxc151355 val_cntp == NULL || *val_cntp == 0) 2053147Sxc151355 return (DLADM_STATUS_BADARG); 2063147Sxc151355 2073147Sxc151355 if (type == DLADM_PROP_VAL_PERSISTENT) { 2083147Sxc151355 return (i_dladm_get_prop_db(link, prop_name, 2093147Sxc151355 prop_val, val_cntp)); 2103147Sxc151355 } 2113147Sxc151355 212*3448Sdh155122 status = i_dladm_get_prop_temp(link, type, prop_name, 213*3448Sdh155122 prop_val, val_cntp); 214*3448Sdh155122 if (status != DLADM_STATUS_NOTFOUND) 215*3448Sdh155122 return (status); 216*3448Sdh155122 2173147Sxc151355 if (wladm_is_valid(link)) { 2183147Sxc151355 wladm_prop_type_t wtype; 2193147Sxc151355 2203147Sxc151355 switch (type) { 2213147Sxc151355 case DLADM_PROP_VAL_CURRENT: 2223147Sxc151355 wtype = WLADM_PROP_VAL_CURRENT; 2233147Sxc151355 break; 2243147Sxc151355 case DLADM_PROP_VAL_DEFAULT: 2253147Sxc151355 wtype = WLADM_PROP_VAL_DEFAULT; 2263147Sxc151355 break; 2273147Sxc151355 case DLADM_PROP_VAL_MODIFIABLE: 2283147Sxc151355 wtype = WLADM_PROP_VAL_MODIFIABLE; 2293147Sxc151355 break; 2303147Sxc151355 default: 2313147Sxc151355 return (DLADM_STATUS_BADARG); 2323147Sxc151355 } 2333147Sxc151355 2343147Sxc151355 return (dladm_wladmstatus2status( 2353147Sxc151355 wladm_get_prop(link, wtype, prop_name, 2363147Sxc151355 prop_val, val_cntp))); 2373147Sxc151355 } 2383147Sxc151355 return (DLADM_STATUS_BADARG); 2393147Sxc151355 } 2403147Sxc151355 2413147Sxc151355 /* 2423147Sxc151355 * Data structures used for implementing persistent link properties 2433147Sxc151355 */ 2443147Sxc151355 typedef struct linkprop_val { 2453147Sxc151355 const char *lv_name; 2463147Sxc151355 struct linkprop_val *lv_nextval; 2473147Sxc151355 } linkprop_val_t; 2483147Sxc151355 2493147Sxc151355 typedef struct linkprop_info { 2503147Sxc151355 const char *li_name; 2513147Sxc151355 struct linkprop_info *li_nextprop; 2523147Sxc151355 struct linkprop_val *li_val; 2533147Sxc151355 } linkprop_info_t; 2543147Sxc151355 2553147Sxc151355 typedef struct linkprop_db_state linkprop_db_state_t; 2563147Sxc151355 2573147Sxc151355 typedef boolean_t (*linkprop_db_op_t)(linkprop_db_state_t *, 2583147Sxc151355 char *, linkprop_info_t *, dladm_status_t *); 2593147Sxc151355 2603147Sxc151355 struct linkprop_db_state { 2613147Sxc151355 linkprop_db_op_t ls_op; 2623147Sxc151355 const char *ls_link; 2633147Sxc151355 const char *ls_propname; 2643147Sxc151355 char **ls_propval; 2653147Sxc151355 uint_t *ls_valcntp; 2663147Sxc151355 }; 2673147Sxc151355 2683147Sxc151355 static void 2693147Sxc151355 free_linkprops(linkprop_info_t *lip) 2703147Sxc151355 { 2713147Sxc151355 linkprop_info_t *lip_next; 2723147Sxc151355 linkprop_val_t *lvp, *lvp_next; 2733147Sxc151355 2743147Sxc151355 for (; lip != NULL; lip = lip_next) { 2753147Sxc151355 lip_next = lip->li_nextprop; 2763147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) { 2773147Sxc151355 lvp_next = lvp->lv_nextval; 2783147Sxc151355 free(lvp); 2793147Sxc151355 } 2803147Sxc151355 free(lip); 2813147Sxc151355 } 2823147Sxc151355 } 2833147Sxc151355 2843147Sxc151355 /* 2853147Sxc151355 * Generate an entry in the link property database. 2863147Sxc151355 * Each entry has this format: 2873147Sxc151355 * <linkname> <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>; 2883147Sxc151355 */ 2893147Sxc151355 static void 2903147Sxc151355 generate_linkprop_line(linkprop_db_state_t *lsp, char *buf, 2913147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 2923147Sxc151355 { 2933147Sxc151355 char tmpbuf[MAXLINELEN]; 2943147Sxc151355 char *ptr, *lim = tmpbuf + MAXLINELEN; 2953147Sxc151355 linkprop_info_t *lip = listp; 2963147Sxc151355 linkprop_val_t *lvp = NULL; 2973147Sxc151355 2983147Sxc151355 /* 2993147Sxc151355 * Delete line if there are no properties left. 3003147Sxc151355 */ 3013147Sxc151355 if (lip == NULL || 3023147Sxc151355 (lip->li_val == NULL && lip->li_nextprop == NULL)) { 3033147Sxc151355 buf[0] = '\0'; 3043147Sxc151355 return; 3053147Sxc151355 } 3063147Sxc151355 ptr = tmpbuf; 3073147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", lsp->ls_link); 3083147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 3093147Sxc151355 /* 3103147Sxc151355 * Skip properties without values. 3113147Sxc151355 */ 3123147Sxc151355 if (lip->li_val == NULL) 3133147Sxc151355 continue; 3143147Sxc151355 3153147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s=", lip->li_name); 3163147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) { 3173147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s%c", 3183147Sxc151355 lvp->lv_name, 3193147Sxc151355 ((lvp->lv_nextval == NULL) ? ';' : ',')); 3203147Sxc151355 } 3213147Sxc151355 } 3223147Sxc151355 if (ptr > lim) { 3233147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 3243147Sxc151355 return; 3253147Sxc151355 } 3263147Sxc151355 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf); 3273147Sxc151355 } 3283147Sxc151355 3293147Sxc151355 /* 3303147Sxc151355 * This function is used to update or create an entry in the persistent db. 3313147Sxc151355 * process_linkprop_db() will first scan the db for an entry matching the 3323147Sxc151355 * specified link. If a match is found, this function is invoked with the 3333147Sxc151355 * entry's contents (buf) and its linked-list representation (listp). lsp 3343147Sxc151355 * holds the name and values of the property to be added or updated; this 3353147Sxc151355 * information will be merged with listp. Subsequently, an updated entry 3363147Sxc151355 * will be written to buf, which will in turn be written to disk by 3373147Sxc151355 * process_linkprop_db(). If no entry matches the specified link, listp 3383147Sxc151355 * will be NULL; a new entry will be generated in this case and it will 3393147Sxc151355 * contain only the property information in lsp. 3403147Sxc151355 */ 3413147Sxc151355 static boolean_t 3423147Sxc151355 process_linkprop_set(linkprop_db_state_t *lsp, char *buf, 3433147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 3443147Sxc151355 { 3453147Sxc151355 dladm_status_t status; 3463147Sxc151355 linkprop_info_t *lastp = NULL, *lip = listp, *nlip = NULL; 3473147Sxc151355 linkprop_val_t **lvpp; 3483147Sxc151355 int i; 3493147Sxc151355 3503147Sxc151355 if (lsp->ls_propname == NULL) { 3513147Sxc151355 buf[0] = '\0'; 3523147Sxc151355 return (B_FALSE); 3533147Sxc151355 } 3543147Sxc151355 3553147Sxc151355 /* 3563147Sxc151355 * Find the linkprop we want to change. 3573147Sxc151355 */ 3583147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 3593147Sxc151355 if (strcmp(lip->li_name, lsp->ls_propname) == 0) 3603147Sxc151355 break; 3613147Sxc151355 3623147Sxc151355 lastp = lip; 3633147Sxc151355 } 3643147Sxc151355 3653147Sxc151355 if (lip == NULL) { 3663147Sxc151355 /* 3673147Sxc151355 * If the linkprop is not found, append it to the list. 3683147Sxc151355 */ 3693147Sxc151355 if ((nlip = malloc(sizeof (linkprop_info_t))) == NULL) { 3703147Sxc151355 status = DLADM_STATUS_NOMEM; 3713147Sxc151355 goto fail; 3723147Sxc151355 } 3733147Sxc151355 /* 3743147Sxc151355 * nlip will need to be freed later if there is no list to 3753147Sxc151355 * append to. 3763147Sxc151355 */ 3773147Sxc151355 if (lastp != NULL) 3783147Sxc151355 lastp->li_nextprop = nlip; 3793147Sxc151355 nlip->li_name = lsp->ls_propname; 3803147Sxc151355 nlip->li_nextprop = NULL; 3813147Sxc151355 nlip->li_val = NULL; 3823147Sxc151355 lvpp = &nlip->li_val; 3833147Sxc151355 } else { 3843147Sxc151355 linkprop_val_t *lvp, *lvp_next; 3853147Sxc151355 3863147Sxc151355 /* 3873147Sxc151355 * If the linkprop is found, delete the existing values from it. 3883147Sxc151355 */ 3893147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) { 3903147Sxc151355 lvp_next = lvp->lv_nextval; 3913147Sxc151355 free(lvp); 3923147Sxc151355 } 3933147Sxc151355 lip->li_val = NULL; 3943147Sxc151355 lvpp = &lip->li_val; 3953147Sxc151355 } 3963147Sxc151355 3973147Sxc151355 /* 3983147Sxc151355 * Fill our linkprop with the specified values. 3993147Sxc151355 */ 4003147Sxc151355 for (i = 0; i < *lsp->ls_valcntp; i++) { 4013147Sxc151355 if ((*lvpp = malloc(sizeof (linkprop_val_t))) == NULL) { 4023147Sxc151355 status = DLADM_STATUS_NOMEM; 4033147Sxc151355 goto fail; 4043147Sxc151355 } 4053147Sxc151355 (*lvpp)->lv_name = lsp->ls_propval[i]; 4063147Sxc151355 (*lvpp)->lv_nextval = NULL; 4073147Sxc151355 lvpp = &(*lvpp)->lv_nextval; 4083147Sxc151355 } 4093147Sxc151355 4103147Sxc151355 if (listp != NULL) { 4113147Sxc151355 generate_linkprop_line(lsp, buf, listp, statusp); 4123147Sxc151355 } else { 4133147Sxc151355 generate_linkprop_line(lsp, buf, nlip, statusp); 4143147Sxc151355 free_linkprops(nlip); 4153147Sxc151355 } 4163147Sxc151355 return (B_FALSE); 4173147Sxc151355 4183147Sxc151355 fail: 4193147Sxc151355 *statusp = status; 4203147Sxc151355 if (listp == NULL) 4213147Sxc151355 free_linkprops(nlip); 4223147Sxc151355 4233147Sxc151355 return (B_FALSE); 4243147Sxc151355 } 4253147Sxc151355 4263147Sxc151355 /* 4273147Sxc151355 * This function is used for retrieving the values for a specific property. 4283147Sxc151355 * It gets called if an entry matching the specified link exists in the db. 4293147Sxc151355 * The entry is converted into a linked-list listp. This list is then scanned 4303147Sxc151355 * for the specified property name; if a matching property exists, its 4313147Sxc151355 * associated values are copied to the array lsp->ls_propval. 4323147Sxc151355 */ 4333147Sxc151355 /* ARGSUSED */ 4343147Sxc151355 static boolean_t 4353147Sxc151355 process_linkprop_get(linkprop_db_state_t *lsp, char *buf, 4363147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 4373147Sxc151355 { 4383147Sxc151355 linkprop_info_t *lip = listp; 4393147Sxc151355 linkprop_val_t *lvp; 4403147Sxc151355 uint_t valcnt = 0; 4413147Sxc151355 4423147Sxc151355 /* 4433147Sxc151355 * Find the linkprop we want to get. 4443147Sxc151355 */ 4453147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 4463147Sxc151355 if (strcmp(lip->li_name, lsp->ls_propname) == 0) 4473147Sxc151355 break; 4483147Sxc151355 } 4493147Sxc151355 if (lip == NULL) { 4503147Sxc151355 *statusp = DLADM_STATUS_NOTFOUND; 4513147Sxc151355 return (B_FALSE); 4523147Sxc151355 } 4533147Sxc151355 4543147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) { 4553147Sxc151355 (void) strncpy(lsp->ls_propval[valcnt], lvp->lv_name, 4563147Sxc151355 DLADM_PROP_VAL_MAX); 4573147Sxc151355 4583147Sxc151355 if (++valcnt >= *lsp->ls_valcntp && lvp->lv_nextval != NULL) { 4593147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 4603147Sxc151355 return (B_FALSE); 4613147Sxc151355 } 4623147Sxc151355 } 4633147Sxc151355 /* 4643147Sxc151355 * This function is meant to be called at most once for each call 4653147Sxc151355 * to process_linkprop_db(). For this reason, it's ok to overwrite 4663147Sxc151355 * the caller's valcnt array size with the actual number of values 4673147Sxc151355 * returned. 4683147Sxc151355 */ 4693147Sxc151355 *lsp->ls_valcntp = valcnt; 4703147Sxc151355 return (B_FALSE); 4713147Sxc151355 } 4723147Sxc151355 4733147Sxc151355 /* 4743147Sxc151355 * This is used for initializing link properties. 4753147Sxc151355 * Unlike the other routines, this gets called for every entry in the 4763147Sxc151355 * database. lsp->ls_link is not user-specified but instead is set to 4773147Sxc151355 * the current link being processed. 4783147Sxc151355 */ 4793147Sxc151355 /* ARGSUSED */ 4803147Sxc151355 static boolean_t 4813147Sxc151355 process_linkprop_init(linkprop_db_state_t *lsp, char *buf, 4823147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 4833147Sxc151355 { 4843147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 4853147Sxc151355 linkprop_info_t *lip = listp; 4863147Sxc151355 linkprop_val_t *lvp; 4873147Sxc151355 uint_t valcnt, i; 4883147Sxc151355 char **propval; 4893147Sxc151355 4903147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 4913147Sxc151355 /* 4923147Sxc151355 * Construct the propval array and fill it with 4933147Sxc151355 * values from listp. 4943147Sxc151355 */ 4953147Sxc151355 for (lvp = lip->li_val, valcnt = 0; 4963147Sxc151355 lvp != NULL; lvp = lvp->lv_nextval, valcnt++); 4973147Sxc151355 4983147Sxc151355 propval = malloc(sizeof (char *) * valcnt); 4993147Sxc151355 if (propval == NULL) { 5003147Sxc151355 *statusp = DLADM_STATUS_NOMEM; 5013147Sxc151355 break; 5023147Sxc151355 } 5033147Sxc151355 lvp = lip->li_val; 5043147Sxc151355 for (i = 0; i < valcnt; i++, lvp = lvp->lv_nextval) 5053147Sxc151355 propval[i] = (char *)lvp->lv_name; 5063147Sxc151355 5073147Sxc151355 status = dladm_set_prop(lsp->ls_link, lip->li_name, 508*3448Sdh155122 propval, valcnt, DLADM_OPT_TEMP, NULL); 5093147Sxc151355 5103147Sxc151355 /* 5113147Sxc151355 * We continue with initializing other properties even 5123147Sxc151355 * after encountering an error. This error will be 5133147Sxc151355 * propagated to the caller via 'statusp'. 5143147Sxc151355 */ 5153147Sxc151355 if (status != DLADM_STATUS_OK) 5163147Sxc151355 *statusp = status; 5173147Sxc151355 5183147Sxc151355 free(propval); 5193147Sxc151355 } 5203147Sxc151355 return (B_TRUE); 5213147Sxc151355 } 5223147Sxc151355 5233147Sxc151355 static int 5243147Sxc151355 parse_linkprops(char *buf, linkprop_info_t **lipp) 5253147Sxc151355 { 5263147Sxc151355 int i, len; 5273147Sxc151355 char *curr; 5283147Sxc151355 linkprop_info_t *lip = NULL; 5293147Sxc151355 linkprop_info_t **tailp = lipp; 5303147Sxc151355 linkprop_val_t *lvp = NULL; 5313147Sxc151355 linkprop_val_t **vtailp = NULL; 5323147Sxc151355 5333147Sxc151355 curr = buf; 5343147Sxc151355 len = strlen(buf); 5353147Sxc151355 for (i = 0; i < len; i++) { 5363147Sxc151355 char c = buf[i]; 5373147Sxc151355 boolean_t match = (c == '=' || c == ',' || c == ';'); 5383147Sxc151355 5393147Sxc151355 /* 5403147Sxc151355 * Move to the next character if there is no match and 5413147Sxc151355 * if we have not reached the last character. 5423147Sxc151355 */ 5433147Sxc151355 if (!match && i != len - 1) 5443147Sxc151355 continue; 5453147Sxc151355 5463147Sxc151355 if (match) { 5473147Sxc151355 /* 5483147Sxc151355 * Nul-terminate the string pointed to by 'curr'. 5493147Sxc151355 */ 5503147Sxc151355 buf[i] = '\0'; 5513147Sxc151355 if (*curr == '\0') 5523147Sxc151355 goto fail; 5533147Sxc151355 } 5543147Sxc151355 5553147Sxc151355 if (lip != NULL) { 5563147Sxc151355 /* 5573147Sxc151355 * We get here after we have processed the "<prop>=" 5583147Sxc151355 * pattern. The pattern we are now interested in is 5593147Sxc151355 * "<val0>,<val1>,...,<valn>;". For each value we 5603147Sxc151355 * find, a linkprop_val_t will be allocated and 5613147Sxc151355 * added to the current 'lip'. 5623147Sxc151355 */ 5633147Sxc151355 if (c == '=') 5643147Sxc151355 goto fail; 5653147Sxc151355 5663147Sxc151355 lvp = malloc(sizeof (*lvp)); 5673147Sxc151355 if (lvp == NULL) 5683147Sxc151355 goto fail; 5693147Sxc151355 5703147Sxc151355 lvp->lv_name = curr; 5713147Sxc151355 lvp->lv_nextval = NULL; 5723147Sxc151355 *vtailp = lvp; 5733147Sxc151355 vtailp = &lvp->lv_nextval; 5743147Sxc151355 5753147Sxc151355 if (c == ';') { 5763147Sxc151355 tailp = &lip->li_nextprop; 5773147Sxc151355 vtailp = NULL; 5783147Sxc151355 lip = NULL; 5793147Sxc151355 } 5803147Sxc151355 } else { 5813147Sxc151355 /* 5823147Sxc151355 * lip == NULL indicates that 'curr' must be refering 5833147Sxc151355 * to a property name. We allocate a new linkprop_info_t 5843147Sxc151355 * append it to the list given by the caller. 5853147Sxc151355 */ 5863147Sxc151355 if (c != '=') 5873147Sxc151355 goto fail; 5883147Sxc151355 5893147Sxc151355 lip = malloc(sizeof (*lip)); 5903147Sxc151355 if (lip == NULL) 5913147Sxc151355 goto fail; 5923147Sxc151355 5933147Sxc151355 lip->li_name = curr; 5943147Sxc151355 lip->li_val = NULL; 5953147Sxc151355 lip->li_nextprop = NULL; 5963147Sxc151355 *tailp = lip; 5973147Sxc151355 vtailp = &lip->li_val; 5983147Sxc151355 } 5993147Sxc151355 curr = buf + i + 1; 6003147Sxc151355 } 6013147Sxc151355 /* 6023147Sxc151355 * The list must be non-empty and the last character must be ';'. 6033147Sxc151355 */ 6043147Sxc151355 if (*lipp == NULL || lip != NULL) 6053147Sxc151355 goto fail; 6063147Sxc151355 6073147Sxc151355 return (0); 6083147Sxc151355 6093147Sxc151355 fail: 6103147Sxc151355 free_linkprops(*lipp); 6113147Sxc151355 *lipp = NULL; 6123147Sxc151355 return (-1); 6133147Sxc151355 } 6143147Sxc151355 6153147Sxc151355 static boolean_t 6163147Sxc151355 process_linkprop_line(linkprop_db_state_t *lsp, char *buf, 6173147Sxc151355 dladm_status_t *statusp) 6183147Sxc151355 { 6193147Sxc151355 linkprop_info_t *lip = NULL; 6203147Sxc151355 int i, len, llen; 6213147Sxc151355 char *str, *lasts; 6223147Sxc151355 boolean_t cont, nolink = B_FALSE; 6233147Sxc151355 6243147Sxc151355 /* 6253147Sxc151355 * Skip leading spaces, blank lines, and comments. 6263147Sxc151355 */ 6273147Sxc151355 len = strlen(buf); 6283147Sxc151355 for (i = 0; i < len; i++) { 6293147Sxc151355 if (!isspace(buf[i])) 6303147Sxc151355 break; 6313147Sxc151355 } 6323147Sxc151355 if (i == len || buf[i] == '#') 6333147Sxc151355 return (B_TRUE); 6343147Sxc151355 6353147Sxc151355 str = buf + i; 6363147Sxc151355 if (lsp->ls_link != NULL) { 6373147Sxc151355 /* 6383147Sxc151355 * Skip links we're not interested in. 6393147Sxc151355 * Note that strncmp() and isspace() are used here 6403147Sxc151355 * instead of strtok() and strcmp() because we don't 6413147Sxc151355 * want to modify buf in case it does not contain the 6423147Sxc151355 * specified link. 6433147Sxc151355 */ 6443147Sxc151355 llen = strlen(lsp->ls_link); 6453147Sxc151355 if (strncmp(str, lsp->ls_link, llen) != 0 || 6463147Sxc151355 !isspace(str[llen])) 6473147Sxc151355 return (B_TRUE); 6483147Sxc151355 } else { 6493147Sxc151355 /* 6503147Sxc151355 * If a link is not specified, find the link name 6513147Sxc151355 * and assign it to lsp->ls_link. 6523147Sxc151355 */ 6533147Sxc151355 if (strtok_r(str, " \n\t", &lasts) == NULL) 6543147Sxc151355 goto fail; 6553147Sxc151355 6563147Sxc151355 llen = strlen(str); 6573147Sxc151355 lsp->ls_link = str; 6583147Sxc151355 nolink = B_TRUE; 6593147Sxc151355 } 6603147Sxc151355 str += llen + 1; 6613147Sxc151355 if (str >= buf + len) 6623147Sxc151355 goto fail; 6633147Sxc151355 6643147Sxc151355 /* 6653147Sxc151355 * Now find the list of link properties. 6663147Sxc151355 */ 6673147Sxc151355 if ((str = strtok_r(str, " \n\t", &lasts)) == NULL) 6683147Sxc151355 goto fail; 6693147Sxc151355 6703147Sxc151355 if (parse_linkprops(str, &lip) < 0) 6713147Sxc151355 goto fail; 6723147Sxc151355 6733147Sxc151355 cont = (*lsp->ls_op)(lsp, buf, lip, statusp); 6743147Sxc151355 free_linkprops(lip); 6753147Sxc151355 if (nolink) 6763147Sxc151355 lsp->ls_link = NULL; 6773147Sxc151355 return (cont); 6783147Sxc151355 6793147Sxc151355 fail: 6803147Sxc151355 free_linkprops(lip); 6813147Sxc151355 if (nolink) 6823147Sxc151355 lsp->ls_link = NULL; 6833147Sxc151355 6843147Sxc151355 /* 6853147Sxc151355 * Delete corrupted line. 6863147Sxc151355 */ 6873147Sxc151355 buf[0] = '\0'; 6883147Sxc151355 return (B_TRUE); 6893147Sxc151355 } 6903147Sxc151355 6913147Sxc151355 static dladm_status_t 6923147Sxc151355 process_linkprop_db(void *arg, FILE *fp, FILE *nfp) 6933147Sxc151355 { 6943147Sxc151355 linkprop_db_state_t *lsp = arg; 6953147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 6963147Sxc151355 char buf[MAXLINELEN]; 6973147Sxc151355 boolean_t cont = B_TRUE; 6983147Sxc151355 6993147Sxc151355 /* 7003147Sxc151355 * This loop processes each line of the configuration file. 7013147Sxc151355 * buf can potentially be modified by process_linkprop_line(). 7023147Sxc151355 * If this is a write operation and buf is not truncated, buf will 7033147Sxc151355 * be written to disk. process_linkprop_line() will no longer be 7043147Sxc151355 * called after it returns B_FALSE; at which point the remainder 7053147Sxc151355 * of the file will continue to be read and, if necessary, written 7063147Sxc151355 * to disk as well. 7073147Sxc151355 */ 7083147Sxc151355 while (fgets(buf, MAXLINELEN, fp) != NULL) { 7093147Sxc151355 if (cont) 7103147Sxc151355 cont = process_linkprop_line(lsp, buf, &status); 7113147Sxc151355 7123147Sxc151355 if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) { 7133147Sxc151355 status = dladm_errno2status(errno); 7143147Sxc151355 break; 7153147Sxc151355 } 7163147Sxc151355 } 7173147Sxc151355 7183147Sxc151355 if (status != DLADM_STATUS_OK || !cont) 7193147Sxc151355 return (status); 7203147Sxc151355 7213147Sxc151355 if (lsp->ls_op == process_linkprop_set) { 7223147Sxc151355 /* 7233147Sxc151355 * If the specified link is not found above, we add the 7243147Sxc151355 * link and its properties to the configuration file. 7253147Sxc151355 */ 7263147Sxc151355 (void) (*lsp->ls_op)(lsp, buf, NULL, &status); 7273147Sxc151355 if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF) 7283147Sxc151355 status = dladm_errno2status(errno); 7293147Sxc151355 } 7303147Sxc151355 7313147Sxc151355 if (lsp->ls_op == process_linkprop_get) 7323147Sxc151355 status = DLADM_STATUS_NOTFOUND; 7333147Sxc151355 7343147Sxc151355 return (status); 7353147Sxc151355 } 7363147Sxc151355 7373147Sxc151355 #define LINKPROP_RW_DB(statep, writeop) \ 7383147Sxc151355 (i_dladm_rw_db("/etc/dladm/linkprop.conf", \ 7393147Sxc151355 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_linkprop_db, \ 7403147Sxc151355 (statep), (writeop))) 7413147Sxc151355 7423147Sxc151355 static dladm_status_t 7433147Sxc151355 i_dladm_set_prop_db(const char *link, const char *prop_name, 7443147Sxc151355 char **prop_val, uint_t val_cnt) 7453147Sxc151355 { 7463147Sxc151355 linkprop_db_state_t state; 7473147Sxc151355 7483147Sxc151355 state.ls_op = process_linkprop_set; 7493147Sxc151355 state.ls_link = link; 7503147Sxc151355 state.ls_propname = prop_name; 7513147Sxc151355 state.ls_propval = prop_val; 7523147Sxc151355 state.ls_valcntp = &val_cnt; 7533147Sxc151355 7543147Sxc151355 return (LINKPROP_RW_DB(&state, B_TRUE)); 7553147Sxc151355 } 7563147Sxc151355 7573147Sxc151355 static dladm_status_t 7583147Sxc151355 i_dladm_get_prop_db(const char *link, const char *prop_name, 7593147Sxc151355 char **prop_val, uint_t *val_cntp) 7603147Sxc151355 { 7613147Sxc151355 linkprop_db_state_t state; 7623147Sxc151355 7633147Sxc151355 state.ls_op = process_linkprop_get; 7643147Sxc151355 state.ls_link = link; 7653147Sxc151355 state.ls_propname = prop_name; 7663147Sxc151355 state.ls_propval = prop_val; 7673147Sxc151355 state.ls_valcntp = val_cntp; 7683147Sxc151355 7693147Sxc151355 return (LINKPROP_RW_DB(&state, B_FALSE)); 7703147Sxc151355 } 7713147Sxc151355 7723147Sxc151355 dladm_status_t 7733147Sxc151355 dladm_init_linkprop(void) 7743147Sxc151355 { 7753147Sxc151355 linkprop_db_state_t state; 7763147Sxc151355 7773147Sxc151355 state.ls_op = process_linkprop_init; 7783147Sxc151355 state.ls_link = NULL; 7793147Sxc151355 state.ls_propname = NULL; 7803147Sxc151355 state.ls_propval = NULL; 7813147Sxc151355 state.ls_valcntp = NULL; 7823147Sxc151355 7833147Sxc151355 return (LINKPROP_RW_DB(&state, B_FALSE)); 7843147Sxc151355 } 785*3448Sdh155122 786*3448Sdh155122 static dladm_status_t 787*3448Sdh155122 i_dladm_get_zoneid(const char *link, zoneid_t *zidp) 788*3448Sdh155122 { 789*3448Sdh155122 int fd; 790*3448Sdh155122 dld_hold_vlan_t dhv; 791*3448Sdh155122 792*3448Sdh155122 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 793*3448Sdh155122 return (dladm_errno2status(errno)); 794*3448Sdh155122 795*3448Sdh155122 bzero(&dhv, sizeof (dld_hold_vlan_t)); 796*3448Sdh155122 (void) strlcpy(dhv.dhv_name, link, IFNAMSIZ); 797*3448Sdh155122 dhv.dhv_zid = -1; 798*3448Sdh155122 799*3448Sdh155122 if (i_dladm_ioctl(fd, DLDIOCZIDGET, &dhv, sizeof (dhv)) < 0 && 800*3448Sdh155122 errno != ENOENT) { 801*3448Sdh155122 dladm_status_t status = dladm_errno2status(errno); 802*3448Sdh155122 803*3448Sdh155122 (void) close(fd); 804*3448Sdh155122 return (status); 805*3448Sdh155122 } 806*3448Sdh155122 807*3448Sdh155122 if (errno == ENOENT) 808*3448Sdh155122 *zidp = GLOBAL_ZONEID; 809*3448Sdh155122 else 810*3448Sdh155122 *zidp = dhv.dhv_zid; 811*3448Sdh155122 812*3448Sdh155122 (void) close(fd); 813*3448Sdh155122 return (DLADM_STATUS_OK); 814*3448Sdh155122 } 815*3448Sdh155122 816*3448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 817*3448Sdh155122 818*3448Sdh155122 static int 819*3448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 820*3448Sdh155122 { 821*3448Sdh155122 char root[MAXPATHLEN]; 822*3448Sdh155122 zone_get_devroot_t real_zone_get_devroot; 823*3448Sdh155122 void *dlhandle; 824*3448Sdh155122 void *sym; 825*3448Sdh155122 int ret; 826*3448Sdh155122 827*3448Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 828*3448Sdh155122 return (-1); 829*3448Sdh155122 830*3448Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 831*3448Sdh155122 (void) dlclose(dlhandle); 832*3448Sdh155122 return (-1); 833*3448Sdh155122 } 834*3448Sdh155122 835*3448Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 836*3448Sdh155122 837*3448Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 838*3448Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 839*3448Sdh155122 (void) dlclose(dlhandle); 840*3448Sdh155122 return (ret); 841*3448Sdh155122 } 842*3448Sdh155122 843*3448Sdh155122 static dladm_status_t 844*3448Sdh155122 i_dladm_add_deventry(zoneid_t zid, const char *link) 845*3448Sdh155122 { 846*3448Sdh155122 char path[MAXPATHLEN]; 847*3448Sdh155122 di_prof_t prof = NULL; 848*3448Sdh155122 char zone_name[ZONENAME_MAX]; 849*3448Sdh155122 dladm_status_t status; 850*3448Sdh155122 851*3448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 852*3448Sdh155122 return (dladm_errno2status(errno)); 853*3448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 854*3448Sdh155122 return (dladm_errno2status(errno)); 855*3448Sdh155122 if (di_prof_init(path, &prof) != 0) 856*3448Sdh155122 return (dladm_errno2status(errno)); 857*3448Sdh155122 858*3448Sdh155122 status = DLADM_STATUS_OK; 859*3448Sdh155122 if (di_prof_add_dev(prof, link) != 0) { 860*3448Sdh155122 status = dladm_errno2status(errno); 861*3448Sdh155122 goto cleanup; 862*3448Sdh155122 } 863*3448Sdh155122 if (di_prof_commit(prof) != 0) 864*3448Sdh155122 status = dladm_errno2status(errno); 865*3448Sdh155122 cleanup: 866*3448Sdh155122 if (prof) 867*3448Sdh155122 di_prof_fini(prof); 868*3448Sdh155122 869*3448Sdh155122 return (status); 870*3448Sdh155122 } 871*3448Sdh155122 872*3448Sdh155122 static dladm_status_t 873*3448Sdh155122 i_dladm_remove_deventry(zoneid_t zid, const char *link) 874*3448Sdh155122 { 875*3448Sdh155122 char path[MAXPATHLEN]; 876*3448Sdh155122 di_prof_t prof = NULL; 877*3448Sdh155122 char zone_name[ZONENAME_MAX]; 878*3448Sdh155122 dladm_status_t status; 879*3448Sdh155122 880*3448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 881*3448Sdh155122 return (dladm_errno2status(errno)); 882*3448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 883*3448Sdh155122 return (dladm_errno2status(errno)); 884*3448Sdh155122 if (di_prof_init(path, &prof) != 0) 885*3448Sdh155122 return (dladm_errno2status(errno)); 886*3448Sdh155122 887*3448Sdh155122 status = DLADM_STATUS_OK; 888*3448Sdh155122 if (di_prof_add_exclude(prof, link) != 0) { 889*3448Sdh155122 status = dladm_errno2status(errno); 890*3448Sdh155122 goto cleanup; 891*3448Sdh155122 } 892*3448Sdh155122 if (di_prof_commit(prof) != 0) 893*3448Sdh155122 status = dladm_errno2status(errno); 894*3448Sdh155122 cleanup: 895*3448Sdh155122 if (prof) 896*3448Sdh155122 di_prof_fini(prof); 897*3448Sdh155122 898*3448Sdh155122 return (status); 899*3448Sdh155122 } 900*3448Sdh155122 901*3448Sdh155122 static dladm_status_t 902*3448Sdh155122 do_get_zone(const char *link, char **prop_val, uint_t *val_cnt) 903*3448Sdh155122 { 904*3448Sdh155122 char zone_name[ZONENAME_MAX]; 905*3448Sdh155122 zoneid_t zid; 906*3448Sdh155122 dladm_status_t status; 907*3448Sdh155122 908*3448Sdh155122 status = i_dladm_get_zoneid(link, &zid); 909*3448Sdh155122 if (status != DLADM_STATUS_OK) 910*3448Sdh155122 return (status); 911*3448Sdh155122 912*3448Sdh155122 *val_cnt = 1; 913*3448Sdh155122 if (zid != GLOBAL_ZONEID) { 914*3448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 915*3448Sdh155122 return (dladm_errno2status(errno)); 916*3448Sdh155122 917*3448Sdh155122 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 918*3448Sdh155122 } else { 919*3448Sdh155122 *prop_val[0] = '\0'; 920*3448Sdh155122 } 921*3448Sdh155122 922*3448Sdh155122 return (DLADM_STATUS_OK); 923*3448Sdh155122 } 924*3448Sdh155122 925*3448Sdh155122 static dladm_status_t 926*3448Sdh155122 do_set_zone(const char *link, val_desc_t *vdp, uint_t val_cnt) 927*3448Sdh155122 { 928*3448Sdh155122 dladm_status_t status; 929*3448Sdh155122 zoneid_t zid_old, zid_new; 930*3448Sdh155122 char buff[IF_NAMESIZE + 1]; 931*3448Sdh155122 struct stat st; 932*3448Sdh155122 933*3448Sdh155122 if (val_cnt != 1) 934*3448Sdh155122 return (DLADM_STATUS_BADVALCNT); 935*3448Sdh155122 936*3448Sdh155122 status = i_dladm_get_zoneid(link, &zid_old); 937*3448Sdh155122 if (status != DLADM_STATUS_OK) 938*3448Sdh155122 return (status); 939*3448Sdh155122 940*3448Sdh155122 /* Do nothing if setting to current value */ 941*3448Sdh155122 zid_new = (zoneid_t)vdp->vd_val; 942*3448Sdh155122 if (zid_new == zid_old) 943*3448Sdh155122 return (DLADM_STATUS_OK); 944*3448Sdh155122 945*3448Sdh155122 /* Do a stat to get the vlan created by MAC, if it's not there */ 946*3448Sdh155122 (void) strcpy(buff, "/dev/"); 947*3448Sdh155122 (void) strlcat(buff, link, IF_NAMESIZE); 948*3448Sdh155122 (void) stat(buff, &st); 949*3448Sdh155122 950*3448Sdh155122 if (zid_old != GLOBAL_ZONEID) { 951*3448Sdh155122 if (dladm_rele_link(link, GLOBAL_ZONEID, B_TRUE) < 0) 952*3448Sdh155122 return (dladm_errno2status(errno)); 953*3448Sdh155122 954*3448Sdh155122 if (zone_remove_datalink(zid_old, (char *)link) != 0 && 955*3448Sdh155122 errno != ENXIO) { 956*3448Sdh155122 status = dladm_errno2status(errno); 957*3448Sdh155122 goto rollback1; 958*3448Sdh155122 } 959*3448Sdh155122 960*3448Sdh155122 status = i_dladm_remove_deventry(zid_old, link); 961*3448Sdh155122 if (status != DLADM_STATUS_OK) 962*3448Sdh155122 goto rollback2; 963*3448Sdh155122 } 964*3448Sdh155122 965*3448Sdh155122 if (zid_new != GLOBAL_ZONEID) { 966*3448Sdh155122 if (zone_add_datalink(zid_new, (char *)link) != 0) { 967*3448Sdh155122 status = dladm_errno2status(errno); 968*3448Sdh155122 goto rollback3; 969*3448Sdh155122 } 970*3448Sdh155122 971*3448Sdh155122 if (dladm_hold_link(link, zid_new, B_TRUE) < 0) { 972*3448Sdh155122 (void) zone_remove_datalink(zid_new, (char *)link); 973*3448Sdh155122 status = dladm_errno2status(errno); 974*3448Sdh155122 goto rollback3; 975*3448Sdh155122 } 976*3448Sdh155122 977*3448Sdh155122 status = i_dladm_add_deventry(zid_new, link); 978*3448Sdh155122 if (status != DLADM_STATUS_OK) { 979*3448Sdh155122 (void) dladm_rele_link(link, GLOBAL_ZONEID, B_FALSE); 980*3448Sdh155122 (void) zone_remove_datalink(zid_new, (char *)link); 981*3448Sdh155122 goto rollback3; 982*3448Sdh155122 } 983*3448Sdh155122 } 984*3448Sdh155122 return (DLADM_STATUS_OK); 985*3448Sdh155122 986*3448Sdh155122 rollback3: 987*3448Sdh155122 if (zid_old != GLOBAL_ZONEID) 988*3448Sdh155122 (void) i_dladm_add_deventry(zid_old, link); 989*3448Sdh155122 rollback2: 990*3448Sdh155122 if (zid_old != GLOBAL_ZONEID) 991*3448Sdh155122 (void) zone_add_datalink(zid_old, (char *)link); 992*3448Sdh155122 rollback1: 993*3448Sdh155122 (void) dladm_hold_link(link, zid_old, B_FALSE); 994*3448Sdh155122 cleanexit: 995*3448Sdh155122 return (status); 996*3448Sdh155122 } 997*3448Sdh155122 998*3448Sdh155122 /* ARGSUSED */ 999*3448Sdh155122 static dladm_status_t 1000*3448Sdh155122 do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 1001*3448Sdh155122 val_desc_t **vdpp) 1002*3448Sdh155122 { 1003*3448Sdh155122 zoneid_t zid; 1004*3448Sdh155122 val_desc_t *vdp = NULL; 1005*3448Sdh155122 1006*3448Sdh155122 if (val_cnt != 1) 1007*3448Sdh155122 return (DLADM_STATUS_BADVALCNT); 1008*3448Sdh155122 1009*3448Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 1010*3448Sdh155122 return (DLADM_STATUS_BADVAL); 1011*3448Sdh155122 1012*3448Sdh155122 if (zid != GLOBAL_ZONEID) { 1013*3448Sdh155122 ushort_t flags; 1014*3448Sdh155122 1015*3448Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 1016*3448Sdh155122 sizeof (flags)) < 0) { 1017*3448Sdh155122 return (dladm_errno2status(errno)); 1018*3448Sdh155122 } 1019*3448Sdh155122 1020*3448Sdh155122 if (!(flags & ZF_NET_EXCL)) { 1021*3448Sdh155122 return (DLADM_STATUS_BADVAL); 1022*3448Sdh155122 } 1023*3448Sdh155122 } 1024*3448Sdh155122 1025*3448Sdh155122 vdp = malloc(sizeof (val_desc_t)); 1026*3448Sdh155122 if (vdp == NULL) 1027*3448Sdh155122 return (DLADM_STATUS_NOMEM); 1028*3448Sdh155122 1029*3448Sdh155122 vdp->vd_val = (void *)zid; 1030*3448Sdh155122 *vdpp = vdp; 1031*3448Sdh155122 return (DLADM_STATUS_OK); 1032*3448Sdh155122 } 1033*3448Sdh155122 1034*3448Sdh155122 static dladm_status_t 1035*3448Sdh155122 i_dladm_get_prop_temp(const char *link, dladm_prop_type_t type, 1036*3448Sdh155122 const char *prop_name, char **prop_val, uint_t *val_cntp) 1037*3448Sdh155122 { 1038*3448Sdh155122 int i; 1039*3448Sdh155122 dladm_status_t status; 1040*3448Sdh155122 uint_t cnt; 1041*3448Sdh155122 prop_desc_t *pdp; 1042*3448Sdh155122 1043*3448Sdh155122 if (link == NULL || prop_name == NULL || prop_val == NULL || 1044*3448Sdh155122 val_cntp == NULL || *val_cntp == 0) 1045*3448Sdh155122 return (DLADM_STATUS_BADARG); 1046*3448Sdh155122 1047*3448Sdh155122 for (i = 0; i < MAX_PROPS; i++) 1048*3448Sdh155122 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 1049*3448Sdh155122 break; 1050*3448Sdh155122 1051*3448Sdh155122 if (i == MAX_PROPS) 1052*3448Sdh155122 return (DLADM_STATUS_NOTFOUND); 1053*3448Sdh155122 1054*3448Sdh155122 pdp = &prop_table[i]; 1055*3448Sdh155122 status = DLADM_STATUS_OK; 1056*3448Sdh155122 1057*3448Sdh155122 switch (type) { 1058*3448Sdh155122 case DLADM_PROP_VAL_CURRENT: 1059*3448Sdh155122 status = pdp->pd_get(link, prop_val, val_cntp); 1060*3448Sdh155122 break; 1061*3448Sdh155122 case DLADM_PROP_VAL_DEFAULT: 1062*3448Sdh155122 if (pdp->pd_defval.vd_name == NULL) { 1063*3448Sdh155122 status = DLADM_STATUS_NOTSUP; 1064*3448Sdh155122 break; 1065*3448Sdh155122 } 1066*3448Sdh155122 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 1067*3448Sdh155122 *val_cntp = 1; 1068*3448Sdh155122 break; 1069*3448Sdh155122 1070*3448Sdh155122 case DLADM_PROP_VAL_MODIFIABLE: 1071*3448Sdh155122 if (pdp->pd_getmod != NULL) { 1072*3448Sdh155122 status = pdp->pd_getmod(link, prop_val, val_cntp); 1073*3448Sdh155122 break; 1074*3448Sdh155122 } 1075*3448Sdh155122 cnt = pdp->pd_nmodval; 1076*3448Sdh155122 if (cnt == 0) { 1077*3448Sdh155122 status = DLADM_STATUS_NOTSUP; 1078*3448Sdh155122 } else if (cnt > *val_cntp) { 1079*3448Sdh155122 status = DLADM_STATUS_TOOSMALL; 1080*3448Sdh155122 } else { 1081*3448Sdh155122 for (i = 0; i < cnt; i++) { 1082*3448Sdh155122 (void) strcpy(prop_val[i], 1083*3448Sdh155122 pdp->pd_modval[i].vd_name); 1084*3448Sdh155122 } 1085*3448Sdh155122 *val_cntp = cnt; 1086*3448Sdh155122 } 1087*3448Sdh155122 break; 1088*3448Sdh155122 default: 1089*3448Sdh155122 status = DLADM_STATUS_BADARG; 1090*3448Sdh155122 break; 1091*3448Sdh155122 } 1092*3448Sdh155122 1093*3448Sdh155122 return (status); 1094*3448Sdh155122 } 1095*3448Sdh155122 1096*3448Sdh155122 static dladm_status_t 1097*3448Sdh155122 i_dladm_set_one_prop_temp(const char *link, prop_desc_t *pdp, char **prop_val, 1098*3448Sdh155122 uint_t val_cnt, uint_t flags) 1099*3448Sdh155122 { 1100*3448Sdh155122 dladm_status_t status; 1101*3448Sdh155122 val_desc_t *vdp = NULL; 1102*3448Sdh155122 uint_t cnt; 1103*3448Sdh155122 1104*3448Sdh155122 if (pdp->pd_temponly && (flags & DLADM_OPT_PERSIST) != 0) 1105*3448Sdh155122 return (DLADM_STATUS_TEMPONLY); 1106*3448Sdh155122 1107*3448Sdh155122 if (pdp->pd_set == NULL) 1108*3448Sdh155122 return (DLADM_STATUS_PROPRDONLY); 1109*3448Sdh155122 1110*3448Sdh155122 if (prop_val != NULL) { 1111*3448Sdh155122 if (pdp->pd_check != NULL) 1112*3448Sdh155122 status = pdp->pd_check(pdp, prop_val, val_cnt, &vdp); 1113*3448Sdh155122 else 1114*3448Sdh155122 status = DLADM_STATUS_BADARG; 1115*3448Sdh155122 1116*3448Sdh155122 if (status != DLADM_STATUS_OK) 1117*3448Sdh155122 return (status); 1118*3448Sdh155122 1119*3448Sdh155122 cnt = val_cnt; 1120*3448Sdh155122 } else { 1121*3448Sdh155122 if (pdp->pd_defval.vd_name == NULL) 1122*3448Sdh155122 return (DLADM_STATUS_NOTSUP); 1123*3448Sdh155122 1124*3448Sdh155122 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 1125*3448Sdh155122 return (DLADM_STATUS_NOMEM); 1126*3448Sdh155122 1127*3448Sdh155122 (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t)); 1128*3448Sdh155122 cnt = 1; 1129*3448Sdh155122 } 1130*3448Sdh155122 1131*3448Sdh155122 status = pdp->pd_set(link, vdp, cnt); 1132*3448Sdh155122 1133*3448Sdh155122 free(vdp); 1134*3448Sdh155122 return (status); 1135*3448Sdh155122 } 1136*3448Sdh155122 1137*3448Sdh155122 static dladm_status_t 1138*3448Sdh155122 i_dladm_set_prop_temp(const char *link, const char *prop_name, char **prop_val, 1139*3448Sdh155122 uint_t val_cnt, uint_t flags, char **errprop) 1140*3448Sdh155122 { 1141*3448Sdh155122 int i; 1142*3448Sdh155122 dladm_status_t status = DLADM_STATUS_OK; 1143*3448Sdh155122 boolean_t found = B_FALSE; 1144*3448Sdh155122 1145*3448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 1146*3448Sdh155122 prop_desc_t *pdp = &prop_table[i]; 1147*3448Sdh155122 dladm_status_t s; 1148*3448Sdh155122 1149*3448Sdh155122 if (prop_name != NULL && 1150*3448Sdh155122 (strcasecmp(prop_name, pdp->pd_name) != 0)) 1151*3448Sdh155122 continue; 1152*3448Sdh155122 1153*3448Sdh155122 found = B_TRUE; 1154*3448Sdh155122 s = i_dladm_set_one_prop_temp(link, pdp, prop_val, val_cnt, 1155*3448Sdh155122 flags); 1156*3448Sdh155122 1157*3448Sdh155122 if (prop_name != NULL) { 1158*3448Sdh155122 status = s; 1159*3448Sdh155122 break; 1160*3448Sdh155122 } else { 1161*3448Sdh155122 if (s != DLADM_STATUS_OK && 1162*3448Sdh155122 s != DLADM_STATUS_NOTSUP) { 1163*3448Sdh155122 if (errprop != NULL) 1164*3448Sdh155122 *errprop = pdp->pd_name; 1165*3448Sdh155122 status = s; 1166*3448Sdh155122 break; 1167*3448Sdh155122 } 1168*3448Sdh155122 } 1169*3448Sdh155122 } 1170*3448Sdh155122 1171*3448Sdh155122 if (!found) 1172*3448Sdh155122 status = DLADM_STATUS_NOTFOUND; 1173*3448Sdh155122 1174*3448Sdh155122 return (status); 1175*3448Sdh155122 } 1176*3448Sdh155122 1177*3448Sdh155122 static boolean_t 1178*3448Sdh155122 i_dladm_is_prop_temponly(const char *prop_name, char **errprop) 1179*3448Sdh155122 { 1180*3448Sdh155122 int i; 1181*3448Sdh155122 1182*3448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 1183*3448Sdh155122 prop_desc_t *pdp = &prop_table[i]; 1184*3448Sdh155122 1185*3448Sdh155122 if (prop_name != NULL && 1186*3448Sdh155122 (strcasecmp(prop_name, pdp->pd_name) != 0)) 1187*3448Sdh155122 continue; 1188*3448Sdh155122 1189*3448Sdh155122 if (errprop != NULL) 1190*3448Sdh155122 *errprop = pdp->pd_name; 1191*3448Sdh155122 1192*3448Sdh155122 if (pdp->pd_temponly) 1193*3448Sdh155122 return (B_TRUE); 1194*3448Sdh155122 } 1195*3448Sdh155122 1196*3448Sdh155122 return (B_FALSE); 1197*3448Sdh155122 } 1198*3448Sdh155122 1199*3448Sdh155122 boolean_t 1200*3448Sdh155122 dladm_is_prop_temponly(const char *prop_name, char **errprop) 1201*3448Sdh155122 { 1202*3448Sdh155122 return (i_dladm_is_prop_temponly(prop_name, errprop)); 1203*3448Sdh155122 } 1204