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