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
it_config_load(it_config_t ** cfg)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
it_config_commit(it_config_t * cfg)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
2125de03f84SSue Gleeson if (ret == 0) {
2135de03f84SSue Gleeson iscsit_fd = open(ISCSIT_NODE, O_RDWR|O_EXCL);
2145de03f84SSue Gleeson if (iscsit_fd != -1) {
2155de03f84SSue Gleeson iop.set_cfg_vers = ISCSIT_API_VERS0;
2165de03f84SSue Gleeson iop.set_cfg_pnvlist = packednv;
2175de03f84SSue Gleeson iop.set_cfg_pnvlist_len = pnv_size;
2185de03f84SSue Gleeson if ((ioctl(iscsit_fd, ISCSIT_IOC_SET_CONFIG,
2195de03f84SSue Gleeson &iop)) != 0) {
2205de03f84SSue Gleeson ret = errno;
2215de03f84SSue Gleeson }
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);
231a6d42e7dSPeter Dunlap }
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
it_config_setprop(it_config_t * cfg,nvlist_t * proplist,nvlist_t ** errlist)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
4087f6f3ee7SPeter 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
it_config_free(it_config_t * cfg)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
it_tgt_create(it_config_t * cfg,it_tgt_t ** tgt,char * tgt_name)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
it_tgt_setprop(it_config_t * cfg,it_tgt_t * tgt,nvlist_t * proplist,nvlist_t ** errlist)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
6577f6f3ee7SPeter Gill 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
it_tgt_delete(it_config_t * cfg,it_tgt_t * tgt,boolean_t force)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
it_tgt_free(it_tgt_t * tgt)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
it_tpgt_create(it_config_t * cfg,it_tgt_t * tgt,it_tpgt_t ** tpgt,char * tpg_name,uint16_t tpgt_tag)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
it_tpgt_delete(it_config_t * cfg,it_tgt_t * tgt,it_tpgt_t * tpgt)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
it_tpgt_free(it_tpgt_t * tpgt)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
it_tpg_create(it_config_t * cfg,it_tpg_t ** tpg,char * tpg_name,char * portal_ip_port)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
it_tpg_delete(it_config_t * cfg,it_tpg_t * tpg,boolean_t force)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
it_tpg_free(it_tpg_t * tpg)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
it_portal_create(it_config_t * cfg,it_tpg_t * tpg,it_portal_t ** portal,char * portal_ip_port)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
it_portal_delete(it_config_t * cfg,it_tpg_t * tpg,it_portal_t * portal)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
it_ini_create(it_config_t * cfg,it_ini_t ** ini,char * ini_node_name)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
it_ini_setprop(it_ini_t * ini,nvlist_t * proplist,nvlist_t ** errlist)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
14157f6f3ee7SPeter Gill 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
it_ini_delete(it_config_t * cfg,it_ini_t * ini)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
it_ini_free(it_ini_t * ini)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
it_validate_tgtprops(nvlist_t * nvl,nvlist_t * errs)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
it_validate_configprops(nvlist_t * nvl,nvlist_t * errs)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
1754bf604c64SPeter 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
1763a6d42e7dSPeter 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
it_validate_iniprops(nvlist_t * nvl,nvlist_t * errs)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
it_iqn_generate(char * iqn_buf,int iqn_buf_len,char * opt_iqn_suffix)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
it_val_pass(char * name,char * val,nvlist_t * e)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
validate_iscsi_name(char * in_name)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
is_iscsit_enabled(void)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
canonical_iscsi_name(char * tgt)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
iqnstr(char * s)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
euistr(char * s)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
free_empty_errlist(nvlist_t ** errlist)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