1*7978SPeter.Dunlap@Sun.COM /* 2*7978SPeter.Dunlap@Sun.COM * CDDL HEADER START 3*7978SPeter.Dunlap@Sun.COM * 4*7978SPeter.Dunlap@Sun.COM * The contents of this file are subject to the terms of the 5*7978SPeter.Dunlap@Sun.COM * Common Development and Distribution License (the "License"). 6*7978SPeter.Dunlap@Sun.COM * You may not use this file except in compliance with the License. 7*7978SPeter.Dunlap@Sun.COM * 8*7978SPeter.Dunlap@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*7978SPeter.Dunlap@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*7978SPeter.Dunlap@Sun.COM * See the License for the specific language governing permissions 11*7978SPeter.Dunlap@Sun.COM * and limitations under the License. 12*7978SPeter.Dunlap@Sun.COM * 13*7978SPeter.Dunlap@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*7978SPeter.Dunlap@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*7978SPeter.Dunlap@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*7978SPeter.Dunlap@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*7978SPeter.Dunlap@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*7978SPeter.Dunlap@Sun.COM * 19*7978SPeter.Dunlap@Sun.COM * CDDL HEADER END 20*7978SPeter.Dunlap@Sun.COM */ 21*7978SPeter.Dunlap@Sun.COM /* 22*7978SPeter.Dunlap@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*7978SPeter.Dunlap@Sun.COM * Use is subject to license terms. 24*7978SPeter.Dunlap@Sun.COM */ 25*7978SPeter.Dunlap@Sun.COM 26*7978SPeter.Dunlap@Sun.COM #include <sys/types.h> 27*7978SPeter.Dunlap@Sun.COM #include <sys/stat.h> 28*7978SPeter.Dunlap@Sun.COM #include <ctype.h> 29*7978SPeter.Dunlap@Sun.COM #include <fcntl.h> 30*7978SPeter.Dunlap@Sun.COM #include <uuid/uuid.h> 31*7978SPeter.Dunlap@Sun.COM #include <errno.h> 32*7978SPeter.Dunlap@Sun.COM #include <unistd.h> 33*7978SPeter.Dunlap@Sun.COM #include <strings.h> 34*7978SPeter.Dunlap@Sun.COM #include <libintl.h> 35*7978SPeter.Dunlap@Sun.COM 36*7978SPeter.Dunlap@Sun.COM #include <libstmf.h> 37*7978SPeter.Dunlap@Sun.COM #include <libiscsit.h> 38*7978SPeter.Dunlap@Sun.COM #include <sys/iscsit/iscsit_common.h> 39*7978SPeter.Dunlap@Sun.COM #include <sys/iscsi_protocol.h> 40*7978SPeter.Dunlap@Sun.COM #include <sys/iscsit/isns_protocol.h> 41*7978SPeter.Dunlap@Sun.COM 42*7978SPeter.Dunlap@Sun.COM /* From iscsitgtd */ 43*7978SPeter.Dunlap@Sun.COM #define TARGET_NAME_VERS 2 44*7978SPeter.Dunlap@Sun.COM 45*7978SPeter.Dunlap@Sun.COM /* this should be defined someplace central... */ 46*7978SPeter.Dunlap@Sun.COM #define ISCSI_NAME_LEN_MAX 223 47*7978SPeter.Dunlap@Sun.COM 48*7978SPeter.Dunlap@Sun.COM /* max length of a base64 encoded secret */ 49*7978SPeter.Dunlap@Sun.COM #define MAX_BASE64_LEN 341 50*7978SPeter.Dunlap@Sun.COM 51*7978SPeter.Dunlap@Sun.COM /* Default RADIUS server port */ 52*7978SPeter.Dunlap@Sun.COM #define DEFAULT_RADIUS_PORT 1812 53*7978SPeter.Dunlap@Sun.COM 54*7978SPeter.Dunlap@Sun.COM /* 55*7978SPeter.Dunlap@Sun.COM * The kernel reserves target portal group tag value 1 as the default. 56*7978SPeter.Dunlap@Sun.COM */ 57*7978SPeter.Dunlap@Sun.COM #define ISCSIT_DEFAULT_TPGT 1 58*7978SPeter.Dunlap@Sun.COM #define MAXTAG 0xffff 59*7978SPeter.Dunlap@Sun.COM 60*7978SPeter.Dunlap@Sun.COM /* helper for property list validation */ 61*7978SPeter.Dunlap@Sun.COM #define PROPERR(lst, key, value) { \ 62*7978SPeter.Dunlap@Sun.COM if (lst) { \ 63*7978SPeter.Dunlap@Sun.COM (void) nvlist_add_string(lst, key, value); \ 64*7978SPeter.Dunlap@Sun.COM } \ 65*7978SPeter.Dunlap@Sun.COM } 66*7978SPeter.Dunlap@Sun.COM 67*7978SPeter.Dunlap@Sun.COM /* helper function declarations */ 68*7978SPeter.Dunlap@Sun.COM static int 69*7978SPeter.Dunlap@Sun.COM it_iqn_generate(char *iqn_buf, int iqn_buf_len, char *opt_iqn_suffix); 70*7978SPeter.Dunlap@Sun.COM 71*7978SPeter.Dunlap@Sun.COM static int 72*7978SPeter.Dunlap@Sun.COM it_val_pass(char *name, char *val, nvlist_t *e); 73*7978SPeter.Dunlap@Sun.COM 74*7978SPeter.Dunlap@Sun.COM /* consider making validate funcs public */ 75*7978SPeter.Dunlap@Sun.COM static int 76*7978SPeter.Dunlap@Sun.COM it_validate_configprops(nvlist_t *nvl, nvlist_t *errs); 77*7978SPeter.Dunlap@Sun.COM 78*7978SPeter.Dunlap@Sun.COM static int 79*7978SPeter.Dunlap@Sun.COM it_validate_tgtprops(nvlist_t *nvl, nvlist_t *errs); 80*7978SPeter.Dunlap@Sun.COM 81*7978SPeter.Dunlap@Sun.COM static int 82*7978SPeter.Dunlap@Sun.COM it_validate_iniprops(nvlist_t *nvl, nvlist_t *errs); 83*7978SPeter.Dunlap@Sun.COM 84*7978SPeter.Dunlap@Sun.COM /* 85*7978SPeter.Dunlap@Sun.COM * Function: it_config_load() 86*7978SPeter.Dunlap@Sun.COM * 87*7978SPeter.Dunlap@Sun.COM * Allocate and create an it_config_t structure representing the 88*7978SPeter.Dunlap@Sun.COM * current iSCSI configuration. This structure is compiled using 89*7978SPeter.Dunlap@Sun.COM * the 'provider' data returned by stmfGetProviderData(). If there 90*7978SPeter.Dunlap@Sun.COM * is no provider data associated with iscsit, the it_config_t 91*7978SPeter.Dunlap@Sun.COM * structure will be set to a default configuration. 92*7978SPeter.Dunlap@Sun.COM * 93*7978SPeter.Dunlap@Sun.COM * Parameters: 94*7978SPeter.Dunlap@Sun.COM * cfg A C representation of the current iSCSI configuration 95*7978SPeter.Dunlap@Sun.COM * 96*7978SPeter.Dunlap@Sun.COM * Return Values: 97*7978SPeter.Dunlap@Sun.COM * 0 Success 98*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocate resources 99*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 100*7978SPeter.Dunlap@Sun.COM */ 101*7978SPeter.Dunlap@Sun.COM int 102*7978SPeter.Dunlap@Sun.COM it_config_load(it_config_t **cfg) 103*7978SPeter.Dunlap@Sun.COM { 104*7978SPeter.Dunlap@Sun.COM int ret = 0; 105*7978SPeter.Dunlap@Sun.COM nvlist_t *cfg_nv = NULL; 106*7978SPeter.Dunlap@Sun.COM it_config_t *newcfg = NULL; 107*7978SPeter.Dunlap@Sun.COM uint64_t stmf_token = 0; 108*7978SPeter.Dunlap@Sun.COM 109*7978SPeter.Dunlap@Sun.COM if (!cfg) { 110*7978SPeter.Dunlap@Sun.COM return (EINVAL); 111*7978SPeter.Dunlap@Sun.COM } 112*7978SPeter.Dunlap@Sun.COM 113*7978SPeter.Dunlap@Sun.COM *cfg = NULL; 114*7978SPeter.Dunlap@Sun.COM 115*7978SPeter.Dunlap@Sun.COM ret = stmfGetProviderDataProt(ISCSIT_MODNAME, &cfg_nv, 116*7978SPeter.Dunlap@Sun.COM STMF_PORT_PROVIDER_TYPE, &stmf_token); 117*7978SPeter.Dunlap@Sun.COM 118*7978SPeter.Dunlap@Sun.COM if ((ret == STMF_STATUS_SUCCESS) || 119*7978SPeter.Dunlap@Sun.COM (ret == STMF_ERROR_NOT_FOUND)) { 120*7978SPeter.Dunlap@Sun.COM /* 121*7978SPeter.Dunlap@Sun.COM * If not initialized yet, return empty it_config_t 122*7978SPeter.Dunlap@Sun.COM * Else, convert nvlist to struct 123*7978SPeter.Dunlap@Sun.COM */ 124*7978SPeter.Dunlap@Sun.COM ret = it_nv_to_config(cfg_nv, &newcfg); 125*7978SPeter.Dunlap@Sun.COM } 126*7978SPeter.Dunlap@Sun.COM 127*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 128*7978SPeter.Dunlap@Sun.COM newcfg->stmf_token = stmf_token; 129*7978SPeter.Dunlap@Sun.COM *cfg = newcfg; 130*7978SPeter.Dunlap@Sun.COM } 131*7978SPeter.Dunlap@Sun.COM 132*7978SPeter.Dunlap@Sun.COM return (ret); 133*7978SPeter.Dunlap@Sun.COM } 134*7978SPeter.Dunlap@Sun.COM 135*7978SPeter.Dunlap@Sun.COM /* 136*7978SPeter.Dunlap@Sun.COM * Function: it_config_commit() 137*7978SPeter.Dunlap@Sun.COM * 138*7978SPeter.Dunlap@Sun.COM * Informs the iscsit service that the configuration has changed and 139*7978SPeter.Dunlap@Sun.COM * commits the new configuration to persistent store by calling 140*7978SPeter.Dunlap@Sun.COM * stmfSetProviderData. This function can be called multiple times 141*7978SPeter.Dunlap@Sun.COM * during a configuration sequence if necessary. 142*7978SPeter.Dunlap@Sun.COM * 143*7978SPeter.Dunlap@Sun.COM * Parameters: 144*7978SPeter.Dunlap@Sun.COM * cfg A C representation of the current iSCSI configuration 145*7978SPeter.Dunlap@Sun.COM * 146*7978SPeter.Dunlap@Sun.COM * Return Values: 147*7978SPeter.Dunlap@Sun.COM * 0 Success 148*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocate resources 149*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid it_config_t structure 150*7978SPeter.Dunlap@Sun.COM * TBD ioctl() failed 151*7978SPeter.Dunlap@Sun.COM * TBD could not save config to STMF 152*7978SPeter.Dunlap@Sun.COM */ 153*7978SPeter.Dunlap@Sun.COM int 154*7978SPeter.Dunlap@Sun.COM it_config_commit(it_config_t *cfg) 155*7978SPeter.Dunlap@Sun.COM { 156*7978SPeter.Dunlap@Sun.COM int ret; 157*7978SPeter.Dunlap@Sun.COM nvlist_t *cfgnv = NULL; 158*7978SPeter.Dunlap@Sun.COM char *packednv = NULL; 159*7978SPeter.Dunlap@Sun.COM int iscsit_fd = -1; 160*7978SPeter.Dunlap@Sun.COM size_t pnv_size; 161*7978SPeter.Dunlap@Sun.COM iscsit_ioc_set_config_t iop; 162*7978SPeter.Dunlap@Sun.COM it_tgt_t *tgtp; 163*7978SPeter.Dunlap@Sun.COM 164*7978SPeter.Dunlap@Sun.COM if (!cfg) { 165*7978SPeter.Dunlap@Sun.COM return (EINVAL); 166*7978SPeter.Dunlap@Sun.COM } 167*7978SPeter.Dunlap@Sun.COM 168*7978SPeter.Dunlap@Sun.COM iscsit_fd = open(ISCSIT_NODE, O_RDWR|O_EXCL); 169*7978SPeter.Dunlap@Sun.COM if (iscsit_fd == -1) { 170*7978SPeter.Dunlap@Sun.COM ret = errno; 171*7978SPeter.Dunlap@Sun.COM return (ret); 172*7978SPeter.Dunlap@Sun.COM } 173*7978SPeter.Dunlap@Sun.COM 174*7978SPeter.Dunlap@Sun.COM ret = it_config_to_nv(cfg, &cfgnv); 175*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 176*7978SPeter.Dunlap@Sun.COM ret = nvlist_size(cfgnv, &pnv_size, NV_ENCODE_NATIVE); 177*7978SPeter.Dunlap@Sun.COM } 178*7978SPeter.Dunlap@Sun.COM 179*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 180*7978SPeter.Dunlap@Sun.COM packednv = malloc(pnv_size); 181*7978SPeter.Dunlap@Sun.COM if (!packednv) { 182*7978SPeter.Dunlap@Sun.COM ret = ENOMEM; 183*7978SPeter.Dunlap@Sun.COM } else { 184*7978SPeter.Dunlap@Sun.COM ret = nvlist_pack(cfgnv, &packednv, &pnv_size, 185*7978SPeter.Dunlap@Sun.COM NV_ENCODE_NATIVE, 0); 186*7978SPeter.Dunlap@Sun.COM } 187*7978SPeter.Dunlap@Sun.COM } 188*7978SPeter.Dunlap@Sun.COM 189*7978SPeter.Dunlap@Sun.COM /* 190*7978SPeter.Dunlap@Sun.COM * Send the changes to the kernel first, for now. Kernel 191*7978SPeter.Dunlap@Sun.COM * will be the final sanity check before config is saved 192*7978SPeter.Dunlap@Sun.COM * persistently. 193*7978SPeter.Dunlap@Sun.COM * 194*7978SPeter.Dunlap@Sun.COM * XXX - this leaves open the simultaneous-change hole 195*7978SPeter.Dunlap@Sun.COM * that STMF was trying to solve, but is a better sanity 196*7978SPeter.Dunlap@Sun.COM * check. Final decision on save order/config generation 197*7978SPeter.Dunlap@Sun.COM * number TBD. 198*7978SPeter.Dunlap@Sun.COM */ 199*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 200*7978SPeter.Dunlap@Sun.COM iop.set_cfg_vers = ISCSIT_API_VERS0; 201*7978SPeter.Dunlap@Sun.COM iop.set_cfg_pnvlist = packednv; 202*7978SPeter.Dunlap@Sun.COM iop.set_cfg_pnvlist_len = pnv_size; 203*7978SPeter.Dunlap@Sun.COM if ((ioctl(iscsit_fd, ISCSIT_IOC_SET_CONFIG, &iop)) != 0) { 204*7978SPeter.Dunlap@Sun.COM ret = errno; 205*7978SPeter.Dunlap@Sun.COM } 206*7978SPeter.Dunlap@Sun.COM } 207*7978SPeter.Dunlap@Sun.COM 208*7978SPeter.Dunlap@Sun.COM /* 209*7978SPeter.Dunlap@Sun.COM * Before saving the config persistently, remove any 210*7978SPeter.Dunlap@Sun.COM * PROP_OLD_TARGET_NAME entries. This is only interesting to 211*7978SPeter.Dunlap@Sun.COM * the active service. 212*7978SPeter.Dunlap@Sun.COM */ 213*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 214*7978SPeter.Dunlap@Sun.COM tgtp = cfg->config_tgt_list; 215*7978SPeter.Dunlap@Sun.COM for (; tgtp != NULL; tgtp = tgtp->tgt_next) { 216*7978SPeter.Dunlap@Sun.COM if (!tgtp->tgt_properties) { 217*7978SPeter.Dunlap@Sun.COM continue; 218*7978SPeter.Dunlap@Sun.COM } 219*7978SPeter.Dunlap@Sun.COM if (nvlist_exists(tgtp->tgt_properties, 220*7978SPeter.Dunlap@Sun.COM PROP_OLD_TARGET_NAME)) { 221*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(tgtp->tgt_properties, 222*7978SPeter.Dunlap@Sun.COM PROP_OLD_TARGET_NAME); 223*7978SPeter.Dunlap@Sun.COM } 224*7978SPeter.Dunlap@Sun.COM } 225*7978SPeter.Dunlap@Sun.COM } 226*7978SPeter.Dunlap@Sun.COM 227*7978SPeter.Dunlap@Sun.COM /* 228*7978SPeter.Dunlap@Sun.COM * stmfGetProviderDataProt() checks to ensure 229*7978SPeter.Dunlap@Sun.COM * that the config data hasn't changed since we fetched it. 230*7978SPeter.Dunlap@Sun.COM * 231*7978SPeter.Dunlap@Sun.COM * The kernel now has a version we need to save persistently. 232*7978SPeter.Dunlap@Sun.COM * CLI will 'do the right thing' and warn the user if it 233*7978SPeter.Dunlap@Sun.COM * gets STMF_ERROR_PROV_DATA_STALE. We'll try once to revert 234*7978SPeter.Dunlap@Sun.COM * the kernel to the persistently saved data, but ultimately, 235*7978SPeter.Dunlap@Sun.COM * it's up to the administrator to validate things are as they 236*7978SPeter.Dunlap@Sun.COM * want them to be. 237*7978SPeter.Dunlap@Sun.COM */ 238*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 239*7978SPeter.Dunlap@Sun.COM ret = stmfSetProviderDataProt(ISCSIT_MODNAME, cfgnv, 240*7978SPeter.Dunlap@Sun.COM STMF_PORT_PROVIDER_TYPE, &(cfg->stmf_token)); 241*7978SPeter.Dunlap@Sun.COM 242*7978SPeter.Dunlap@Sun.COM if (ret == STMF_STATUS_SUCCESS) { 243*7978SPeter.Dunlap@Sun.COM ret = 0; 244*7978SPeter.Dunlap@Sun.COM } else if (ret == STMF_ERROR_NOMEM) { 245*7978SPeter.Dunlap@Sun.COM ret = ENOMEM; 246*7978SPeter.Dunlap@Sun.COM } else if (ret == STMF_ERROR_PROV_DATA_STALE) { 247*7978SPeter.Dunlap@Sun.COM int st; 248*7978SPeter.Dunlap@Sun.COM it_config_t *rcfg = NULL; 249*7978SPeter.Dunlap@Sun.COM 250*7978SPeter.Dunlap@Sun.COM st = it_config_load(&rcfg); 251*7978SPeter.Dunlap@Sun.COM if (st == 0) { 252*7978SPeter.Dunlap@Sun.COM (void) it_config_commit(rcfg); 253*7978SPeter.Dunlap@Sun.COM it_config_free(rcfg); 254*7978SPeter.Dunlap@Sun.COM } 255*7978SPeter.Dunlap@Sun.COM } 256*7978SPeter.Dunlap@Sun.COM } 257*7978SPeter.Dunlap@Sun.COM 258*7978SPeter.Dunlap@Sun.COM (void) close(iscsit_fd); 259*7978SPeter.Dunlap@Sun.COM 260*7978SPeter.Dunlap@Sun.COM if (packednv) { 261*7978SPeter.Dunlap@Sun.COM free(packednv); 262*7978SPeter.Dunlap@Sun.COM } 263*7978SPeter.Dunlap@Sun.COM 264*7978SPeter.Dunlap@Sun.COM if (cfgnv) { 265*7978SPeter.Dunlap@Sun.COM nvlist_free(cfgnv); 266*7978SPeter.Dunlap@Sun.COM } 267*7978SPeter.Dunlap@Sun.COM 268*7978SPeter.Dunlap@Sun.COM return (ret); 269*7978SPeter.Dunlap@Sun.COM } 270*7978SPeter.Dunlap@Sun.COM 271*7978SPeter.Dunlap@Sun.COM /* 272*7978SPeter.Dunlap@Sun.COM * Function: it_config_setprop() 273*7978SPeter.Dunlap@Sun.COM * 274*7978SPeter.Dunlap@Sun.COM * Validate the provided property list and set the global properties 275*7978SPeter.Dunlap@Sun.COM * for iSCSI Target. If errlist is not NULL, returns detailed 276*7978SPeter.Dunlap@Sun.COM * errors for each property that failed. The format for errorlist 277*7978SPeter.Dunlap@Sun.COM * is key = property, value = error string. 278*7978SPeter.Dunlap@Sun.COM * 279*7978SPeter.Dunlap@Sun.COM * Parameters: 280*7978SPeter.Dunlap@Sun.COM * 281*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 282*7978SPeter.Dunlap@Sun.COM * it_config_load() 283*7978SPeter.Dunlap@Sun.COM * proplist nvlist_t containing properties for this target. 284*7978SPeter.Dunlap@Sun.COM * errlist (optional) nvlist_t of errors encountered when 285*7978SPeter.Dunlap@Sun.COM * validating the properties. 286*7978SPeter.Dunlap@Sun.COM * 287*7978SPeter.Dunlap@Sun.COM * Return Values: 288*7978SPeter.Dunlap@Sun.COM * 0 Success 289*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid property 290*7978SPeter.Dunlap@Sun.COM * 291*7978SPeter.Dunlap@Sun.COM */ 292*7978SPeter.Dunlap@Sun.COM int 293*7978SPeter.Dunlap@Sun.COM it_config_setprop(it_config_t *cfg, nvlist_t *proplist, nvlist_t **errlist) 294*7978SPeter.Dunlap@Sun.COM { 295*7978SPeter.Dunlap@Sun.COM int ret; 296*7978SPeter.Dunlap@Sun.COM it_portal_t *isns = NULL; 297*7978SPeter.Dunlap@Sun.COM it_portal_t *pnext = NULL; 298*7978SPeter.Dunlap@Sun.COM it_portal_t *newisnslist = NULL; 299*7978SPeter.Dunlap@Sun.COM char **arr; 300*7978SPeter.Dunlap@Sun.COM uint32_t count; 301*7978SPeter.Dunlap@Sun.COM uint32_t newcount; 302*7978SPeter.Dunlap@Sun.COM nvlist_t *cprops = NULL; 303*7978SPeter.Dunlap@Sun.COM char *val = NULL; 304*7978SPeter.Dunlap@Sun.COM 305*7978SPeter.Dunlap@Sun.COM if (!cfg || !proplist) { 306*7978SPeter.Dunlap@Sun.COM return (EINVAL); 307*7978SPeter.Dunlap@Sun.COM } 308*7978SPeter.Dunlap@Sun.COM 309*7978SPeter.Dunlap@Sun.COM if (errlist) { 310*7978SPeter.Dunlap@Sun.COM (void) nvlist_alloc(errlist, 0, 0); 311*7978SPeter.Dunlap@Sun.COM } 312*7978SPeter.Dunlap@Sun.COM 313*7978SPeter.Dunlap@Sun.COM /* 314*7978SPeter.Dunlap@Sun.COM * copy the existing properties, merge, then validate 315*7978SPeter.Dunlap@Sun.COM * the merged properties before committing them. 316*7978SPeter.Dunlap@Sun.COM */ 317*7978SPeter.Dunlap@Sun.COM if (cfg->config_global_properties) { 318*7978SPeter.Dunlap@Sun.COM ret = nvlist_dup(cfg->config_global_properties, &cprops, 0); 319*7978SPeter.Dunlap@Sun.COM } else { 320*7978SPeter.Dunlap@Sun.COM ret = nvlist_alloc(&cprops, NV_UNIQUE_NAME, 0); 321*7978SPeter.Dunlap@Sun.COM } 322*7978SPeter.Dunlap@Sun.COM 323*7978SPeter.Dunlap@Sun.COM /* base64 encode the radius secret, if it's changed */ 324*7978SPeter.Dunlap@Sun.COM val = NULL; 325*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(proplist, PROP_RADIUS_SECRET, &val); 326*7978SPeter.Dunlap@Sun.COM if (val) { 327*7978SPeter.Dunlap@Sun.COM char bsecret[MAX_BASE64_LEN]; 328*7978SPeter.Dunlap@Sun.COM 329*7978SPeter.Dunlap@Sun.COM ret = it_val_pass(PROP_RADIUS_SECRET, val, *errlist); 330*7978SPeter.Dunlap@Sun.COM 331*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 332*7978SPeter.Dunlap@Sun.COM (void) memset(bsecret, 0, MAX_BASE64_LEN); 333*7978SPeter.Dunlap@Sun.COM 334*7978SPeter.Dunlap@Sun.COM ret = iscsi_binary_to_base64_str((uint8_t *)val, 335*7978SPeter.Dunlap@Sun.COM strlen(val), bsecret, MAX_BASE64_LEN); 336*7978SPeter.Dunlap@Sun.COM 337*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 338*7978SPeter.Dunlap@Sun.COM /* replace the value in the nvlist */ 339*7978SPeter.Dunlap@Sun.COM ret = nvlist_add_string(proplist, 340*7978SPeter.Dunlap@Sun.COM PROP_RADIUS_SECRET, bsecret); 341*7978SPeter.Dunlap@Sun.COM } 342*7978SPeter.Dunlap@Sun.COM } 343*7978SPeter.Dunlap@Sun.COM } 344*7978SPeter.Dunlap@Sun.COM 345*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 346*7978SPeter.Dunlap@Sun.COM ret = nvlist_merge(cprops, proplist, 0); 347*7978SPeter.Dunlap@Sun.COM } 348*7978SPeter.Dunlap@Sun.COM 349*7978SPeter.Dunlap@Sun.COM /* see if we need to remove the radius server setting */ 350*7978SPeter.Dunlap@Sun.COM val = NULL; 351*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(cprops, PROP_RADIUS_SERVER, &val); 352*7978SPeter.Dunlap@Sun.COM if (val && (strcasecmp(val, "none") == 0)) { 353*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(cprops, PROP_RADIUS_SERVER); 354*7978SPeter.Dunlap@Sun.COM } 355*7978SPeter.Dunlap@Sun.COM 356*7978SPeter.Dunlap@Sun.COM /* and/or remove the alias */ 357*7978SPeter.Dunlap@Sun.COM val = NULL; 358*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(cprops, PROP_ALIAS, &val); 359*7978SPeter.Dunlap@Sun.COM if (val && (strcasecmp(val, "none") == 0)) { 360*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(cprops, PROP_ALIAS); 361*7978SPeter.Dunlap@Sun.COM } 362*7978SPeter.Dunlap@Sun.COM 363*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 364*7978SPeter.Dunlap@Sun.COM ret = it_validate_configprops(cprops, *errlist); 365*7978SPeter.Dunlap@Sun.COM } 366*7978SPeter.Dunlap@Sun.COM 367*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 368*7978SPeter.Dunlap@Sun.COM if (cprops) { 369*7978SPeter.Dunlap@Sun.COM nvlist_free(cprops); 370*7978SPeter.Dunlap@Sun.COM } 371*7978SPeter.Dunlap@Sun.COM return (ret); 372*7978SPeter.Dunlap@Sun.COM } 373*7978SPeter.Dunlap@Sun.COM 374*7978SPeter.Dunlap@Sun.COM /* 375*7978SPeter.Dunlap@Sun.COM * Update iSNS server list, if exists in provided property list. 376*7978SPeter.Dunlap@Sun.COM */ 377*7978SPeter.Dunlap@Sun.COM ret = nvlist_lookup_string_array(proplist, PROP_ISNS_SERVER, 378*7978SPeter.Dunlap@Sun.COM &arr, &count); 379*7978SPeter.Dunlap@Sun.COM 380*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 381*7978SPeter.Dunlap@Sun.COM /* special case: if "none", remove all defined */ 382*7978SPeter.Dunlap@Sun.COM if (strcasecmp(arr[0], "none") != 0) { 383*7978SPeter.Dunlap@Sun.COM ret = it_array_to_portallist(arr, count, 384*7978SPeter.Dunlap@Sun.COM ISNS_DEFAULT_SERVER_PORT, &newisnslist, &newcount); 385*7978SPeter.Dunlap@Sun.COM } else { 386*7978SPeter.Dunlap@Sun.COM newisnslist = NULL; 387*7978SPeter.Dunlap@Sun.COM newcount = 0; 388*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(cprops, PROP_ISNS_SERVER); 389*7978SPeter.Dunlap@Sun.COM } 390*7978SPeter.Dunlap@Sun.COM 391*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 392*7978SPeter.Dunlap@Sun.COM isns = cfg->config_isns_svr_list; 393*7978SPeter.Dunlap@Sun.COM while (isns) { 394*7978SPeter.Dunlap@Sun.COM pnext = isns->next; 395*7978SPeter.Dunlap@Sun.COM free(isns); 396*7978SPeter.Dunlap@Sun.COM isns = pnext; 397*7978SPeter.Dunlap@Sun.COM } 398*7978SPeter.Dunlap@Sun.COM 399*7978SPeter.Dunlap@Sun.COM cfg->config_isns_svr_list = newisnslist; 400*7978SPeter.Dunlap@Sun.COM cfg->config_isns_svr_count = newcount; 401*7978SPeter.Dunlap@Sun.COM 402*7978SPeter.Dunlap@Sun.COM /* 403*7978SPeter.Dunlap@Sun.COM * Replace the array in the nvlist to ensure 404*7978SPeter.Dunlap@Sun.COM * duplicates are properly removed & port numbers 405*7978SPeter.Dunlap@Sun.COM * are added. 406*7978SPeter.Dunlap@Sun.COM */ 407*7978SPeter.Dunlap@Sun.COM if (newcount > 0) { 408*7978SPeter.Dunlap@Sun.COM int i = 0; 409*7978SPeter.Dunlap@Sun.COM char **newarray; 410*7978SPeter.Dunlap@Sun.COM 411*7978SPeter.Dunlap@Sun.COM newarray = malloc(sizeof (char *) * newcount); 412*7978SPeter.Dunlap@Sun.COM if (newarray == NULL) { 413*7978SPeter.Dunlap@Sun.COM ret = ENOMEM; 414*7978SPeter.Dunlap@Sun.COM } else { 415*7978SPeter.Dunlap@Sun.COM for (isns = newisnslist; isns != NULL; 416*7978SPeter.Dunlap@Sun.COM isns = isns->next) { 417*7978SPeter.Dunlap@Sun.COM (void) sockaddr_to_str( 418*7978SPeter.Dunlap@Sun.COM &(isns->portal_addr), 419*7978SPeter.Dunlap@Sun.COM &(newarray[i++])); 420*7978SPeter.Dunlap@Sun.COM } 421*7978SPeter.Dunlap@Sun.COM (void) nvlist_add_string_array(cprops, 422*7978SPeter.Dunlap@Sun.COM PROP_ISNS_SERVER, newarray, 423*7978SPeter.Dunlap@Sun.COM newcount); 424*7978SPeter.Dunlap@Sun.COM 425*7978SPeter.Dunlap@Sun.COM for (i = 0; i < newcount; i++) { 426*7978SPeter.Dunlap@Sun.COM if (newarray[i]) { 427*7978SPeter.Dunlap@Sun.COM free(newarray[i]); 428*7978SPeter.Dunlap@Sun.COM } 429*7978SPeter.Dunlap@Sun.COM } 430*7978SPeter.Dunlap@Sun.COM free(newarray); 431*7978SPeter.Dunlap@Sun.COM } 432*7978SPeter.Dunlap@Sun.COM } 433*7978SPeter.Dunlap@Sun.COM } 434*7978SPeter.Dunlap@Sun.COM } else if (ret == ENOENT) { 435*7978SPeter.Dunlap@Sun.COM /* not an error */ 436*7978SPeter.Dunlap@Sun.COM ret = 0; 437*7978SPeter.Dunlap@Sun.COM } 438*7978SPeter.Dunlap@Sun.COM 439*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 440*7978SPeter.Dunlap@Sun.COM /* replace the global properties list */ 441*7978SPeter.Dunlap@Sun.COM nvlist_free(cfg->config_global_properties); 442*7978SPeter.Dunlap@Sun.COM cfg->config_global_properties = cprops; 443*7978SPeter.Dunlap@Sun.COM } else { 444*7978SPeter.Dunlap@Sun.COM if (cprops) { 445*7978SPeter.Dunlap@Sun.COM nvlist_free(cprops); 446*7978SPeter.Dunlap@Sun.COM } 447*7978SPeter.Dunlap@Sun.COM } 448*7978SPeter.Dunlap@Sun.COM 449*7978SPeter.Dunlap@Sun.COM return (ret); 450*7978SPeter.Dunlap@Sun.COM } 451*7978SPeter.Dunlap@Sun.COM 452*7978SPeter.Dunlap@Sun.COM /* 453*7978SPeter.Dunlap@Sun.COM * Function: it_config_free() 454*7978SPeter.Dunlap@Sun.COM * 455*7978SPeter.Dunlap@Sun.COM * Free any resources associated with the it_config_t structure. 456*7978SPeter.Dunlap@Sun.COM * 457*7978SPeter.Dunlap@Sun.COM * Parameters: 458*7978SPeter.Dunlap@Sun.COM * cfg A C representation of the current iSCSI configuration 459*7978SPeter.Dunlap@Sun.COM */ 460*7978SPeter.Dunlap@Sun.COM void 461*7978SPeter.Dunlap@Sun.COM it_config_free(it_config_t *cfg) 462*7978SPeter.Dunlap@Sun.COM { 463*7978SPeter.Dunlap@Sun.COM it_config_free_cmn(cfg); 464*7978SPeter.Dunlap@Sun.COM } 465*7978SPeter.Dunlap@Sun.COM 466*7978SPeter.Dunlap@Sun.COM /* 467*7978SPeter.Dunlap@Sun.COM * Function: it_tgt_create() 468*7978SPeter.Dunlap@Sun.COM * 469*7978SPeter.Dunlap@Sun.COM * Allocate and create an it_tgt_t structure representing a new iSCSI 470*7978SPeter.Dunlap@Sun.COM * target node. If tgt_name is NULL, then a unique target node name will 471*7978SPeter.Dunlap@Sun.COM * be generated automatically. Otherwise, the value of tgt_name will be 472*7978SPeter.Dunlap@Sun.COM * used as the target node name. The new it_tgt_t structure is added to 473*7978SPeter.Dunlap@Sun.COM * the target list (cfg_tgt_list) in the configuration structure, and the 474*7978SPeter.Dunlap@Sun.COM * new target will not be instantiated until the modified configuration 475*7978SPeter.Dunlap@Sun.COM * is committed by calling it_config_commit(). 476*7978SPeter.Dunlap@Sun.COM * 477*7978SPeter.Dunlap@Sun.COM * Parameters: 478*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 479*7978SPeter.Dunlap@Sun.COM * it_config_load() 480*7978SPeter.Dunlap@Sun.COM * tgt Pointer to an iSCSI target structure 481*7978SPeter.Dunlap@Sun.COM * tgt_name The target node name for the target to be created. 482*7978SPeter.Dunlap@Sun.COM * The name must be in either IQN or EUI format. If 483*7978SPeter.Dunlap@Sun.COM * this value is NULL, a node name will be generated 484*7978SPeter.Dunlap@Sun.COM * automatically in IQN format. 485*7978SPeter.Dunlap@Sun.COM * 486*7978SPeter.Dunlap@Sun.COM * Return Values: 487*7978SPeter.Dunlap@Sun.COM * 0 Success 488*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocated resources 489*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 490*7978SPeter.Dunlap@Sun.COM * EFAULT Invalid iSCSI name specified 491*7978SPeter.Dunlap@Sun.COM */ 492*7978SPeter.Dunlap@Sun.COM int 493*7978SPeter.Dunlap@Sun.COM it_tgt_create(it_config_t *cfg, it_tgt_t **tgt, char *tgt_name) 494*7978SPeter.Dunlap@Sun.COM { 495*7978SPeter.Dunlap@Sun.COM int ret = 0; 496*7978SPeter.Dunlap@Sun.COM it_tgt_t *ptr; 497*7978SPeter.Dunlap@Sun.COM it_tgt_t *cfgtgt; 498*7978SPeter.Dunlap@Sun.COM char *namep = tgt_name; 499*7978SPeter.Dunlap@Sun.COM char buf[ISCSI_NAME_LEN_MAX + 1]; 500*7978SPeter.Dunlap@Sun.COM 501*7978SPeter.Dunlap@Sun.COM if (!cfg || !tgt) { 502*7978SPeter.Dunlap@Sun.COM return (EINVAL); 503*7978SPeter.Dunlap@Sun.COM } 504*7978SPeter.Dunlap@Sun.COM 505*7978SPeter.Dunlap@Sun.COM if (!namep) { 506*7978SPeter.Dunlap@Sun.COM /* generate a name */ 507*7978SPeter.Dunlap@Sun.COM 508*7978SPeter.Dunlap@Sun.COM ret = it_iqn_generate(buf, sizeof (buf), NULL); 509*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 510*7978SPeter.Dunlap@Sun.COM return (ret); 511*7978SPeter.Dunlap@Sun.COM } 512*7978SPeter.Dunlap@Sun.COM namep = buf; 513*7978SPeter.Dunlap@Sun.COM } else { 514*7978SPeter.Dunlap@Sun.COM /* validate the passed-in name */ 515*7978SPeter.Dunlap@Sun.COM if (!validate_iscsi_name(namep)) { 516*7978SPeter.Dunlap@Sun.COM return (EFAULT); 517*7978SPeter.Dunlap@Sun.COM } 518*7978SPeter.Dunlap@Sun.COM } 519*7978SPeter.Dunlap@Sun.COM 520*7978SPeter.Dunlap@Sun.COM /* make sure this name isn't already on the list */ 521*7978SPeter.Dunlap@Sun.COM cfgtgt = cfg->config_tgt_list; 522*7978SPeter.Dunlap@Sun.COM while (cfgtgt != NULL) { 523*7978SPeter.Dunlap@Sun.COM if (strcmp(namep, cfgtgt->tgt_name) == 0) { 524*7978SPeter.Dunlap@Sun.COM return (EEXIST); 525*7978SPeter.Dunlap@Sun.COM } 526*7978SPeter.Dunlap@Sun.COM cfgtgt = cfgtgt->tgt_next; 527*7978SPeter.Dunlap@Sun.COM } 528*7978SPeter.Dunlap@Sun.COM 529*7978SPeter.Dunlap@Sun.COM ptr = calloc(1, sizeof (it_tgt_t)); 530*7978SPeter.Dunlap@Sun.COM if (ptr == NULL) { 531*7978SPeter.Dunlap@Sun.COM return (ENOMEM); 532*7978SPeter.Dunlap@Sun.COM } 533*7978SPeter.Dunlap@Sun.COM 534*7978SPeter.Dunlap@Sun.COM (void) strlcpy(ptr->tgt_name, namep, sizeof (ptr->tgt_name)); 535*7978SPeter.Dunlap@Sun.COM ptr->tgt_generation = 1; 536*7978SPeter.Dunlap@Sun.COM ptr->tgt_next = cfg->config_tgt_list; 537*7978SPeter.Dunlap@Sun.COM cfg->config_tgt_list = ptr; 538*7978SPeter.Dunlap@Sun.COM cfg->config_tgt_count++; 539*7978SPeter.Dunlap@Sun.COM 540*7978SPeter.Dunlap@Sun.COM *tgt = ptr; 541*7978SPeter.Dunlap@Sun.COM 542*7978SPeter.Dunlap@Sun.COM return (0); 543*7978SPeter.Dunlap@Sun.COM } 544*7978SPeter.Dunlap@Sun.COM 545*7978SPeter.Dunlap@Sun.COM /* 546*7978SPeter.Dunlap@Sun.COM * Function: it_tgt_setprop() 547*7978SPeter.Dunlap@Sun.COM * 548*7978SPeter.Dunlap@Sun.COM * Validate the provided property list and set the properties for 549*7978SPeter.Dunlap@Sun.COM * the specified target. If errlist is not NULL, returns detailed 550*7978SPeter.Dunlap@Sun.COM * errors for each property that failed. The format for errorlist 551*7978SPeter.Dunlap@Sun.COM * is key = property, value = error string. 552*7978SPeter.Dunlap@Sun.COM * 553*7978SPeter.Dunlap@Sun.COM * Parameters: 554*7978SPeter.Dunlap@Sun.COM * 555*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 556*7978SPeter.Dunlap@Sun.COM * it_config_load() 557*7978SPeter.Dunlap@Sun.COM * tgt Pointer to an iSCSI target structure 558*7978SPeter.Dunlap@Sun.COM * proplist nvlist_t containing properties for this target. 559*7978SPeter.Dunlap@Sun.COM * errlist (optional) nvlist_t of errors encountered when 560*7978SPeter.Dunlap@Sun.COM * validating the properties. 561*7978SPeter.Dunlap@Sun.COM * 562*7978SPeter.Dunlap@Sun.COM * Return Values: 563*7978SPeter.Dunlap@Sun.COM * 0 Success 564*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid property 565*7978SPeter.Dunlap@Sun.COM * 566*7978SPeter.Dunlap@Sun.COM */ 567*7978SPeter.Dunlap@Sun.COM int 568*7978SPeter.Dunlap@Sun.COM it_tgt_setprop(it_config_t *cfg, it_tgt_t *tgt, nvlist_t *proplist, 569*7978SPeter.Dunlap@Sun.COM nvlist_t **errlist) 570*7978SPeter.Dunlap@Sun.COM { 571*7978SPeter.Dunlap@Sun.COM int ret; 572*7978SPeter.Dunlap@Sun.COM nvlist_t *tprops = NULL; 573*7978SPeter.Dunlap@Sun.COM char *val = NULL; 574*7978SPeter.Dunlap@Sun.COM 575*7978SPeter.Dunlap@Sun.COM if (!cfg || !tgt || !proplist) { 576*7978SPeter.Dunlap@Sun.COM return (EINVAL); 577*7978SPeter.Dunlap@Sun.COM } 578*7978SPeter.Dunlap@Sun.COM 579*7978SPeter.Dunlap@Sun.COM if (errlist) { 580*7978SPeter.Dunlap@Sun.COM (void) nvlist_alloc(errlist, 0, 0); 581*7978SPeter.Dunlap@Sun.COM } 582*7978SPeter.Dunlap@Sun.COM 583*7978SPeter.Dunlap@Sun.COM /* 584*7978SPeter.Dunlap@Sun.COM * copy the existing properties, merge, then validate 585*7978SPeter.Dunlap@Sun.COM * the merged properties before committing them. 586*7978SPeter.Dunlap@Sun.COM */ 587*7978SPeter.Dunlap@Sun.COM if (tgt->tgt_properties) { 588*7978SPeter.Dunlap@Sun.COM ret = nvlist_dup(tgt->tgt_properties, &tprops, 0); 589*7978SPeter.Dunlap@Sun.COM } else { 590*7978SPeter.Dunlap@Sun.COM ret = nvlist_alloc(&tprops, NV_UNIQUE_NAME, 0); 591*7978SPeter.Dunlap@Sun.COM } 592*7978SPeter.Dunlap@Sun.COM 593*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 594*7978SPeter.Dunlap@Sun.COM ret = nvlist_merge(tprops, proplist, 0); 595*7978SPeter.Dunlap@Sun.COM } 596*7978SPeter.Dunlap@Sun.COM 597*7978SPeter.Dunlap@Sun.COM /* unset chap username or alias if requested */ 598*7978SPeter.Dunlap@Sun.COM val = NULL; 599*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(proplist, PROP_TARGET_CHAP_USER, &val); 600*7978SPeter.Dunlap@Sun.COM if (val && (strcasecmp(val, "none") == 0)) { 601*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(tprops, PROP_TARGET_CHAP_USER); 602*7978SPeter.Dunlap@Sun.COM } 603*7978SPeter.Dunlap@Sun.COM 604*7978SPeter.Dunlap@Sun.COM val = NULL; 605*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(proplist, PROP_ALIAS, &val); 606*7978SPeter.Dunlap@Sun.COM if (val && (strcasecmp(val, "none") == 0)) { 607*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(tprops, PROP_ALIAS); 608*7978SPeter.Dunlap@Sun.COM } 609*7978SPeter.Dunlap@Sun.COM 610*7978SPeter.Dunlap@Sun.COM /* base64 encode the CHAP secret, if it's changed */ 611*7978SPeter.Dunlap@Sun.COM val = NULL; 612*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string(proplist, PROP_TARGET_CHAP_SECRET, &val); 613*7978SPeter.Dunlap@Sun.COM if (val) { 614*7978SPeter.Dunlap@Sun.COM char bsecret[MAX_BASE64_LEN]; 615*7978SPeter.Dunlap@Sun.COM 616*7978SPeter.Dunlap@Sun.COM ret = it_val_pass(PROP_TARGET_CHAP_SECRET, val, *errlist); 617*7978SPeter.Dunlap@Sun.COM 618*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 619*7978SPeter.Dunlap@Sun.COM (void) memset(bsecret, 0, MAX_BASE64_LEN); 620*7978SPeter.Dunlap@Sun.COM 621*7978SPeter.Dunlap@Sun.COM ret = iscsi_binary_to_base64_str((uint8_t *)val, 622*7978SPeter.Dunlap@Sun.COM strlen(val), bsecret, MAX_BASE64_LEN); 623*7978SPeter.Dunlap@Sun.COM 624*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 625*7978SPeter.Dunlap@Sun.COM /* replace the value in the nvlist */ 626*7978SPeter.Dunlap@Sun.COM ret = nvlist_add_string(tprops, 627*7978SPeter.Dunlap@Sun.COM PROP_TARGET_CHAP_SECRET, bsecret); 628*7978SPeter.Dunlap@Sun.COM } 629*7978SPeter.Dunlap@Sun.COM } 630*7978SPeter.Dunlap@Sun.COM } 631*7978SPeter.Dunlap@Sun.COM 632*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 633*7978SPeter.Dunlap@Sun.COM ret = it_validate_tgtprops(tprops, *errlist); 634*7978SPeter.Dunlap@Sun.COM } 635*7978SPeter.Dunlap@Sun.COM 636*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 637*7978SPeter.Dunlap@Sun.COM if (tprops) { 638*7978SPeter.Dunlap@Sun.COM nvlist_free(tprops); 639*7978SPeter.Dunlap@Sun.COM } 640*7978SPeter.Dunlap@Sun.COM return (ret); 641*7978SPeter.Dunlap@Sun.COM } 642*7978SPeter.Dunlap@Sun.COM 643*7978SPeter.Dunlap@Sun.COM if (tgt->tgt_properties) { 644*7978SPeter.Dunlap@Sun.COM nvlist_free(tgt->tgt_properties); 645*7978SPeter.Dunlap@Sun.COM } 646*7978SPeter.Dunlap@Sun.COM tgt->tgt_properties = tprops; 647*7978SPeter.Dunlap@Sun.COM 648*7978SPeter.Dunlap@Sun.COM return (0); 649*7978SPeter.Dunlap@Sun.COM } 650*7978SPeter.Dunlap@Sun.COM 651*7978SPeter.Dunlap@Sun.COM 652*7978SPeter.Dunlap@Sun.COM /* 653*7978SPeter.Dunlap@Sun.COM * Function: it_tgt_delete() 654*7978SPeter.Dunlap@Sun.COM * 655*7978SPeter.Dunlap@Sun.COM * Delete target represented by 'tgt', where 'tgt' is an existing 656*7978SPeter.Dunlap@Sun.COM * it_tgt_structure within the configuration 'cfg'. The target removal 657*7978SPeter.Dunlap@Sun.COM * will not take effect until the modified configuration is committed 658*7978SPeter.Dunlap@Sun.COM * by calling it_config_commit(). 659*7978SPeter.Dunlap@Sun.COM * 660*7978SPeter.Dunlap@Sun.COM * Parameters: 661*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 662*7978SPeter.Dunlap@Sun.COM * it_config_load() 663*7978SPeter.Dunlap@Sun.COM * tgt Pointer to an iSCSI target structure 664*7978SPeter.Dunlap@Sun.COM * 665*7978SPeter.Dunlap@Sun.COM * force Set the target to offline before removing it from 666*7978SPeter.Dunlap@Sun.COM * the config. If not specified, the operation will 667*7978SPeter.Dunlap@Sun.COM * fail if the target is determined to be online. 668*7978SPeter.Dunlap@Sun.COM * Return Values: 669*7978SPeter.Dunlap@Sun.COM * 0 Success 670*7978SPeter.Dunlap@Sun.COM * EBUSY Target is online 671*7978SPeter.Dunlap@Sun.COM */ 672*7978SPeter.Dunlap@Sun.COM int 673*7978SPeter.Dunlap@Sun.COM it_tgt_delete(it_config_t *cfg, it_tgt_t *tgt, boolean_t force) 674*7978SPeter.Dunlap@Sun.COM { 675*7978SPeter.Dunlap@Sun.COM int ret; 676*7978SPeter.Dunlap@Sun.COM it_tgt_t *ptgt; 677*7978SPeter.Dunlap@Sun.COM it_tgt_t *prev = NULL; 678*7978SPeter.Dunlap@Sun.COM stmfDevid devid; 679*7978SPeter.Dunlap@Sun.COM stmfTargetProperties props; 680*7978SPeter.Dunlap@Sun.COM 681*7978SPeter.Dunlap@Sun.COM if (!cfg || !tgt) { 682*7978SPeter.Dunlap@Sun.COM return (0); 683*7978SPeter.Dunlap@Sun.COM } 684*7978SPeter.Dunlap@Sun.COM 685*7978SPeter.Dunlap@Sun.COM ptgt = cfg->config_tgt_list; 686*7978SPeter.Dunlap@Sun.COM while (ptgt != NULL) { 687*7978SPeter.Dunlap@Sun.COM if (strcmp(tgt->tgt_name, ptgt->tgt_name) == 0) { 688*7978SPeter.Dunlap@Sun.COM break; 689*7978SPeter.Dunlap@Sun.COM } 690*7978SPeter.Dunlap@Sun.COM prev = ptgt; 691*7978SPeter.Dunlap@Sun.COM ptgt = ptgt->tgt_next; 692*7978SPeter.Dunlap@Sun.COM } 693*7978SPeter.Dunlap@Sun.COM 694*7978SPeter.Dunlap@Sun.COM if (!ptgt) { 695*7978SPeter.Dunlap@Sun.COM return (0); 696*7978SPeter.Dunlap@Sun.COM } 697*7978SPeter.Dunlap@Sun.COM 698*7978SPeter.Dunlap@Sun.COM /* 699*7978SPeter.Dunlap@Sun.COM * check to see if this target is offline. If it is not, 700*7978SPeter.Dunlap@Sun.COM * and the 'force' flag is TRUE, tell STMF to offline it 701*7978SPeter.Dunlap@Sun.COM * before removing from the configuration. 702*7978SPeter.Dunlap@Sun.COM */ 703*7978SPeter.Dunlap@Sun.COM ret = stmfDevidFromIscsiName(ptgt->tgt_name, &devid); 704*7978SPeter.Dunlap@Sun.COM if (ret != STMF_STATUS_SUCCESS) { 705*7978SPeter.Dunlap@Sun.COM /* can't happen? */ 706*7978SPeter.Dunlap@Sun.COM return (EINVAL); 707*7978SPeter.Dunlap@Sun.COM } 708*7978SPeter.Dunlap@Sun.COM 709*7978SPeter.Dunlap@Sun.COM ret = stmfGetTargetProperties(&devid, &props); 710*7978SPeter.Dunlap@Sun.COM if (ret == STMF_STATUS_SUCCESS) { 711*7978SPeter.Dunlap@Sun.COM /* 712*7978SPeter.Dunlap@Sun.COM * only other return is STMF_ERROR_NOT_FOUND, which 713*7978SPeter.Dunlap@Sun.COM * means we don't have to offline it. 714*7978SPeter.Dunlap@Sun.COM */ 715*7978SPeter.Dunlap@Sun.COM if (props.status == STMF_TARGET_PORT_ONLINE) { 716*7978SPeter.Dunlap@Sun.COM if (!force) { 717*7978SPeter.Dunlap@Sun.COM return (EBUSY); 718*7978SPeter.Dunlap@Sun.COM } 719*7978SPeter.Dunlap@Sun.COM ret = stmfOfflineTarget(&devid); 720*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 721*7978SPeter.Dunlap@Sun.COM return (EBUSY); 722*7978SPeter.Dunlap@Sun.COM } 723*7978SPeter.Dunlap@Sun.COM } 724*7978SPeter.Dunlap@Sun.COM } 725*7978SPeter.Dunlap@Sun.COM 726*7978SPeter.Dunlap@Sun.COM if (prev) { 727*7978SPeter.Dunlap@Sun.COM prev->tgt_next = ptgt->tgt_next; 728*7978SPeter.Dunlap@Sun.COM } else { 729*7978SPeter.Dunlap@Sun.COM /* first one on the list */ 730*7978SPeter.Dunlap@Sun.COM cfg->config_tgt_list = ptgt->tgt_next; 731*7978SPeter.Dunlap@Sun.COM } 732*7978SPeter.Dunlap@Sun.COM 733*7978SPeter.Dunlap@Sun.COM ptgt->tgt_next = NULL; /* Only free this target */ 734*7978SPeter.Dunlap@Sun.COM 735*7978SPeter.Dunlap@Sun.COM cfg->config_tgt_count--; 736*7978SPeter.Dunlap@Sun.COM it_tgt_free(ptgt); 737*7978SPeter.Dunlap@Sun.COM 738*7978SPeter.Dunlap@Sun.COM return (0); 739*7978SPeter.Dunlap@Sun.COM } 740*7978SPeter.Dunlap@Sun.COM 741*7978SPeter.Dunlap@Sun.COM /* 742*7978SPeter.Dunlap@Sun.COM * Function: it_tgt_free() 743*7978SPeter.Dunlap@Sun.COM * 744*7978SPeter.Dunlap@Sun.COM * Frees an it_tgt_t structure. If tgt_next is not NULL, frees 745*7978SPeter.Dunlap@Sun.COM * all structures in the list. 746*7978SPeter.Dunlap@Sun.COM */ 747*7978SPeter.Dunlap@Sun.COM void 748*7978SPeter.Dunlap@Sun.COM it_tgt_free(it_tgt_t *tgt) 749*7978SPeter.Dunlap@Sun.COM { 750*7978SPeter.Dunlap@Sun.COM it_tgt_free_cmn(tgt); 751*7978SPeter.Dunlap@Sun.COM } 752*7978SPeter.Dunlap@Sun.COM 753*7978SPeter.Dunlap@Sun.COM /* 754*7978SPeter.Dunlap@Sun.COM * Function: it_tpgt_create() 755*7978SPeter.Dunlap@Sun.COM * 756*7978SPeter.Dunlap@Sun.COM * Allocate and create an it_tpgt_t structure representing a new iSCSI 757*7978SPeter.Dunlap@Sun.COM * target portal group tag. The new it_tpgt_t structure is added to the 758*7978SPeter.Dunlap@Sun.COM * target tpgt list (tgt_tpgt_list) in the it_tgt_t structure. The new 759*7978SPeter.Dunlap@Sun.COM * target portal group tag will not be instantiated until the modified 760*7978SPeter.Dunlap@Sun.COM * configuration is committed by calling it_config_commit(). 761*7978SPeter.Dunlap@Sun.COM * 762*7978SPeter.Dunlap@Sun.COM * Parameters: 763*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 764*7978SPeter.Dunlap@Sun.COM * it_config_load() 765*7978SPeter.Dunlap@Sun.COM * tgt Pointer to the iSCSI target structure associated 766*7978SPeter.Dunlap@Sun.COM * with the target portal group tag 767*7978SPeter.Dunlap@Sun.COM * tpgt Pointer to a target portal group tag structure 768*7978SPeter.Dunlap@Sun.COM * tpg_name The name of the TPG to be associated with this TPGT 769*7978SPeter.Dunlap@Sun.COM * tpgt_tag 16-bit numerical identifier for this TPGT. If 770*7978SPeter.Dunlap@Sun.COM * tpgt_tag is '0', this function will choose the 771*7978SPeter.Dunlap@Sun.COM * tag number. If tpgt_tag is >0, and the requested 772*7978SPeter.Dunlap@Sun.COM * tag is determined to be in use, another value 773*7978SPeter.Dunlap@Sun.COM * will be chosen. 774*7978SPeter.Dunlap@Sun.COM * 775*7978SPeter.Dunlap@Sun.COM * Return Values: 776*7978SPeter.Dunlap@Sun.COM * 0 Success 777*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocate resources 778*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 779*7978SPeter.Dunlap@Sun.COM * EEXIST Specified tag name is already used. 780*7978SPeter.Dunlap@Sun.COM * E2BIG No available tag numbers 781*7978SPeter.Dunlap@Sun.COM */ 782*7978SPeter.Dunlap@Sun.COM int 783*7978SPeter.Dunlap@Sun.COM it_tpgt_create(it_config_t *cfg, it_tgt_t *tgt, it_tpgt_t **tpgt, 784*7978SPeter.Dunlap@Sun.COM char *tpg_name, uint16_t tpgt_tag) 785*7978SPeter.Dunlap@Sun.COM { 786*7978SPeter.Dunlap@Sun.COM it_tpgt_t *ptr = NULL; 787*7978SPeter.Dunlap@Sun.COM it_tpgt_t *cfgt; 788*7978SPeter.Dunlap@Sun.COM char tagid_used[MAXTAG + 1]; 789*7978SPeter.Dunlap@Sun.COM uint16_t tagid = ISCSIT_DEFAULT_TPGT; 790*7978SPeter.Dunlap@Sun.COM 791*7978SPeter.Dunlap@Sun.COM if (!cfg || !tgt || !tpgt || !tpg_name) { 792*7978SPeter.Dunlap@Sun.COM return (EINVAL); 793*7978SPeter.Dunlap@Sun.COM } 794*7978SPeter.Dunlap@Sun.COM 795*7978SPeter.Dunlap@Sun.COM (void) memset(&(tagid_used[0]), 0, sizeof (tagid_used)); 796*7978SPeter.Dunlap@Sun.COM 797*7978SPeter.Dunlap@Sun.COM /* 798*7978SPeter.Dunlap@Sun.COM * Make sure this name and/or tag isn't already on the list 799*7978SPeter.Dunlap@Sun.COM * At the same time, capture all tag ids in use for this target 800*7978SPeter.Dunlap@Sun.COM * 801*7978SPeter.Dunlap@Sun.COM * About tag numbering -- since tag numbers are used by 802*7978SPeter.Dunlap@Sun.COM * the iSCSI protocol, we should be careful about reusing 803*7978SPeter.Dunlap@Sun.COM * them too quickly. Start with a value greater than the 804*7978SPeter.Dunlap@Sun.COM * highest one currently defined. If current == MAXTAG, 805*7978SPeter.Dunlap@Sun.COM * just find an unused tag. 806*7978SPeter.Dunlap@Sun.COM */ 807*7978SPeter.Dunlap@Sun.COM cfgt = tgt->tgt_tpgt_list; 808*7978SPeter.Dunlap@Sun.COM while (cfgt != NULL) { 809*7978SPeter.Dunlap@Sun.COM tagid_used[cfgt->tpgt_tag] = 1; 810*7978SPeter.Dunlap@Sun.COM 811*7978SPeter.Dunlap@Sun.COM if (strcmp(tpg_name, cfgt->tpgt_tpg_name) == 0) { 812*7978SPeter.Dunlap@Sun.COM return (EEXIST); 813*7978SPeter.Dunlap@Sun.COM } 814*7978SPeter.Dunlap@Sun.COM 815*7978SPeter.Dunlap@Sun.COM if (cfgt->tpgt_tag > tagid) { 816*7978SPeter.Dunlap@Sun.COM tagid = cfgt->tpgt_tag; 817*7978SPeter.Dunlap@Sun.COM } 818*7978SPeter.Dunlap@Sun.COM 819*7978SPeter.Dunlap@Sun.COM cfgt = cfgt->tpgt_next; 820*7978SPeter.Dunlap@Sun.COM } 821*7978SPeter.Dunlap@Sun.COM 822*7978SPeter.Dunlap@Sun.COM if ((tpgt_tag > ISCSIT_DEFAULT_TPGT) && (tpgt_tag < MAXTAG) && 823*7978SPeter.Dunlap@Sun.COM (tagid_used[tpgt_tag] == 0)) { 824*7978SPeter.Dunlap@Sun.COM /* ok to use requested */ 825*7978SPeter.Dunlap@Sun.COM tagid = tpgt_tag; 826*7978SPeter.Dunlap@Sun.COM } else if (tagid == MAXTAG) { 827*7978SPeter.Dunlap@Sun.COM /* 828*7978SPeter.Dunlap@Sun.COM * The highest value is used, find an available id. 829*7978SPeter.Dunlap@Sun.COM */ 830*7978SPeter.Dunlap@Sun.COM tagid = ISCSIT_DEFAULT_TPGT + 1; 831*7978SPeter.Dunlap@Sun.COM for (; tagid < MAXTAG; tagid++) { 832*7978SPeter.Dunlap@Sun.COM if (tagid_used[tagid] == 0) { 833*7978SPeter.Dunlap@Sun.COM break; 834*7978SPeter.Dunlap@Sun.COM } 835*7978SPeter.Dunlap@Sun.COM } 836*7978SPeter.Dunlap@Sun.COM if (tagid >= MAXTAG) { 837*7978SPeter.Dunlap@Sun.COM return (E2BIG); 838*7978SPeter.Dunlap@Sun.COM } 839*7978SPeter.Dunlap@Sun.COM } else { 840*7978SPeter.Dunlap@Sun.COM /* next available ID */ 841*7978SPeter.Dunlap@Sun.COM tagid++; 842*7978SPeter.Dunlap@Sun.COM } 843*7978SPeter.Dunlap@Sun.COM 844*7978SPeter.Dunlap@Sun.COM ptr = calloc(1, sizeof (it_tpgt_t)); 845*7978SPeter.Dunlap@Sun.COM if (!ptr) { 846*7978SPeter.Dunlap@Sun.COM return (ENOMEM); 847*7978SPeter.Dunlap@Sun.COM } 848*7978SPeter.Dunlap@Sun.COM 849*7978SPeter.Dunlap@Sun.COM (void) strlcpy(ptr->tpgt_tpg_name, tpg_name, 850*7978SPeter.Dunlap@Sun.COM sizeof (ptr->tpgt_tpg_name)); 851*7978SPeter.Dunlap@Sun.COM ptr->tpgt_generation = 1; 852*7978SPeter.Dunlap@Sun.COM ptr->tpgt_tag = tagid; 853*7978SPeter.Dunlap@Sun.COM 854*7978SPeter.Dunlap@Sun.COM ptr->tpgt_next = tgt->tgt_tpgt_list; 855*7978SPeter.Dunlap@Sun.COM tgt->tgt_tpgt_list = ptr; 856*7978SPeter.Dunlap@Sun.COM tgt->tgt_tpgt_count++; 857*7978SPeter.Dunlap@Sun.COM tgt->tgt_generation++; 858*7978SPeter.Dunlap@Sun.COM 859*7978SPeter.Dunlap@Sun.COM *tpgt = ptr; 860*7978SPeter.Dunlap@Sun.COM 861*7978SPeter.Dunlap@Sun.COM return (0); 862*7978SPeter.Dunlap@Sun.COM } 863*7978SPeter.Dunlap@Sun.COM 864*7978SPeter.Dunlap@Sun.COM /* 865*7978SPeter.Dunlap@Sun.COM * Function: it_tpgt_delete() 866*7978SPeter.Dunlap@Sun.COM * 867*7978SPeter.Dunlap@Sun.COM * Delete the target portal group tag represented by 'tpgt', where 868*7978SPeter.Dunlap@Sun.COM * 'tpgt' is an existing is_tpgt_t structure within the target 'tgt'. 869*7978SPeter.Dunlap@Sun.COM * The target portal group tag removal will not take effect until the 870*7978SPeter.Dunlap@Sun.COM * modified configuration is committed by calling it_config_commit(). 871*7978SPeter.Dunlap@Sun.COM * 872*7978SPeter.Dunlap@Sun.COM * Parameters: 873*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 874*7978SPeter.Dunlap@Sun.COM * it_config_load() 875*7978SPeter.Dunlap@Sun.COM * tgt Pointer to the iSCSI target structure associated 876*7978SPeter.Dunlap@Sun.COM * with the target portal group tag 877*7978SPeter.Dunlap@Sun.COM * tpgt Pointer to a target portal group tag structure 878*7978SPeter.Dunlap@Sun.COM */ 879*7978SPeter.Dunlap@Sun.COM void 880*7978SPeter.Dunlap@Sun.COM it_tpgt_delete(it_config_t *cfg, it_tgt_t *tgt, it_tpgt_t *tpgt) 881*7978SPeter.Dunlap@Sun.COM { 882*7978SPeter.Dunlap@Sun.COM it_tpgt_t *ptr; 883*7978SPeter.Dunlap@Sun.COM it_tpgt_t *prev = NULL; 884*7978SPeter.Dunlap@Sun.COM 885*7978SPeter.Dunlap@Sun.COM if (!cfg || !tgt || !tpgt) { 886*7978SPeter.Dunlap@Sun.COM return; 887*7978SPeter.Dunlap@Sun.COM } 888*7978SPeter.Dunlap@Sun.COM 889*7978SPeter.Dunlap@Sun.COM ptr = tgt->tgt_tpgt_list; 890*7978SPeter.Dunlap@Sun.COM while (ptr) { 891*7978SPeter.Dunlap@Sun.COM if (ptr->tpgt_tag == tpgt->tpgt_tag) { 892*7978SPeter.Dunlap@Sun.COM break; 893*7978SPeter.Dunlap@Sun.COM } 894*7978SPeter.Dunlap@Sun.COM prev = ptr; 895*7978SPeter.Dunlap@Sun.COM ptr = ptr->tpgt_next; 896*7978SPeter.Dunlap@Sun.COM } 897*7978SPeter.Dunlap@Sun.COM 898*7978SPeter.Dunlap@Sun.COM if (!ptr) { 899*7978SPeter.Dunlap@Sun.COM return; 900*7978SPeter.Dunlap@Sun.COM } 901*7978SPeter.Dunlap@Sun.COM 902*7978SPeter.Dunlap@Sun.COM if (prev) { 903*7978SPeter.Dunlap@Sun.COM prev->tpgt_next = ptr->tpgt_next; 904*7978SPeter.Dunlap@Sun.COM } else { 905*7978SPeter.Dunlap@Sun.COM tgt->tgt_tpgt_list = ptr->tpgt_next; 906*7978SPeter.Dunlap@Sun.COM } 907*7978SPeter.Dunlap@Sun.COM ptr->tpgt_next = NULL; 908*7978SPeter.Dunlap@Sun.COM 909*7978SPeter.Dunlap@Sun.COM tgt->tgt_tpgt_count--; 910*7978SPeter.Dunlap@Sun.COM tgt->tgt_generation++; 911*7978SPeter.Dunlap@Sun.COM 912*7978SPeter.Dunlap@Sun.COM it_tpgt_free(ptr); 913*7978SPeter.Dunlap@Sun.COM } 914*7978SPeter.Dunlap@Sun.COM 915*7978SPeter.Dunlap@Sun.COM /* 916*7978SPeter.Dunlap@Sun.COM * Function: it_tpgt_free() 917*7978SPeter.Dunlap@Sun.COM * 918*7978SPeter.Dunlap@Sun.COM * Deallocates resources of an it_tpgt_t structure. If tpgt->next 919*7978SPeter.Dunlap@Sun.COM * is not NULL, frees all members of the list. 920*7978SPeter.Dunlap@Sun.COM */ 921*7978SPeter.Dunlap@Sun.COM void 922*7978SPeter.Dunlap@Sun.COM it_tpgt_free(it_tpgt_t *tpgt) 923*7978SPeter.Dunlap@Sun.COM { 924*7978SPeter.Dunlap@Sun.COM it_tpgt_free_cmn(tpgt); 925*7978SPeter.Dunlap@Sun.COM } 926*7978SPeter.Dunlap@Sun.COM 927*7978SPeter.Dunlap@Sun.COM /* 928*7978SPeter.Dunlap@Sun.COM * Function: it_tpg_create() 929*7978SPeter.Dunlap@Sun.COM * 930*7978SPeter.Dunlap@Sun.COM * Allocate and create an it_tpg_t structure representing a new iSCSI 931*7978SPeter.Dunlap@Sun.COM * target portal group. The new it_tpg_t structure is added to the global 932*7978SPeter.Dunlap@Sun.COM * tpg list (cfg_tgt_list) in the it_config_t structure. The new target 933*7978SPeter.Dunlap@Sun.COM * portal group will not be instantiated until the modified configuration 934*7978SPeter.Dunlap@Sun.COM * is committed by calling it_config_commit(). 935*7978SPeter.Dunlap@Sun.COM * 936*7978SPeter.Dunlap@Sun.COM * Parameters: 937*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 938*7978SPeter.Dunlap@Sun.COM * it_config_load() 939*7978SPeter.Dunlap@Sun.COM * tpg Pointer to the it_tpg_t structure representing 940*7978SPeter.Dunlap@Sun.COM * the target portal group 941*7978SPeter.Dunlap@Sun.COM * tpg_name Identifier for the target portal group 942*7978SPeter.Dunlap@Sun.COM * portal_ip_port A string containing an appropriatedly formatted 943*7978SPeter.Dunlap@Sun.COM * IP address:port. Both IPv4 and IPv6 addresses are 944*7978SPeter.Dunlap@Sun.COM * permitted. This value becomes the first portal in 945*7978SPeter.Dunlap@Sun.COM * the TPG -- applications can add additional values 946*7978SPeter.Dunlap@Sun.COM * using it_portal_create() before committing the TPG. 947*7978SPeter.Dunlap@Sun.COM * Return Values: 948*7978SPeter.Dunlap@Sun.COM * 0 Success 949*7978SPeter.Dunlap@Sun.COM * ENOMEM Cannot allocate resources 950*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 951*7978SPeter.Dunlap@Sun.COM * EEXIST Requested portal in use by another target portal 952*7978SPeter.Dunlap@Sun.COM * group 953*7978SPeter.Dunlap@Sun.COM */ 954*7978SPeter.Dunlap@Sun.COM int 955*7978SPeter.Dunlap@Sun.COM it_tpg_create(it_config_t *cfg, it_tpg_t **tpg, char *tpg_name, 956*7978SPeter.Dunlap@Sun.COM char *portal_ip_port) 957*7978SPeter.Dunlap@Sun.COM { 958*7978SPeter.Dunlap@Sun.COM int ret; 959*7978SPeter.Dunlap@Sun.COM it_tpg_t *ptr; 960*7978SPeter.Dunlap@Sun.COM it_portal_t *portal = NULL; 961*7978SPeter.Dunlap@Sun.COM 962*7978SPeter.Dunlap@Sun.COM if (!cfg || !tpg || !tpg_name || !portal_ip_port) { 963*7978SPeter.Dunlap@Sun.COM return (EINVAL); 964*7978SPeter.Dunlap@Sun.COM } 965*7978SPeter.Dunlap@Sun.COM 966*7978SPeter.Dunlap@Sun.COM *tpg = NULL; 967*7978SPeter.Dunlap@Sun.COM 968*7978SPeter.Dunlap@Sun.COM ptr = cfg->config_tpg_list; 969*7978SPeter.Dunlap@Sun.COM while (ptr) { 970*7978SPeter.Dunlap@Sun.COM if (strcmp(tpg_name, ptr->tpg_name) == 0) { 971*7978SPeter.Dunlap@Sun.COM break; 972*7978SPeter.Dunlap@Sun.COM } 973*7978SPeter.Dunlap@Sun.COM ptr = ptr->tpg_next; 974*7978SPeter.Dunlap@Sun.COM } 975*7978SPeter.Dunlap@Sun.COM 976*7978SPeter.Dunlap@Sun.COM if (ptr) { 977*7978SPeter.Dunlap@Sun.COM return (EEXIST); 978*7978SPeter.Dunlap@Sun.COM } 979*7978SPeter.Dunlap@Sun.COM 980*7978SPeter.Dunlap@Sun.COM ptr = calloc(1, sizeof (it_tpg_t)); 981*7978SPeter.Dunlap@Sun.COM if (!ptr) { 982*7978SPeter.Dunlap@Sun.COM return (ENOMEM); 983*7978SPeter.Dunlap@Sun.COM } 984*7978SPeter.Dunlap@Sun.COM 985*7978SPeter.Dunlap@Sun.COM ptr->tpg_generation = 1; 986*7978SPeter.Dunlap@Sun.COM (void) strlcpy(ptr->tpg_name, tpg_name, sizeof (ptr->tpg_name)); 987*7978SPeter.Dunlap@Sun.COM 988*7978SPeter.Dunlap@Sun.COM /* create the portal */ 989*7978SPeter.Dunlap@Sun.COM ret = it_portal_create(cfg, ptr, &portal, portal_ip_port); 990*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 991*7978SPeter.Dunlap@Sun.COM free(ptr); 992*7978SPeter.Dunlap@Sun.COM return (ret); 993*7978SPeter.Dunlap@Sun.COM } 994*7978SPeter.Dunlap@Sun.COM 995*7978SPeter.Dunlap@Sun.COM ptr->tpg_next = cfg->config_tpg_list; 996*7978SPeter.Dunlap@Sun.COM cfg->config_tpg_list = ptr; 997*7978SPeter.Dunlap@Sun.COM cfg->config_tpg_count++; 998*7978SPeter.Dunlap@Sun.COM 999*7978SPeter.Dunlap@Sun.COM *tpg = ptr; 1000*7978SPeter.Dunlap@Sun.COM 1001*7978SPeter.Dunlap@Sun.COM return (0); 1002*7978SPeter.Dunlap@Sun.COM } 1003*7978SPeter.Dunlap@Sun.COM 1004*7978SPeter.Dunlap@Sun.COM /* 1005*7978SPeter.Dunlap@Sun.COM * Function: it_tpg_delete() 1006*7978SPeter.Dunlap@Sun.COM * 1007*7978SPeter.Dunlap@Sun.COM * Delete target portal group represented by 'tpg', where 'tpg' is an 1008*7978SPeter.Dunlap@Sun.COM * existing it_tpg_t structure within the global configuration 'cfg'. 1009*7978SPeter.Dunlap@Sun.COM * The target portal group removal will not take effect until the 1010*7978SPeter.Dunlap@Sun.COM * modified configuration is committed by calling it_config_commit(). 1011*7978SPeter.Dunlap@Sun.COM * 1012*7978SPeter.Dunlap@Sun.COM * Parameters: 1013*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configuration obtained from 1014*7978SPeter.Dunlap@Sun.COM * it_config_load() 1015*7978SPeter.Dunlap@Sun.COM * tpg Pointer to the it_tpg_t structure representing 1016*7978SPeter.Dunlap@Sun.COM * the target portal group 1017*7978SPeter.Dunlap@Sun.COM * force Remove this target portal group even if it's 1018*7978SPeter.Dunlap@Sun.COM * associated with one or more targets. 1019*7978SPeter.Dunlap@Sun.COM * 1020*7978SPeter.Dunlap@Sun.COM * Return Values: 1021*7978SPeter.Dunlap@Sun.COM * 0 Success 1022*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 1023*7978SPeter.Dunlap@Sun.COM * EBUSY Portal group associated with one or more targets. 1024*7978SPeter.Dunlap@Sun.COM */ 1025*7978SPeter.Dunlap@Sun.COM int 1026*7978SPeter.Dunlap@Sun.COM it_tpg_delete(it_config_t *cfg, it_tpg_t *tpg, boolean_t force) 1027*7978SPeter.Dunlap@Sun.COM { 1028*7978SPeter.Dunlap@Sun.COM it_tpg_t *ptr; 1029*7978SPeter.Dunlap@Sun.COM it_tpg_t *prev = NULL; 1030*7978SPeter.Dunlap@Sun.COM it_tgt_t *tgt; 1031*7978SPeter.Dunlap@Sun.COM it_tpgt_t *tpgt; 1032*7978SPeter.Dunlap@Sun.COM it_tpgt_t *ntpgt; 1033*7978SPeter.Dunlap@Sun.COM 1034*7978SPeter.Dunlap@Sun.COM if (!cfg || !tpg) { 1035*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1036*7978SPeter.Dunlap@Sun.COM } 1037*7978SPeter.Dunlap@Sun.COM 1038*7978SPeter.Dunlap@Sun.COM ptr = cfg->config_tpg_list; 1039*7978SPeter.Dunlap@Sun.COM while (ptr) { 1040*7978SPeter.Dunlap@Sun.COM if (strcmp(ptr->tpg_name, tpg->tpg_name) == 0) { 1041*7978SPeter.Dunlap@Sun.COM break; 1042*7978SPeter.Dunlap@Sun.COM } 1043*7978SPeter.Dunlap@Sun.COM prev = ptr; 1044*7978SPeter.Dunlap@Sun.COM ptr = ptr->tpg_next; 1045*7978SPeter.Dunlap@Sun.COM } 1046*7978SPeter.Dunlap@Sun.COM 1047*7978SPeter.Dunlap@Sun.COM if (!ptr) { 1048*7978SPeter.Dunlap@Sun.COM return (0); 1049*7978SPeter.Dunlap@Sun.COM } 1050*7978SPeter.Dunlap@Sun.COM 1051*7978SPeter.Dunlap@Sun.COM /* 1052*7978SPeter.Dunlap@Sun.COM * See if any targets are using this portal group. 1053*7978SPeter.Dunlap@Sun.COM * If there are, and the force flag is not set, fail. 1054*7978SPeter.Dunlap@Sun.COM */ 1055*7978SPeter.Dunlap@Sun.COM tgt = cfg->config_tgt_list; 1056*7978SPeter.Dunlap@Sun.COM while (tgt) { 1057*7978SPeter.Dunlap@Sun.COM tpgt = tgt->tgt_tpgt_list; 1058*7978SPeter.Dunlap@Sun.COM while (tpgt) { 1059*7978SPeter.Dunlap@Sun.COM ntpgt = tpgt->tpgt_next; 1060*7978SPeter.Dunlap@Sun.COM 1061*7978SPeter.Dunlap@Sun.COM if (strcmp(tpgt->tpgt_tpg_name, tpg->tpg_name) 1062*7978SPeter.Dunlap@Sun.COM == 0) { 1063*7978SPeter.Dunlap@Sun.COM if (!force) { 1064*7978SPeter.Dunlap@Sun.COM return (EBUSY); 1065*7978SPeter.Dunlap@Sun.COM } 1066*7978SPeter.Dunlap@Sun.COM it_tpgt_delete(cfg, tgt, tpgt); 1067*7978SPeter.Dunlap@Sun.COM } 1068*7978SPeter.Dunlap@Sun.COM 1069*7978SPeter.Dunlap@Sun.COM tpgt = ntpgt; 1070*7978SPeter.Dunlap@Sun.COM } 1071*7978SPeter.Dunlap@Sun.COM tgt = tgt->tgt_next; 1072*7978SPeter.Dunlap@Sun.COM } 1073*7978SPeter.Dunlap@Sun.COM 1074*7978SPeter.Dunlap@Sun.COM /* Now that it's not in use anywhere, remove the TPG */ 1075*7978SPeter.Dunlap@Sun.COM if (prev) { 1076*7978SPeter.Dunlap@Sun.COM prev->tpg_next = ptr->tpg_next; 1077*7978SPeter.Dunlap@Sun.COM } else { 1078*7978SPeter.Dunlap@Sun.COM cfg->config_tpg_list = ptr->tpg_next; 1079*7978SPeter.Dunlap@Sun.COM } 1080*7978SPeter.Dunlap@Sun.COM ptr->tpg_next = NULL; 1081*7978SPeter.Dunlap@Sun.COM 1082*7978SPeter.Dunlap@Sun.COM cfg->config_tpg_count--; 1083*7978SPeter.Dunlap@Sun.COM 1084*7978SPeter.Dunlap@Sun.COM it_tpg_free(ptr); 1085*7978SPeter.Dunlap@Sun.COM 1086*7978SPeter.Dunlap@Sun.COM return (0); 1087*7978SPeter.Dunlap@Sun.COM } 1088*7978SPeter.Dunlap@Sun.COM 1089*7978SPeter.Dunlap@Sun.COM /* 1090*7978SPeter.Dunlap@Sun.COM * Function: it_tpg_free() 1091*7978SPeter.Dunlap@Sun.COM * 1092*7978SPeter.Dunlap@Sun.COM * Deallocates resources associated with an it_tpg_t structure. 1093*7978SPeter.Dunlap@Sun.COM * If tpg->next is not NULL, frees all members of the list. 1094*7978SPeter.Dunlap@Sun.COM */ 1095*7978SPeter.Dunlap@Sun.COM void 1096*7978SPeter.Dunlap@Sun.COM it_tpg_free(it_tpg_t *tpg) 1097*7978SPeter.Dunlap@Sun.COM { 1098*7978SPeter.Dunlap@Sun.COM it_tpg_free_cmn(tpg); 1099*7978SPeter.Dunlap@Sun.COM } 1100*7978SPeter.Dunlap@Sun.COM 1101*7978SPeter.Dunlap@Sun.COM /* 1102*7978SPeter.Dunlap@Sun.COM * Function: it_portal_create() 1103*7978SPeter.Dunlap@Sun.COM * 1104*7978SPeter.Dunlap@Sun.COM * Add an it_portal_t structure presenting a new portal to the specified 1105*7978SPeter.Dunlap@Sun.COM * target portal group. The change to the target portal group will not take 1106*7978SPeter.Dunlap@Sun.COM * effect until the modified configuration is committed by calling 1107*7978SPeter.Dunlap@Sun.COM * it_config_commit(). 1108*7978SPeter.Dunlap@Sun.COM * 1109*7978SPeter.Dunlap@Sun.COM * Parameters: 1110*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configration obtained from 1111*7978SPeter.Dunlap@Sun.COM * it_config_load() 1112*7978SPeter.Dunlap@Sun.COM * tpg Pointer to the it_tpg_t structure representing the 1113*7978SPeter.Dunlap@Sun.COM * target portal group 1114*7978SPeter.Dunlap@Sun.COM * portal Pointer to the it_portal_t structure representing 1115*7978SPeter.Dunlap@Sun.COM * the portal 1116*7978SPeter.Dunlap@Sun.COM * portal_ip_port A string containing an appropriately formatted 1117*7978SPeter.Dunlap@Sun.COM * IP address or IP address:port in either IPv4 or 1118*7978SPeter.Dunlap@Sun.COM * IPv6 format. 1119*7978SPeter.Dunlap@Sun.COM * Return Values: 1120*7978SPeter.Dunlap@Sun.COM * 0 Success 1121*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocate resources 1122*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter 1123*7978SPeter.Dunlap@Sun.COM * EEXIST Portal already configured for another portal group 1124*7978SPeter.Dunlap@Sun.COM */ 1125*7978SPeter.Dunlap@Sun.COM int 1126*7978SPeter.Dunlap@Sun.COM it_portal_create(it_config_t *cfg, it_tpg_t *tpg, it_portal_t **portal, 1127*7978SPeter.Dunlap@Sun.COM char *portal_ip_port) 1128*7978SPeter.Dunlap@Sun.COM { 1129*7978SPeter.Dunlap@Sun.COM struct sockaddr_storage sa; 1130*7978SPeter.Dunlap@Sun.COM it_portal_t *ptr; 1131*7978SPeter.Dunlap@Sun.COM it_tpg_t *ctpg = NULL; 1132*7978SPeter.Dunlap@Sun.COM 1133*7978SPeter.Dunlap@Sun.COM if (!cfg || !tpg || !portal || !portal_ip_port) { 1134*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1135*7978SPeter.Dunlap@Sun.COM } 1136*7978SPeter.Dunlap@Sun.COM 1137*7978SPeter.Dunlap@Sun.COM if ((it_common_convert_sa(portal_ip_port, &sa, ISCSI_LISTEN_PORT)) 1138*7978SPeter.Dunlap@Sun.COM == NULL) { 1139*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1140*7978SPeter.Dunlap@Sun.COM } 1141*7978SPeter.Dunlap@Sun.COM 1142*7978SPeter.Dunlap@Sun.COM /* Check that this portal doesn't appear in any other tag */ 1143*7978SPeter.Dunlap@Sun.COM ctpg = cfg->config_tpg_list; 1144*7978SPeter.Dunlap@Sun.COM while (ctpg) { 1145*7978SPeter.Dunlap@Sun.COM ptr = ctpg->tpg_portal_list; 1146*7978SPeter.Dunlap@Sun.COM for (; ptr != NULL; ptr = ptr->next) { 1147*7978SPeter.Dunlap@Sun.COM if (it_sa_compare(&(ptr->portal_addr), &sa) != 0) { 1148*7978SPeter.Dunlap@Sun.COM continue; 1149*7978SPeter.Dunlap@Sun.COM } 1150*7978SPeter.Dunlap@Sun.COM 1151*7978SPeter.Dunlap@Sun.COM /* 1152*7978SPeter.Dunlap@Sun.COM * Existing in the same group is not an error, 1153*7978SPeter.Dunlap@Sun.COM * but don't add it again. 1154*7978SPeter.Dunlap@Sun.COM */ 1155*7978SPeter.Dunlap@Sun.COM if (strcmp(ctpg->tpg_name, tpg->tpg_name) == 0) { 1156*7978SPeter.Dunlap@Sun.COM return (0); 1157*7978SPeter.Dunlap@Sun.COM } else { 1158*7978SPeter.Dunlap@Sun.COM /* Not allowed */ 1159*7978SPeter.Dunlap@Sun.COM return (EEXIST); 1160*7978SPeter.Dunlap@Sun.COM } 1161*7978SPeter.Dunlap@Sun.COM } 1162*7978SPeter.Dunlap@Sun.COM ctpg = ctpg->tpg_next; 1163*7978SPeter.Dunlap@Sun.COM } 1164*7978SPeter.Dunlap@Sun.COM 1165*7978SPeter.Dunlap@Sun.COM ptr = calloc(1, sizeof (it_portal_t)); 1166*7978SPeter.Dunlap@Sun.COM if (!ptr) { 1167*7978SPeter.Dunlap@Sun.COM return (ENOMEM); 1168*7978SPeter.Dunlap@Sun.COM } 1169*7978SPeter.Dunlap@Sun.COM 1170*7978SPeter.Dunlap@Sun.COM (void) memcpy(&(ptr->portal_addr), &sa, 1171*7978SPeter.Dunlap@Sun.COM sizeof (struct sockaddr_storage)); 1172*7978SPeter.Dunlap@Sun.COM ptr->next = tpg->tpg_portal_list; 1173*7978SPeter.Dunlap@Sun.COM tpg->tpg_portal_list = ptr; 1174*7978SPeter.Dunlap@Sun.COM tpg->tpg_portal_count++; 1175*7978SPeter.Dunlap@Sun.COM tpg->tpg_generation++; 1176*7978SPeter.Dunlap@Sun.COM 1177*7978SPeter.Dunlap@Sun.COM return (0); 1178*7978SPeter.Dunlap@Sun.COM } 1179*7978SPeter.Dunlap@Sun.COM 1180*7978SPeter.Dunlap@Sun.COM /* 1181*7978SPeter.Dunlap@Sun.COM * Function: it_portal_delete() 1182*7978SPeter.Dunlap@Sun.COM * 1183*7978SPeter.Dunlap@Sun.COM * Remove the specified portal from the specified target portal group. 1184*7978SPeter.Dunlap@Sun.COM * The portal removal will not take effect until the modified configuration 1185*7978SPeter.Dunlap@Sun.COM * is committed by calling it_config_commit(). 1186*7978SPeter.Dunlap@Sun.COM * 1187*7978SPeter.Dunlap@Sun.COM * Parameters: 1188*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configration obtained from 1189*7978SPeter.Dunlap@Sun.COM * it_config_load() 1190*7978SPeter.Dunlap@Sun.COM * tpg Pointer to the it_tpg_t structure representing the 1191*7978SPeter.Dunlap@Sun.COM * target portal group 1192*7978SPeter.Dunlap@Sun.COM * portal Pointer to the it_portal_t structure representing 1193*7978SPeter.Dunlap@Sun.COM * the portal 1194*7978SPeter.Dunlap@Sun.COM */ 1195*7978SPeter.Dunlap@Sun.COM void 1196*7978SPeter.Dunlap@Sun.COM it_portal_delete(it_config_t *cfg, it_tpg_t *tpg, it_portal_t *portal) 1197*7978SPeter.Dunlap@Sun.COM { 1198*7978SPeter.Dunlap@Sun.COM it_portal_t *ptr; 1199*7978SPeter.Dunlap@Sun.COM it_portal_t *prev; 1200*7978SPeter.Dunlap@Sun.COM 1201*7978SPeter.Dunlap@Sun.COM if (!cfg || !tpg || !portal) { 1202*7978SPeter.Dunlap@Sun.COM return; 1203*7978SPeter.Dunlap@Sun.COM } 1204*7978SPeter.Dunlap@Sun.COM 1205*7978SPeter.Dunlap@Sun.COM ptr = tpg->tpg_portal_list; 1206*7978SPeter.Dunlap@Sun.COM while (ptr) { 1207*7978SPeter.Dunlap@Sun.COM if (memcmp(&(ptr->portal_addr), &(portal->portal_addr), 1208*7978SPeter.Dunlap@Sun.COM sizeof (ptr->portal_addr)) == 0) { 1209*7978SPeter.Dunlap@Sun.COM break; 1210*7978SPeter.Dunlap@Sun.COM } 1211*7978SPeter.Dunlap@Sun.COM prev = ptr; 1212*7978SPeter.Dunlap@Sun.COM ptr = ptr->next; 1213*7978SPeter.Dunlap@Sun.COM } 1214*7978SPeter.Dunlap@Sun.COM 1215*7978SPeter.Dunlap@Sun.COM if (!ptr) { 1216*7978SPeter.Dunlap@Sun.COM return; 1217*7978SPeter.Dunlap@Sun.COM } 1218*7978SPeter.Dunlap@Sun.COM 1219*7978SPeter.Dunlap@Sun.COM if (prev) { 1220*7978SPeter.Dunlap@Sun.COM prev->next = ptr->next; 1221*7978SPeter.Dunlap@Sun.COM } else { 1222*7978SPeter.Dunlap@Sun.COM tpg->tpg_portal_list = ptr->next; 1223*7978SPeter.Dunlap@Sun.COM } 1224*7978SPeter.Dunlap@Sun.COM tpg->tpg_portal_count--; 1225*7978SPeter.Dunlap@Sun.COM tpg->tpg_generation++; 1226*7978SPeter.Dunlap@Sun.COM 1227*7978SPeter.Dunlap@Sun.COM free(ptr); 1228*7978SPeter.Dunlap@Sun.COM } 1229*7978SPeter.Dunlap@Sun.COM 1230*7978SPeter.Dunlap@Sun.COM /* 1231*7978SPeter.Dunlap@Sun.COM * Function: it_ini_create() 1232*7978SPeter.Dunlap@Sun.COM * 1233*7978SPeter.Dunlap@Sun.COM * Add an initiator context to the global configuration. The new 1234*7978SPeter.Dunlap@Sun.COM * initiator context will not be instantiated until the modified 1235*7978SPeter.Dunlap@Sun.COM * configuration is committed by calling it_config_commit(). 1236*7978SPeter.Dunlap@Sun.COM * 1237*7978SPeter.Dunlap@Sun.COM * Parameters: 1238*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configration obtained from 1239*7978SPeter.Dunlap@Sun.COM * it_config_load() 1240*7978SPeter.Dunlap@Sun.COM * ini Pointer to the it_ini_t structure representing 1241*7978SPeter.Dunlap@Sun.COM * the initiator context. 1242*7978SPeter.Dunlap@Sun.COM * ini_node_name The iSCSI node name of the remote initiator. 1243*7978SPeter.Dunlap@Sun.COM * 1244*7978SPeter.Dunlap@Sun.COM * Return Values: 1245*7978SPeter.Dunlap@Sun.COM * 0 Success 1246*7978SPeter.Dunlap@Sun.COM * ENOMEM Could not allocate resources 1247*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid parameter. 1248*7978SPeter.Dunlap@Sun.COM * EFAULT Invalid initiator name 1249*7978SPeter.Dunlap@Sun.COM */ 1250*7978SPeter.Dunlap@Sun.COM int 1251*7978SPeter.Dunlap@Sun.COM it_ini_create(it_config_t *cfg, it_ini_t **ini, char *ini_node_name) 1252*7978SPeter.Dunlap@Sun.COM { 1253*7978SPeter.Dunlap@Sun.COM it_ini_t *ptr; 1254*7978SPeter.Dunlap@Sun.COM 1255*7978SPeter.Dunlap@Sun.COM if (!cfg || !ini || !ini_node_name) { 1256*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1257*7978SPeter.Dunlap@Sun.COM } 1258*7978SPeter.Dunlap@Sun.COM 1259*7978SPeter.Dunlap@Sun.COM /* 1260*7978SPeter.Dunlap@Sun.COM * Ensure this is a valid ini name 1261*7978SPeter.Dunlap@Sun.COM */ 1262*7978SPeter.Dunlap@Sun.COM if (!validate_iscsi_name(ini_node_name)) { 1263*7978SPeter.Dunlap@Sun.COM return (EFAULT); 1264*7978SPeter.Dunlap@Sun.COM } 1265*7978SPeter.Dunlap@Sun.COM 1266*7978SPeter.Dunlap@Sun.COM ptr = cfg->config_ini_list; 1267*7978SPeter.Dunlap@Sun.COM while (ptr) { 1268*7978SPeter.Dunlap@Sun.COM if (strcmp(ptr->ini_name, ini_node_name) == 0) { 1269*7978SPeter.Dunlap@Sun.COM break; 1270*7978SPeter.Dunlap@Sun.COM } 1271*7978SPeter.Dunlap@Sun.COM ptr = ptr->ini_next; 1272*7978SPeter.Dunlap@Sun.COM } 1273*7978SPeter.Dunlap@Sun.COM 1274*7978SPeter.Dunlap@Sun.COM if (ptr) { 1275*7978SPeter.Dunlap@Sun.COM return (EEXIST); 1276*7978SPeter.Dunlap@Sun.COM } 1277*7978SPeter.Dunlap@Sun.COM 1278*7978SPeter.Dunlap@Sun.COM ptr = calloc(1, sizeof (it_ini_t)); 1279*7978SPeter.Dunlap@Sun.COM if (!ptr) { 1280*7978SPeter.Dunlap@Sun.COM return (ENOMEM); 1281*7978SPeter.Dunlap@Sun.COM } 1282*7978SPeter.Dunlap@Sun.COM 1283*7978SPeter.Dunlap@Sun.COM (void) strlcpy(ptr->ini_name, ini_node_name, sizeof (ptr->ini_name)); 1284*7978SPeter.Dunlap@Sun.COM ptr->ini_generation = 1; 1285*7978SPeter.Dunlap@Sun.COM /* nvlist for props? */ 1286*7978SPeter.Dunlap@Sun.COM 1287*7978SPeter.Dunlap@Sun.COM ptr->ini_next = cfg->config_ini_list; 1288*7978SPeter.Dunlap@Sun.COM cfg->config_ini_list = ptr; 1289*7978SPeter.Dunlap@Sun.COM cfg->config_ini_count++; 1290*7978SPeter.Dunlap@Sun.COM 1291*7978SPeter.Dunlap@Sun.COM *ini = ptr; 1292*7978SPeter.Dunlap@Sun.COM 1293*7978SPeter.Dunlap@Sun.COM return (0); 1294*7978SPeter.Dunlap@Sun.COM } 1295*7978SPeter.Dunlap@Sun.COM 1296*7978SPeter.Dunlap@Sun.COM /* 1297*7978SPeter.Dunlap@Sun.COM * Function: it_ini_setprop() 1298*7978SPeter.Dunlap@Sun.COM * 1299*7978SPeter.Dunlap@Sun.COM * Validate the provided property list and set the initiator properties. 1300*7978SPeter.Dunlap@Sun.COM * If errlist is not NULL, returns detailed errors for each property 1301*7978SPeter.Dunlap@Sun.COM * that failed. The format for errorlist is key = property, 1302*7978SPeter.Dunlap@Sun.COM * value = error string. 1303*7978SPeter.Dunlap@Sun.COM * 1304*7978SPeter.Dunlap@Sun.COM * Parameters: 1305*7978SPeter.Dunlap@Sun.COM * 1306*7978SPeter.Dunlap@Sun.COM * ini The initiator being updated. 1307*7978SPeter.Dunlap@Sun.COM * proplist nvlist_t containing properties for this target. 1308*7978SPeter.Dunlap@Sun.COM * errlist (optional) nvlist_t of errors encountered when 1309*7978SPeter.Dunlap@Sun.COM * validating the properties. 1310*7978SPeter.Dunlap@Sun.COM * 1311*7978SPeter.Dunlap@Sun.COM * Return Values: 1312*7978SPeter.Dunlap@Sun.COM * 0 Success 1313*7978SPeter.Dunlap@Sun.COM * EINVAL Invalid property 1314*7978SPeter.Dunlap@Sun.COM * 1315*7978SPeter.Dunlap@Sun.COM */ 1316*7978SPeter.Dunlap@Sun.COM int 1317*7978SPeter.Dunlap@Sun.COM it_ini_setprop(it_ini_t *ini, nvlist_t *proplist, nvlist_t **errlist) 1318*7978SPeter.Dunlap@Sun.COM { 1319*7978SPeter.Dunlap@Sun.COM int ret; 1320*7978SPeter.Dunlap@Sun.COM nvlist_t *iprops = NULL; 1321*7978SPeter.Dunlap@Sun.COM char *val = NULL; 1322*7978SPeter.Dunlap@Sun.COM 1323*7978SPeter.Dunlap@Sun.COM if (!ini || !proplist) { 1324*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1325*7978SPeter.Dunlap@Sun.COM } 1326*7978SPeter.Dunlap@Sun.COM 1327*7978SPeter.Dunlap@Sun.COM if (errlist) { 1328*7978SPeter.Dunlap@Sun.COM (void) nvlist_alloc(errlist, 0, 0); 1329*7978SPeter.Dunlap@Sun.COM } 1330*7978SPeter.Dunlap@Sun.COM 1331*7978SPeter.Dunlap@Sun.COM /* 1332*7978SPeter.Dunlap@Sun.COM * copy the existing properties, merge, then validate 1333*7978SPeter.Dunlap@Sun.COM * the merged properties before committing them. 1334*7978SPeter.Dunlap@Sun.COM */ 1335*7978SPeter.Dunlap@Sun.COM if (ini->ini_properties) { 1336*7978SPeter.Dunlap@Sun.COM ret = nvlist_dup(ini->ini_properties, &iprops, 0); 1337*7978SPeter.Dunlap@Sun.COM } else { 1338*7978SPeter.Dunlap@Sun.COM ret = nvlist_alloc(&iprops, NV_UNIQUE_NAME, 0); 1339*7978SPeter.Dunlap@Sun.COM } 1340*7978SPeter.Dunlap@Sun.COM 1341*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 1342*7978SPeter.Dunlap@Sun.COM ret = nvlist_merge(iprops, proplist, 0); 1343*7978SPeter.Dunlap@Sun.COM } 1344*7978SPeter.Dunlap@Sun.COM 1345*7978SPeter.Dunlap@Sun.COM /* unset chap username if requested */ 1346*7978SPeter.Dunlap@Sun.COM if ((nvlist_lookup_string(proplist, PROP_CHAP_USER, &val)) == 0) { 1347*7978SPeter.Dunlap@Sun.COM if (strcasecmp(val, "none") == 0) { 1348*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(iprops, PROP_CHAP_USER); 1349*7978SPeter.Dunlap@Sun.COM } 1350*7978SPeter.Dunlap@Sun.COM } 1351*7978SPeter.Dunlap@Sun.COM 1352*7978SPeter.Dunlap@Sun.COM /* base64 encode the CHAP secret, if it's changed */ 1353*7978SPeter.Dunlap@Sun.COM if ((nvlist_lookup_string(proplist, PROP_CHAP_SECRET, &val)) == 0) { 1354*7978SPeter.Dunlap@Sun.COM char bsecret[MAX_BASE64_LEN]; 1355*7978SPeter.Dunlap@Sun.COM 1356*7978SPeter.Dunlap@Sun.COM ret = it_val_pass(PROP_CHAP_SECRET, val, *errlist); 1357*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 1358*7978SPeter.Dunlap@Sun.COM (void) memset(bsecret, 0, MAX_BASE64_LEN); 1359*7978SPeter.Dunlap@Sun.COM 1360*7978SPeter.Dunlap@Sun.COM ret = iscsi_binary_to_base64_str((uint8_t *)val, 1361*7978SPeter.Dunlap@Sun.COM strlen(val), bsecret, MAX_BASE64_LEN); 1362*7978SPeter.Dunlap@Sun.COM 1363*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 1364*7978SPeter.Dunlap@Sun.COM /* replace the value in the nvlist */ 1365*7978SPeter.Dunlap@Sun.COM ret = nvlist_add_string(iprops, 1366*7978SPeter.Dunlap@Sun.COM PROP_CHAP_SECRET, bsecret); 1367*7978SPeter.Dunlap@Sun.COM } 1368*7978SPeter.Dunlap@Sun.COM } 1369*7978SPeter.Dunlap@Sun.COM } 1370*7978SPeter.Dunlap@Sun.COM 1371*7978SPeter.Dunlap@Sun.COM if (ret == 0) { 1372*7978SPeter.Dunlap@Sun.COM ret = it_validate_iniprops(iprops, *errlist); 1373*7978SPeter.Dunlap@Sun.COM } 1374*7978SPeter.Dunlap@Sun.COM 1375*7978SPeter.Dunlap@Sun.COM if (ret != 0) { 1376*7978SPeter.Dunlap@Sun.COM if (iprops) { 1377*7978SPeter.Dunlap@Sun.COM nvlist_free(iprops); 1378*7978SPeter.Dunlap@Sun.COM } 1379*7978SPeter.Dunlap@Sun.COM return (ret); 1380*7978SPeter.Dunlap@Sun.COM } 1381*7978SPeter.Dunlap@Sun.COM 1382*7978SPeter.Dunlap@Sun.COM if (ini->ini_properties) { 1383*7978SPeter.Dunlap@Sun.COM nvlist_free(ini->ini_properties); 1384*7978SPeter.Dunlap@Sun.COM } 1385*7978SPeter.Dunlap@Sun.COM ini->ini_properties = iprops; 1386*7978SPeter.Dunlap@Sun.COM 1387*7978SPeter.Dunlap@Sun.COM return (0); 1388*7978SPeter.Dunlap@Sun.COM } 1389*7978SPeter.Dunlap@Sun.COM 1390*7978SPeter.Dunlap@Sun.COM /* 1391*7978SPeter.Dunlap@Sun.COM * Function: it_ini_delete() 1392*7978SPeter.Dunlap@Sun.COM * 1393*7978SPeter.Dunlap@Sun.COM * Remove the specified initiator context from the global configuration. 1394*7978SPeter.Dunlap@Sun.COM * The removal will not take effect until the modified configuration is 1395*7978SPeter.Dunlap@Sun.COM * committed by calling it_config_commit(). 1396*7978SPeter.Dunlap@Sun.COM * 1397*7978SPeter.Dunlap@Sun.COM * Parameters: 1398*7978SPeter.Dunlap@Sun.COM * cfg The current iSCSI configration obtained from 1399*7978SPeter.Dunlap@Sun.COM * it_config_load() 1400*7978SPeter.Dunlap@Sun.COM * ini Pointer to the it_ini_t structure representing 1401*7978SPeter.Dunlap@Sun.COM * the initiator context. 1402*7978SPeter.Dunlap@Sun.COM */ 1403*7978SPeter.Dunlap@Sun.COM void 1404*7978SPeter.Dunlap@Sun.COM it_ini_delete(it_config_t *cfg, it_ini_t *ini) 1405*7978SPeter.Dunlap@Sun.COM { 1406*7978SPeter.Dunlap@Sun.COM it_ini_t *ptr; 1407*7978SPeter.Dunlap@Sun.COM it_ini_t *prev = NULL; 1408*7978SPeter.Dunlap@Sun.COM 1409*7978SPeter.Dunlap@Sun.COM if (!cfg || !ini) { 1410*7978SPeter.Dunlap@Sun.COM return; 1411*7978SPeter.Dunlap@Sun.COM } 1412*7978SPeter.Dunlap@Sun.COM 1413*7978SPeter.Dunlap@Sun.COM ptr = cfg->config_ini_list; 1414*7978SPeter.Dunlap@Sun.COM while (ptr) { 1415*7978SPeter.Dunlap@Sun.COM if (strcmp(ptr->ini_name, ini->ini_name) == 0) { 1416*7978SPeter.Dunlap@Sun.COM break; 1417*7978SPeter.Dunlap@Sun.COM } 1418*7978SPeter.Dunlap@Sun.COM prev = ptr; 1419*7978SPeter.Dunlap@Sun.COM ptr = ptr->ini_next; 1420*7978SPeter.Dunlap@Sun.COM } 1421*7978SPeter.Dunlap@Sun.COM 1422*7978SPeter.Dunlap@Sun.COM if (!ptr) { 1423*7978SPeter.Dunlap@Sun.COM return; 1424*7978SPeter.Dunlap@Sun.COM } 1425*7978SPeter.Dunlap@Sun.COM 1426*7978SPeter.Dunlap@Sun.COM if (prev) { 1427*7978SPeter.Dunlap@Sun.COM prev->ini_next = ptr->ini_next; 1428*7978SPeter.Dunlap@Sun.COM } else { 1429*7978SPeter.Dunlap@Sun.COM cfg->config_ini_list = ptr->ini_next; 1430*7978SPeter.Dunlap@Sun.COM } 1431*7978SPeter.Dunlap@Sun.COM 1432*7978SPeter.Dunlap@Sun.COM ptr->ini_next = NULL; /* Only free this initiator */ 1433*7978SPeter.Dunlap@Sun.COM 1434*7978SPeter.Dunlap@Sun.COM cfg->config_ini_count--; 1435*7978SPeter.Dunlap@Sun.COM 1436*7978SPeter.Dunlap@Sun.COM it_ini_free(ptr); 1437*7978SPeter.Dunlap@Sun.COM } 1438*7978SPeter.Dunlap@Sun.COM 1439*7978SPeter.Dunlap@Sun.COM /* 1440*7978SPeter.Dunlap@Sun.COM * Function: it_ini_free() 1441*7978SPeter.Dunlap@Sun.COM * 1442*7978SPeter.Dunlap@Sun.COM * Deallocates resources of an it_ini_t structure. If ini->next is 1443*7978SPeter.Dunlap@Sun.COM * not NULL, frees all members of the list. 1444*7978SPeter.Dunlap@Sun.COM */ 1445*7978SPeter.Dunlap@Sun.COM void 1446*7978SPeter.Dunlap@Sun.COM it_ini_free(it_ini_t *ini) 1447*7978SPeter.Dunlap@Sun.COM { 1448*7978SPeter.Dunlap@Sun.COM it_ini_free_cmn(ini); 1449*7978SPeter.Dunlap@Sun.COM } 1450*7978SPeter.Dunlap@Sun.COM 1451*7978SPeter.Dunlap@Sun.COM /* 1452*7978SPeter.Dunlap@Sun.COM * Goes through the target property list and validates 1453*7978SPeter.Dunlap@Sun.COM * each entry. If errs is non-NULL, will return explicit errors 1454*7978SPeter.Dunlap@Sun.COM * for each property that fails validation. 1455*7978SPeter.Dunlap@Sun.COM */ 1456*7978SPeter.Dunlap@Sun.COM static int 1457*7978SPeter.Dunlap@Sun.COM it_validate_tgtprops(nvlist_t *nvl, nvlist_t *errs) 1458*7978SPeter.Dunlap@Sun.COM { 1459*7978SPeter.Dunlap@Sun.COM int errcnt = 0; 1460*7978SPeter.Dunlap@Sun.COM nvpair_t *nvp = NULL; 1461*7978SPeter.Dunlap@Sun.COM data_type_t nvtype; 1462*7978SPeter.Dunlap@Sun.COM char *name; 1463*7978SPeter.Dunlap@Sun.COM char *val; 1464*7978SPeter.Dunlap@Sun.COM char *auth = NULL; 1465*7978SPeter.Dunlap@Sun.COM 1466*7978SPeter.Dunlap@Sun.COM if (!nvl) { 1467*7978SPeter.Dunlap@Sun.COM return (0); 1468*7978SPeter.Dunlap@Sun.COM } 1469*7978SPeter.Dunlap@Sun.COM 1470*7978SPeter.Dunlap@Sun.COM while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 1471*7978SPeter.Dunlap@Sun.COM name = nvpair_name(nvp); 1472*7978SPeter.Dunlap@Sun.COM nvtype = nvpair_type(nvp); 1473*7978SPeter.Dunlap@Sun.COM 1474*7978SPeter.Dunlap@Sun.COM if (!name) { 1475*7978SPeter.Dunlap@Sun.COM continue; 1476*7978SPeter.Dunlap@Sun.COM } 1477*7978SPeter.Dunlap@Sun.COM 1478*7978SPeter.Dunlap@Sun.COM val = NULL; 1479*7978SPeter.Dunlap@Sun.COM if (strcmp(name, PROP_TARGET_CHAP_USER) == 0) { 1480*7978SPeter.Dunlap@Sun.COM if (nvtype != DATA_TYPE_STRING) { 1481*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1482*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1483*7978SPeter.Dunlap@Sun.COM errcnt++; 1484*7978SPeter.Dunlap@Sun.COM continue; 1485*7978SPeter.Dunlap@Sun.COM } 1486*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_TARGET_CHAP_SECRET) == 0) { 1487*7978SPeter.Dunlap@Sun.COM /* 1488*7978SPeter.Dunlap@Sun.COM * must be between 12 and 255 chars in cleartext. 1489*7978SPeter.Dunlap@Sun.COM * will be base64 encoded when it's set. 1490*7978SPeter.Dunlap@Sun.COM */ 1491*7978SPeter.Dunlap@Sun.COM if (nvtype == DATA_TYPE_STRING) { 1492*7978SPeter.Dunlap@Sun.COM (void) nvpair_value_string(nvp, &val); 1493*7978SPeter.Dunlap@Sun.COM } 1494*7978SPeter.Dunlap@Sun.COM 1495*7978SPeter.Dunlap@Sun.COM if (!val) { 1496*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1497*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1498*7978SPeter.Dunlap@Sun.COM errcnt++; 1499*7978SPeter.Dunlap@Sun.COM continue; 1500*7978SPeter.Dunlap@Sun.COM } 1501*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_ALIAS) == 0) { 1502*7978SPeter.Dunlap@Sun.COM if (nvtype != DATA_TYPE_STRING) { 1503*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1504*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1505*7978SPeter.Dunlap@Sun.COM errcnt++; 1506*7978SPeter.Dunlap@Sun.COM continue; 1507*7978SPeter.Dunlap@Sun.COM } 1508*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_AUTH) == 0) { 1509*7978SPeter.Dunlap@Sun.COM if (nvtype == DATA_TYPE_STRING) { 1510*7978SPeter.Dunlap@Sun.COM val = NULL; 1511*7978SPeter.Dunlap@Sun.COM (void) nvpair_value_string(nvp, &val); 1512*7978SPeter.Dunlap@Sun.COM } 1513*7978SPeter.Dunlap@Sun.COM 1514*7978SPeter.Dunlap@Sun.COM if (!val) { 1515*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1516*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1517*7978SPeter.Dunlap@Sun.COM errcnt++; 1518*7978SPeter.Dunlap@Sun.COM continue; 1519*7978SPeter.Dunlap@Sun.COM } 1520*7978SPeter.Dunlap@Sun.COM if ((strcmp(val, PA_AUTH_NONE) != 0) && 1521*7978SPeter.Dunlap@Sun.COM (strcmp(val, PA_AUTH_CHAP) != 0) && 1522*7978SPeter.Dunlap@Sun.COM (strcmp(val, PA_AUTH_RADIUS) != 0) && 1523*7978SPeter.Dunlap@Sun.COM (strcmp(val, "default") != 0)) { 1524*7978SPeter.Dunlap@Sun.COM PROPERR(errs, val, gettext( 1525*7978SPeter.Dunlap@Sun.COM "must be none, chap, radius or default")); 1526*7978SPeter.Dunlap@Sun.COM errcnt++; 1527*7978SPeter.Dunlap@Sun.COM } 1528*7978SPeter.Dunlap@Sun.COM auth = val; 1529*7978SPeter.Dunlap@Sun.COM continue; 1530*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_OLD_TARGET_NAME) == 0) { 1531*7978SPeter.Dunlap@Sun.COM continue; 1532*7978SPeter.Dunlap@Sun.COM } else { 1533*7978SPeter.Dunlap@Sun.COM /* unrecognized property */ 1534*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, gettext("unrecognized property")); 1535*7978SPeter.Dunlap@Sun.COM errcnt++; 1536*7978SPeter.Dunlap@Sun.COM } 1537*7978SPeter.Dunlap@Sun.COM } 1538*7978SPeter.Dunlap@Sun.COM 1539*7978SPeter.Dunlap@Sun.COM if (errcnt) { 1540*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1541*7978SPeter.Dunlap@Sun.COM } 1542*7978SPeter.Dunlap@Sun.COM 1543*7978SPeter.Dunlap@Sun.COM /* if auth is being set to default, remove from this nvlist */ 1544*7978SPeter.Dunlap@Sun.COM if (auth && (strcmp(auth, "default") == 0)) { 1545*7978SPeter.Dunlap@Sun.COM (void) nvlist_remove_all(nvl, PROP_AUTH); 1546*7978SPeter.Dunlap@Sun.COM } 1547*7978SPeter.Dunlap@Sun.COM 1548*7978SPeter.Dunlap@Sun.COM return (0); 1549*7978SPeter.Dunlap@Sun.COM } 1550*7978SPeter.Dunlap@Sun.COM 1551*7978SPeter.Dunlap@Sun.COM /* 1552*7978SPeter.Dunlap@Sun.COM * Goes through the config property list and validates 1553*7978SPeter.Dunlap@Sun.COM * each entry. If errs is non-NULL, will return explicit errors 1554*7978SPeter.Dunlap@Sun.COM * for each property that fails validation. 1555*7978SPeter.Dunlap@Sun.COM */ 1556*7978SPeter.Dunlap@Sun.COM static int 1557*7978SPeter.Dunlap@Sun.COM it_validate_configprops(nvlist_t *nvl, nvlist_t *errs) 1558*7978SPeter.Dunlap@Sun.COM { 1559*7978SPeter.Dunlap@Sun.COM int errcnt = 0; 1560*7978SPeter.Dunlap@Sun.COM nvpair_t *nvp = NULL; 1561*7978SPeter.Dunlap@Sun.COM data_type_t nvtype; 1562*7978SPeter.Dunlap@Sun.COM char *name; 1563*7978SPeter.Dunlap@Sun.COM char *val; 1564*7978SPeter.Dunlap@Sun.COM struct sockaddr_storage sa; 1565*7978SPeter.Dunlap@Sun.COM char *auth = NULL; 1566*7978SPeter.Dunlap@Sun.COM 1567*7978SPeter.Dunlap@Sun.COM if (!nvl) { 1568*7978SPeter.Dunlap@Sun.COM return (0); 1569*7978SPeter.Dunlap@Sun.COM } 1570*7978SPeter.Dunlap@Sun.COM 1571*7978SPeter.Dunlap@Sun.COM while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 1572*7978SPeter.Dunlap@Sun.COM name = nvpair_name(nvp); 1573*7978SPeter.Dunlap@Sun.COM nvtype = nvpair_type(nvp); 1574*7978SPeter.Dunlap@Sun.COM 1575*7978SPeter.Dunlap@Sun.COM if (!name) { 1576*7978SPeter.Dunlap@Sun.COM continue; 1577*7978SPeter.Dunlap@Sun.COM } 1578*7978SPeter.Dunlap@Sun.COM 1579*7978SPeter.Dunlap@Sun.COM val = NULL; 1580*7978SPeter.Dunlap@Sun.COM 1581*7978SPeter.Dunlap@Sun.COM /* prefetch string value as we mostly need it */ 1582*7978SPeter.Dunlap@Sun.COM if (nvtype == DATA_TYPE_STRING) { 1583*7978SPeter.Dunlap@Sun.COM (void) nvpair_value_string(nvp, &val); 1584*7978SPeter.Dunlap@Sun.COM } 1585*7978SPeter.Dunlap@Sun.COM 1586*7978SPeter.Dunlap@Sun.COM if (strcmp(name, PROP_ALIAS) == 0) { 1587*7978SPeter.Dunlap@Sun.COM if (!val) { 1588*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1589*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1590*7978SPeter.Dunlap@Sun.COM errcnt++; 1591*7978SPeter.Dunlap@Sun.COM } 1592*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_AUTH) == 0) { 1593*7978SPeter.Dunlap@Sun.COM if (!val) { 1594*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1595*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1596*7978SPeter.Dunlap@Sun.COM errcnt++; 1597*7978SPeter.Dunlap@Sun.COM continue; 1598*7978SPeter.Dunlap@Sun.COM } 1599*7978SPeter.Dunlap@Sun.COM 1600*7978SPeter.Dunlap@Sun.COM if ((strcmp(val, PA_AUTH_NONE) != 0) && 1601*7978SPeter.Dunlap@Sun.COM (strcmp(val, PA_AUTH_CHAP) != 0) && 1602*7978SPeter.Dunlap@Sun.COM (strcmp(val, PA_AUTH_RADIUS) != 0)) { 1603*7978SPeter.Dunlap@Sun.COM PROPERR(errs, PROP_AUTH, 1604*7978SPeter.Dunlap@Sun.COM gettext("must be none, chap or radius")); 1605*7978SPeter.Dunlap@Sun.COM errcnt++; 1606*7978SPeter.Dunlap@Sun.COM } 1607*7978SPeter.Dunlap@Sun.COM 1608*7978SPeter.Dunlap@Sun.COM auth = val; 1609*7978SPeter.Dunlap@Sun.COM 1610*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_ISNS_ENABLED) == 0) { 1611*7978SPeter.Dunlap@Sun.COM if (nvtype != DATA_TYPE_BOOLEAN_VALUE) { 1612*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1613*7978SPeter.Dunlap@Sun.COM gettext("must be a boolean value")); 1614*7978SPeter.Dunlap@Sun.COM errcnt++; 1615*7978SPeter.Dunlap@Sun.COM } 1616*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_ISNS_SERVER) == 0) { 1617*7978SPeter.Dunlap@Sun.COM char **arr = NULL; 1618*7978SPeter.Dunlap@Sun.COM uint32_t acount = 0; 1619*7978SPeter.Dunlap@Sun.COM 1620*7978SPeter.Dunlap@Sun.COM (void) nvlist_lookup_string_array(nvl, name, 1621*7978SPeter.Dunlap@Sun.COM &arr, &acount); 1622*7978SPeter.Dunlap@Sun.COM 1623*7978SPeter.Dunlap@Sun.COM while (acount > 0) { 1624*7978SPeter.Dunlap@Sun.COM if (strcasecmp(arr[acount - 1], "none") == 0) { 1625*7978SPeter.Dunlap@Sun.COM break; 1626*7978SPeter.Dunlap@Sun.COM } 1627*7978SPeter.Dunlap@Sun.COM if ((it_common_convert_sa(arr[acount - 1], 1628*7978SPeter.Dunlap@Sun.COM &sa, 0)) == NULL) { 1629*7978SPeter.Dunlap@Sun.COM PROPERR(errs, arr[acount - 1], 1630*7978SPeter.Dunlap@Sun.COM gettext("invalid address")); 1631*7978SPeter.Dunlap@Sun.COM errcnt++; 1632*7978SPeter.Dunlap@Sun.COM } 1633*7978SPeter.Dunlap@Sun.COM acount--; 1634*7978SPeter.Dunlap@Sun.COM } 1635*7978SPeter.Dunlap@Sun.COM 1636*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_RADIUS_SECRET) == 0) { 1637*7978SPeter.Dunlap@Sun.COM if (!val) { 1638*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1639*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1640*7978SPeter.Dunlap@Sun.COM errcnt++; 1641*7978SPeter.Dunlap@Sun.COM continue; 1642*7978SPeter.Dunlap@Sun.COM } 1643*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_RADIUS_SERVER) == 0) { 1644*7978SPeter.Dunlap@Sun.COM struct sockaddr_storage sa; 1645*7978SPeter.Dunlap@Sun.COM 1646*7978SPeter.Dunlap@Sun.COM if (!val) { 1647*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1648*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1649*7978SPeter.Dunlap@Sun.COM errcnt++; 1650*7978SPeter.Dunlap@Sun.COM continue; 1651*7978SPeter.Dunlap@Sun.COM } 1652*7978SPeter.Dunlap@Sun.COM 1653*7978SPeter.Dunlap@Sun.COM if ((it_common_convert_sa(val, &sa, 1654*7978SPeter.Dunlap@Sun.COM DEFAULT_RADIUS_PORT)) == NULL) { 1655*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1656*7978SPeter.Dunlap@Sun.COM gettext("invalid address")); 1657*7978SPeter.Dunlap@Sun.COM errcnt++; 1658*7978SPeter.Dunlap@Sun.COM } else { 1659*7978SPeter.Dunlap@Sun.COM /* 1660*7978SPeter.Dunlap@Sun.COM * rewrite this property to ensure port 1661*7978SPeter.Dunlap@Sun.COM * number is added. 1662*7978SPeter.Dunlap@Sun.COM */ 1663*7978SPeter.Dunlap@Sun.COM char *rad = NULL; 1664*7978SPeter.Dunlap@Sun.COM 1665*7978SPeter.Dunlap@Sun.COM if (sockaddr_to_str(&sa, &rad) == 0) { 1666*7978SPeter.Dunlap@Sun.COM (void) nvlist_add_string(nvl, 1667*7978SPeter.Dunlap@Sun.COM name, rad); 1668*7978SPeter.Dunlap@Sun.COM } 1669*7978SPeter.Dunlap@Sun.COM } 1670*7978SPeter.Dunlap@Sun.COM } else { 1671*7978SPeter.Dunlap@Sun.COM /* unrecognized property */ 1672*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, gettext("unrecognized property")); 1673*7978SPeter.Dunlap@Sun.COM errcnt++; 1674*7978SPeter.Dunlap@Sun.COM } 1675*7978SPeter.Dunlap@Sun.COM } 1676*7978SPeter.Dunlap@Sun.COM 1677*7978SPeter.Dunlap@Sun.COM /* 1678*7978SPeter.Dunlap@Sun.COM * if auth = radius, ensure radius server & secret are set. 1679*7978SPeter.Dunlap@Sun.COM */ 1680*7978SPeter.Dunlap@Sun.COM if (auth) { 1681*7978SPeter.Dunlap@Sun.COM if (strcmp(auth, PA_AUTH_RADIUS) == 0) { 1682*7978SPeter.Dunlap@Sun.COM /* need server & secret for radius */ 1683*7978SPeter.Dunlap@Sun.COM if (!nvlist_exists(nvl, PROP_RADIUS_SERVER)) { 1684*7978SPeter.Dunlap@Sun.COM PROPERR(errs, PROP_RADIUS_SERVER, 1685*7978SPeter.Dunlap@Sun.COM gettext("missing required property")); 1686*7978SPeter.Dunlap@Sun.COM errcnt++; 1687*7978SPeter.Dunlap@Sun.COM } 1688*7978SPeter.Dunlap@Sun.COM if (!nvlist_exists(nvl, PROP_RADIUS_SECRET)) { 1689*7978SPeter.Dunlap@Sun.COM PROPERR(errs, PROP_RADIUS_SECRET, 1690*7978SPeter.Dunlap@Sun.COM gettext("missing required property")); 1691*7978SPeter.Dunlap@Sun.COM errcnt++; 1692*7978SPeter.Dunlap@Sun.COM } 1693*7978SPeter.Dunlap@Sun.COM } 1694*7978SPeter.Dunlap@Sun.COM } 1695*7978SPeter.Dunlap@Sun.COM 1696*7978SPeter.Dunlap@Sun.COM if (errcnt) { 1697*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1698*7978SPeter.Dunlap@Sun.COM } 1699*7978SPeter.Dunlap@Sun.COM 1700*7978SPeter.Dunlap@Sun.COM return (0); 1701*7978SPeter.Dunlap@Sun.COM } 1702*7978SPeter.Dunlap@Sun.COM 1703*7978SPeter.Dunlap@Sun.COM /* 1704*7978SPeter.Dunlap@Sun.COM * Goes through the ini property list and validates 1705*7978SPeter.Dunlap@Sun.COM * each entry. If errs is non-NULL, will return explicit errors 1706*7978SPeter.Dunlap@Sun.COM * for each property that fails validation. 1707*7978SPeter.Dunlap@Sun.COM */ 1708*7978SPeter.Dunlap@Sun.COM static int 1709*7978SPeter.Dunlap@Sun.COM it_validate_iniprops(nvlist_t *nvl, nvlist_t *errs) 1710*7978SPeter.Dunlap@Sun.COM { 1711*7978SPeter.Dunlap@Sun.COM int errcnt = 0; 1712*7978SPeter.Dunlap@Sun.COM nvpair_t *nvp = NULL; 1713*7978SPeter.Dunlap@Sun.COM data_type_t nvtype; 1714*7978SPeter.Dunlap@Sun.COM char *name; 1715*7978SPeter.Dunlap@Sun.COM char *val; 1716*7978SPeter.Dunlap@Sun.COM 1717*7978SPeter.Dunlap@Sun.COM if (!nvl) { 1718*7978SPeter.Dunlap@Sun.COM return (0); 1719*7978SPeter.Dunlap@Sun.COM } 1720*7978SPeter.Dunlap@Sun.COM 1721*7978SPeter.Dunlap@Sun.COM while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 1722*7978SPeter.Dunlap@Sun.COM name = nvpair_name(nvp); 1723*7978SPeter.Dunlap@Sun.COM nvtype = nvpair_type(nvp); 1724*7978SPeter.Dunlap@Sun.COM 1725*7978SPeter.Dunlap@Sun.COM if (!name) { 1726*7978SPeter.Dunlap@Sun.COM continue; 1727*7978SPeter.Dunlap@Sun.COM } 1728*7978SPeter.Dunlap@Sun.COM 1729*7978SPeter.Dunlap@Sun.COM if (strcmp(name, PROP_CHAP_USER) == 0) { 1730*7978SPeter.Dunlap@Sun.COM if (nvtype != DATA_TYPE_STRING) { 1731*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1732*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1733*7978SPeter.Dunlap@Sun.COM errcnt++; 1734*7978SPeter.Dunlap@Sun.COM continue; 1735*7978SPeter.Dunlap@Sun.COM } 1736*7978SPeter.Dunlap@Sun.COM } else if (strcmp(name, PROP_CHAP_SECRET) == 0) { 1737*7978SPeter.Dunlap@Sun.COM /* 1738*7978SPeter.Dunlap@Sun.COM * must be between 12 and 255 chars in cleartext. 1739*7978SPeter.Dunlap@Sun.COM * will be base64 encoded when it's set. 1740*7978SPeter.Dunlap@Sun.COM */ 1741*7978SPeter.Dunlap@Sun.COM if (nvtype == DATA_TYPE_STRING) { 1742*7978SPeter.Dunlap@Sun.COM val = NULL; 1743*7978SPeter.Dunlap@Sun.COM (void) nvpair_value_string(nvp, &val); 1744*7978SPeter.Dunlap@Sun.COM } 1745*7978SPeter.Dunlap@Sun.COM 1746*7978SPeter.Dunlap@Sun.COM if (!val) { 1747*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, 1748*7978SPeter.Dunlap@Sun.COM gettext("must be a string value")); 1749*7978SPeter.Dunlap@Sun.COM errcnt++; 1750*7978SPeter.Dunlap@Sun.COM continue; 1751*7978SPeter.Dunlap@Sun.COM } 1752*7978SPeter.Dunlap@Sun.COM } else { 1753*7978SPeter.Dunlap@Sun.COM /* unrecognized property */ 1754*7978SPeter.Dunlap@Sun.COM PROPERR(errs, name, gettext("unrecognized property")); 1755*7978SPeter.Dunlap@Sun.COM errcnt++; 1756*7978SPeter.Dunlap@Sun.COM } 1757*7978SPeter.Dunlap@Sun.COM } 1758*7978SPeter.Dunlap@Sun.COM 1759*7978SPeter.Dunlap@Sun.COM if (errcnt) { 1760*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1761*7978SPeter.Dunlap@Sun.COM } 1762*7978SPeter.Dunlap@Sun.COM 1763*7978SPeter.Dunlap@Sun.COM return (0); 1764*7978SPeter.Dunlap@Sun.COM } 1765*7978SPeter.Dunlap@Sun.COM 1766*7978SPeter.Dunlap@Sun.COM static int 1767*7978SPeter.Dunlap@Sun.COM it_iqn_generate(char *iqn_buf, int iqn_buf_len, char *opt_iqn_suffix) 1768*7978SPeter.Dunlap@Sun.COM { 1769*7978SPeter.Dunlap@Sun.COM int ret; 1770*7978SPeter.Dunlap@Sun.COM uuid_t id; 1771*7978SPeter.Dunlap@Sun.COM char id_str[UUID_PRINTABLE_STRING_LENGTH]; 1772*7978SPeter.Dunlap@Sun.COM 1773*7978SPeter.Dunlap@Sun.COM uuid_generate_random(id); 1774*7978SPeter.Dunlap@Sun.COM uuid_unparse(id, id_str); 1775*7978SPeter.Dunlap@Sun.COM 1776*7978SPeter.Dunlap@Sun.COM if (opt_iqn_suffix) { 1777*7978SPeter.Dunlap@Sun.COM ret = snprintf(iqn_buf, iqn_buf_len, "iqn.1986-03.com.sun:" 1778*7978SPeter.Dunlap@Sun.COM "%02d:%s.%s", TARGET_NAME_VERS, id_str, opt_iqn_suffix); 1779*7978SPeter.Dunlap@Sun.COM } else { 1780*7978SPeter.Dunlap@Sun.COM ret = snprintf(iqn_buf, iqn_buf_len, "iqn.1986-03.com.sun:" 1781*7978SPeter.Dunlap@Sun.COM "%02d:%s", TARGET_NAME_VERS, id_str); 1782*7978SPeter.Dunlap@Sun.COM } 1783*7978SPeter.Dunlap@Sun.COM 1784*7978SPeter.Dunlap@Sun.COM if (ret > iqn_buf_len) { 1785*7978SPeter.Dunlap@Sun.COM return (1); 1786*7978SPeter.Dunlap@Sun.COM } 1787*7978SPeter.Dunlap@Sun.COM 1788*7978SPeter.Dunlap@Sun.COM return (0); 1789*7978SPeter.Dunlap@Sun.COM } 1790*7978SPeter.Dunlap@Sun.COM 1791*7978SPeter.Dunlap@Sun.COM static int 1792*7978SPeter.Dunlap@Sun.COM it_val_pass(char *name, char *val, nvlist_t *e) 1793*7978SPeter.Dunlap@Sun.COM { 1794*7978SPeter.Dunlap@Sun.COM size_t sz; 1795*7978SPeter.Dunlap@Sun.COM 1796*7978SPeter.Dunlap@Sun.COM if (!name || !val) { 1797*7978SPeter.Dunlap@Sun.COM return (EINVAL); 1798*7978SPeter.Dunlap@Sun.COM } 1799*7978SPeter.Dunlap@Sun.COM 1800*7978SPeter.Dunlap@Sun.COM /* 1801*7978SPeter.Dunlap@Sun.COM * must be at least 12 chars and less than 256 chars cleartext. 1802*7978SPeter.Dunlap@Sun.COM */ 1803*7978SPeter.Dunlap@Sun.COM sz = strlen(val); 1804*7978SPeter.Dunlap@Sun.COM 1805*7978SPeter.Dunlap@Sun.COM /* 1806*7978SPeter.Dunlap@Sun.COM * Since we will be automatically encoding secrets we don't really 1807*7978SPeter.Dunlap@Sun.COM * need the prefix anymore. 1808*7978SPeter.Dunlap@Sun.COM */ 1809*7978SPeter.Dunlap@Sun.COM if (sz < 12) { 1810*7978SPeter.Dunlap@Sun.COM PROPERR(e, name, gettext("secret too short")); 1811*7978SPeter.Dunlap@Sun.COM } else if (sz > 255) { 1812*7978SPeter.Dunlap@Sun.COM PROPERR(e, name, gettext("secret too long")); 1813*7978SPeter.Dunlap@Sun.COM } else { 1814*7978SPeter.Dunlap@Sun.COM /* all is well */ 1815*7978SPeter.Dunlap@Sun.COM return (0); 1816*7978SPeter.Dunlap@Sun.COM } 1817*7978SPeter.Dunlap@Sun.COM 1818*7978SPeter.Dunlap@Sun.COM return (1); 1819*7978SPeter.Dunlap@Sun.COM } 1820*7978SPeter.Dunlap@Sun.COM 1821*7978SPeter.Dunlap@Sun.COM /* 1822*7978SPeter.Dunlap@Sun.COM * Function: validate_iscsi_name() 1823*7978SPeter.Dunlap@Sun.COM * 1824*7978SPeter.Dunlap@Sun.COM * Ensures the passed-in string is a valid IQN or EUI iSCSI name 1825*7978SPeter.Dunlap@Sun.COM * 1826*7978SPeter.Dunlap@Sun.COM */ 1827*7978SPeter.Dunlap@Sun.COM boolean_t 1828*7978SPeter.Dunlap@Sun.COM validate_iscsi_name(char *in_name) 1829*7978SPeter.Dunlap@Sun.COM { 1830*7978SPeter.Dunlap@Sun.COM size_t in_len; 1831*7978SPeter.Dunlap@Sun.COM int i; 1832*7978SPeter.Dunlap@Sun.COM char month[3]; 1833*7978SPeter.Dunlap@Sun.COM 1834*7978SPeter.Dunlap@Sun.COM if (in_name == NULL) { 1835*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1836*7978SPeter.Dunlap@Sun.COM } 1837*7978SPeter.Dunlap@Sun.COM 1838*7978SPeter.Dunlap@Sun.COM in_len = strlen(in_name); 1839*7978SPeter.Dunlap@Sun.COM if (in_len < 12) { 1840*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1841*7978SPeter.Dunlap@Sun.COM } 1842*7978SPeter.Dunlap@Sun.COM 1843*7978SPeter.Dunlap@Sun.COM if (strncasecmp(in_name, "iqn.", 4) == 0) { 1844*7978SPeter.Dunlap@Sun.COM /* 1845*7978SPeter.Dunlap@Sun.COM * IQN names are iqn.yyyy-mm.<xxx> 1846*7978SPeter.Dunlap@Sun.COM */ 1847*7978SPeter.Dunlap@Sun.COM if ((!isdigit(in_name[4])) || 1848*7978SPeter.Dunlap@Sun.COM (!isdigit(in_name[5])) || 1849*7978SPeter.Dunlap@Sun.COM (!isdigit(in_name[6])) || 1850*7978SPeter.Dunlap@Sun.COM (!isdigit(in_name[7])) || 1851*7978SPeter.Dunlap@Sun.COM (in_name[8] != '-') || 1852*7978SPeter.Dunlap@Sun.COM (!isdigit(in_name[9])) || 1853*7978SPeter.Dunlap@Sun.COM (!isdigit(in_name[10])) || 1854*7978SPeter.Dunlap@Sun.COM (in_name[11] != '.')) { 1855*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1856*7978SPeter.Dunlap@Sun.COM } 1857*7978SPeter.Dunlap@Sun.COM 1858*7978SPeter.Dunlap@Sun.COM (void) strncpy(month, &(in_name[9]), 2); 1859*7978SPeter.Dunlap@Sun.COM month[2] = '\0'; 1860*7978SPeter.Dunlap@Sun.COM 1861*7978SPeter.Dunlap@Sun.COM i = atoi(month); 1862*7978SPeter.Dunlap@Sun.COM if ((i < 0) || (i > 12)) { 1863*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1864*7978SPeter.Dunlap@Sun.COM } 1865*7978SPeter.Dunlap@Sun.COM 1866*7978SPeter.Dunlap@Sun.COM /* Finally, validate the overall length, in wide chars */ 1867*7978SPeter.Dunlap@Sun.COM in_len = mbstowcs(NULL, in_name, 0); 1868*7978SPeter.Dunlap@Sun.COM if (in_len > ISCSI_NAME_LEN_MAX) { 1869*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1870*7978SPeter.Dunlap@Sun.COM } 1871*7978SPeter.Dunlap@Sun.COM } else if (strncasecmp(in_name, "eui.", 4) == 0) { 1872*7978SPeter.Dunlap@Sun.COM /* 1873*7978SPeter.Dunlap@Sun.COM * EUI names are "eui." + 16 hex chars 1874*7978SPeter.Dunlap@Sun.COM */ 1875*7978SPeter.Dunlap@Sun.COM if (in_len != 20) { 1876*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1877*7978SPeter.Dunlap@Sun.COM } 1878*7978SPeter.Dunlap@Sun.COM 1879*7978SPeter.Dunlap@Sun.COM for (i = 4; i < in_len; i++) { 1880*7978SPeter.Dunlap@Sun.COM if (!isxdigit(in_name[i])) { 1881*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1882*7978SPeter.Dunlap@Sun.COM } 1883*7978SPeter.Dunlap@Sun.COM } 1884*7978SPeter.Dunlap@Sun.COM } else { 1885*7978SPeter.Dunlap@Sun.COM return (B_FALSE); 1886*7978SPeter.Dunlap@Sun.COM } 1887*7978SPeter.Dunlap@Sun.COM 1888*7978SPeter.Dunlap@Sun.COM return (B_TRUE); 1889*7978SPeter.Dunlap@Sun.COM } 1890