Home | History | Annotate | Download | only in iscsitgtd
      1  2314    mcneal /*
      2  2314    mcneal  * CDDL HEADER START
      3  2314    mcneal  *
      4  2314    mcneal  * The contents of this file are subject to the terms of the
      5  2314    mcneal  * Common Development and Distribution License (the "License").
      6  2314    mcneal  * You may not use this file except in compliance with the License.
      7  2314    mcneal  *
      8  2314    mcneal  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  2314    mcneal  * or http://www.opensolaris.org/os/licensing.
     10  2314    mcneal  * See the License for the specific language governing permissions
     11  2314    mcneal  * and limitations under the License.
     12  2314    mcneal  *
     13  2314    mcneal  * When distributing Covered Code, include this CDDL HEADER in each
     14  2314    mcneal  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  2314    mcneal  * If applicable, add the following below this CDDL HEADER, with the
     16  2314    mcneal  * fields enclosed by brackets "[]" replaced with your own identifying
     17  2314    mcneal  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  2314    mcneal  *
     19  2314    mcneal  * CDDL HEADER END
     20  2314    mcneal  */
     21  2314    mcneal 
     22  2314    mcneal /*
     23  5806  zl149053  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  2314    mcneal  * Use is subject to license terms.
     25  2314    mcneal  */
     26  2314    mcneal 
     27  2314    mcneal #include <sys/types.h>
     28  2314    mcneal #include <time.h>
     29  2314    mcneal #include <sys/utsname.h>
     30  2314    mcneal #include <unistd.h>
     31  2314    mcneal #include <sys/param.h>
     32  2314    mcneal #include <fcntl.h>
     33  2314    mcneal #include <sys/stat.h>
     34  2314    mcneal #include <errno.h>
     35  2314    mcneal #include <strings.h>
     36  2314    mcneal #include <assert.h>
     37  2314    mcneal #include <sys/socket.h>
     38  2314    mcneal #include <netdb.h>
     39  4483  zl149053 #include <libgen.h>
     40  6761  nbhavyan #include <libzfs.h>
     41  7018  ks202890 #include <syslog.h>
     42  2314    mcneal 
     43  3126       ahl #include <iscsitgt_impl.h>
     44  2314    mcneal #include "queue.h"
     45  2314    mcneal #include "utility.h"
     46  2314    mcneal #include "iscsi_cmd.h"
     47  2314    mcneal #include "target.h"
     48  2314    mcneal #include "errcode.h"
     49  4348  ts143224 #include "isns_client.h"
     50  5137  zl149053 #include "mgmt_scf.h"
     51  2314    mcneal 
     52  6278   jdunham static char *modify_target(tgt_node_t *x, ucred_t *cred);
     53  5137  zl149053 static char *modify_initiator(tgt_node_t *x);
     54  5137  zl149053 static char *modify_admin(tgt_node_t *x);
     55  5137  zl149053 static char *modify_tpgt(tgt_node_t *x);
     56  6278   jdunham static char *modify_zfs(tgt_node_t *x, ucred_t *cred);
     57  6761  nbhavyan static char *validate_zfs_iscsitgt(tgt_node_t *x);
     58  3126       ahl static Boolean_t modify_element(char *, char *, tgt_node_t *, match_type_t);
     59  6783  pc198268 static Boolean_t delete_element(char *,  tgt_node_t *, match_type_t);
     60  2314    mcneal 
     61  2314    mcneal /*
     62  2314    mcneal  * []----
     63  2314    mcneal  * | modify_func -- dispatch routine for objects
     64  2314    mcneal  * []----
     65  2314    mcneal  */
     66  2314    mcneal /*ARGSUSED*/
     67  2314    mcneal void
     68  3545    mcneal modify_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt,
     69  3545    mcneal     ucred_t *cred)
     70  2314    mcneal {
     71  3126       ahl 	tgt_node_t	*x;
     72  2314    mcneal 	char		*reply_msg	= NULL;
     73  2314    mcneal 
     74  5806  zl149053 	x = p->x_child;
     75  5806  zl149053 
     76  5806  zl149053 	if (p->x_child == NULL) {
     77  5806  zl149053 		xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
     78  5806  zl149053 	} else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) {
     79  6278   jdunham 		reply_msg = modify_zfs(x, cred);
     80  5806  zl149053 	} else if (check_auth_modify(cred) != True) {
     81  5137  zl149053 		xml_rtn_msg(&reply_msg, ERR_NO_PERMISSION);
     82  2314    mcneal 	} else {
     83  2314    mcneal 		if (x->x_name == NULL) {
     84  2314    mcneal 			xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT);
     85  2314    mcneal 		} else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) {
     86  6278   jdunham 			reply_msg = modify_target(x, cred);
     87  2314    mcneal 		} else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) {
     88  5137  zl149053 			reply_msg = modify_initiator(x);
     89  2314    mcneal 		} else if (strcmp(x->x_name, XML_ELEMENT_ADMIN) == 0) {
     90  5137  zl149053 			reply_msg = modify_admin(x);
     91  2314    mcneal 		} else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) {
     92  5137  zl149053 			reply_msg = modify_tpgt(x);
     93  2314    mcneal 		} else {
     94  2314    mcneal 			xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT);
     95  2314    mcneal 		}
     96  2314    mcneal 	}
     97  2314    mcneal 	queue_message_set(reply, 0, msg_mgmt_rply, reply_msg);
     98  2314    mcneal }
     99  2314    mcneal 
    100  2314    mcneal /*
    101  2314    mcneal  * []----
    102  2314    mcneal  * | modify_target -- updates one or more properties for a target
    103  2314    mcneal  * []----
    104  2314    mcneal  */
    105  2314    mcneal static char *
    106  6278   jdunham modify_target(tgt_node_t *x, ucred_t *cred)
    107  2314    mcneal {
    108  4348  ts143224 	char		*msg		= NULL;
    109  4348  ts143224 	char		*name		= NULL;
    110  4483  zl149053 	char		iscsi_path[MAXPATHLEN];
    111  5137  zl149053 	char		targ_name[64];
    112  4483  zl149053 	char		*iscsi		= NULL;
    113  4348  ts143224 	char		*prop		= NULL;
    114  4348  ts143224 	char		path[MAXPATHLEN];
    115  4348  ts143224 	char		*m;
    116  4348  ts143224 	char		buf[512];		/* one sector size block */
    117  4348  ts143224 	tgt_node_t	*t		= NULL;
    118  4348  ts143224 	tgt_node_t	*list		= NULL;
    119  4348  ts143224 	tgt_node_t	*c		= NULL;
    120  7857       Tim 	tgt_node_t	*node		= NULL;
    121  4348  ts143224 	tgt_node_t	*tpgt		= NULL;
    122  2314    mcneal 	Boolean_t	change_made	= False;
    123  4348  ts143224 	int		lun		= 0;
    124  5137  zl149053 	int		fd;
    125  4348  ts143224 	uint64_t	val, new_lu_size, cur_lu_size;
    126  2314    mcneal 	struct stat	st;
    127  6278   jdunham 	uint32_t	isns_mods	= 0;
    128  2314    mcneal 
    129  7725       Tim 	(void) pthread_rwlock_wrlock(&targ_config_mutex);
    130  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
    131  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
    132  7725       Tim 		goto error;
    133  2314    mcneal 	}
    134  2314    mcneal 
    135  6653  ts143224 	while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
    136  2314    mcneal 	    t)) != NULL) {
    137  2314    mcneal 		if (strcmp(t->x_value, name) == 0) {
    138  2314    mcneal 			break;
    139  2314    mcneal 		}
    140  6278   jdunham 	}
    141  6278   jdunham 	if (t == NULL) {
    142  6278   jdunham 		free(name);
    143  6278   jdunham 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
    144  7725       Tim 		goto error;
    145  6278   jdunham 	}
    146  6278   jdunham 
    147  6278   jdunham 	if (tgt_find_attr_str(t, XML_ELEMENT_INCORE, &m) == True) {
    148  6278   jdunham 		if (strcmp(m, "true") == 0) {
    149  6278   jdunham 			free(m);
    150  7984       Tim 			free(name);
    151  7725       Tim 			(void) pthread_rwlock_unlock(&targ_config_mutex);
    152  6278   jdunham 			return (modify_zfs(x, cred));
    153  6278   jdunham 		}
    154  6278   jdunham 		free(m);
    155  2314    mcneal 	}
    156  2314    mcneal 
    157  4483  zl149053 	/*
    158  4483  zl149053 	 * Under base dir, file 'target name' is a symbolic link
    159  4483  zl149053 	 * to the real directory 'IQN name' which stores params and back
    160  4483  zl149053 	 * storage. Therefore we can easily get IQN name from target
    161  4483  zl149053 	 * name by read the symbolic link content.
    162  4483  zl149053 	 */
    163  6821  nbhavyan 	(void) snprintf(path, sizeof (path), "%s/%s", target_basedir, name);
    164  4483  zl149053 	bzero(iscsi_path, sizeof (iscsi_path));
    165  6821  nbhavyan 	(void) readlink(path, iscsi_path, sizeof (iscsi_path));
    166  4483  zl149053 	iscsi = basename(iscsi_path);
    167  4483  zl149053 
    168  2314    mcneal 	/* ---- Finished with these so go ahead and release the memory ---- */
    169  6821  nbhavyan 	(void) strncpy(targ_name, name, sizeof (targ_name));
    170  2314    mcneal 	free(name);
    171  2314    mcneal 
    172  2314    mcneal 	/*
    173  2314    mcneal 	 * Grow the LU. We currently do not support shrinking the LU and
    174  2314    mcneal 	 * that is only because it's unknown if any applications could support
    175  2314    mcneal 	 * that type of data loss. To support shrinking all that would be
    176  2314    mcneal 	 * needed is to remove the new/old size check and perform a truncation.
    177  2314    mcneal 	 * The actually truncation request should be shipped off to the T10
    178  2314    mcneal 	 * layer so that the LU thread can remap the smaller size without
    179  2314    mcneal 	 * anyone accessing the data.
    180  2314    mcneal 	 */
    181  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) {
    182  2314    mcneal 		if (prop == NULL) {
    183  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
    184  7725       Tim 			goto error;
    185  2314    mcneal 		}
    186  2314    mcneal 		if (strtoll_multiplier(prop, &new_lu_size) == False) {
    187  2314    mcneal 			free(prop);
    188  2314    mcneal 			xml_rtn_msg(&msg, ERR_INVALID_SIZE);
    189  7725       Tim 			goto error;
    190  2314    mcneal 		}
    191  2314    mcneal 		free(prop);
    192  2314    mcneal 		if ((new_lu_size % 512LL) != 0) {
    193  2314    mcneal 			xml_rtn_msg(&msg, ERR_SIZE_MOD_BLOCK);
    194  7725       Tim 			goto error;
    195  2314    mcneal 		}
    196  2314    mcneal 		new_lu_size /= 512LL;
    197  2314    mcneal 
    198  2314    mcneal 		/* ---- default to LUN 0 ---- */
    199  3126       ahl 		(void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun);
    200  2314    mcneal 
    201  4487  zl149053 		/* ---- read in current parameters ---- */
    202  7857       Tim 		if (mgmt_get_param(&node, targ_name, lun) == False) {
    203  7857       Tim 			xml_rtn_msg(&msg, ERR_OPEN_PARAM_FILE_FAILED);
    204  7857       Tim 			goto error;
    205  7857       Tim 		}
    206  2314    mcneal 
    207  2314    mcneal 		/* ---- validate that we're indeed growing the LU ---- */
    208  3126       ahl 		if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) ==
    209  2314    mcneal 		    False) {
    210  2314    mcneal 			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
    211  7725       Tim 			goto error;
    212  2314    mcneal 		}
    213  2314    mcneal 		if (strtoll_multiplier(prop, &cur_lu_size) == False) {
    214  2314    mcneal 			free(prop);
    215  2314    mcneal 			xml_rtn_msg(&msg, ERR_INVALID_SIZE);
    216  7725       Tim 			goto error;
    217  2314    mcneal 		}
    218  2314    mcneal 		free(prop);
    219  2314    mcneal 
    220  2314    mcneal 		if (new_lu_size < cur_lu_size) {
    221  2314    mcneal 			xml_rtn_msg(&msg, ERR_CANT_SHRINK_LU);
    222  7725       Tim 			goto error;
    223  2314    mcneal 		}
    224  2314    mcneal 
    225  2314    mcneal 		/* ---- check that this LU is of type 'disk' or 'tape' ---- */
    226  3126       ahl 		if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) ==
    227  2314    mcneal 		    False) {
    228  2314    mcneal 			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
    229  7725       Tim 			goto error;
    230  2314    mcneal 		}
    231  2314    mcneal 		if ((strcmp(prop, TGT_TYPE_DISK) != 0) &&
    232  2314    mcneal 		    (strcmp(prop, TGT_TYPE_TAPE) != 0)) {
    233  2314    mcneal 			xml_rtn_msg(&msg, ERR_RESIZE_WRONG_DTYPE);
    234  7984       Tim 			free(prop);
    235  7725       Tim 			goto error;
    236  2314    mcneal 		}
    237  2314    mcneal 		free(prop);
    238  2314    mcneal 
    239  2314    mcneal 		/* ---- validate the backing store is a regular file ---- */
    240  6821  nbhavyan 		(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
    241  6821  nbhavyan 		    target_basedir, iscsi, LUNBASE, lun);
    242  2314    mcneal 		if (stat(path, &st) == -1) {
    243  2314    mcneal 			xml_rtn_msg(&msg, ERR_STAT_BACKING_FAILED);
    244  7725       Tim 			goto error;
    245  2314    mcneal 		}
    246  2314    mcneal 		if ((st.st_mode & S_IFMT) != S_IFREG) {
    247  2314    mcneal 			xml_rtn_msg(&msg,
    248  2314    mcneal 			    ERR_DISK_BACKING_MUST_BE_REGULAR_FILE);
    249  7725       Tim 			goto error;
    250  2314    mcneal 		}
    251  2314    mcneal 
    252  2314    mcneal 		/* ---- update the parameter node with new size ---- */
    253  4483  zl149053 		if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &new_lu_size))
    254  7984       Tim 		    == NULL) {
    255  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    256  7725       Tim 			goto error;
    257  2314    mcneal 		}
    258  3126       ahl 		tgt_node_replace(node, c, MatchName);
    259  3126       ahl 		tgt_node_free(c);
    260  2314    mcneal 
    261  2314    mcneal 		/* ---- now update params file ---- */
    262  6821  nbhavyan 		(void) mgmt_param_save2scf(node, targ_name, lun);
    263  2314    mcneal 
    264  2314    mcneal 		/* ---- grow lu backing store ---- */
    265  6821  nbhavyan 		(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
    266  6821  nbhavyan 		    target_basedir, iscsi, LUNBASE, lun);
    267  2314    mcneal 		if ((fd = open(path, O_RDWR|O_CREAT|O_LARGEFILE, 0600)) < 0) {
    268  2314    mcneal 			xml_rtn_msg(&msg, ERR_LUN_NOT_FOUND);
    269  7725       Tim 			goto error;
    270  2314    mcneal 		}
    271  2314    mcneal 		(void) lseek(fd, (new_lu_size * 512LL) - 512LL, 0);
    272  2314    mcneal 		bzero(buf, sizeof (buf));
    273  2314    mcneal 		if (write(fd, buf, sizeof (buf)) != sizeof (buf)) {
    274  2314    mcneal 			xml_rtn_msg(&msg, ERR_LUN_NOT_GROWN);
    275  7984       Tim 			(void) close(fd);
    276  7725       Tim 			goto error;
    277  2314    mcneal 		}
    278  2314    mcneal 		(void) close(fd);
    279  2314    mcneal 
    280  2314    mcneal 		/* ---- send updates to current initiators via ASC/ASCQ ---- */
    281  2314    mcneal 		iscsi_capacity_change(iscsi, lun);
    282  2314    mcneal 
    283  2314    mcneal 		prop = NULL;
    284  3126       ahl 		tgt_node_free(node);
    285  7984       Tim 		node = NULL;
    286  4483  zl149053 		change_made = True;
    287  2314    mcneal 	}
    288  2314    mcneal 
    289  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
    290  2314    mcneal 		if (prop == NULL) {
    291  4348  ts143224 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
    292  7725       Tim 			goto error;
    293  2314    mcneal 		}
    294  2314    mcneal 
    295  2314    mcneal 		/*
    296  2314    mcneal 		 * Validate that the Target Portal Group Tag is reasonable.
    297  2314    mcneal 		 */
    298  2314    mcneal 		val = strtoll(prop, &m, 0);
    299  2314    mcneal 		if ((val < TPGT_MIN) || (val > TPGT_MAX) ||
    300  2314    mcneal 		    ((m != NULL) && (*m != '\0'))) {
    301  2314    mcneal 			xml_rtn_msg(&msg, ERR_INVALID_TPGT);
    302  2314    mcneal 			free(prop);
    303  7725       Tim 			goto error;
    304  4348  ts143224 		}
    305  4348  ts143224 
    306  4348  ts143224 		/* update isns only if TPGT contains ip_addr */
    307  6653  ts143224 		tpgt = NULL;
    308  6653  ts143224 		while ((tpgt = tgt_node_next_child(main_config,
    309  6653  ts143224 		    XML_ELEMENT_TPGT, tpgt)) != NULL) {
    310  4348  ts143224 			if (strcmp(prop, tpgt->x_value) != 0)
    311  4348  ts143224 				continue;
    312  4348  ts143224 			if (tgt_node_next(tpgt, XML_ELEMENT_IPADDR, NULL)
    313  4348  ts143224 			    != NULL) {
    314  4348  ts143224 				isns_mods |= ISNS_MOD_TPGT;
    315  4348  ts143224 				break;
    316  5137  zl149053 			} else {
    317  5137  zl149053 				xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR);
    318  7984       Tim 				free(prop);
    319  7725       Tim 				goto error;
    320  4348  ts143224 			}
    321  2314    mcneal 		}
    322  2314    mcneal 
    323  3126       ahl 		if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
    324  2314    mcneal 		    NULL) {
    325  2314    mcneal 			free(prop);
    326  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    327  7725       Tim 			goto error;
    328  2314    mcneal 		}
    329  2314    mcneal 
    330  3126       ahl 		if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST,
    331  2314    mcneal 		    NULL)) != NULL) {
    332  3126       ahl 			tgt_node_replace(list, c, MatchBoth);
    333  2314    mcneal 			/*
    334  3126       ahl 			 * tgt_node_replace will duplicate the child node
    335  3126       ahl 			 * tgt_node_add which is used below just links it
    336  2314    mcneal 			 * into the tree.
    337  2314    mcneal 			 */
    338  3126       ahl 			tgt_node_free(c);
    339  2314    mcneal 		} else {
    340  3126       ahl 			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
    341  2314    mcneal 			if (list == NULL) {
    342  2314    mcneal 				free(prop);
    343  2314    mcneal 				xml_rtn_msg(&msg, ERR_NO_MEM);
    344  7725       Tim 				goto error;
    345  2314    mcneal 			}
    346  3126       ahl 			tgt_node_add(list, c);
    347  3126       ahl 			tgt_node_add(t, list);
    348  2314    mcneal 		}
    349  4348  ts143224 
    350  2314    mcneal 		free(prop);
    351  2314    mcneal 		prop = NULL;
    352  2314    mcneal 		change_made = True;
    353  2314    mcneal 	}
    354  2314    mcneal 
    355  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
    356  2314    mcneal 		if (prop == NULL) {
    357  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
    358  7725       Tim 			goto error;
    359  2314    mcneal 		}
    360  2314    mcneal 
    361  6653  ts143224 		c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
    362  2314    mcneal 		if (c == NULL) {
    363  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    364  7984       Tim 			free(prop);
    365  7725       Tim 			goto error;
    366  2314    mcneal 		}
    367  3126       ahl 		if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST,
    368  2314    mcneal 		    NULL)) != NULL) {
    369  3126       ahl 			tgt_node_replace(list, c, MatchBoth);
    370  2314    mcneal 			/* ---- See above usage ---- */
    371  3126       ahl 			tgt_node_free(c);
    372  2314    mcneal 		} else {
    373  3126       ahl 			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
    374  2314    mcneal 			if (list == NULL) {
    375  2314    mcneal 				xml_rtn_msg(&msg, ERR_NO_MEM);
    376  7984       Tim 				free(prop);
    377  7725       Tim 				goto error;
    378  2314    mcneal 			}
    379  3126       ahl 			tgt_node_add(list, c);
    380  3126       ahl 			tgt_node_add(t, list);
    381  2314    mcneal 		}
    382  2314    mcneal 		free(prop);
    383  2314    mcneal 		prop = NULL;
    384  2314    mcneal 		change_made = True;
    385  2314    mcneal 	}
    386  2314    mcneal 
    387  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) {
    388  2314    mcneal 		if (prop == NULL) {
    389  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS);
    390  7725       Tim 			goto error;
    391  2314    mcneal 		}
    392  2314    mcneal 
    393  2314    mcneal 		if (modify_element(XML_ELEMENT_ALIAS, prop, t, MatchName) ==
    394  2314    mcneal 		    False) {
    395  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    396  7984       Tim 			free(prop);
    397  7725       Tim 			goto error;
    398  2314    mcneal 		}
    399  2314    mcneal 		free(prop);
    400  2314    mcneal 		prop = NULL;
    401  4348  ts143224 		isns_mods |= ISNS_MOD_ALIAS;
    402  2314    mcneal 		change_made = True;
    403  2314    mcneal 	}
    404  2314    mcneal 
    405  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) {
    406  2314    mcneal 		if (prop == NULL) {
    407  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV);
    408  7725       Tim 			goto error;
    409  2314    mcneal 		}
    410  2314    mcneal 
    411  2314    mcneal 		if ((strtoll_multiplier(prop, &val) == False) ||
    412  2314    mcneal 		    (val < MAXRCVDATA_MIN) || (val > MAXRCVDATA_MAX)) {
    413  2314    mcneal 			free(prop);
    414  2314    mcneal 			xml_rtn_msg(&msg, ERR_INVALID_MAXRECV);
    415  7725       Tim 			goto error;
    416  2314    mcneal 		}
    417  2314    mcneal 		free(prop);
    418  2314    mcneal 		if ((prop = malloc(32)) == NULL) {
    419  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    420  7725       Tim 			goto error;
    421  2314    mcneal 		}
    422  6821  nbhavyan 		(void) snprintf(prop, 32, "%d", val);
    423  2314    mcneal 
    424  2314    mcneal 		if (modify_element(XML_ELEMENT_MAXRECV, prop, t, MatchName) ==
    425  2314    mcneal 		    False) {
    426  2314    mcneal 			free(prop);
    427  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    428  7725       Tim 			goto error;
    429  2314    mcneal 		}
    430  2314    mcneal 		free(prop);
    431  2314    mcneal 		prop = NULL;
    432  2314    mcneal 		change_made = True;
    433  2314    mcneal 	}
    434  2314    mcneal 
    435  2314    mcneal 	if (change_made == True) {
    436  5137  zl149053 		if (mgmt_config_save2scf() == False) {
    437  4348  ts143224 			xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED);
    438  7725       Tim 			goto error;
    439  4348  ts143224 		}
    440  4348  ts143224 		if (isns_enabled() == True) {
    441  4348  ts143224 			if (isns_dev_update(t->x_value, isns_mods) != 0) {
    442  7018  ks202890 				xml_rtn_msg(&msg, ERR_ISNS_ERROR);
    443  7725       Tim 				goto error;
    444  4348  ts143224 			}
    445  4348  ts143224 		}
    446  4348  ts143224 		xml_rtn_msg(&msg, ERR_SUCCESS);
    447  2314    mcneal 	} else {
    448  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
    449  2314    mcneal 	}
    450  2314    mcneal 
    451  7725       Tim error:
    452  7725       Tim 	(void) pthread_rwlock_unlock(&targ_config_mutex);
    453  7857       Tim 	if (node)
    454  7857       Tim 		tgt_node_free(node);
    455  2314    mcneal 	return (msg);
    456  2314    mcneal }
    457  2314    mcneal 
    458  2314    mcneal /*
    459  2314    mcneal  * []----
    460  2314    mcneal  * | modify_initiator -- store the CHAP information for an initiator
    461  2314    mcneal  * []----
    462  2314    mcneal  */
    463  2314    mcneal static char *
    464  5137  zl149053 modify_initiator(tgt_node_t *x)
    465  2314    mcneal {
    466  4348  ts143224 	char		*msg		= NULL;
    467  4348  ts143224 	char		*name		= NULL;
    468  4348  ts143224 	char		*prop		= NULL;
    469  3126       ahl 	tgt_node_t	*inode		= NULL;
    470  2314    mcneal 	Boolean_t	changes_made	= False;
    471  2314    mcneal 
    472  7725       Tim 	(void) pthread_rwlock_wrlock(&targ_config_mutex);
    473  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
    474  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
    475  7725       Tim 		goto error;
    476  2314    mcneal 	}
    477  2314    mcneal 
    478  6653  ts143224 	while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
    479  2314    mcneal 	    inode)) != NULL) {
    480  2314    mcneal 		if (strcmp(inode->x_value, name) == 0)
    481  2314    mcneal 			break;
    482  2314    mcneal 	}
    483  2314    mcneal 
    484  2314    mcneal 	/*
    485  2314    mcneal 	 * We no longer need the name since we should have found the node
    486  2314    mcneal 	 * it refers to and this way we don't have to worry about freeing
    487  2314    mcneal 	 * the storage later.
    488  2314    mcneal 	 */
    489  2314    mcneal 	free(name);
    490  2314    mcneal 
    491  2314    mcneal 	if (inode == NULL) {
    492  2314    mcneal 		xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
    493  7725       Tim 		goto error;
    494  2314    mcneal 	}
    495  2314    mcneal 
    496  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) {
    497  2314    mcneal 		if (prop == NULL) {
    498  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPSECRET);
    499  7725       Tim 			goto error;
    500  2314    mcneal 		}
    501  2314    mcneal 
    502  2314    mcneal 		if (modify_element(XML_ELEMENT_CHAPSECRET, prop, inode,
    503  2314    mcneal 		    MatchName) == False) {
    504  6783  pc198268 			free(prop);
    505  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    506  7725       Tim 			goto error;
    507  2314    mcneal 		}
    508  2314    mcneal 		free(prop);
    509  6783  pc198268 		changes_made = True;
    510  6783  pc198268 	}
    511  6783  pc198268 
    512  6783  pc198268 	if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPSECRET,
    513  6783  pc198268 	    &prop) == True) {
    514  6783  pc198268 		if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
    515  6783  pc198268 			if (prop != NULL)
    516  6783  pc198268 				free(prop);
    517  6783  pc198268 			xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
    518  7725       Tim 			goto error;
    519  6783  pc198268 		}
    520  6783  pc198268 		free(prop);
    521  6783  pc198268 
    522  6783  pc198268 		if (delete_element(XML_ELEMENT_CHAPSECRET, inode,
    523  6783  pc198268 		    MatchName) == False) {
    524  6783  pc198268 			xml_rtn_msg(&msg, ERR_NO_MEM);
    525  7725       Tim 			goto error;
    526  6783  pc198268 		}
    527  2314    mcneal 		changes_made = True;
    528  2314    mcneal 	}
    529  2314    mcneal 
    530  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) {
    531  2314    mcneal 		if (prop == NULL) {
    532  2314    mcneal 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPNAME);
    533  7725       Tim 			goto error;
    534  2314    mcneal 		}
    535  2314    mcneal 
    536  2314    mcneal 		if (modify_element(XML_ELEMENT_CHAPNAME, prop, inode,
    537  2314    mcneal 		    MatchName) == False) {
    538  2314    mcneal 			xml_rtn_msg(&msg, ERR_NO_MEM);
    539  7725       Tim 			free(prop);
    540  7725       Tim 			goto error;
    541  2314    mcneal 		}
    542  2314    mcneal 		free(prop);
    543  6783  pc198268 		changes_made = True;
    544  6783  pc198268 	}
    545  6783  pc198268 
    546  6783  pc198268 	if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPNAME, &prop) == True) {
    547  6783  pc198268 		if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
    548  6783  pc198268 			if (prop != NULL)
    549  6783  pc198268 				free(prop);
    550  6783  pc198268 			xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
    551  7725       Tim 			goto error;
    552  6783  pc198268 		}
    553  6783  pc198268 		free(prop);
    554  6783  pc198268 
    555  6783  pc198268 
    556  6783  pc198268 		if (delete_element(XML_ELEMENT_CHAPNAME, inode,
    557  6783  pc198268 		    MatchName) == False) {
    558  6783  pc198268 			xml_rtn_msg(&msg, ERR_NO_MEM);
    559  7725       Tim 			goto error;
    560  6783  pc198268 		}
    561  2314    mcneal 		changes_made = True;
    562  2314    mcneal 	}
    563  2314    mcneal 
    564  2314    mcneal 	if (changes_made == True) {
    565  6861       htk 		if (mgmt_config_save2scf() == True) {
    566  2314    mcneal 			xml_rtn_msg(&msg, ERR_SUCCESS);
    567  6861       htk 		} else {
    568  6861       htk 			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
    569  6861       htk 		}
    570  2314    mcneal 	} else {
    571  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
    572  2314    mcneal 	}
    573  2314    mcneal 
    574  7725       Tim error:
    575  7725       Tim 	(void) pthread_rwlock_unlock(&targ_config_mutex);
    576  2314    mcneal 	return (msg);
    577  2314    mcneal }
    578  2314    mcneal 
    579  2314    mcneal /*
    580  2314    mcneal  * []----
    581  2314    mcneal  * | modify_admin -- modify one or more of the admin related props
    582  2314    mcneal  * []----
    583  2314    mcneal  */
    584  2314    mcneal static char *
    585  5137  zl149053 modify_admin(tgt_node_t *x)
    586  2314    mcneal {
    587  4348  ts143224 	char		*msg	= NULL;
    588  4348  ts143224 	char		*prop;
    589  2314    mcneal 	Boolean_t	changes_made = False;
    590  6920  ks202890 	Boolean_t	update_isns = False;
    591  2314    mcneal 	admin_table_t	*ap;
    592  2314    mcneal 
    593  2314    mcneal 	for (ap = admin_prop_list; ap->name; ap++) {
    594  3126       ahl 		if (tgt_find_value_str(x, ap->name, &prop) == True) {
    595  6920  ks202890 
    596  2314    mcneal 			if ((prop == NULL) || (strlen(prop) == 0))
    597  2314    mcneal 				break;
    598  2314    mcneal 
    599  2314    mcneal 			/*
    600  2314    mcneal 			 * Do the function call first if it exists which
    601  2314    mcneal 			 * will allow possible checking to be done first.
    602  2314    mcneal 			 */
    603  2314    mcneal 			if (ap->func) {
    604  6783  pc198268 				msg = (*ap->func)(ap->name, prop);
    605  6783  pc198268 				if (msg != NULL) {
    606  6783  pc198268 					free(prop);
    607  2314    mcneal 					return (msg);
    608  6783  pc198268 				}
    609  2314    mcneal 			}
    610  6783  pc198268 
    611  7725       Tim 			(void) pthread_rwlock_wrlock(&targ_config_mutex);
    612  6783  pc198268 			if (ap->delete_name == NULL) {
    613  6783  pc198268 				if (modify_element(ap->name, prop, main_config,
    614  6783  pc198268 				    MatchName) == False) {
    615  6783  pc198268 					xml_rtn_msg(&msg, ERR_NO_MEM);
    616  6783  pc198268 					free(prop);
    617  7725       Tim 					(void) pthread_rwlock_unlock(
    618  7725       Tim 					    &targ_config_mutex);
    619  6783  pc198268 					return (msg);
    620  6783  pc198268 				}
    621  6783  pc198268 			} else {
    622  6783  pc198268 				if (strcmp(prop, XML_VALUE_TRUE) != 0) {
    623  6783  pc198268 					xml_rtn_msg(&msg,
    624  6783  pc198268 					    ERR_SYNTAX_MISSING_OPERAND);
    625  6783  pc198268 					free(prop);
    626  7725       Tim 					(void) pthread_rwlock_unlock(
    627  7725       Tim 					    &targ_config_mutex);
    628  6783  pc198268 					return (msg);
    629  6783  pc198268 				}
    630  6783  pc198268 				if (delete_element(ap->delete_name,
    631  6783  pc198268 				    main_config, MatchName) == False) {
    632  6783  pc198268 					xml_rtn_msg(&msg, ERR_NO_MEM);
    633  6783  pc198268 					free(prop);
    634  7725       Tim 					(void) pthread_rwlock_unlock(
    635  7725       Tim 					    &targ_config_mutex);
    636  6783  pc198268 					return (msg);
    637  6783  pc198268 				}
    638  2314    mcneal 			}
    639  7725       Tim 			(void) pthread_rwlock_unlock(&targ_config_mutex);
    640  6920  ks202890 			if (0 == strcmp(ap->name, XML_ELEMENT_ISNS_ACCESS) ||
    641  6920  ks202890 			    0 == strcmp(ap->name, XML_ELEMENT_ISNS_SERV)) {
    642  6920  ks202890 				update_isns = True;
    643  6920  ks202890 			}
    644  2314    mcneal 			free(prop);
    645  2314    mcneal 			changes_made = True;
    646  2314    mcneal 		}
    647  2314    mcneal 	}
    648  2314    mcneal 
    649  2314    mcneal 	if (changes_made == True) {
    650  4348  ts143224 		/* isns_update updates isns_access & isns server name */
    651  6920  ks202890 		if (update_isns == True) {
    652  6920  ks202890 			if (isns_update() != 0) {
    653  6920  ks202890 				xml_rtn_msg(&msg, ERR_ISNS_ERROR);
    654  6920  ks202890 				return (msg);
    655  6920  ks202890 			}
    656  4348  ts143224 		}
    657  6861       htk 		if (mgmt_config_save2scf() == True) {
    658  2314    mcneal 			xml_rtn_msg(&msg, ERR_SUCCESS);
    659  6861       htk 		} else {
    660  6861       htk 			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
    661  6861       htk 		}
    662  2314    mcneal 	} else {
    663  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
    664  2314    mcneal 	}
    665  2314    mcneal 
    666  2314    mcneal 	return (msg);
    667  2314    mcneal }
    668  2314    mcneal 
    669  2314    mcneal /*
    670  2314    mcneal  * []----
    671  2314    mcneal  * | modify_tpgt -- add an IP-address to a target portal group
    672  2314    mcneal  * []----
    673  2314    mcneal  */
    674  2314    mcneal static char *
    675  5137  zl149053 modify_tpgt(tgt_node_t *x)
    676  2314    mcneal {
    677  2314    mcneal 	struct addrinfo	*res	= NULL;
    678  4348  ts143224 	char		*msg	= NULL;
    679  4348  ts143224 	char		*name	= NULL;
    680  4348  ts143224 	char		*ip_str	= NULL;
    681  3126       ahl 	tgt_node_t	*tnode	= NULL;
    682  8007   Charles 	tgt_node_t	*list	= NULL;
    683  2314    mcneal 
    684  7725       Tim 	(void) pthread_rwlock_wrlock(&targ_config_mutex);
    685  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
    686  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
    687  2314    mcneal 		goto error;
    688  2314    mcneal 	}
    689  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) {
    690  2314    mcneal 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR);
    691  2314    mcneal 		goto error;
    692  2314    mcneal 	}
    693  2314    mcneal 	if ((getaddrinfo(ip_str, NULL, NULL, &res) != 0) || (res == NULL)) {
    694  2314    mcneal 		xml_rtn_msg(&msg, ERR_INVALID_IP);
    695  2314    mcneal 		goto error;
    696  2314    mcneal 	}
    697  6653  ts143224 	while ((tnode = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
    698  2314    mcneal 	    tnode)) != NULL) {
    699  2314    mcneal 		if (strcmp(tnode->x_value, name) == 0)
    700  2314    mcneal 			break;
    701  2314    mcneal 	}
    702  2314    mcneal 	if (tnode == NULL) {
    703  2314    mcneal 		xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
    704  2314    mcneal 		goto error;
    705  2314    mcneal 	}
    706  8007   Charles 
    707  8007   Charles 	if ((list = tgt_node_next(tnode, XML_ELEMENT_IPADDRLIST, NULL))
    708  8007   Charles 	    == NULL) {
    709  8007   Charles 		list = tgt_node_alloc(XML_ELEMENT_IPADDRLIST, String, "");
    710  8007   Charles 		if (list == NULL) {
    711  8007   Charles 			xml_rtn_msg(&msg, ERR_NO_MEM);
    712  8007   Charles 			goto error;
    713  8007   Charles 		}
    714  8007   Charles 		tgt_node_add(tnode, list);
    715  8007   Charles 	}
    716  8007   Charles 	if (modify_element(XML_ELEMENT_IPADDR, ip_str, list, MatchBoth) ==
    717  2314    mcneal 	    False) {
    718  2314    mcneal 		xml_rtn_msg(&msg, ERR_NO_MEM);
    719  7725       Tim 		goto error;
    720  2314    mcneal 	}
    721  2314    mcneal 
    722  6861       htk 	if (mgmt_config_save2scf() == True) {
    723  2314    mcneal 		xml_rtn_msg(&msg, ERR_SUCCESS);
    724  6861       htk 	} else {
    725  6861       htk 		/* tpgt change should be updated to smf */
    726  6861       htk 		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
    727  6861       htk 	}
    728  2314    mcneal 
    729  4348  ts143224 	/*
    730  4348  ts143224 	 * Re-register all targets, currently there's no method to
    731  4348  ts143224 	 * update TPGT for individual target
    732  4348  ts143224 	 */
    733  4348  ts143224 	if (isns_enabled() == True) {
    734  6821  nbhavyan 		(void) isns_reg_all();
    735  4348  ts143224 	}
    736  4348  ts143224 
    737  2314    mcneal error:
    738  2314    mcneal 	if (name)
    739  2314    mcneal 		free(name);
    740  2314    mcneal 	if (ip_str)
    741  2314    mcneal 		free(ip_str);
    742  7857       Tim 	if (res)
    743  7857       Tim 		freeaddrinfo(res);
    744  7725       Tim 	(void) pthread_rwlock_unlock(&targ_config_mutex);
    745  2314    mcneal 	return (msg);
    746  2314    mcneal }
    747  2314    mcneal 
    748  3545    mcneal /*
    749  3545    mcneal  * modify_zfs -- test for the existence of a certain dataset being shared
    750  3545    mcneal  *
    751  3545    mcneal  * Called when someone uses the iscsitgt_is_shared() function from libiscsitgt.
    752  3545    mcneal  * All that
    753  3545    mcneal  */
    754  3126       ahl static char *
    755  6278   jdunham modify_zfs(tgt_node_t *x, ucred_t *cred)
    756  3126       ahl {
    757  4348  ts143224 	char		*msg		= NULL;
    758  4348  ts143224 	char		*dataset	= NULL;
    759  6278   jdunham 	char		*prop;
    760  6278   jdunham 	char		*m;
    761  3126       ahl 	tgt_node_t	*n		= NULL;
    762  6278   jdunham 	tgt_node_t	*t		= NULL;
    763  6278   jdunham 	tgt_node_t	*list		= NULL;
    764  6278   jdunham 	tgt_node_t	*c1, *c2;
    765  6278   jdunham 	Boolean_t	change_made	= False;
    766  6278   jdunham 	uint64_t	size;
    767  6278   jdunham 	int		status;
    768  6278   jdunham 	int		val;
    769  6761  nbhavyan 	char		*tru = "true";
    770  3126       ahl 
    771  7725       Tim 	(void) pthread_rwlock_wrlock(&targ_config_mutex);
    772  3126       ahl 	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
    773  3126       ahl 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
    774  7725       Tim 		goto error;
    775  6761  nbhavyan 	}
    776  6761  nbhavyan 
    777  6761  nbhavyan 	/*
    778  6761  nbhavyan 	 * Validate request
    779  6761  nbhavyan 	 */
    780  6761  nbhavyan 	if (tgt_find_value_str(x, XML_ELEMENT_VALIDATE, &tru)) {
    781  7725       Tim 		(void) pthread_rwlock_unlock(&targ_config_mutex);
    782  7857       Tim 		if (tru)
    783  7857       Tim 			free(tru);
    784  7857       Tim 		free(dataset);
    785  6761  nbhavyan 		return (validate_zfs_iscsitgt(x));
    786  3126       ahl 	}
    787  3126       ahl 
    788  6278   jdunham 	/*
    789  6278   jdunham 	 * Check for existance of ZFS shareiscsi properties
    790  6278   jdunham 	 */
    791  6278   jdunham 	status = get_zfs_shareiscsi(dataset, &n, &size, cred);
    792  6278   jdunham 	if ((status != ERR_SUCCESS) && (status != ERR_NULL_XML_MESSAGE)) {
    793  3126       ahl 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
    794  3126       ahl 		goto error;
    795  3126       ahl 	}
    796  3126       ahl 
    797  6653  ts143224 	while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, t))
    798  6278   jdunham 	    != NULL) {
    799  6278   jdunham 		if (strcmp(t->x_value, dataset) == 0)
    800  3126       ahl 			break;
    801  3126       ahl 	}
    802  6278   jdunham 	if (t == NULL) {
    803  3126       ahl 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
    804  3126       ahl 		goto error;
    805  3126       ahl 	}
    806  3126       ahl 
    807  6278   jdunham 	if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
    808  6278   jdunham 		if (prop == NULL) {
    809  6278   jdunham 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
    810  6278   jdunham 			goto error;
    811  6278   jdunham 		}
    812  6278   jdunham 
    813  6278   jdunham 		/*
    814  6278   jdunham 		 * Validate that the Target Portal Group Tag is reasonable.
    815  6278   jdunham 		 */
    816  6278   jdunham 		val = strtoll(prop, &m, 0);
    817  6278   jdunham 		if ((val < TPGT_MIN) || (val > TPGT_MAX) ||
    818  6278   jdunham 		    ((m != NULL) && (*m != '\0'))) {
    819  6278   jdunham 			xml_rtn_msg(&msg, ERR_INVALID_TPGT);
    820  6278   jdunham 			goto error;
    821  6278   jdunham 		}
    822  6278   jdunham 
    823  6278   jdunham 		if ((c1 = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
    824  6278   jdunham 		    NULL) {
    825  6278   jdunham 			xml_rtn_msg(&msg, ERR_NO_MEM);
    826  6278   jdunham 			goto error;
    827  6278   jdunham 		}
    828  6278   jdunham 
    829  6278   jdunham 		/*
    830  6278   jdunham 		 * Due to the fact that the targets_config differs from the
    831  6278   jdunham 		 * ZVOL properties stored in zfs_shareiscsi, two lists need to
    832  6278   jdunham 		 * be updated
    833  6278   jdunham 		 */
    834  6278   jdunham 		c2 = tgt_node_dup(c1);
    835  6278   jdunham 		if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL))
    836  6278   jdunham 		    != NULL) {
    837  6278   jdunham 			/*
    838  6278   jdunham 			 * tgt_node_replace will duplicate the child node
    839  6278   jdunham 			 * tgt_node_add which is used below just links it
    840  6278   jdunham 			 * into the tree.
    841  6278   jdunham 			 */
    842  6278   jdunham 			tgt_node_replace(list, c1, MatchBoth);
    843  6278   jdunham 			tgt_node_free(c1);
    844  6278   jdunham 		} else {
    845  6278   jdunham 			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
    846  6278   jdunham 			if (list == NULL) {
    847  6278   jdunham 				xml_rtn_msg(&msg, ERR_NO_MEM);
    848  6278   jdunham 				goto error;
    849  6278   jdunham 			}
    850  6278   jdunham 			tgt_node_add(list, c1);
    851  6278   jdunham 			tgt_node_add(t, list);
    852  6278   jdunham 		}
    853  6278   jdunham 		if ((list = tgt_node_next(n, XML_ELEMENT_TPGTLIST, NULL))
    854  6278   jdunham 		    != NULL) {
    855  6278   jdunham 			/*
    856  6278   jdunham 			 * tgt_node_replace will duplicate the child node
    857  6278   jdunham 			 * tgt_node_add which is used below just links it
    858  6278   jdunham 			 * into the tree.
    859  6278   jdunham 			 */
    860  6278   jdunham 			tgt_node_replace(list, c2, MatchBoth);
    861  6278   jdunham 			tgt_node_free(c2);
    862  6278   jdunham 		} else {
    863  6278   jdunham 			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
    864  6278   jdunham 			if (list == NULL) {
    865  6278   jdunham 				xml_rtn_msg(&msg, ERR_NO_MEM);
    866  6278   jdunham 				goto error;
    867  6278   jdunham 			}
    868  6278   jdunham 			tgt_node_add(list, c2);
    869  6278   jdunham 			tgt_node_add(n, list);
    870  6278   jdunham 		}
    871  6278   jdunham 		change_made = True;
    872  6278   jdunham 	}
    873  6278   jdunham 
    874  6278   jdunham 	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
    875  6278   jdunham 		if (prop == NULL) {
    876  6278   jdunham 			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
    877  6278   jdunham 			goto error;
    878  6278   jdunham 		}
    879  6278   jdunham 
    880  6278   jdunham 		c1 = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
    881  6278   jdunham 		if (c1 == NULL) {
    882  6278   jdunham 			xml_rtn_msg(&msg, ERR_NO_MEM);
    883  6278   jdunham 			goto error;
    884  6278   jdunham 		}
    885  6278   jdunham 
    886  6278   jdunham 		/*
    887  6278   jdunham 		 * Due to the fact that the targets_config differs from the
    888  6278   jdunham 		 * ZVOL properties stored in zfs_shareiscsi, two lists need to
    889  6278   jdunham 		 * be updated
    890  6278   jdunham 		 */
    891  6278   jdunham 		c2 = tgt_node_dup(c1);
    892  6278   jdunham 		if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL))
    893  6278   jdunham 		    != NULL) {
    894  6278   jdunham 			/*
    895  6278   jdunham 			 * tgt_node_replace will duplicate the child node
    896  6278   jdunham 			 * tgt_node_add which is used below just links it
    897  6278   jdunham 			 * into the tree.
    898  6278   jdunham 			 */
    899  6278   jdunham 			tgt_node_replace(list, c1, MatchBoth);
    900  6278   jdunham 			tgt_node_free(c1);
    901  6278   jdunham 		} else {
    902  6278   jdunham 			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
    903  6278   jdunham 			if (list == NULL) {
    904  6278   jdunham 				xml_rtn_msg(&msg, ERR_NO_MEM);
    905  6278   jdunham 				goto error;
    906  6278   jdunham 			}
    907  6278   jdunham 			tgt_node_add(list, c1);
    908  6278   jdunham 			tgt_node_add(t, list);
    909  6278   jdunham 		}
    910  6278   jdunham 		if ((list = tgt_node_next(n, XML_ELEMENT_ACLLIST, NULL))
    911  6278   jdunham 		    != NULL) {
    912  6278   jdunham 			/*
    913  6278   jdunham 			 * tgt_node_replace will duplicate the child node
    914  6278   jdunham 			 * tgt_node_add which is used below just links it
    915  6278   jdunham 			 * into the tree.
    916  6278   jdunham 			 */
    917  6278   jdunham 			tgt_node_replace(list, c2, MatchBoth);
    918  6278   jdunham 			tgt_node_free(c2);
    919  6278   jdunham 		} else {
    920  6278   jdunham 			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
    921  6278   jdunham 			if (list == NULL) {
    922  6278   jdunham 				xml_rtn_msg(&msg, ERR_NO_MEM);
    923  6278   jdunham 				goto error;
    924  6278   jdunham 			}
    925  6278   jdunham 			tgt_node_add(list, c2);
    926  6278   jdunham 			tgt_node_add(n, list);
    927  6278   jdunham 		}
    928  6278   jdunham 
    929  6278   jdunham 		change_made = True;
    930  6278   jdunham 	}
    931  6278   jdunham 
    932  6278   jdunham 	if (change_made == True) {
    933  6278   jdunham 		status = put_zfs_shareiscsi(dataset, n);
    934  6278   jdunham 		if (status != ERR_SUCCESS) {
    935  6278   jdunham 			xml_rtn_msg(&msg, status);
    936  6278   jdunham 			goto error;
    937  6278   jdunham 		} else {
    938  6278   jdunham 			xml_rtn_msg(&msg, ERR_SUCCESS);
    939  6278   jdunham 		}
    940  6278   jdunham 	} else {
    941  6278   jdunham 		xml_rtn_msg(&msg, ERR_SUCCESS);
    942  6278   jdunham 	}
    943  3126       ahl 
    944  3126       ahl error:
    945  6278   jdunham 	if (n)
    946  6278   jdunham 		tgt_node_free(n);
    947  3126       ahl 	if (dataset)
    948  3126       ahl 		free(dataset);
    949  3126       ahl 
    950  7725       Tim 	(void) pthread_rwlock_unlock(&targ_config_mutex);
    951  3126       ahl 	return (msg);
    952  3126       ahl }
    953  3126       ahl 
    954  2314    mcneal /*
    955  6761  nbhavyan  * Just checking the existance of the given target. Here we check whether
    956  6761  nbhavyan  * both zfs and iscsitarget aware of the given target/volume. It neither
    957  6761  nbhavyan  * care about the credentials nor SHAREISCSI properties.
    958  6761  nbhavyan  */
    959  6761  nbhavyan static char *
    960  6761  nbhavyan validate_zfs_iscsitgt(tgt_node_t *x)
    961  6761  nbhavyan {
    962  6761  nbhavyan 	char		*msg		= NULL;
    963  6761  nbhavyan 	char		*prop		= NULL;
    964  6761  nbhavyan 	char		*dataset	= NULL;
    965  6761  nbhavyan 	libzfs_handle_t	*zh		= NULL;
    966  6761  nbhavyan 	zfs_handle_t	*zfsh		= NULL;
    967  6761  nbhavyan 	tgt_node_t	*n		= NULL;
    968  6761  nbhavyan 
    969  6761  nbhavyan 	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) {
    970  6761  nbhavyan 		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
    971  6761  nbhavyan 		return (msg);
    972  6761  nbhavyan 	}
    973  6761  nbhavyan 
    974  6761  nbhavyan 	if (((zh = libzfs_init()) == NULL) ||
    975  6761  nbhavyan 	    ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) {
    976  6761  nbhavyan 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
    977  6761  nbhavyan 		goto error;
    978  6761  nbhavyan 	}
    979  6761  nbhavyan 
    980  6761  nbhavyan 	while ((n = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, n)) !=
    981  6761  nbhavyan 	    NULL) {
    982  6761  nbhavyan 		if (strcmp(n->x_value, dataset) == 0)
    983  6761  nbhavyan 			break;
    984  6761  nbhavyan 	}
    985  6761  nbhavyan 	if (n == NULL) {
    986  6761  nbhavyan 		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
    987  6761  nbhavyan 		goto error;
    988  6761  nbhavyan 	}
    989  6761  nbhavyan 
    990  6761  nbhavyan 	xml_rtn_msg(&msg, ERR_SUCCESS);
    991  6761  nbhavyan 
    992  6761  nbhavyan error:
    993  6761  nbhavyan 	if (zfsh)
    994  6761  nbhavyan 		zfs_close(zfsh);
    995  6761  nbhavyan 	if (prop)
    996  6761  nbhavyan 		free(prop);
    997  6761  nbhavyan 	if (zh)
    998  6761  nbhavyan 		libzfs_fini(zh);
    999  6761  nbhavyan 	if (dataset)
   1000  6761  nbhavyan 		free(dataset);
   1001  6761  nbhavyan 
   1002  6761  nbhavyan 	return (msg);
   1003  6761  nbhavyan 
   1004  6761  nbhavyan }
   1005  6761  nbhavyan 
   1006  6761  nbhavyan 
   1007  6761  nbhavyan /*
   1008  2314    mcneal  * []----
   1009  2314    mcneal  * | modify_element -- helper function to create node and add it to parent
   1010  2314    mcneal  * |
   1011  2314    mcneal  * | A False return value indicates a failure to allocate enough memory.
   1012  2314    mcneal  * []----
   1013  2314    mcneal  */
   1014  2314    mcneal static Boolean_t
   1015  3126       ahl modify_element(char *name, char *value, tgt_node_t *p, match_type_t m)
   1016  2314    mcneal {
   1017  3126       ahl 	tgt_node_t	*c;
   1018  2314    mcneal 
   1019  5137  zl149053 
   1020  5137  zl149053 	if ((c = tgt_node_alloc(name, String, value)) == NULL) {
   1021  2314    mcneal 		return (False);
   1022  5137  zl149053 	} else {
   1023  3126       ahl 		tgt_node_replace(p, c, m);
   1024  3126       ahl 		tgt_node_free(c);
   1025  2314    mcneal 		return (True);
   1026  2314    mcneal 	}
   1027  2314    mcneal }
   1028  2314    mcneal 
   1029  2314    mcneal /*
   1030  2314    mcneal  * []----
   1031  6783  pc198268  * | delete_element -- helper function to remove a node from a parent
   1032  6783  pc198268  * |
   1033  6783  pc198268  * | A False return value indicates a failure to allocate enough memory.
   1034  6783  pc198268  * []----
   1035  6783  pc198268  */
   1036  6783  pc198268 static Boolean_t
   1037  6783  pc198268 delete_element(char *name, tgt_node_t *p, match_type_t m)
   1038  6783  pc198268 {
   1039  6783  pc198268 	tgt_node_t	*c;
   1040  6783  pc198268 
   1041  6783  pc198268 	if ((c = tgt_node_alloc(name, String, NULL)) == NULL) {
   1042  6783  pc198268 		return (False);
   1043  6783  pc198268 	}
   1044  6783  pc198268 	tgt_node_remove(p, c, m);
   1045  6783  pc198268 	tgt_node_free(c);
   1046  6783  pc198268 	return (True);
   1047  6783  pc198268 }
   1048  6783  pc198268 
   1049  6783  pc198268 /*
   1050  6783  pc198268  * []----
   1051  2314    mcneal  * | update_basedir -- update the global target directory
   1052  2314    mcneal  * |
   1053  2314    mcneal  * | Most of the properties when updated require no futher processing. The
   1054  2314    mcneal  * | target base directory however must be updated if it hasn't been set.
   1055  2314    mcneal  * | On a new system the daemon will not have any location to place the
   1056  2314    mcneal  * | backing store and target configuration files. On a live system we would
   1057  2314    mcneal  * | screw things up if we changed the global variable if it was already
   1058  2314    mcneal  * | in use, so we only allow the updating to occur if there are no targets.
   1059  2314    mcneal  * []----
   1060  2314    mcneal  */
   1061  2314    mcneal /*ARGSUSED*/
   1062  2314    mcneal char *
   1063  2314    mcneal update_basedir(char *name, char *prop)
   1064  2314    mcneal {
   1065  3126       ahl 	tgt_node_t	*targ	= NULL;
   1066  4348  ts143224 	char		*msg	= NULL;
   1067  6278   jdunham 	char		*v;
   1068  2314    mcneal 
   1069  2314    mcneal 	if ((prop == NULL) || (strlen(prop) == 0) || (prop[0] != '/')) {
   1070  2314    mcneal 		xml_rtn_msg(&msg, ERR_INVALID_BASEDIR);
   1071  2314    mcneal 		return (msg);
   1072  2314    mcneal 	}
   1073  2314    mcneal 
   1074  6653  ts143224 	while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
   1075  6653  ts143224 	    targ)) != NULL) {
   1076  3282    mcneal 		/*
   1077  6278   jdunham 		 * Traverse the list of configured targets, serching for any
   1078  6278   jdunham 		 * target that is using the current base-directory. Fail the
   1079  6278   jdunham 		 * update if found.
   1080  6278   jdunham 		 *
   1081  6278   jdunham 		 * The only targets that do not use the base-directory at this
   1082  6278   jdunham 		 * time are those targets persisted in ZFS.
   1083  3282    mcneal 		 */
   1084  6278   jdunham 		if (tgt_find_attr_str(targ, XML_ELEMENT_INCORE, &v) == True) {
   1085  6278   jdunham 			if (v != NULL) {
   1086  6278   jdunham 				if (strcmp(v, XML_VALUE_TRUE) == 0) {
   1087  6278   jdunham 					free(v);
   1088  6278   jdunham 					continue;
   1089  6278   jdunham 				}
   1090  6278   jdunham 				free(v);
   1091  6278   jdunham 			}
   1092  3282    mcneal 		}
   1093  6278   jdunham 
   1094  6278   jdunham 		/*
   1095  6278   jdunham 		 * Found at least one target, so fail
   1096  6278   jdunham 		 */
   1097  6278   jdunham 		xml_rtn_msg(&msg, ERR_VALID_TARG_EXIST);
   1098  6278   jdunham 		return (msg);
   1099  2314    mcneal 	}
   1100  2314    mcneal 
   1101  6278   jdunham 	if (target_basedir) {
   1102  2314    mcneal 		free(target_basedir);
   1103  6278   jdunham 	}
   1104  6278   jdunham 	target_basedir = strdup(prop);
   1105  6278   jdunham 	if ((mkdir(target_basedir, 0700) != 0) && (errno != EEXIST)) {
   1106  6278   jdunham 		xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED);
   1107  6278   jdunham 		free(target_basedir);
   1108  6278   jdunham 		target_basedir = NULL;
   1109  2314    mcneal 	}
   1110  2314    mcneal 	return (msg);
   1111  2314    mcneal }
   1112  2314    mcneal 
   1113  2314    mcneal /*
   1114  2314    mcneal  * []----
   1115  2314    mcneal  * | validate_radius -- validate that server[:port] are valid
   1116  2314    mcneal  * []----
   1117  2314    mcneal  */
   1118  2314    mcneal char *
   1119  2314    mcneal valid_radius_srv(char *name, char *prop)
   1120  2314    mcneal {
   1121  2314    mcneal 	struct addrinfo	*res	= NULL;
   1122  4348  ts143224 	char		*msg	= NULL;
   1123  4348  ts143224 	char		*sp, *p;
   1124  2314    mcneal 	int		port;
   1125  2314    mcneal 
   1126  2314    mcneal 	if ((sp = strdup(prop)) == NULL) {
   1127  2314    mcneal 		xml_rtn_msg(&msg, ERR_NO_MEM);
   1128  2314    mcneal 		return (msg);
   1129  2314    mcneal 	} else if ((p = strrchr(sp, ':')) != NULL) {
   1130  2314    mcneal 		*p++ = '\0';
   1131  2314    mcneal 		port = atoi(p);
   1132  2314    mcneal 		if ((port < 1) || (port > 65535)) {
   1133  2314    mcneal 			xml_rtn_msg(&msg, ERR_INVALID_RADSRV);
   1134  2314    mcneal 			free(sp);
   1135  2314    mcneal 			return (msg);
   1136  2314    mcneal 		}
   1137  2314    mcneal 	}
   1138  2314    mcneal 	if ((getaddrinfo(sp, NULL, NULL, &res) != 0) || (res == NULL))
   1139  2314    mcneal 		xml_rtn_msg(&msg, ERR_INVALID_RADSRV);
   1140  2314    mcneal 	else
   1141  2314    mcneal 		freeaddrinfo(res);
   1142  2314    mcneal 	free(sp);
   1143  2314    mcneal 	return (msg);
   1144  2314    mcneal }
   1145  4348  ts143224 
   1146  4348  ts143224 /*
   1147  4348  ts143224  * []----
   1148  4348  ts143224  * | validate_isns_server -- validate that server[:port] are valid
   1149  4348  ts143224  * []----
   1150  4348  ts143224  */
   1151  4348  ts143224 char *
   1152  4348  ts143224 valid_isns_srv(char *name, char *prop)
   1153  4348  ts143224 {
   1154  4348  ts143224 	char		*msg	= NULL;
   1155  4348  ts143224 	char		*sp, *p;
   1156  6086  ts143224 	int		so;
   1157  4348  ts143224 	int		port;
   1158  4348  ts143224 
   1159  7018  ks202890 	if (strlen(prop) > MAXHOSTNAMELEN) {
   1160  7018  ks202890 		xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
   1161  7018  ks202890 		return (msg);
   1162  7018  ks202890 	}
   1163  7018  ks202890 
   1164  4348  ts143224 	if ((sp = strdup(prop)) == NULL) {
   1165  4348  ts143224 		xml_rtn_msg(&msg, ERR_NO_MEM);
   1166  4348  ts143224 		return (msg);
   1167  6086  ts143224 	}
   1168  6086  ts143224 	if ((p = strrchr(sp, ':')) != NULL) {
   1169  4348  ts143224 		*p++ = '\0';
   1170  4348  ts143224 		port = atoi(p);
   1171  4348  ts143224 		if ((port < 1) || (port > 65535)) {
   1172  4348  ts143224 			xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
   1173  4348  ts143224 			free(sp);
   1174  4348  ts143224 			return (msg);
   1175  4348  ts143224 		}
   1176  4348  ts143224 	}
   1177  6086  ts143224 
   1178  6086  ts143224 	so = isns_open(sp);
   1179  7018  ks202890 	if (so < 0) {
   1180  7018  ks202890 		if (isns_enabled() == True) {
   1181  7018  ks202890 			xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
   1182  7018  ks202890 		} else { /* Just print a warning and accept the server */
   1183  7018  ks202890 			syslog(LOG_ALERT,
   1184  7018  ks202890 			    "Check if the server:%s is valid", sp);
   1185  7018  ks202890 		}
   1186  7018  ks202890 	} else {
   1187  6086  ts143224 		isns_close(so);
   1188  7018  ks202890 	}
   1189  4348  ts143224 	free(sp);
   1190  4348  ts143224 	return (msg);
   1191  4348  ts143224 }
   1192