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 /* 223448Sdh155122 * 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> 323448Sdh155122 #include <sys/types.h> 333147Sxc151355 #include <sys/stat.h> 343448Sdh155122 #include <sys/dld.h> 353448Sdh155122 #include <sys/zone.h> 363448Sdh155122 #include <fcntl.h> 373448Sdh155122 #include <unistd.h> 383448Sdh155122 #include <libdevinfo.h> 393448Sdh155122 #include <zone.h> 40*3871Syz147064 #include <libdllink.h> 413147Sxc151355 #include <libdladm_impl.h> 42*3871Syz147064 #include <libdlwlan.h> 433448Sdh155122 #include <dlfcn.h> 443448Sdh155122 #include <link.h> 453448Sdh155122 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 *); 503448Sdh155122 static dladm_status_t i_dladm_get_prop_temp(const char *, dladm_prop_type_t, 513448Sdh155122 const char *, char **, uint_t *); 523448Sdh155122 static dladm_status_t i_dladm_set_prop_temp(const char *, const char *, 533448Sdh155122 char **, uint_t, uint_t, char **); 543448Sdh155122 static boolean_t i_dladm_is_prop_temponly(const char *prop_name, 553448Sdh155122 char **); 563448Sdh155122 573448Sdh155122 typedef struct val_desc { 583448Sdh155122 char *vd_name; 593448Sdh155122 void *vd_val; 603448Sdh155122 } val_desc_t; 613448Sdh155122 623448Sdh155122 struct prop_desc; 633448Sdh155122 643448Sdh155122 typedef dladm_status_t pd_getf_t(const char *, char **, uint_t *); 653448Sdh155122 typedef dladm_status_t pd_setf_t(const char *, val_desc_t *, uint_t); 663448Sdh155122 typedef dladm_status_t pd_checkf_t(struct prop_desc *, char **, 673448Sdh155122 uint_t, val_desc_t **); 683448Sdh155122 693448Sdh155122 static pd_getf_t do_get_zone; 703448Sdh155122 static pd_setf_t do_set_zone; 713448Sdh155122 static pd_checkf_t do_check_zone; 723448Sdh155122 733448Sdh155122 typedef struct prop_desc { 743448Sdh155122 char *pd_name; 753448Sdh155122 val_desc_t pd_defval; 763448Sdh155122 val_desc_t *pd_modval; 773448Sdh155122 uint_t pd_nmodval; 783448Sdh155122 boolean_t pd_temponly; 793448Sdh155122 pd_setf_t *pd_set; 803448Sdh155122 pd_getf_t *pd_getmod; 813448Sdh155122 pd_getf_t *pd_get; 823448Sdh155122 pd_checkf_t *pd_check; 833448Sdh155122 } prop_desc_t; 843448Sdh155122 853448Sdh155122 static prop_desc_t prop_table[] = { 863448Sdh155122 { "zone", { "", NULL }, NULL, 0, B_TRUE, 873448Sdh155122 do_set_zone, NULL, 883448Sdh155122 do_get_zone, do_check_zone} 893448Sdh155122 }; 903448Sdh155122 913448Sdh155122 #define MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) 923147Sxc151355 933147Sxc151355 dladm_status_t 943147Sxc151355 dladm_set_prop(const char *link, const char *prop_name, char **prop_val, 953448Sdh155122 uint_t val_cnt, uint_t flags, char **errprop) 963147Sxc151355 { 973147Sxc151355 dladm_status_t status = DLADM_STATUS_BADARG; 983147Sxc151355 993147Sxc151355 if (link == NULL || (prop_val == NULL && val_cnt > 0) || 1003147Sxc151355 (prop_val != NULL && val_cnt == 0) || flags == 0) 1013147Sxc151355 return (DLADM_STATUS_BADARG); 1023147Sxc151355 1033147Sxc151355 if ((flags & DLADM_OPT_TEMP) != 0) { 1043448Sdh155122 status = i_dladm_set_prop_temp(link, prop_name, prop_val, 1053448Sdh155122 val_cnt, flags, errprop); 1063448Sdh155122 if (status == DLADM_STATUS_TEMPONLY && 1073448Sdh155122 (flags & DLADM_OPT_PERSIST) != 0) 1083448Sdh155122 return (DLADM_STATUS_TEMPONLY); 1093448Sdh155122 1103448Sdh155122 if (status == DLADM_STATUS_NOTFOUND) { 1113448Sdh155122 status = DLADM_STATUS_BADARG; 112*3871Syz147064 if (dladm_wlan_is_valid(link)) { 113*3871Syz147064 status = dladm_wlan_set_prop(link, prop_name, 114*3871Syz147064 prop_val, val_cnt, errprop); 1153448Sdh155122 } 1163147Sxc151355 } 1173147Sxc151355 if (status != DLADM_STATUS_OK) 1183147Sxc151355 return (status); 1193147Sxc151355 } 1203147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) { 1213448Sdh155122 if (i_dladm_is_prop_temponly(prop_name, errprop)) 1223448Sdh155122 return (DLADM_STATUS_TEMPONLY); 1233448Sdh155122 1243147Sxc151355 status = i_dladm_set_prop_db(link, prop_name, 1253147Sxc151355 prop_val, val_cnt); 1263147Sxc151355 } 1273147Sxc151355 return (status); 1283147Sxc151355 } 1293147Sxc151355 1303147Sxc151355 dladm_status_t 1313147Sxc151355 dladm_walk_prop(const char *link, void *arg, 1323147Sxc151355 boolean_t (*func)(void *, const char *)) 1333147Sxc151355 { 1343448Sdh155122 int i; 1353448Sdh155122 1363147Sxc151355 if (link == NULL || func == NULL) 1373147Sxc151355 return (DLADM_STATUS_BADARG); 1383147Sxc151355 1393448Sdh155122 /* For wifi links, show wifi properties first */ 140*3871Syz147064 if (dladm_wlan_is_valid(link)) { 1413448Sdh155122 dladm_status_t status; 1423448Sdh155122 143*3871Syz147064 status = dladm_wlan_walk_prop(link, arg, func); 1443448Sdh155122 if (status != DLADM_STATUS_OK) 1453448Sdh155122 return (status); 1463147Sxc151355 } 1473448Sdh155122 1483448Sdh155122 /* Then show data-link properties if there are any */ 1493448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 1503448Sdh155122 if (!func(arg, prop_table[i].pd_name)) 1513448Sdh155122 break; 1523448Sdh155122 } 1533448Sdh155122 return (DLADM_STATUS_OK); 1543147Sxc151355 } 1553147Sxc151355 1563147Sxc151355 dladm_status_t 1573147Sxc151355 dladm_get_prop(const char *link, dladm_prop_type_t type, 1583147Sxc151355 const char *prop_name, char **prop_val, uint_t *val_cntp) 1593147Sxc151355 { 1603448Sdh155122 dladm_status_t status; 1613448Sdh155122 1623147Sxc151355 if (link == NULL || prop_name == NULL || prop_val == NULL || 1633147Sxc151355 val_cntp == NULL || *val_cntp == 0) 1643147Sxc151355 return (DLADM_STATUS_BADARG); 1653147Sxc151355 1663147Sxc151355 if (type == DLADM_PROP_VAL_PERSISTENT) { 167*3871Syz147064 if (i_dladm_is_prop_temponly(prop_name, NULL)) 168*3871Syz147064 return (DLADM_STATUS_TEMPONLY); 1693147Sxc151355 return (i_dladm_get_prop_db(link, prop_name, 1703147Sxc151355 prop_val, val_cntp)); 1713147Sxc151355 } 1723147Sxc151355 1733448Sdh155122 status = i_dladm_get_prop_temp(link, type, prop_name, 1743448Sdh155122 prop_val, val_cntp); 1753448Sdh155122 if (status != DLADM_STATUS_NOTFOUND) 1763448Sdh155122 return (status); 1773448Sdh155122 178*3871Syz147064 if (dladm_wlan_is_valid(link)) { 179*3871Syz147064 return (dladm_wlan_get_prop(link, type, prop_name, 180*3871Syz147064 prop_val, val_cntp)); 1813147Sxc151355 } 1823147Sxc151355 return (DLADM_STATUS_BADARG); 1833147Sxc151355 } 1843147Sxc151355 1853147Sxc151355 /* 1863147Sxc151355 * Data structures used for implementing persistent link properties 1873147Sxc151355 */ 1883147Sxc151355 typedef struct linkprop_val { 1893147Sxc151355 const char *lv_name; 1903147Sxc151355 struct linkprop_val *lv_nextval; 1913147Sxc151355 } linkprop_val_t; 1923147Sxc151355 1933147Sxc151355 typedef struct linkprop_info { 1943147Sxc151355 const char *li_name; 1953147Sxc151355 struct linkprop_info *li_nextprop; 1963147Sxc151355 struct linkprop_val *li_val; 1973147Sxc151355 } linkprop_info_t; 1983147Sxc151355 1993147Sxc151355 typedef struct linkprop_db_state linkprop_db_state_t; 2003147Sxc151355 2013147Sxc151355 typedef boolean_t (*linkprop_db_op_t)(linkprop_db_state_t *, 2023147Sxc151355 char *, linkprop_info_t *, dladm_status_t *); 2033147Sxc151355 2043147Sxc151355 struct linkprop_db_state { 2053147Sxc151355 linkprop_db_op_t ls_op; 2063147Sxc151355 const char *ls_link; 2073147Sxc151355 const char *ls_propname; 2083147Sxc151355 char **ls_propval; 2093147Sxc151355 uint_t *ls_valcntp; 2103147Sxc151355 }; 2113147Sxc151355 2123147Sxc151355 static void 2133147Sxc151355 free_linkprops(linkprop_info_t *lip) 2143147Sxc151355 { 2153147Sxc151355 linkprop_info_t *lip_next; 2163147Sxc151355 linkprop_val_t *lvp, *lvp_next; 2173147Sxc151355 2183147Sxc151355 for (; lip != NULL; lip = lip_next) { 2193147Sxc151355 lip_next = lip->li_nextprop; 2203147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) { 2213147Sxc151355 lvp_next = lvp->lv_nextval; 2223147Sxc151355 free(lvp); 2233147Sxc151355 } 2243147Sxc151355 free(lip); 2253147Sxc151355 } 2263147Sxc151355 } 2273147Sxc151355 2283147Sxc151355 /* 2293147Sxc151355 * Generate an entry in the link property database. 2303147Sxc151355 * Each entry has this format: 2313147Sxc151355 * <linkname> <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>; 2323147Sxc151355 */ 2333147Sxc151355 static void 2343147Sxc151355 generate_linkprop_line(linkprop_db_state_t *lsp, char *buf, 2353147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 2363147Sxc151355 { 2373147Sxc151355 char tmpbuf[MAXLINELEN]; 2383147Sxc151355 char *ptr, *lim = tmpbuf + MAXLINELEN; 2393147Sxc151355 linkprop_info_t *lip = listp; 2403147Sxc151355 linkprop_val_t *lvp = NULL; 2413147Sxc151355 2423147Sxc151355 /* 2433147Sxc151355 * Delete line if there are no properties left. 2443147Sxc151355 */ 2453147Sxc151355 if (lip == NULL || 2463147Sxc151355 (lip->li_val == NULL && lip->li_nextprop == NULL)) { 2473147Sxc151355 buf[0] = '\0'; 2483147Sxc151355 return; 2493147Sxc151355 } 2503147Sxc151355 ptr = tmpbuf; 2513147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", lsp->ls_link); 2523147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 2533147Sxc151355 /* 2543147Sxc151355 * Skip properties without values. 2553147Sxc151355 */ 2563147Sxc151355 if (lip->li_val == NULL) 2573147Sxc151355 continue; 2583147Sxc151355 2593147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s=", lip->li_name); 2603147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) { 2613147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s%c", 2623147Sxc151355 lvp->lv_name, 2633147Sxc151355 ((lvp->lv_nextval == NULL) ? ';' : ',')); 2643147Sxc151355 } 2653147Sxc151355 } 2663147Sxc151355 if (ptr > lim) { 2673147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 2683147Sxc151355 return; 2693147Sxc151355 } 2703147Sxc151355 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf); 2713147Sxc151355 } 2723147Sxc151355 2733147Sxc151355 /* 2743147Sxc151355 * This function is used to update or create an entry in the persistent db. 2753147Sxc151355 * process_linkprop_db() will first scan the db for an entry matching the 2763147Sxc151355 * specified link. If a match is found, this function is invoked with the 2773147Sxc151355 * entry's contents (buf) and its linked-list representation (listp). lsp 2783147Sxc151355 * holds the name and values of the property to be added or updated; this 2793147Sxc151355 * information will be merged with listp. Subsequently, an updated entry 2803147Sxc151355 * will be written to buf, which will in turn be written to disk by 2813147Sxc151355 * process_linkprop_db(). If no entry matches the specified link, listp 2823147Sxc151355 * will be NULL; a new entry will be generated in this case and it will 2833147Sxc151355 * contain only the property information in lsp. 2843147Sxc151355 */ 2853147Sxc151355 static boolean_t 2863147Sxc151355 process_linkprop_set(linkprop_db_state_t *lsp, char *buf, 2873147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 2883147Sxc151355 { 2893147Sxc151355 dladm_status_t status; 2903147Sxc151355 linkprop_info_t *lastp = NULL, *lip = listp, *nlip = NULL; 2913147Sxc151355 linkprop_val_t **lvpp; 2923147Sxc151355 int i; 2933147Sxc151355 2943147Sxc151355 if (lsp->ls_propname == NULL) { 2953147Sxc151355 buf[0] = '\0'; 2963147Sxc151355 return (B_FALSE); 2973147Sxc151355 } 2983147Sxc151355 2993147Sxc151355 /* 3003147Sxc151355 * Find the linkprop we want to change. 3013147Sxc151355 */ 3023147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 3033147Sxc151355 if (strcmp(lip->li_name, lsp->ls_propname) == 0) 3043147Sxc151355 break; 3053147Sxc151355 3063147Sxc151355 lastp = lip; 3073147Sxc151355 } 3083147Sxc151355 3093147Sxc151355 if (lip == NULL) { 3103147Sxc151355 /* 3113147Sxc151355 * If the linkprop is not found, append it to the list. 3123147Sxc151355 */ 3133147Sxc151355 if ((nlip = malloc(sizeof (linkprop_info_t))) == NULL) { 3143147Sxc151355 status = DLADM_STATUS_NOMEM; 3153147Sxc151355 goto fail; 3163147Sxc151355 } 3173147Sxc151355 /* 3183147Sxc151355 * nlip will need to be freed later if there is no list to 3193147Sxc151355 * append to. 3203147Sxc151355 */ 3213147Sxc151355 if (lastp != NULL) 3223147Sxc151355 lastp->li_nextprop = nlip; 3233147Sxc151355 nlip->li_name = lsp->ls_propname; 3243147Sxc151355 nlip->li_nextprop = NULL; 3253147Sxc151355 nlip->li_val = NULL; 3263147Sxc151355 lvpp = &nlip->li_val; 3273147Sxc151355 } else { 3283147Sxc151355 linkprop_val_t *lvp, *lvp_next; 3293147Sxc151355 3303147Sxc151355 /* 3313147Sxc151355 * If the linkprop is found, delete the existing values from it. 3323147Sxc151355 */ 3333147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) { 3343147Sxc151355 lvp_next = lvp->lv_nextval; 3353147Sxc151355 free(lvp); 3363147Sxc151355 } 3373147Sxc151355 lip->li_val = NULL; 3383147Sxc151355 lvpp = &lip->li_val; 3393147Sxc151355 } 3403147Sxc151355 3413147Sxc151355 /* 3423147Sxc151355 * Fill our linkprop with the specified values. 3433147Sxc151355 */ 3443147Sxc151355 for (i = 0; i < *lsp->ls_valcntp; i++) { 3453147Sxc151355 if ((*lvpp = malloc(sizeof (linkprop_val_t))) == NULL) { 3463147Sxc151355 status = DLADM_STATUS_NOMEM; 3473147Sxc151355 goto fail; 3483147Sxc151355 } 3493147Sxc151355 (*lvpp)->lv_name = lsp->ls_propval[i]; 3503147Sxc151355 (*lvpp)->lv_nextval = NULL; 3513147Sxc151355 lvpp = &(*lvpp)->lv_nextval; 3523147Sxc151355 } 3533147Sxc151355 3543147Sxc151355 if (listp != NULL) { 3553147Sxc151355 generate_linkprop_line(lsp, buf, listp, statusp); 3563147Sxc151355 } else { 3573147Sxc151355 generate_linkprop_line(lsp, buf, nlip, statusp); 3583147Sxc151355 free_linkprops(nlip); 3593147Sxc151355 } 3603147Sxc151355 return (B_FALSE); 3613147Sxc151355 3623147Sxc151355 fail: 3633147Sxc151355 *statusp = status; 3643147Sxc151355 if (listp == NULL) 3653147Sxc151355 free_linkprops(nlip); 3663147Sxc151355 3673147Sxc151355 return (B_FALSE); 3683147Sxc151355 } 3693147Sxc151355 3703147Sxc151355 /* 3713147Sxc151355 * This function is used for retrieving the values for a specific property. 3723147Sxc151355 * It gets called if an entry matching the specified link exists in the db. 3733147Sxc151355 * The entry is converted into a linked-list listp. This list is then scanned 3743147Sxc151355 * for the specified property name; if a matching property exists, its 3753147Sxc151355 * associated values are copied to the array lsp->ls_propval. 3763147Sxc151355 */ 3773147Sxc151355 /* ARGSUSED */ 3783147Sxc151355 static boolean_t 3793147Sxc151355 process_linkprop_get(linkprop_db_state_t *lsp, char *buf, 3803147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 3813147Sxc151355 { 3823147Sxc151355 linkprop_info_t *lip = listp; 3833147Sxc151355 linkprop_val_t *lvp; 3843147Sxc151355 uint_t valcnt = 0; 3853147Sxc151355 3863147Sxc151355 /* 3873147Sxc151355 * Find the linkprop we want to get. 3883147Sxc151355 */ 3893147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 3903147Sxc151355 if (strcmp(lip->li_name, lsp->ls_propname) == 0) 3913147Sxc151355 break; 3923147Sxc151355 } 3933147Sxc151355 if (lip == NULL) { 3943147Sxc151355 *statusp = DLADM_STATUS_NOTFOUND; 3953147Sxc151355 return (B_FALSE); 3963147Sxc151355 } 3973147Sxc151355 3983147Sxc151355 for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) { 3993147Sxc151355 (void) strncpy(lsp->ls_propval[valcnt], lvp->lv_name, 4003147Sxc151355 DLADM_PROP_VAL_MAX); 4013147Sxc151355 4023147Sxc151355 if (++valcnt >= *lsp->ls_valcntp && lvp->lv_nextval != NULL) { 4033147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 4043147Sxc151355 return (B_FALSE); 4053147Sxc151355 } 4063147Sxc151355 } 4073147Sxc151355 /* 4083147Sxc151355 * This function is meant to be called at most once for each call 4093147Sxc151355 * to process_linkprop_db(). For this reason, it's ok to overwrite 4103147Sxc151355 * the caller's valcnt array size with the actual number of values 4113147Sxc151355 * returned. 4123147Sxc151355 */ 4133147Sxc151355 *lsp->ls_valcntp = valcnt; 4143147Sxc151355 return (B_FALSE); 4153147Sxc151355 } 4163147Sxc151355 4173147Sxc151355 /* 4183147Sxc151355 * This is used for initializing link properties. 4193147Sxc151355 * Unlike the other routines, this gets called for every entry in the 4203147Sxc151355 * database. lsp->ls_link is not user-specified but instead is set to 4213147Sxc151355 * the current link being processed. 4223147Sxc151355 */ 4233147Sxc151355 /* ARGSUSED */ 4243147Sxc151355 static boolean_t 4253147Sxc151355 process_linkprop_init(linkprop_db_state_t *lsp, char *buf, 4263147Sxc151355 linkprop_info_t *listp, dladm_status_t *statusp) 4273147Sxc151355 { 4283147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 4293147Sxc151355 linkprop_info_t *lip = listp; 4303147Sxc151355 linkprop_val_t *lvp; 4313147Sxc151355 uint_t valcnt, i; 4323147Sxc151355 char **propval; 4333147Sxc151355 4343147Sxc151355 for (; lip != NULL; lip = lip->li_nextprop) { 4353147Sxc151355 /* 4363147Sxc151355 * Construct the propval array and fill it with 4373147Sxc151355 * values from listp. 4383147Sxc151355 */ 4393147Sxc151355 for (lvp = lip->li_val, valcnt = 0; 4403147Sxc151355 lvp != NULL; lvp = lvp->lv_nextval, valcnt++); 4413147Sxc151355 4423147Sxc151355 propval = malloc(sizeof (char *) * valcnt); 4433147Sxc151355 if (propval == NULL) { 4443147Sxc151355 *statusp = DLADM_STATUS_NOMEM; 4453147Sxc151355 break; 4463147Sxc151355 } 4473147Sxc151355 lvp = lip->li_val; 4483147Sxc151355 for (i = 0; i < valcnt; i++, lvp = lvp->lv_nextval) 4493147Sxc151355 propval[i] = (char *)lvp->lv_name; 4503147Sxc151355 4513147Sxc151355 status = dladm_set_prop(lsp->ls_link, lip->li_name, 4523448Sdh155122 propval, valcnt, DLADM_OPT_TEMP, NULL); 4533147Sxc151355 4543147Sxc151355 /* 4553147Sxc151355 * We continue with initializing other properties even 4563147Sxc151355 * after encountering an error. This error will be 4573147Sxc151355 * propagated to the caller via 'statusp'. 4583147Sxc151355 */ 4593147Sxc151355 if (status != DLADM_STATUS_OK) 4603147Sxc151355 *statusp = status; 4613147Sxc151355 4623147Sxc151355 free(propval); 4633147Sxc151355 } 4643147Sxc151355 return (B_TRUE); 4653147Sxc151355 } 4663147Sxc151355 4673147Sxc151355 static int 4683147Sxc151355 parse_linkprops(char *buf, linkprop_info_t **lipp) 4693147Sxc151355 { 4703147Sxc151355 int i, len; 4713147Sxc151355 char *curr; 4723147Sxc151355 linkprop_info_t *lip = NULL; 4733147Sxc151355 linkprop_info_t **tailp = lipp; 4743147Sxc151355 linkprop_val_t *lvp = NULL; 4753147Sxc151355 linkprop_val_t **vtailp = NULL; 4763147Sxc151355 4773147Sxc151355 curr = buf; 4783147Sxc151355 len = strlen(buf); 4793147Sxc151355 for (i = 0; i < len; i++) { 4803147Sxc151355 char c = buf[i]; 4813147Sxc151355 boolean_t match = (c == '=' || c == ',' || c == ';'); 4823147Sxc151355 4833147Sxc151355 /* 4843147Sxc151355 * Move to the next character if there is no match and 4853147Sxc151355 * if we have not reached the last character. 4863147Sxc151355 */ 4873147Sxc151355 if (!match && i != len - 1) 4883147Sxc151355 continue; 4893147Sxc151355 4903147Sxc151355 if (match) { 4913147Sxc151355 /* 4923147Sxc151355 * Nul-terminate the string pointed to by 'curr'. 4933147Sxc151355 */ 4943147Sxc151355 buf[i] = '\0'; 4953147Sxc151355 if (*curr == '\0') 4963147Sxc151355 goto fail; 4973147Sxc151355 } 4983147Sxc151355 4993147Sxc151355 if (lip != NULL) { 5003147Sxc151355 /* 5013147Sxc151355 * We get here after we have processed the "<prop>=" 5023147Sxc151355 * pattern. The pattern we are now interested in is 5033147Sxc151355 * "<val0>,<val1>,...,<valn>;". For each value we 5043147Sxc151355 * find, a linkprop_val_t will be allocated and 5053147Sxc151355 * added to the current 'lip'. 5063147Sxc151355 */ 5073147Sxc151355 if (c == '=') 5083147Sxc151355 goto fail; 5093147Sxc151355 5103147Sxc151355 lvp = malloc(sizeof (*lvp)); 5113147Sxc151355 if (lvp == NULL) 5123147Sxc151355 goto fail; 5133147Sxc151355 5143147Sxc151355 lvp->lv_name = curr; 5153147Sxc151355 lvp->lv_nextval = NULL; 5163147Sxc151355 *vtailp = lvp; 5173147Sxc151355 vtailp = &lvp->lv_nextval; 5183147Sxc151355 5193147Sxc151355 if (c == ';') { 5203147Sxc151355 tailp = &lip->li_nextprop; 5213147Sxc151355 vtailp = NULL; 5223147Sxc151355 lip = NULL; 5233147Sxc151355 } 5243147Sxc151355 } else { 5253147Sxc151355 /* 5263147Sxc151355 * lip == NULL indicates that 'curr' must be refering 5273147Sxc151355 * to a property name. We allocate a new linkprop_info_t 5283147Sxc151355 * append it to the list given by the caller. 5293147Sxc151355 */ 5303147Sxc151355 if (c != '=') 5313147Sxc151355 goto fail; 5323147Sxc151355 5333147Sxc151355 lip = malloc(sizeof (*lip)); 5343147Sxc151355 if (lip == NULL) 5353147Sxc151355 goto fail; 5363147Sxc151355 5373147Sxc151355 lip->li_name = curr; 5383147Sxc151355 lip->li_val = NULL; 5393147Sxc151355 lip->li_nextprop = NULL; 5403147Sxc151355 *tailp = lip; 5413147Sxc151355 vtailp = &lip->li_val; 5423147Sxc151355 } 5433147Sxc151355 curr = buf + i + 1; 5443147Sxc151355 } 5453147Sxc151355 /* 5463147Sxc151355 * The list must be non-empty and the last character must be ';'. 5473147Sxc151355 */ 5483147Sxc151355 if (*lipp == NULL || lip != NULL) 5493147Sxc151355 goto fail; 5503147Sxc151355 5513147Sxc151355 return (0); 5523147Sxc151355 5533147Sxc151355 fail: 5543147Sxc151355 free_linkprops(*lipp); 5553147Sxc151355 *lipp = NULL; 5563147Sxc151355 return (-1); 5573147Sxc151355 } 5583147Sxc151355 5593147Sxc151355 static boolean_t 5603147Sxc151355 process_linkprop_line(linkprop_db_state_t *lsp, char *buf, 5613147Sxc151355 dladm_status_t *statusp) 5623147Sxc151355 { 5633147Sxc151355 linkprop_info_t *lip = NULL; 5643147Sxc151355 int i, len, llen; 5653147Sxc151355 char *str, *lasts; 5663147Sxc151355 boolean_t cont, nolink = B_FALSE; 5673147Sxc151355 5683147Sxc151355 /* 5693147Sxc151355 * Skip leading spaces, blank lines, and comments. 5703147Sxc151355 */ 5713147Sxc151355 len = strlen(buf); 5723147Sxc151355 for (i = 0; i < len; i++) { 5733147Sxc151355 if (!isspace(buf[i])) 5743147Sxc151355 break; 5753147Sxc151355 } 5763147Sxc151355 if (i == len || buf[i] == '#') 5773147Sxc151355 return (B_TRUE); 5783147Sxc151355 5793147Sxc151355 str = buf + i; 5803147Sxc151355 if (lsp->ls_link != NULL) { 5813147Sxc151355 /* 5823147Sxc151355 * Skip links we're not interested in. 5833147Sxc151355 * Note that strncmp() and isspace() are used here 5843147Sxc151355 * instead of strtok() and strcmp() because we don't 5853147Sxc151355 * want to modify buf in case it does not contain the 5863147Sxc151355 * specified link. 5873147Sxc151355 */ 5883147Sxc151355 llen = strlen(lsp->ls_link); 5893147Sxc151355 if (strncmp(str, lsp->ls_link, llen) != 0 || 5903147Sxc151355 !isspace(str[llen])) 5913147Sxc151355 return (B_TRUE); 5923147Sxc151355 } else { 5933147Sxc151355 /* 5943147Sxc151355 * If a link is not specified, find the link name 5953147Sxc151355 * and assign it to lsp->ls_link. 5963147Sxc151355 */ 5973147Sxc151355 if (strtok_r(str, " \n\t", &lasts) == NULL) 5983147Sxc151355 goto fail; 5993147Sxc151355 6003147Sxc151355 llen = strlen(str); 6013147Sxc151355 lsp->ls_link = str; 6023147Sxc151355 nolink = B_TRUE; 6033147Sxc151355 } 6043147Sxc151355 str += llen + 1; 6053147Sxc151355 if (str >= buf + len) 6063147Sxc151355 goto fail; 6073147Sxc151355 6083147Sxc151355 /* 6093147Sxc151355 * Now find the list of link properties. 6103147Sxc151355 */ 6113147Sxc151355 if ((str = strtok_r(str, " \n\t", &lasts)) == NULL) 6123147Sxc151355 goto fail; 6133147Sxc151355 6143147Sxc151355 if (parse_linkprops(str, &lip) < 0) 6153147Sxc151355 goto fail; 6163147Sxc151355 6173147Sxc151355 cont = (*lsp->ls_op)(lsp, buf, lip, statusp); 6183147Sxc151355 free_linkprops(lip); 6193147Sxc151355 if (nolink) 6203147Sxc151355 lsp->ls_link = NULL; 6213147Sxc151355 return (cont); 6223147Sxc151355 6233147Sxc151355 fail: 6243147Sxc151355 free_linkprops(lip); 6253147Sxc151355 if (nolink) 6263147Sxc151355 lsp->ls_link = NULL; 6273147Sxc151355 6283147Sxc151355 /* 6293147Sxc151355 * Delete corrupted line. 6303147Sxc151355 */ 6313147Sxc151355 buf[0] = '\0'; 6323147Sxc151355 return (B_TRUE); 6333147Sxc151355 } 6343147Sxc151355 6353147Sxc151355 static dladm_status_t 6363147Sxc151355 process_linkprop_db(void *arg, FILE *fp, FILE *nfp) 6373147Sxc151355 { 6383147Sxc151355 linkprop_db_state_t *lsp = arg; 6393147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 6403147Sxc151355 char buf[MAXLINELEN]; 6413147Sxc151355 boolean_t cont = B_TRUE; 6423147Sxc151355 6433147Sxc151355 /* 6443147Sxc151355 * This loop processes each line of the configuration file. 6453147Sxc151355 * buf can potentially be modified by process_linkprop_line(). 6463147Sxc151355 * If this is a write operation and buf is not truncated, buf will 6473147Sxc151355 * be written to disk. process_linkprop_line() will no longer be 6483147Sxc151355 * called after it returns B_FALSE; at which point the remainder 6493147Sxc151355 * of the file will continue to be read and, if necessary, written 6503147Sxc151355 * to disk as well. 6513147Sxc151355 */ 6523147Sxc151355 while (fgets(buf, MAXLINELEN, fp) != NULL) { 6533147Sxc151355 if (cont) 6543147Sxc151355 cont = process_linkprop_line(lsp, buf, &status); 6553147Sxc151355 6563147Sxc151355 if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) { 6573147Sxc151355 status = dladm_errno2status(errno); 6583147Sxc151355 break; 6593147Sxc151355 } 6603147Sxc151355 } 6613147Sxc151355 6623147Sxc151355 if (status != DLADM_STATUS_OK || !cont) 6633147Sxc151355 return (status); 6643147Sxc151355 6653147Sxc151355 if (lsp->ls_op == process_linkprop_set) { 6663147Sxc151355 /* 6673147Sxc151355 * If the specified link is not found above, we add the 6683147Sxc151355 * link and its properties to the configuration file. 6693147Sxc151355 */ 6703147Sxc151355 (void) (*lsp->ls_op)(lsp, buf, NULL, &status); 6713147Sxc151355 if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF) 6723147Sxc151355 status = dladm_errno2status(errno); 6733147Sxc151355 } 6743147Sxc151355 6753147Sxc151355 if (lsp->ls_op == process_linkprop_get) 6763147Sxc151355 status = DLADM_STATUS_NOTFOUND; 6773147Sxc151355 6783147Sxc151355 return (status); 6793147Sxc151355 } 6803147Sxc151355 6813147Sxc151355 #define LINKPROP_RW_DB(statep, writeop) \ 6823147Sxc151355 (i_dladm_rw_db("/etc/dladm/linkprop.conf", \ 6833147Sxc151355 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_linkprop_db, \ 6843147Sxc151355 (statep), (writeop))) 6853147Sxc151355 6863147Sxc151355 static dladm_status_t 6873147Sxc151355 i_dladm_set_prop_db(const char *link, const char *prop_name, 6883147Sxc151355 char **prop_val, uint_t val_cnt) 6893147Sxc151355 { 6903147Sxc151355 linkprop_db_state_t state; 6913147Sxc151355 6923147Sxc151355 state.ls_op = process_linkprop_set; 6933147Sxc151355 state.ls_link = link; 6943147Sxc151355 state.ls_propname = prop_name; 6953147Sxc151355 state.ls_propval = prop_val; 6963147Sxc151355 state.ls_valcntp = &val_cnt; 6973147Sxc151355 6983147Sxc151355 return (LINKPROP_RW_DB(&state, B_TRUE)); 6993147Sxc151355 } 7003147Sxc151355 7013147Sxc151355 static dladm_status_t 7023147Sxc151355 i_dladm_get_prop_db(const char *link, const char *prop_name, 7033147Sxc151355 char **prop_val, uint_t *val_cntp) 7043147Sxc151355 { 7053147Sxc151355 linkprop_db_state_t state; 7063147Sxc151355 7073147Sxc151355 state.ls_op = process_linkprop_get; 7083147Sxc151355 state.ls_link = link; 7093147Sxc151355 state.ls_propname = prop_name; 7103147Sxc151355 state.ls_propval = prop_val; 7113147Sxc151355 state.ls_valcntp = val_cntp; 7123147Sxc151355 7133147Sxc151355 return (LINKPROP_RW_DB(&state, B_FALSE)); 7143147Sxc151355 } 7153147Sxc151355 7163147Sxc151355 dladm_status_t 7173147Sxc151355 dladm_init_linkprop(void) 7183147Sxc151355 { 7193147Sxc151355 linkprop_db_state_t state; 7203147Sxc151355 7213147Sxc151355 state.ls_op = process_linkprop_init; 7223147Sxc151355 state.ls_link = NULL; 7233147Sxc151355 state.ls_propname = NULL; 7243147Sxc151355 state.ls_propval = NULL; 7253147Sxc151355 state.ls_valcntp = NULL; 7263147Sxc151355 7273147Sxc151355 return (LINKPROP_RW_DB(&state, B_FALSE)); 7283147Sxc151355 } 7293448Sdh155122 7303448Sdh155122 static dladm_status_t 7313448Sdh155122 i_dladm_get_zoneid(const char *link, zoneid_t *zidp) 7323448Sdh155122 { 7333448Sdh155122 int fd; 7343448Sdh155122 dld_hold_vlan_t dhv; 7353448Sdh155122 7363448Sdh155122 if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 7373448Sdh155122 return (dladm_errno2status(errno)); 7383448Sdh155122 7393448Sdh155122 bzero(&dhv, sizeof (dld_hold_vlan_t)); 7403448Sdh155122 (void) strlcpy(dhv.dhv_name, link, IFNAMSIZ); 7413448Sdh155122 dhv.dhv_zid = -1; 7423448Sdh155122 7433448Sdh155122 if (i_dladm_ioctl(fd, DLDIOCZIDGET, &dhv, sizeof (dhv)) < 0 && 7443448Sdh155122 errno != ENOENT) { 7453448Sdh155122 dladm_status_t status = dladm_errno2status(errno); 7463448Sdh155122 7473448Sdh155122 (void) close(fd); 7483448Sdh155122 return (status); 7493448Sdh155122 } 7503448Sdh155122 7513448Sdh155122 if (errno == ENOENT) 7523448Sdh155122 *zidp = GLOBAL_ZONEID; 7533448Sdh155122 else 7543448Sdh155122 *zidp = dhv.dhv_zid; 7553448Sdh155122 7563448Sdh155122 (void) close(fd); 7573448Sdh155122 return (DLADM_STATUS_OK); 7583448Sdh155122 } 7593448Sdh155122 7603448Sdh155122 typedef int (*zone_get_devroot_t)(char *, char *, size_t); 7613448Sdh155122 7623448Sdh155122 static int 7633448Sdh155122 i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen) 7643448Sdh155122 { 7653448Sdh155122 char root[MAXPATHLEN]; 7663448Sdh155122 zone_get_devroot_t real_zone_get_devroot; 7673448Sdh155122 void *dlhandle; 7683448Sdh155122 void *sym; 7693448Sdh155122 int ret; 7703448Sdh155122 7713448Sdh155122 if ((dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY)) == NULL) 7723448Sdh155122 return (-1); 7733448Sdh155122 7743448Sdh155122 if ((sym = dlsym(dlhandle, "zone_get_devroot")) == NULL) { 7753448Sdh155122 (void) dlclose(dlhandle); 7763448Sdh155122 return (-1); 7773448Sdh155122 } 7783448Sdh155122 7793448Sdh155122 real_zone_get_devroot = (zone_get_devroot_t)sym; 7803448Sdh155122 7813448Sdh155122 if ((ret = real_zone_get_devroot(zone_name, root, sizeof (root))) == 0) 7823448Sdh155122 (void) snprintf(dev, devlen, "%s%s", root, "/dev"); 7833448Sdh155122 (void) dlclose(dlhandle); 7843448Sdh155122 return (ret); 7853448Sdh155122 } 7863448Sdh155122 7873448Sdh155122 static dladm_status_t 7883448Sdh155122 i_dladm_add_deventry(zoneid_t zid, const char *link) 7893448Sdh155122 { 7903448Sdh155122 char path[MAXPATHLEN]; 7913448Sdh155122 di_prof_t prof = NULL; 7923448Sdh155122 char zone_name[ZONENAME_MAX]; 7933448Sdh155122 dladm_status_t status; 7943448Sdh155122 7953448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 7963448Sdh155122 return (dladm_errno2status(errno)); 7973448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 7983448Sdh155122 return (dladm_errno2status(errno)); 7993448Sdh155122 if (di_prof_init(path, &prof) != 0) 8003448Sdh155122 return (dladm_errno2status(errno)); 8013448Sdh155122 8023448Sdh155122 status = DLADM_STATUS_OK; 8033448Sdh155122 if (di_prof_add_dev(prof, link) != 0) { 8043448Sdh155122 status = dladm_errno2status(errno); 8053448Sdh155122 goto cleanup; 8063448Sdh155122 } 8073448Sdh155122 if (di_prof_commit(prof) != 0) 8083448Sdh155122 status = dladm_errno2status(errno); 8093448Sdh155122 cleanup: 8103448Sdh155122 if (prof) 8113448Sdh155122 di_prof_fini(prof); 8123448Sdh155122 8133448Sdh155122 return (status); 8143448Sdh155122 } 8153448Sdh155122 8163448Sdh155122 static dladm_status_t 8173448Sdh155122 i_dladm_remove_deventry(zoneid_t zid, const char *link) 8183448Sdh155122 { 8193448Sdh155122 char path[MAXPATHLEN]; 8203448Sdh155122 di_prof_t prof = NULL; 8213448Sdh155122 char zone_name[ZONENAME_MAX]; 8223448Sdh155122 dladm_status_t status; 8233448Sdh155122 8243448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8253448Sdh155122 return (dladm_errno2status(errno)); 8263448Sdh155122 if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0) 8273448Sdh155122 return (dladm_errno2status(errno)); 8283448Sdh155122 if (di_prof_init(path, &prof) != 0) 8293448Sdh155122 return (dladm_errno2status(errno)); 8303448Sdh155122 8313448Sdh155122 status = DLADM_STATUS_OK; 8323448Sdh155122 if (di_prof_add_exclude(prof, link) != 0) { 8333448Sdh155122 status = dladm_errno2status(errno); 8343448Sdh155122 goto cleanup; 8353448Sdh155122 } 8363448Sdh155122 if (di_prof_commit(prof) != 0) 8373448Sdh155122 status = dladm_errno2status(errno); 8383448Sdh155122 cleanup: 8393448Sdh155122 if (prof) 8403448Sdh155122 di_prof_fini(prof); 8413448Sdh155122 8423448Sdh155122 return (status); 8433448Sdh155122 } 8443448Sdh155122 8453448Sdh155122 static dladm_status_t 8463448Sdh155122 do_get_zone(const char *link, char **prop_val, uint_t *val_cnt) 8473448Sdh155122 { 8483448Sdh155122 char zone_name[ZONENAME_MAX]; 8493448Sdh155122 zoneid_t zid; 8503448Sdh155122 dladm_status_t status; 8513448Sdh155122 8523448Sdh155122 status = i_dladm_get_zoneid(link, &zid); 8533448Sdh155122 if (status != DLADM_STATUS_OK) 8543448Sdh155122 return (status); 8553448Sdh155122 8563448Sdh155122 *val_cnt = 1; 8573448Sdh155122 if (zid != GLOBAL_ZONEID) { 8583448Sdh155122 if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0) 8593448Sdh155122 return (dladm_errno2status(errno)); 8603448Sdh155122 8613448Sdh155122 (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX); 8623448Sdh155122 } else { 8633448Sdh155122 *prop_val[0] = '\0'; 8643448Sdh155122 } 8653448Sdh155122 8663448Sdh155122 return (DLADM_STATUS_OK); 8673448Sdh155122 } 8683448Sdh155122 8693448Sdh155122 static dladm_status_t 8703448Sdh155122 do_set_zone(const char *link, val_desc_t *vdp, uint_t val_cnt) 8713448Sdh155122 { 8723448Sdh155122 dladm_status_t status; 8733448Sdh155122 zoneid_t zid_old, zid_new; 8743448Sdh155122 char buff[IF_NAMESIZE + 1]; 8753448Sdh155122 struct stat st; 8763448Sdh155122 8773448Sdh155122 if (val_cnt != 1) 8783448Sdh155122 return (DLADM_STATUS_BADVALCNT); 8793448Sdh155122 8803448Sdh155122 status = i_dladm_get_zoneid(link, &zid_old); 8813448Sdh155122 if (status != DLADM_STATUS_OK) 8823448Sdh155122 return (status); 8833448Sdh155122 8843448Sdh155122 /* Do nothing if setting to current value */ 8853448Sdh155122 zid_new = (zoneid_t)vdp->vd_val; 8863448Sdh155122 if (zid_new == zid_old) 8873448Sdh155122 return (DLADM_STATUS_OK); 8883448Sdh155122 8893448Sdh155122 /* Do a stat to get the vlan created by MAC, if it's not there */ 8903448Sdh155122 (void) strcpy(buff, "/dev/"); 8913448Sdh155122 (void) strlcat(buff, link, IF_NAMESIZE); 8923448Sdh155122 (void) stat(buff, &st); 8933448Sdh155122 8943448Sdh155122 if (zid_old != GLOBAL_ZONEID) { 8953448Sdh155122 if (dladm_rele_link(link, GLOBAL_ZONEID, B_TRUE) < 0) 8963448Sdh155122 return (dladm_errno2status(errno)); 8973448Sdh155122 8983448Sdh155122 if (zone_remove_datalink(zid_old, (char *)link) != 0 && 8993448Sdh155122 errno != ENXIO) { 9003448Sdh155122 status = dladm_errno2status(errno); 9013448Sdh155122 goto rollback1; 9023448Sdh155122 } 9033448Sdh155122 9043448Sdh155122 status = i_dladm_remove_deventry(zid_old, link); 9053448Sdh155122 if (status != DLADM_STATUS_OK) 9063448Sdh155122 goto rollback2; 9073448Sdh155122 } 9083448Sdh155122 9093448Sdh155122 if (zid_new != GLOBAL_ZONEID) { 9103448Sdh155122 if (zone_add_datalink(zid_new, (char *)link) != 0) { 9113448Sdh155122 status = dladm_errno2status(errno); 9123448Sdh155122 goto rollback3; 9133448Sdh155122 } 9143448Sdh155122 9153448Sdh155122 if (dladm_hold_link(link, zid_new, B_TRUE) < 0) { 9163448Sdh155122 (void) zone_remove_datalink(zid_new, (char *)link); 9173448Sdh155122 status = dladm_errno2status(errno); 9183448Sdh155122 goto rollback3; 9193448Sdh155122 } 9203448Sdh155122 9213448Sdh155122 status = i_dladm_add_deventry(zid_new, link); 9223448Sdh155122 if (status != DLADM_STATUS_OK) { 9233448Sdh155122 (void) dladm_rele_link(link, GLOBAL_ZONEID, B_FALSE); 9243448Sdh155122 (void) zone_remove_datalink(zid_new, (char *)link); 9253448Sdh155122 goto rollback3; 9263448Sdh155122 } 9273448Sdh155122 } 9283448Sdh155122 return (DLADM_STATUS_OK); 9293448Sdh155122 9303448Sdh155122 rollback3: 9313448Sdh155122 if (zid_old != GLOBAL_ZONEID) 9323448Sdh155122 (void) i_dladm_add_deventry(zid_old, link); 9333448Sdh155122 rollback2: 9343448Sdh155122 if (zid_old != GLOBAL_ZONEID) 9353448Sdh155122 (void) zone_add_datalink(zid_old, (char *)link); 9363448Sdh155122 rollback1: 9373448Sdh155122 (void) dladm_hold_link(link, zid_old, B_FALSE); 9383448Sdh155122 cleanexit: 9393448Sdh155122 return (status); 9403448Sdh155122 } 9413448Sdh155122 9423448Sdh155122 /* ARGSUSED */ 9433448Sdh155122 static dladm_status_t 9443448Sdh155122 do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt, 9453448Sdh155122 val_desc_t **vdpp) 9463448Sdh155122 { 9473448Sdh155122 zoneid_t zid; 9483448Sdh155122 val_desc_t *vdp = NULL; 9493448Sdh155122 9503448Sdh155122 if (val_cnt != 1) 9513448Sdh155122 return (DLADM_STATUS_BADVALCNT); 9523448Sdh155122 9533448Sdh155122 if ((zid = getzoneidbyname(*prop_val)) == -1) 9543448Sdh155122 return (DLADM_STATUS_BADVAL); 9553448Sdh155122 9563448Sdh155122 if (zid != GLOBAL_ZONEID) { 9573448Sdh155122 ushort_t flags; 9583448Sdh155122 9593448Sdh155122 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags, 9603448Sdh155122 sizeof (flags)) < 0) { 9613448Sdh155122 return (dladm_errno2status(errno)); 9623448Sdh155122 } 9633448Sdh155122 9643448Sdh155122 if (!(flags & ZF_NET_EXCL)) { 9653448Sdh155122 return (DLADM_STATUS_BADVAL); 9663448Sdh155122 } 9673448Sdh155122 } 9683448Sdh155122 9693448Sdh155122 vdp = malloc(sizeof (val_desc_t)); 9703448Sdh155122 if (vdp == NULL) 9713448Sdh155122 return (DLADM_STATUS_NOMEM); 9723448Sdh155122 9733448Sdh155122 vdp->vd_val = (void *)zid; 9743448Sdh155122 *vdpp = vdp; 9753448Sdh155122 return (DLADM_STATUS_OK); 9763448Sdh155122 } 9773448Sdh155122 9783448Sdh155122 static dladm_status_t 9793448Sdh155122 i_dladm_get_prop_temp(const char *link, dladm_prop_type_t type, 9803448Sdh155122 const char *prop_name, char **prop_val, uint_t *val_cntp) 9813448Sdh155122 { 9823448Sdh155122 int i; 9833448Sdh155122 dladm_status_t status; 9843448Sdh155122 uint_t cnt; 9853448Sdh155122 prop_desc_t *pdp; 9863448Sdh155122 9873448Sdh155122 if (link == NULL || prop_name == NULL || prop_val == NULL || 9883448Sdh155122 val_cntp == NULL || *val_cntp == 0) 9893448Sdh155122 return (DLADM_STATUS_BADARG); 9903448Sdh155122 9913448Sdh155122 for (i = 0; i < MAX_PROPS; i++) 9923448Sdh155122 if (strcasecmp(prop_name, prop_table[i].pd_name) == 0) 9933448Sdh155122 break; 9943448Sdh155122 9953448Sdh155122 if (i == MAX_PROPS) 9963448Sdh155122 return (DLADM_STATUS_NOTFOUND); 9973448Sdh155122 9983448Sdh155122 pdp = &prop_table[i]; 9993448Sdh155122 status = DLADM_STATUS_OK; 10003448Sdh155122 10013448Sdh155122 switch (type) { 10023448Sdh155122 case DLADM_PROP_VAL_CURRENT: 10033448Sdh155122 status = pdp->pd_get(link, prop_val, val_cntp); 10043448Sdh155122 break; 10053448Sdh155122 case DLADM_PROP_VAL_DEFAULT: 10063448Sdh155122 if (pdp->pd_defval.vd_name == NULL) { 10073448Sdh155122 status = DLADM_STATUS_NOTSUP; 10083448Sdh155122 break; 10093448Sdh155122 } 10103448Sdh155122 (void) strcpy(*prop_val, pdp->pd_defval.vd_name); 10113448Sdh155122 *val_cntp = 1; 10123448Sdh155122 break; 10133448Sdh155122 10143448Sdh155122 case DLADM_PROP_VAL_MODIFIABLE: 10153448Sdh155122 if (pdp->pd_getmod != NULL) { 10163448Sdh155122 status = pdp->pd_getmod(link, prop_val, val_cntp); 10173448Sdh155122 break; 10183448Sdh155122 } 10193448Sdh155122 cnt = pdp->pd_nmodval; 10203448Sdh155122 if (cnt == 0) { 10213448Sdh155122 status = DLADM_STATUS_NOTSUP; 10223448Sdh155122 } else if (cnt > *val_cntp) { 10233448Sdh155122 status = DLADM_STATUS_TOOSMALL; 10243448Sdh155122 } else { 10253448Sdh155122 for (i = 0; i < cnt; i++) { 10263448Sdh155122 (void) strcpy(prop_val[i], 10273448Sdh155122 pdp->pd_modval[i].vd_name); 10283448Sdh155122 } 10293448Sdh155122 *val_cntp = cnt; 10303448Sdh155122 } 10313448Sdh155122 break; 10323448Sdh155122 default: 10333448Sdh155122 status = DLADM_STATUS_BADARG; 10343448Sdh155122 break; 10353448Sdh155122 } 10363448Sdh155122 10373448Sdh155122 return (status); 10383448Sdh155122 } 10393448Sdh155122 10403448Sdh155122 static dladm_status_t 10413448Sdh155122 i_dladm_set_one_prop_temp(const char *link, prop_desc_t *pdp, char **prop_val, 10423448Sdh155122 uint_t val_cnt, uint_t flags) 10433448Sdh155122 { 10443448Sdh155122 dladm_status_t status; 10453448Sdh155122 val_desc_t *vdp = NULL; 10463448Sdh155122 uint_t cnt; 10473448Sdh155122 10483448Sdh155122 if (pdp->pd_temponly && (flags & DLADM_OPT_PERSIST) != 0) 10493448Sdh155122 return (DLADM_STATUS_TEMPONLY); 10503448Sdh155122 10513448Sdh155122 if (pdp->pd_set == NULL) 10523448Sdh155122 return (DLADM_STATUS_PROPRDONLY); 10533448Sdh155122 10543448Sdh155122 if (prop_val != NULL) { 10553448Sdh155122 if (pdp->pd_check != NULL) 10563448Sdh155122 status = pdp->pd_check(pdp, prop_val, val_cnt, &vdp); 10573448Sdh155122 else 10583448Sdh155122 status = DLADM_STATUS_BADARG; 10593448Sdh155122 10603448Sdh155122 if (status != DLADM_STATUS_OK) 10613448Sdh155122 return (status); 10623448Sdh155122 10633448Sdh155122 cnt = val_cnt; 10643448Sdh155122 } else { 10653448Sdh155122 if (pdp->pd_defval.vd_name == NULL) 10663448Sdh155122 return (DLADM_STATUS_NOTSUP); 10673448Sdh155122 10683448Sdh155122 if ((vdp = malloc(sizeof (val_desc_t))) == NULL) 10693448Sdh155122 return (DLADM_STATUS_NOMEM); 10703448Sdh155122 10713448Sdh155122 (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t)); 10723448Sdh155122 cnt = 1; 10733448Sdh155122 } 10743448Sdh155122 10753448Sdh155122 status = pdp->pd_set(link, vdp, cnt); 10763448Sdh155122 10773448Sdh155122 free(vdp); 10783448Sdh155122 return (status); 10793448Sdh155122 } 10803448Sdh155122 10813448Sdh155122 static dladm_status_t 10823448Sdh155122 i_dladm_set_prop_temp(const char *link, const char *prop_name, char **prop_val, 10833448Sdh155122 uint_t val_cnt, uint_t flags, char **errprop) 10843448Sdh155122 { 10853448Sdh155122 int i; 10863448Sdh155122 dladm_status_t status = DLADM_STATUS_OK; 10873448Sdh155122 boolean_t found = B_FALSE; 10883448Sdh155122 10893448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 10903448Sdh155122 prop_desc_t *pdp = &prop_table[i]; 10913448Sdh155122 dladm_status_t s; 10923448Sdh155122 10933448Sdh155122 if (prop_name != NULL && 10943448Sdh155122 (strcasecmp(prop_name, pdp->pd_name) != 0)) 10953448Sdh155122 continue; 10963448Sdh155122 10973448Sdh155122 found = B_TRUE; 10983448Sdh155122 s = i_dladm_set_one_prop_temp(link, pdp, prop_val, val_cnt, 10993448Sdh155122 flags); 11003448Sdh155122 11013448Sdh155122 if (prop_name != NULL) { 11023448Sdh155122 status = s; 11033448Sdh155122 break; 11043448Sdh155122 } else { 11053448Sdh155122 if (s != DLADM_STATUS_OK && 11063448Sdh155122 s != DLADM_STATUS_NOTSUP) { 11073448Sdh155122 if (errprop != NULL) 11083448Sdh155122 *errprop = pdp->pd_name; 11093448Sdh155122 status = s; 11103448Sdh155122 break; 11113448Sdh155122 } 11123448Sdh155122 } 11133448Sdh155122 } 11143448Sdh155122 11153448Sdh155122 if (!found) 11163448Sdh155122 status = DLADM_STATUS_NOTFOUND; 11173448Sdh155122 11183448Sdh155122 return (status); 11193448Sdh155122 } 11203448Sdh155122 11213448Sdh155122 static boolean_t 11223448Sdh155122 i_dladm_is_prop_temponly(const char *prop_name, char **errprop) 11233448Sdh155122 { 11243448Sdh155122 int i; 11253448Sdh155122 11263448Sdh155122 for (i = 0; i < MAX_PROPS; i++) { 11273448Sdh155122 prop_desc_t *pdp = &prop_table[i]; 11283448Sdh155122 11293448Sdh155122 if (prop_name != NULL && 11303448Sdh155122 (strcasecmp(prop_name, pdp->pd_name) != 0)) 11313448Sdh155122 continue; 11323448Sdh155122 11333448Sdh155122 if (errprop != NULL) 11343448Sdh155122 *errprop = pdp->pd_name; 11353448Sdh155122 11363448Sdh155122 if (pdp->pd_temponly) 11373448Sdh155122 return (B_TRUE); 11383448Sdh155122 } 11393448Sdh155122 11403448Sdh155122 return (B_FALSE); 11413448Sdh155122 } 1142