Exemple #1
0
/*ARGSUSED*/
char *
update_basedir(char *name, char *prop)
{
	tgt_node_t	*targ	= NULL;
	char		*msg	= NULL;
	char		*v;

	if ((prop == NULL) || (strlen(prop) == 0) || (prop[0] != '/')) {
		xml_rtn_msg(&msg, ERR_INVALID_BASEDIR);
		return (msg);
	}

	while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    targ)) != NULL) {
		/*
		 * Traverse the list of configured targets, serching for any
		 * target that is using the current base-directory. Fail the
		 * update if found.
		 *
		 * The only targets that do not use the base-directory at this
		 * time are those targets persisted in ZFS.
		 */
		if (tgt_find_attr_str(targ, XML_ELEMENT_INCORE, &v) == True) {
			if (v != NULL) {
				if (strcmp(v, XML_VALUE_TRUE) == 0) {
					free(v);
					continue;
				}
				free(v);
			}
		}

		/*
		 * Found at least one target, so fail
		 */
		xml_rtn_msg(&msg, ERR_VALID_TARG_EXIST);
		return (msg);
	}

	if (target_basedir) {
		free(target_basedir);
	}
	target_basedir = strdup(prop);
	if ((mkdir(target_basedir, 0700) != 0) && (errno != EEXIST)) {
		xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED);
		free(target_basedir);
		target_basedir = NULL;
	}
	return (msg);
}
Exemple #2
0
Fichier : util.c Projet : imp/slist
Boolean_t
validate_version(tgt_node_t *node, int *maj_p, int *min_p)
{
	char	*vers_str	= NULL;
	char	*minor_part;
	int	maj, min;

	if ((tgt_find_attr_str(node, XML_ELEMENT_VERS, &vers_str) == False) ||
	    (vers_str == NULL))
		return (False);

	maj = strtol(vers_str, &minor_part, 0);
	if ((maj > *maj_p) || (minor_part == NULL) || (*minor_part != '.')) {
		free(vers_str);
		return (False);
	}

	min	= strtol(&minor_part[1], NULL, 0);
	*maj_p	= maj;
	*min_p	= min;
	free(vers_str);

	return (True);
}
Exemple #3
0
/*
 * []----
 * | modify_target -- updates one or more properties for a target
 * []----
 */
static char *
modify_target(tgt_node_t *x, ucred_t *cred)
{
	char		*msg		= NULL;
	char		*name		= NULL;
	char		iscsi_path[MAXPATHLEN];
	char		targ_name[64];
	char		*iscsi		= NULL;
	char		*prop		= NULL;
	char		path[MAXPATHLEN];
	char		*m;
	char		buf[512];		/* one sector size block */
	tgt_node_t	*t		= NULL;
	tgt_node_t	*list		= NULL;
	tgt_node_t	*c		= NULL;
	tgt_node_t	*node		= NULL;
	tgt_node_t	*tpgt		= NULL;
	Boolean_t	change_made	= False;
	int		lun		= 0;
	int		fd;
	uint64_t	val, new_lu_size, cur_lu_size;
	struct stat	st;
	uint32_t	isns_mods	= 0;

	(void) pthread_rwlock_wrlock(&targ_config_mutex);
	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
		goto error;
	}

	while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    t)) != NULL) {
		if (strcmp(t->x_value, name) == 0) {
			break;
		}
	}
	if (t == NULL) {
		free(name);
		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
		goto error;
	}

	if (tgt_find_attr_str(t, XML_ELEMENT_INCORE, &m) == True) {
		if (strcmp(m, "true") == 0) {
			free(m);
			free(name);
			(void) pthread_rwlock_unlock(&targ_config_mutex);
			return (modify_zfs(x, cred));
		}
		free(m);
	}

	/*
	 * Under base dir, file 'target name' is a symbolic link
	 * to the real directory 'IQN name' which stores params and back
	 * storage. Therefore we can easily get IQN name from target
	 * name by read the symbolic link content.
	 */
	(void) snprintf(path, sizeof (path), "%s/%s", target_basedir, name);
	bzero(iscsi_path, sizeof (iscsi_path));
	(void) readlink(path, iscsi_path, sizeof (iscsi_path));
	iscsi = basename(iscsi_path);

	/* ---- Finished with these so go ahead and release the memory ---- */
	(void) strncpy(targ_name, name, sizeof (targ_name));
	free(name);

	/*
	 * Grow the LU. We currently do not support shrinking the LU and
	 * that is only because it's unknown if any applications could support
	 * that type of data loss. To support shrinking all that would be
	 * needed is to remove the new/old size check and perform a truncation.
	 * The actually truncation request should be shipped off to the T10
	 * layer so that the LU thread can remap the smaller size without
	 * anyone accessing the data.
	 */
	if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
			goto error;
		}
		if (strtoll_multiplier(prop, &new_lu_size) == False) {
			free(prop);
			xml_rtn_msg(&msg, ERR_INVALID_SIZE);
			goto error;
		}
		free(prop);
		if ((new_lu_size % 512LL) != 0) {
			xml_rtn_msg(&msg, ERR_SIZE_MOD_BLOCK);
			goto error;
		}
		new_lu_size /= 512LL;

		/* ---- default to LUN 0 ---- */
		(void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun);

		/* ---- read in current parameters ---- */
		if (mgmt_get_param(&node, targ_name, lun) == False) {
			xml_rtn_msg(&msg, ERR_OPEN_PARAM_FILE_FAILED);
			goto error;
		}

		/* ---- validate that we're indeed growing the LU ---- */
		if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) ==
		    False) {
			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
			goto error;
		}
		if (strtoll_multiplier(prop, &cur_lu_size) == False) {
			free(prop);
			xml_rtn_msg(&msg, ERR_INVALID_SIZE);
			goto error;
		}
		free(prop);

		if (new_lu_size < cur_lu_size) {
			xml_rtn_msg(&msg, ERR_CANT_SHRINK_LU);
			goto error;
		}

		/* ---- check that this LU is of type 'disk' or 'tape' ---- */
		if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) ==
		    False) {
			xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED);
			goto error;
		}
		if ((strcmp(prop, TGT_TYPE_DISK) != 0) &&
		    (strcmp(prop, TGT_TYPE_TAPE) != 0)) {
			xml_rtn_msg(&msg, ERR_RESIZE_WRONG_DTYPE);
			free(prop);
			goto error;
		}
		free(prop);

		/* ---- validate the backing store is a regular file ---- */
		(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
		    target_basedir, iscsi, LUNBASE, lun);
		if (stat(path, &st) == -1) {
			xml_rtn_msg(&msg, ERR_STAT_BACKING_FAILED);
			goto error;
		}
		if ((st.st_mode & S_IFMT) != S_IFREG) {
			xml_rtn_msg(&msg,
			    ERR_DISK_BACKING_MUST_BE_REGULAR_FILE);
			goto error;
		}

		/* ---- update the parameter node with new size ---- */
		if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &new_lu_size))
		    == NULL) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		tgt_node_replace(node, c, MatchName);
		tgt_node_free(c);

		/* ---- now update params file ---- */
		(void) mgmt_param_save2scf(node, targ_name, lun);

		/* ---- grow lu backing store ---- */
		(void) snprintf(path, sizeof (path), "%s/%s/%s%d",
		    target_basedir, iscsi, LUNBASE, lun);
		if ((fd = open(path, O_RDWR|O_CREAT|O_LARGEFILE, 0600)) < 0) {
			xml_rtn_msg(&msg, ERR_LUN_NOT_FOUND);
			goto error;
		}
		(void) lseek(fd, (new_lu_size * 512LL) - 512LL, 0);
		bzero(buf, sizeof (buf));
		if (write(fd, buf, sizeof (buf)) != sizeof (buf)) {
			xml_rtn_msg(&msg, ERR_LUN_NOT_GROWN);
			(void) close(fd);
			goto error;
		}
		(void) close(fd);

		/* ---- send updates to current initiators via ASC/ASCQ ---- */
		iscsi_capacity_change(iscsi, lun);

		prop = NULL;
		tgt_node_free(node);
		node = NULL;
		change_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT);
			goto error;
		}

		/*
		 * Validate that the Target Portal Group Tag is reasonable.
		 */
		val = strtoll(prop, &m, 0);
		if ((val < TPGT_MIN) || (val > TPGT_MAX) ||
		    ((m != NULL) && (*m != '\0'))) {
			xml_rtn_msg(&msg, ERR_INVALID_TPGT);
			free(prop);
			goto error;
		}

		/* update isns only if TPGT contains ip_addr */
		tpgt = NULL;
		while ((tpgt = tgt_node_next_child(main_config,
		    XML_ELEMENT_TPGT, tpgt)) != NULL) {
			if (strcmp(prop, tpgt->x_value) != 0)
				continue;
			if (tgt_node_next(tpgt, XML_ELEMENT_IPADDR, NULL)
			    != NULL) {
				isns_mods |= ISNS_MOD_TPGT;
				break;
			} else {
				xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR);
				free(prop);
				goto error;
			}
		}

		if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) ==
		    NULL) {
			free(prop);
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}

		if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST,
		    NULL)) != NULL) {
			tgt_node_replace(list, c, MatchBoth);
			/*
			 * tgt_node_replace will duplicate the child node
			 * tgt_node_add which is used below just links it
			 * into the tree.
			 */
			tgt_node_free(c);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
			if (list == NULL) {
				free(prop);
				xml_rtn_msg(&msg, ERR_NO_MEM);
				goto error;
			}
			tgt_node_add(list, c);
			tgt_node_add(t, list);
		}

		free(prop);
		prop = NULL;
		change_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
			goto error;
		}

		c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
		if (c == NULL) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			free(prop);
			goto error;
		}
		if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST,
		    NULL)) != NULL) {
			tgt_node_replace(list, c, MatchBoth);
			/* ---- See above usage ---- */
			tgt_node_free(c);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
			if (list == NULL) {
				xml_rtn_msg(&msg, ERR_NO_MEM);
				free(prop);
				goto error;
			}
			tgt_node_add(list, c);
			tgt_node_add(t, list);
		}
		free(prop);
		prop = NULL;
		change_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS);
			goto error;
		}

		if (modify_element(XML_ELEMENT_ALIAS, prop, t, MatchName) ==
		    False) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			free(prop);
			goto error;
		}
		free(prop);
		prop = NULL;
		isns_mods |= ISNS_MOD_ALIAS;
		change_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV);
			goto error;
		}

		if ((strtoll_multiplier(prop, &val) == False) ||
		    (val < MAXRCVDATA_MIN) || (val > MAXRCVDATA_MAX)) {
			free(prop);
			xml_rtn_msg(&msg, ERR_INVALID_MAXRECV);
			goto error;
		}
		free(prop);
		if ((prop = malloc(32)) == NULL) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		(void) snprintf(prop, 32, "%d", val);

		if (modify_element(XML_ELEMENT_MAXRECV, prop, t, MatchName) ==
		    False) {
			free(prop);
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		free(prop);
		prop = NULL;
		change_made = True;
	}

	if (change_made == True) {
		if (mgmt_config_save2scf() == False) {
			xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED);
			goto error;
		}
		if (isns_enabled() == True) {
			if (isns_dev_update(t->x_value, isns_mods) != 0) {
				xml_rtn_msg(&msg, ERR_ISNS_ERROR);
				goto error;
			}
		}
		xml_rtn_msg(&msg, ERR_SUCCESS);
	} else {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
	}

error:
	(void) pthread_rwlock_unlock(&targ_config_mutex);
	if (node)
		tgt_node_free(node);
	return (msg);
}
Exemple #4
0
/*
 * mgmt_config_save2scf() saves main configuration to scf
 * See also : mgmt_get_main_config()
 */
Boolean_t
mgmt_config_save2scf()
{
	targ_scf_t *h = NULL;
	scf_property_t *prop = NULL;
	scf_value_t *value = NULL;
	scf_iter_t *iter = NULL;
	char *pgname = NULL;
	ssize_t max_name_len;
	char passcode[32];
	char *incore = NULL;
	unsigned int	outlen;
	tgt_node_t	*n = NULL;
	tgt_node_t	*pn = NULL;
	tgt_node_t	*tn = NULL;
	scf_transaction_t *tx = NULL;
	secret_list_t	*sl_head;
	secret_list_t	*sl_tail;
	Boolean_t status = False;

	h = mgmt_handle_init();

	if (h == NULL)
		return (status);

	prop = scf_property_create(h->t_handle);
	value = scf_value_create(h->t_handle);
	iter = scf_iter_create(h->t_handle);

	if (alloc_scf_name(&max_name_len, (void *)&pgname) == False) {
		goto error;
	}

	(void) pthread_mutex_lock(&scf_conf_mutex);

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		(void) scf_pg_delete(h->t_pg);
		(void) mgmt_transaction_end(h);
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		(void) scf_pg_delete(h->t_pg);
		(void) mgmt_transaction_end(h);
	}

	if (scf_iter_service_pgs_typed(iter, h->t_service, "configuration")
	    == -1) {
		goto error;
	}

	tx = scf_transaction_create(h->t_handle);
	while (scf_iter_next_pg(iter, h->t_pg) > 0) {
		(void) scf_transaction_start(tx, h->t_pg);
		(void) scf_pg_delete(h->t_pg);
		(void) scf_transaction_commit(tx);
	}
	scf_transaction_reset(tx);
	scf_transaction_destroy(tx);

	sl_head = (secret_list_t *)calloc(1, sizeof (secret_list_t));
	sl_tail = sl_head;

	if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
		for (n = main_config->x_child; n; n = n->x_sibling) {
			if ((tgt_find_attr_str(n, XML_ELEMENT_INCORE, &incore))
			    == True) {
				if (strcmp(incore, "true") == 0) {
					/*
					 * Ignore in core only elements.
					 * zvol target is the only one with
					 * incore attr as of now.
					 */
					free(incore);
					continue;
				}
				/* if incore is false continue on */
				free(incore);
			}
			if (strcmp(n->x_name,
			    XML_ELEMENT_CHAPSECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("main");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			/* so does the radius server secret */
			if (strcmp(n->x_name,
			    XML_ELEMENT_RAD_SECRET) == 0) {
				sl_tail->next =  (secret_list_t *)
				    calloc(1, sizeof (secret_list_t));
				sl_tail = sl_tail->next;
				sl_tail->name = strdup("radius");
				sl_tail->secret = strdup(n->x_value);
				continue;
			}
			if (n->x_child == NULL) {
				new_property(h, n);
			}
		}
		new_property(h, main_config->x_attr);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		(void) mgmt_transaction_end(h);
	}

	/* now update target/initiator/tpgt information */
	for (n = main_config->x_child; n; n = n->x_sibling) {
		if (n->x_child == NULL)
			continue;

		if ((tgt_find_attr_str(n, XML_ELEMENT_INCORE, &incore))
		    == True) {
			if (strcmp(incore, "true") == 0) {
				/*
				 * Ignore in core only elements.
				 * zvol target is the only one with
				 * incore attr as of now.
				 */
				free(incore);
				continue;
			}
			/* if incore is false continue on */
			free(incore);
		}

		(void) snprintf(pgname, max_name_len, "%s_%s", n->x_name,
		    n->x_value);

		if (mgmt_transaction_start(h, pgname, "configuration")
		    == True) {
			for (pn = n->x_child; pn; pn = pn->x_sibling) {
				if (strcmp(pn->x_name,
				    XML_ELEMENT_CHAPSECRET) == 0) {
					sl_tail->next =  (secret_list_t *)
					    calloc(1, sizeof (secret_list_t));
					sl_tail = sl_tail->next;
					sl_tail->name = (char *)
					    calloc(1, strlen(n->x_value) + 3);
					(void) snprintf(sl_tail->name,
					    strlen(n->x_value) + 3,
					    "I_%s", n->x_value);
					sl_tail->secret = strdup(pn->x_value);
					continue;
				}
				if (pn->x_child == NULL) {
					/* normal property */
					new_property(h, pn);
				} else {
					/* pn -> xxx-list */
					new_value_list(h, pn);
				}
				tn = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME,
				    String, ISCSI_AUTH_MODIFY);
				new_property(h, tn);
				tgt_node_free(tn);
				tn = tgt_node_alloc(ISCSI_VALUE_AUTHNAME,
				    String, ISCSI_AUTH_VALUE);
				new_property(h, tn);
				tgt_node_free(tn);
			}
			(void) mgmt_transaction_end(h);
		} else
			goto error;
	}

	if (mgmt_transaction_start(h, "passwords", "application") == True) {
		while (sl_head != NULL) {
			/* Here we use sl_tail as a temporari var */
			sl_tail = sl_head->next;
			if (sl_head->name) {
				/* max length of encoded passwd is 24B */
				(void) sasl_encode64(sl_head->secret,
				    strlen(sl_head->secret), passcode,
				    sizeof (passcode), &outlen);

				n = tgt_node_alloc(sl_head->name, String,
				    passcode);
				new_property(h, n);
				tgt_node_free(n);
			}
			if (sl_head->name)
				free(sl_head->name);
			if (sl_head->secret)
				free(sl_head->secret);
			free(sl_head);
			sl_head = sl_tail;
		}
		n = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
		    ISCSI_AUTH_READ);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
		    ISCSI_AUTH_VALUE);
		new_property(h, n);
		tgt_node_free(n);
		n = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
		    ISCSI_AUTH_MODIFY);
		new_property(h, n);
		tgt_node_free(n);
		(void) mgmt_transaction_end(h);
	}

	if (smf_refresh_instance(SA_TARGET_SVC_INSTANCE_FMRI) != 0)
		goto error;

	status = True;
error:
	(void) pthread_mutex_unlock(&scf_conf_mutex);
	free(pgname);
	scf_iter_destroy(iter);
	scf_value_destroy(value);
	scf_property_destroy(prop);
	mgmt_handle_fini(h);
	return (status);
}