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