예제 #1
0
파일: util.c 프로젝트: imp/slist
/*
 * convert_to_tpgt -- return a TPGT based on the target address
 *
 * If a target doesn't have a TPGT list then just return the default
 * value of 1. Otherwise determine which TPGT the target address is
 * part of and find that TPGT value in the list of TPGTs this target
 * is willing to expose. If the TPGT value is not found in the list
 * return zero which will break the connection.
 */
static int
convert_to_tpgt(iscsi_conn_t *c, tgt_node_t *targ)
{
	tgt_node_t	*list;
	tgt_node_t	*tpgt		= NULL;
	int		addr_tpgt, pos_tpgt;

	/*
	 * If this target doesn't have a list of target portal group tags
	 * just return the default which is 1.
	 */
	list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL);
	if (list == NULL)
		return (1);

	/*
	 * If we don't find our IP in the general configuration list
	 * we'll use the default value which is 1 according to RFC3720.
	 */
	addr_tpgt = find_main_tpgt(&(c->c_target_sockaddr));

	while ((tpgt = tgt_node_next(list, XML_ELEMENT_TPGT, tpgt)) != NULL) {
		(void) tgt_find_value_int(tpgt, XML_ELEMENT_TPGT, &pos_tpgt);
		if (pos_tpgt == addr_tpgt) {
			return (addr_tpgt);
		}
	}

	return (0);
}
예제 #2
0
파일: util.c 프로젝트: imp/slist
/*
 * []----
 * | convert_local_tpgt -- Convert a local tpgt name to real addresses
 * |
 * | To simplify the configuration files targets only have a target portal
 * | group tag string(s) associated. In the main configuration file there's
 * | a tpgt element which has one or more ip-address elements. So the tag
 * | is located and the actual data is inserted into the outgoing stream.
 * []----
 */
static Boolean_t
convert_local_tpgt(char **text, int *text_length, char *local_tpgt)
{
	tgt_node_t	*tpgt	= NULL;
	tgt_node_t 	*x;
	char		buf[80];
	char		ipaddr[4];

	while ((tpgt = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
	    tpgt)) != NULL) {
		if (strcmp(tpgt->x_value, local_tpgt) == 0) {

			/*
			 * The only children of the tpgt element are
			 * ip-address elements. The value of each element is
			 * the string we need to use. So, we don't need to
			 * check the node's name to see if this is correct or
			 * not.
			 */
			if ((tpgt = tgt_node_next(tpgt, XML_ELEMENT_IPADDRLIST,
			    NULL)) == NULL) {
				return (False);
			}

			x = NULL;
			while ((x = tgt_node_next(tpgt, XML_ELEMENT_IPADDR, x))
			    != NULL) {
				if (inet_pton(AF_INET, x->x_value, &ipaddr)
				    == 1) {
					/*
					 * Valid IPv4 address
					 */
					(void) snprintf(buf, sizeof (buf),

					    "%s,%s", x->x_value, local_tpgt);
				} else {
					/*
					 * Invalid IPv4 address
					 * try with brackets (RFC2732)
					 */
					(void) snprintf(buf, sizeof (buf),
					    "[%s],%s", x->x_value, local_tpgt);
				}
				(void) add_text(text, text_length,
				    "TargetAddress", buf);
			}
			break;
		}
	}

	return (True);
}
예제 #3
0
파일: util.c 프로젝트: alhazred/onarm
/*
 * []----
 * | find_main_tpgt -- Looks up the IP address and finds a match TPGT
 * |
 * | If no TPGT for this address exists the routine returns 0 which
 * | is an illegal TPGT value.
 * []----
 */
static int
find_main_tpgt(struct sockaddr_storage *pst)
{
	char		ip_addr[16];
	tgt_node_t	*tpgt				= NULL;
	tgt_node_t	*ip_node			= NULL;
	struct in_addr	addr;
	struct in6_addr	addr6;

	/*
	 * Hardly can you believe that such struct-to-struct
	 * assignment IS valid.
	 */
	addr = ((struct sockaddr_in *)pst)->sin_addr;
	addr6 = ((struct sockaddr_in6 *)pst)->sin6_addr;

	while ((tpgt = tgt_node_next(main_config, XML_ELEMENT_TPGT,
	    tpgt)) != NULL) {

		ip_node = NULL;
		while ((ip_node = tgt_node_next(tpgt, XML_ELEMENT_IPADDR,
		    ip_node)) != NULL) {

			if (pst->ss_family == AF_INET) {

				if (inet_pton(AF_INET, ip_node->x_value,
				    ip_addr) != 1) {
					continue;
				}
				if (bcmp(ip_addr, &addr,
					sizeof (struct in_addr)) == 0) {
					return (atoi(tpgt->x_value));
				}
			} else if (pst->ss_family == AF_INET6) {

				if (inet_pton(AF_INET6, ip_node->x_value,
				    ip_addr) != 1) {
					continue;
				}
				if (bcmp(ip_addr, &addr6,
					sizeof (struct in6_addr)) == 0) {
					return (atoi(tpgt->x_value));
				}
			}
		}
	}

	return (0);
}
예제 #4
0
static char *
remove_initiator(tgt_node_t *x)
{
	char		*msg	= NULL;
	char		*name;
	tgt_node_t	*node	= NULL;

	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
		return (msg);
	}
	while ((node = tgt_node_next(main_config, XML_ELEMENT_INIT, node)) !=
	    NULL) {
		if (strcmp(node->x_value, name) == 0)
			break;
	}
	free(name);
	if (node == NULL) {
		xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
		return (msg);
	}
	if (tgt_find_value_str(x, XML_ELEMENT_ALL, &name) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_ALL);
		return (msg);
	}
	(void) tgt_node_remove(main_config, node, MatchBoth);

	if (mgmt_config_save2scf() == True)
		xml_rtn_msg(&msg, ERR_SUCCESS);

	return (msg);
}
예제 #5
0
파일: util.c 프로젝트: alhazred/onarm
static Boolean_t
connection_parameters_get(iscsi_conn_t *c, char *targ_name)
{
	tgt_node_t	*targ, *alias;
	Boolean_t	rval	= False;

	if ((targ = find_target_node(targ_name)) != NULL) {

		if (check_access(targ, c->c_sess->s_i_name, False) == False)
			return (False);

		/*
		 * Have a valid node for our target. Start looking
		 * for connection oriented parameters.
		 */
		if ((c->c_tpgt = convert_to_tpgt(c, targ)) == 0)
			return (False);
		if ((alias = tgt_node_next(targ, XML_ELEMENT_ALIAS, NULL)) ==
		    NULL) {
			(void) tgt_find_value_str(targ, XML_ELEMENT_TARG,
			    &c->c_targ_alias);
		} else {
			(void) tgt_find_value_str(alias, XML_ELEMENT_ALIAS,
			    &c->c_targ_alias);
		}

		(void) tgt_find_value_int(targ, XML_ELEMENT_MAXCMDS,
		    &c->c_maxcmdsn);
		rval = True;
	}

	return (rval);
}
예제 #6
0
파일: xml.c 프로젝트: imp/slist
tgt_node_t *
tgt_node_next(tgt_node_t *n, char *name, tgt_node_t *cur)
{
	tgt_node_t	*x;
	tgt_node_t	*p;

	if (n == NULL)
		return (NULL);

	if (cur != NULL) {
		for (x = cur->x_sibling; x; x = x->x_sibling)
			if (strcmp(x->x_name, name) == 0)
				return (x);
		return (NULL);
	}

	if (n->x_name == NULL)
		return (NULL);

	if (strcmp(n->x_name, name) == 0)
		return (n);
	for (x = n->x_child; x; x = x->x_sibling)
		if ((p = tgt_node_next(x, name, 0)) != NULL)
			return (p);
	return (NULL);
}
예제 #7
0
파일: util.c 프로젝트: alhazred/onarm
/*
 * []----
 * | add_targets -- add TargetName and TargetAddress to text argument
 * |
 * | Add targets which this initiator is allowed to see based on
 * | the access_list associated with a target. If a target doesn't
 * | have an access list then let everyone see it.
 * []----
 */
static Boolean_t
add_targets(iscsi_conn_t *c, char **text, int *text_length)
{
	tgt_node_t	*targ		= NULL;
	Boolean_t	rval		= True;
	char		*targ_name	= NULL;

	while ((rval == True) && ((targ = tgt_node_next(targets_config,
	    XML_ELEMENT_TARG, targ)) != NULL)) {

		if (check_access(targ, c->c_sess->s_i_name, False) == True) {

			if (tgt_find_value_str(targ, XML_ELEMENT_INAME,
			    &targ_name) == False) {
				rval = False;
				break;
			}
			queue_prt(c->c_mgmtq, Q_CONN_LOGIN,
			    "CON%x    %24s = %s\n", c->c_num, "TargetName",
			    targ_name);

			(void) add_text(text, text_length, "TargetName",
			    targ_name);
			free(targ_name);
			add_target_address(c, text, text_length, targ);
		}
	}
	return (rval);
}
예제 #8
0
파일: util.c 프로젝트: alhazred/onarm
/*
 * []----
 * | add_target_address -- find and add any target address information
 * []----
 */
static void
add_target_address(iscsi_conn_t *c, char **text, int *text_length,
    tgt_node_t *targ)
{
	tgt_node_t	*tpgt_list;
	tgt_node_t	*tpgt = NULL;
	struct sockaddr_in	*sp4;
	struct sockaddr_in6	*sp6;
	/*
	 * 7 is enough room for the largest TPGT of "65536", the ',' and a NULL
	 */
	char	buf[INET6_ADDRSTRLEN + 7];
	char	net_buf[INET6_ADDRSTRLEN];

	if ((tpgt_list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST,
	    NULL)) == NULL) {
		if_target_address(text, text_length,
		    (struct sockaddr *)&c->c_target_sockaddr);
		return;
	}

	while ((tpgt = tgt_node_next(tpgt_list, XML_ELEMENT_TPGT,
	    tpgt)) != NULL) {
		if (convert_local_tpgt(text, text_length, tpgt->x_value) ==
		    False) {
			if (c->c_target_sockaddr.ss_family == AF_INET) {
				/*CSTYLED*/
				sp4 = (struct sockaddr_in *)&c->c_target_sockaddr;
				(void) snprintf(buf, sizeof (buf), "%s,%s",
				    inet_ntop(sp4->sin_family,
				    (void *)&sp4->sin_addr,
				    net_buf, sizeof (net_buf)),
				    tpgt->x_value);
			} else {
				/*CSTYLED*/
				sp6 = (struct sockaddr_in6 *)&c->c_target_sockaddr;
				(void) snprintf(buf, sizeof (buf), "%s,%s",
				    inet_ntop(sp6->sin6_family,
				    (void *)&sp6->sin6_addr,
				    net_buf, sizeof (net_buf)),
				    tpgt->x_value);
			}
			(void) add_text(text, text_length, "TargetAddress",
			    buf);
		}
	}
}
예제 #9
0
파일: mgmt_scf.c 프로젝트: alhazred/onarm
/*
 * mgmt_convert_param() converts legacy params file of each LUN
 * to scf data. It will convert LUNs under one target each time.
 * Args:
 *   dir - string of directory where param file is stored
 *   tnode - node tree which contains to a target
 */
Boolean_t
mgmt_convert_param(char *dir, tgt_node_t *tnode)
{
	Boolean_t	ret = False;
	char		path[MAXPATHLEN];
	int		xml_fd = -1;
	int		n;
	int		lun_num;
	tgt_node_t	*lun = NULL;
	tgt_node_t	*params = NULL;
	xmlTextReaderPtr	r;

	while ((lun = tgt_node_next(tnode, XML_ELEMENT_LUN, lun)) != NULL) {
		if ((tgt_find_value_int(lun, XML_ELEMENT_LUN, &lun_num)) ==
		    False)
			continue;
		(void) snprintf(path, sizeof (path), "%s/%s%d",
		    dir, PARAMBASE, lun_num);
		if ((xml_fd = open(path, O_RDONLY)) < 0)
			continue;
		if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
		    NULL, NULL, 0)) == NULL)
			continue;

		n = xmlTextReaderRead(r);
		while (n == 1) {
			if (tgt_node_process(r, &params) == False) {
				break;
			}
			n = xmlTextReaderRead(r);
		}
		if (n < 0) {
			ret = False;
			break;
		}

		if (mgmt_param_save2scf(params, tnode->x_value, lun_num)
		    != True) {
			ret = False;
			break;
		} else {
			backup(path, tnode->x_value);
			ret = True;
		}
		params = NULL;
		(void) close(xml_fd);
		xmlTextReaderClose(r);
		xmlFreeTextReader(r);
	}

	if (ret == False)
		syslog(LOG_ERR, "Converting target %s params failed", dir);
	return (ret);
}
예제 #10
0
파일: util.c 프로젝트: alhazred/onarm
/*
 * []----
 * | find_target_node -- given a target IQN name, return the XML node
 * []----
 */
tgt_node_t *
find_target_node(char *targ_name)
{
	tgt_node_t	*tnode	= NULL;
	char		*iname;

	while ((tnode = tgt_node_next(targets_config, XML_ELEMENT_TARG,
	    tnode)) != NULL) {
		if (tgt_find_value_str(tnode, XML_ELEMENT_INAME, &iname) ==
		    True) {
			if (strcmp(iname, targ_name) == 0) {
				free(iname);
				return (tnode);
			} else
				free(iname);
		}
	}

	return (NULL);
}
예제 #11
0
static char *
remove_target(tgt_node_t *x)
{
	char		*msg			= NULL;
	char		*prop			= NULL;
	tgt_node_t	*targ			= NULL;
	tgt_node_t	*list;
	tgt_node_t	*c			= NULL;
	Boolean_t	change_made		= False;
	int		lun_num;

	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
		return (msg);
	}

	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) !=
	    NULL) {
		if (strcmp(targ->x_value, prop) == 0)
			break;
	}
	free(prop);
	if (targ == NULL) {
		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
		return (msg);
	}
	if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL);
			return (msg);
		}
		if ((list = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) ==
		    NULL) {
			free(prop);
			xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND);
			return (msg);
		}
		c = tgt_node_alloc(XML_ELEMENT_ACLINIT, String, prop);
		if (tgt_node_remove(list, c, MatchBoth) == False) {
			xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
			goto error;
		}
		tgt_node_free(c);
		if (list->x_child == NULL)
			(void) tgt_node_remove(targ, list, MatchName);
		free(prop);
		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);
			return (msg);
		}
		if ((list = tgt_node_next(targ, XML_ELEMENT_TPGTLIST, NULL)) ==
		    NULL) {
			free(prop);
			xml_rtn_msg(&msg, ERR_ACL_NOT_FOUND);
			return (msg);
		}
		c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop);
		if (tgt_node_remove(list, c, MatchBoth) == False) {
			xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
			goto error;
		}
		tgt_node_free(c);
		if (list->x_child == NULL)
			(void) tgt_node_remove(targ, list, MatchName);
		free(prop);

		/* update isns */
		if (isns_enabled()) {
			if (isns_dev_update(targ->x_value, ISNS_MOD_TPGT) != 0)
				syslog(LOG_ALERT, "ISNS register failed\n");
		}

		change_made = True;
	}
	if (tgt_find_value_int(x, XML_ELEMENT_LUN, &lun_num) == True) {

		if (tgt_find_value_intchk(x, XML_ELEMENT_LUN, &lun_num) ==
		    False) {
			xml_rtn_msg(&msg, ERR_LUN_INVALID_RANGE);
			return (msg);
		}

		/*
		 * Save the iscsi-name which we'll need to remove LUNs.
		 */
		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
		    False) {
			xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
			return (msg);
		}

		logout_targ(prop);
		thick_provo_stop(prop, lun_num);

		remove_target_common(targ->x_value, lun_num, &msg);
		if (msg != NULL)
			goto error;

		/* ISNS de-register target if it's the last lun */
		if (lun_num == 0 && isns_enabled() == True) {
			if (isns_dereg(prop) != 0)
				syslog(LOG_INFO, "ISNS dereg failed\n");
		}

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

	if (change_made == True) {
		if (mgmt_config_save2scf() == True)
			xml_rtn_msg(&msg, ERR_SUCCESS);
	} else {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
	}

	return (msg);

error:
	if (c != NULL)
		tgt_node_free(c);
	if (prop != NULL)
		free(prop);
	return (msg);
}
예제 #12
0
파일: mgmt_scf.c 프로젝트: alhazred/onarm
/*
 * this function tries to convert configuration in files into scf
 * it loads xml conf into node tree then dump them to scf with
 * mgmt_config_save2scf()
 * this function has 3 return values:
 * CONVERT_OK: successfully converted
 * CONVERT_INIT_NEW: configuration files dont exist, created a new scf entry
 * CONVERT_FAIL: some error occurred in conversion and no scf entry created.
 *               In this case, user have to check files manually and try
 *               conversion again.
 */
convert_ret_t
mgmt_convert_conf()
{
	targ_scf_t		*h = NULL;
	xmlTextReaderPtr	r;
	convert_ret_t		ret = CONVERT_FAIL;
	int			xml_fd = -1;
	int			n;
	tgt_node_t		*node = NULL;
	tgt_node_t		*next = NULL;
	char			path[MAXPATHLEN];
	char			*target = NULL;

	h = mgmt_handle_init();
	if (h == NULL)
		return (CONVERT_FAIL);

	/* check main config in pgroup iscsitgt */
	if (scf_service_get_pg(h->t_service, "iscsitgt", h->t_pg) == 0) {
		ret = CONVERT_OK;
		goto done;
	}

	/* check the conf files */
	if (access(config_file, R_OK) != 0) {
		/*
		 * if there is no configuration file, initialize
		 * an empty scf entry
		 */
		if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
			ret = CONVERT_INIT_NEW;

			node = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
			new_property(h, node);
			tgt_node_free(node);
			/* "daemonize" is set to true by default */
			node = tgt_node_alloc(XML_ELEMENT_DBGDAEMON, String,
			    "true");
			new_property(h, node);
			tgt_node_free(node);
			node = NULL;
			node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
			    ISCSI_AUTH_MODIFY);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
			    ISCSI_AUTH_VALUE);
			new_property(h, node);
			tgt_node_free(node);
			mgmt_transaction_end(h);
		} else {
			syslog(LOG_ERR, "Creating empty entry failed");
			ret = CONVERT_FAIL;
			goto done;
		}
		if (mgmt_transaction_start(h, "passwords", "application") ==
		    True) {
			node = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
			    ISCSI_AUTH_READ);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
			    ISCSI_AUTH_MODIFY);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
			    ISCSI_AUTH_VALUE);
			new_property(h, node);
			tgt_node_free(node);
			mgmt_transaction_end(h);
		} else {
			syslog(LOG_ERR, "Creating empty entry failed");
			ret = CONVERT_FAIL;
		}
		goto done;
	}

	if ((xml_fd = open(config_file, O_RDONLY)) >= 0)
		r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, 0);

	if (r != NULL) {
		n = xmlTextReaderRead(r);
		while (n == 1) {
			if (tgt_node_process(r, &node) == False) {
				break;
			}
			n = xmlTextReaderRead(r);
		}
		if (n < 0) {
			syslog(LOG_ERR, "Parsing main config failed");
			ret = CONVERT_FAIL;
			goto done;
		}

		main_config = node;

		(void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR,
		    &target_basedir);

		if (target_basedir == NULL)
			target_basedir = strdup(DEFAULT_TARGET_BASEDIR);

		/* Now convert targets' config if possible */
		if (xml_fd != -1)
			(void) close(xml_fd);
		xmlTextReaderClose(r);
		xmlFreeTextReader(r);
		xmlCleanupParser();
		r = NULL;
		xml_fd = -1;
		node = NULL;

		(void) snprintf(path, MAXPATHLEN, "%s/%s",
		    target_basedir, "config.xml");

		if ((xml_fd = open(path, O_RDONLY)) >= 0)
			r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
			    NULL, NULL, 0);

		if (r != NULL) {
			n = xmlTextReaderRead(r);
			while (n == 1) {
				if (tgt_node_process(r, &node) == False) {
					break;
				}
				n = xmlTextReaderRead(r);
			}
			if (n < 0) {
				syslog(LOG_ERR, "Parsing target conf failed");
				ret = CONVERT_FAIL;
				goto done;
			}

			/* now combine main_config and node */
			if (node) {
				next = NULL;
				while ((next = tgt_node_next(node,
				    XML_ELEMENT_TARG, next)) != NULL) {
					tgt_node_add(main_config,
					    tgt_node_dup(next));
				}
				tgt_node_free(node);
			}

			if (mgmt_config_save2scf() != True) {
				syslog(LOG_ERR, "Converting config failed");
				if (xml_fd != -1)
					(void) close(xml_fd);
				xmlTextReaderClose(r);
				xmlFreeTextReader(r);
				xmlCleanupParser();
				ret = CONVERT_FAIL;
				goto done;
			}

			/* Copy files into backup dir */
			(void) snprintf(path, sizeof (path), "%s/backup",
			    target_basedir);
			if ((mkdir(path, 0755) == -1) && (errno != EEXIST)) {
				syslog(LOG_ERR, "Creating backup dir failed");
				ret = CONVERT_FAIL;
				goto done;
			}
			backup(config_file, NULL);
			(void) snprintf(path, MAXPATHLEN, "%s/%s",
			    target_basedir, "config.xml");
			backup(path, NULL);


			while ((next = tgt_node_next(main_config,
			    XML_ELEMENT_TARG, next)) != NULL) {
				if (tgt_find_value_str(next, XML_ELEMENT_INAME,
				    &target) == False) {
					continue;
				}
				(void) snprintf(path, MAXPATHLEN, "%s/%s",
				    target_basedir, target);
				if (mgmt_convert_param(path, next)
				    != True) {
					ret = CONVERT_FAIL;
					goto done;
				}
				free(target);
			}

			ret = CONVERT_OK;
			syslog(LOG_NOTICE, "Conversion succeeded");

			xmlTextReaderClose(r);
			xmlFreeTextReader(r);
			xmlCleanupParser();
		} else {
			syslog(LOG_ERR, "Reading targets config failed");
			ret = CONVERT_FAIL;
			goto done;
		}
	} else {
		syslog(LOG_ERR, "Reading main config failed");
		ret = CONVERT_FAIL;
		goto done;
	}

done:
	if (xml_fd != -1)
		(void) close(xml_fd);
	mgmt_handle_fini(h);
	return (ret);
}
예제 #13
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);
}
예제 #14
0
파일: util.c 프로젝트: imp/slist
/*
 * []----
 * | check_access -- see if the requesting initiator is in the ACL
 * |
 * | Optionally will also check to see if this initiator requires
 * | authentication.
 * []----
 */
Boolean_t
check_access(tgt_node_t *targ, char *initiator_name, Boolean_t req_chap)
{
	tgt_node_t	*acl;
	tgt_node_t	*inode		= NULL;
	tgt_node_t	*tgt_initiator	= NULL;
	char		*dummy;
	Boolean_t	valid		= False;
	Boolean_t	found_chap	= False;
	Boolean_t	access		= False;

	/*
	 * If ISNS is enable check for access privilege from isns server
	 */
	if (isns_enabled() == True) {
		if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &dummy)
		    == False) {
			return (False);
		}
		access = isns_qry_initiator(dummy, initiator_name);
		free(dummy);
		if (req_chap == False) {
			return (access);
		}

		/* Need to check if CHAP is needed for initiator */
		while ((inode = tgt_node_next_child(main_config,
		    XML_ELEMENT_INIT, inode)) != NULL) {
			if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy)
			    == True) {
				if (strcmp(dummy, initiator_name) == 0) {
					free(dummy);
					if (tgt_find_value_str(inode,
					    XML_ELEMENT_CHAPSECRET, &dummy)
					    == True) {
						free(dummy);
						found_chap = True;
						break;
					}
				}
			}
		}
		if (access == True) {
			if ((req_chap == True) && (found_chap == True))
				access = False;
		}
		return (access);
	}

	/*
	 * If there's no ACL for this target everyone has access.
	 */
	if ((acl = tgt_node_next(targ, XML_ELEMENT_ACLLIST, NULL)) == NULL)
		return (True);

	/*
	 * Find the local initiator name and also save the knowledge
	 * if the initiator had a CHAP secret.
	 */
	inode = NULL;
	while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
	    inode)) != NULL) {
		if (tgt_find_value_str(inode, XML_ELEMENT_INAME, &dummy) ==
		    True) {
			if (strcmp(dummy, initiator_name) == 0) {
				free(dummy);
				if (tgt_find_value_str(inode,
				    XML_ELEMENT_CHAPSECRET, &dummy) == True) {
					free(dummy);
					found_chap = True;
				}
				break;
			} else {
				free(dummy);
			}
		}
	}

	if ((acl != NULL) && (inode == NULL))
		return (False);

	while ((tgt_initiator = tgt_node_next(acl, XML_ELEMENT_INIT,
	    tgt_initiator)) != NULL) {

		if (strcmp(inode->x_value, tgt_initiator->x_value) == 0) {
			valid = True;
			break;
		}
	}

	if (valid == True) {

		/*
		 * If req_chap is True it means the login code hasn't gone
		 * through the authentication phase and it's trying to
		 * determine if the initiator should have done so. If
		 * we find a CHAP-secret then this routine will fail.
		 * No CHAP-secret for an initiator just means that a
		 * simple ACL list is used. This can be spoofed easily
		 * enough and is mainly used to limit the number of
		 * targets an initiator would see.
		 */
		if ((req_chap == True) && (found_chap == True))
			valid = False;
	}

	return (valid);
}
예제 #15
0
/*
 * []----
 * | modify_tpgt -- add an IP-address to a target portal group
 * []----
 */
static char *
modify_tpgt(tgt_node_t *x)
{
	struct addrinfo	*res	= NULL;
	char		*msg	= NULL;
	char		*name	= NULL;
	char		*ip_str	= NULL;
	tgt_node_t	*tnode	= NULL;
	tgt_node_t	*list	= NULL;

	(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;
	}
	if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR);
		goto error;
	}
	if ((getaddrinfo(ip_str, NULL, NULL, &res) != 0) || (res == NULL)) {
		xml_rtn_msg(&msg, ERR_INVALID_IP);
		goto error;
	}
	while ((tnode = tgt_node_next_child(main_config, XML_ELEMENT_TPGT,
	    tnode)) != NULL) {
		if (strcmp(tnode->x_value, name) == 0)
			break;
	}
	if (tnode == NULL) {
		xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
		goto error;
	}

	if ((list = tgt_node_next(tnode, XML_ELEMENT_IPADDRLIST, NULL))
	    == NULL) {
		list = tgt_node_alloc(XML_ELEMENT_IPADDRLIST, String, "");
		if (list == NULL) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		tgt_node_add(tnode, list);
	}
	if (modify_element(XML_ELEMENT_IPADDR, ip_str, list, MatchBoth) ==
	    False) {
		xml_rtn_msg(&msg, ERR_NO_MEM);
		goto error;
	}

	if (mgmt_config_save2scf() == True) {
		xml_rtn_msg(&msg, ERR_SUCCESS);
	} else {
		/* tpgt change should be updated to smf */
		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
	}

	/*
	 * Re-register all targets, currently there's no method to
	 * update TPGT for individual target
	 */
	if (isns_enabled() == True) {
		(void) isns_reg_all();
	}

error:
	if (name)
		free(name);
	if (ip_str)
		free(ip_str);
	if (res)
		freeaddrinfo(res);
	(void) pthread_rwlock_unlock(&targ_config_mutex);
	return (msg);
}
예제 #16
0
파일: isns_client.c 프로젝트: imp/slist
/*
 * Find ip-addr associated with TPGT, don't send if no ip-addr is
 * found for a TPGT
 */
static int
append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd)
{
	tgt_node_t	*t, *x;
	tgt_node_t	*pgt	= NULL;
	tgt_node_t	*iplist	= NULL;
	tgt_node_t	*tpgt	= NULL;
	ip_t		eid;

	/* Always add the default TPGT (1) */
	(void) isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL,
	    1);
	if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
	    eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
	    eid_ip.ip_len) != 0) {
		return (-1);
	}
	if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID,
	    ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
		return (-1);
	}

	/* Get the remainning TPGT-LIST */
	if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL))
	    != NULL) {
		/* find tgpt from tpgt-list */
		while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt))
		    != NULL) {
			/* update isns only if TPGT contains ip_addr */
			while ((tpgt = tgt_node_next_child(main_config,
			    XML_ELEMENT_TPGT, tpgt)) != NULL) {
				if (strcmp(pgt->x_value, tpgt->x_value) != 0)
					continue;
				if ((iplist = tgt_node_next(tpgt,
				    XML_ELEMENT_IPADDRLIST, NULL)) != NULL)
					break;
			}
			if (tpgt == NULL || iplist == NULL)
				continue;
			if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID,
			    ISNS_PG_TAG_SZ, NULL,
			    strtol(pgt->x_value, NULL, 0)) != 0) {
				return (-1);
			}

			/* get ip-addr & port */
			for (x = iplist->x_child; x; x = x->x_sibling) {
				if (get_ip_addr(x->x_value, &eid) < 0)
					continue;
				if (isns_append_attr(cmd,
				    ISNS_PG_PORTAL_IP_ADDR_ATTR_ID,
				    eid.ai_addrlen, (void *)&eid.ip_adr,
				    eid.ip_len) != 0) {
					return (-1);
				}
				if (isns_append_attr(cmd,
				    ISNS_PG_PORTAL_PORT_ATTR_ID,
				    ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
					return (-1);
				}
			}
		}
	}

	return (0);
}
예제 #17
0
static char *
remove_tpgt(tgt_node_t *x)
{
	char		*msg		= NULL;
	char		*prop		= NULL;
	tgt_node_t	*node		= NULL;
	tgt_node_t	*c		= NULL;
	Boolean_t	change_made	= False;

	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
		return (msg);
	}
	while ((node = tgt_node_next(main_config, XML_ELEMENT_TPGT, node)) !=
	    NULL) {
		if (strcmp(node->x_value, prop) == 0)
			break;
	}
	free(prop);
	if (node == NULL) {
		xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND);
		return (msg);
	}
	if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &prop) == True) {
		if (prop == NULL) {
			xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_IPADDR);
			return (msg);
		}
		c = tgt_node_alloc(XML_ELEMENT_IPADDR, String, prop);
		if (tgt_node_remove(node, c, MatchBoth) == False) {
			xml_rtn_msg(&msg, ERR_INVALID_IP);
			goto error;
		}
		tgt_node_free(c);
		free(prop);
		change_made = True;
	}
	if ((change_made != True) &&
	    (tgt_find_value_str(x, XML_ELEMENT_ALL, &prop) == True)) {
		tgt_node_remove(main_config, node, MatchBoth);
		change_made = True;
	}

	if (change_made == True) {
		/* Isns re-register all target */
		if (isns_enabled() == True)
			isns_reg_all();
		if (mgmt_config_save2scf() == True)
			xml_rtn_msg(&msg, ERR_SUCCESS);
	} else {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
	}

	return (msg);

error:
	if (c != NULL)
		tgt_node_free(c);
	if (prop != NULL)
		free(prop);
	return (msg);
}
예제 #18
0
/*
 * modify_zfs -- test for the existence of a certain dataset being shared
 *
 * Called when someone uses the iscsitgt_is_shared() function from libiscsitgt.
 * All that
 */
static char *
modify_zfs(tgt_node_t *x, ucred_t *cred)
{
	char		*msg		= NULL;
	char		*dataset	= NULL;
	char		*prop;
	char		*m;
	tgt_node_t	*n		= NULL;
	tgt_node_t	*t		= NULL;
	tgt_node_t	*list		= NULL;
	tgt_node_t	*c1, *c2;
	Boolean_t	change_made	= False;
	uint64_t	size;
	int		status;
	int		val;
	char		*tru = "true";

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

	/*
	 * Validate request
	 */
	if (tgt_find_value_str(x, XML_ELEMENT_VALIDATE, &tru)) {
		(void) pthread_rwlock_unlock(&targ_config_mutex);
		if (tru)
			free(tru);
		free(dataset);
		return (validate_zfs_iscsitgt(x));
	}

	/*
	 * Check for existance of ZFS shareiscsi properties
	 */
	status = get_zfs_shareiscsi(dataset, &n, &size, cred);
	if ((status != ERR_SUCCESS) && (status != ERR_NULL_XML_MESSAGE)) {
		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
		goto error;
	}

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

	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);
			goto error;
		}

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

		/*
		 * Due to the fact that the targets_config differs from the
		 * ZVOL properties stored in zfs_shareiscsi, two lists need to
		 * be updated
		 */
		c2 = tgt_node_dup(c1);
		if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL))
		    != NULL) {
			/*
			 * tgt_node_replace will duplicate the child node
			 * tgt_node_add which is used below just links it
			 * into the tree.
			 */
			tgt_node_replace(list, c1, MatchBoth);
			tgt_node_free(c1);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
			if (list == NULL) {
				xml_rtn_msg(&msg, ERR_NO_MEM);
				goto error;
			}
			tgt_node_add(list, c1);
			tgt_node_add(t, list);
		}
		if ((list = tgt_node_next(n, XML_ELEMENT_TPGTLIST, NULL))
		    != NULL) {
			/*
			 * tgt_node_replace will duplicate the child node
			 * tgt_node_add which is used below just links it
			 * into the tree.
			 */
			tgt_node_replace(list, c2, MatchBoth);
			tgt_node_free(c2);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, "");
			if (list == NULL) {
				xml_rtn_msg(&msg, ERR_NO_MEM);
				goto error;
			}
			tgt_node_add(list, c2);
			tgt_node_add(n, list);
		}
		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;
		}

		c1 = tgt_node_alloc(XML_ELEMENT_INIT, String, prop);
		if (c1 == NULL) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}

		/*
		 * Due to the fact that the targets_config differs from the
		 * ZVOL properties stored in zfs_shareiscsi, two lists need to
		 * be updated
		 */
		c2 = tgt_node_dup(c1);
		if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL))
		    != NULL) {
			/*
			 * tgt_node_replace will duplicate the child node
			 * tgt_node_add which is used below just links it
			 * into the tree.
			 */
			tgt_node_replace(list, c1, MatchBoth);
			tgt_node_free(c1);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
			if (list == NULL) {
				xml_rtn_msg(&msg, ERR_NO_MEM);
				goto error;
			}
			tgt_node_add(list, c1);
			tgt_node_add(t, list);
		}
		if ((list = tgt_node_next(n, XML_ELEMENT_ACLLIST, NULL))
		    != NULL) {
			/*
			 * tgt_node_replace will duplicate the child node
			 * tgt_node_add which is used below just links it
			 * into the tree.
			 */
			tgt_node_replace(list, c2, MatchBoth);
			tgt_node_free(c2);
		} else {
			list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, "");
			if (list == NULL) {
				xml_rtn_msg(&msg, ERR_NO_MEM);
				goto error;
			}
			tgt_node_add(list, c2);
			tgt_node_add(n, list);
		}

		change_made = True;
	}

	if (change_made == True) {
		status = put_zfs_shareiscsi(dataset, n);
		if (status != ERR_SUCCESS) {
			xml_rtn_msg(&msg, status);
			goto error;
		} else {
			xml_rtn_msg(&msg, ERR_SUCCESS);
		}
	} else {
		xml_rtn_msg(&msg, ERR_SUCCESS);
	}

error:
	if (n)
		tgt_node_free(n);
	if (dataset)
		free(dataset);

	(void) pthread_rwlock_unlock(&targ_config_mutex);
	return (msg);
}
예제 #19
0
파일: main.c 프로젝트: CoryXie/opensolaris
static int
listTpgt(int operandLen, char *operand[], cmdOptions_t *options)
{
	char		*first_str	= NULL;
	tgt_node_t	*node		= NULL;
	tgt_node_t	*n1		= NULL; /* pointer to node (depth=1) */
	tgt_node_t	*n2		= NULL; /* pointer to node (depth=2) */
	cmdOptions_t	*optionList	= options;
	Boolean_t	verbose		= False;
	int		addrs;

	if (operand == NULL)
		return (1);

	tgt_buf_add_tag(&first_str, "list", Tag_Start);
	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_Start);

	if (operandLen)
		tgt_buf_add(&first_str, XML_ELEMENT_NAME, operand[0]);
	if (optionList) {
		switch (optionList->optval) {
		case 0: /* no options, treat as --verbose */
			break;
		case 'v':
			verbose = True;
			tgt_buf_add(&first_str,
			    XML_ELEMENT_VERBOSE, OPT_TRUE);
			break;
		default:
			(void) fprintf(stderr, "%s: %c: %s\n",
			    cmdName, optionList->optval,
			    gettext("unknown option"));
			free(first_str);
			return (1);
		}
	}

	tgt_buf_add_tag(&first_str, XML_ELEMENT_TPGT, Tag_End);
	tgt_buf_add_tag(&first_str, "list", Tag_End);

	if ((node = tgt_door_call(first_str, 0)) == NULL) {
		(void) fprintf(stderr, "%s: %s\n", cmdName,
		    gettext("No reponse from daemon"));
		return (1);
	}
	free(first_str);

	if (strcmp(node->x_name, XML_ELEMENT_RESULT)) {
		(void) fprintf(stderr, "%s: %s\n", cmdName,
		    gettext("Bad XML response"));
		return (1);
	}

	n1 = NULL;
	while (n1 = tgt_node_next_child(node, XML_ELEMENT_TPGT, n1)) {
		(void) printf("%s: %s\n", gettext("TPGT"), n1->x_value);
		n2 = NULL;
		addrs = 0;
		while (n2 = tgt_node_next(n1, XML_ELEMENT_IPADDR, n2)) {
			if (verbose == True)
				(void) printf("%s%s: %s\n", dospace(1),
				    gettext("IP Address"),
				    n2 ? n2->x_value : gettext("Not set"));
			addrs++;
		}

		if (verbose == False) {
			(void) printf("%s%s: %d\n", dospace(1),
			    gettext("IP Address count"), addrs);
		} else if (addrs == 0) {

			/*
			 * Verbose is true, but there where no addresses
			 * for this TPGT. To keep the output consistent
			 * dump a "Not set" string out.
			 */
			(void) printf("%s%s: %s\n", dospace(1),
			    gettext("IP Address"), gettext("Not set"));
		}
	}

	return (0);
}
예제 #20
0
/*
 * remove_zfs -- unshare a ZVOL from the target
 */
static char *
remove_zfs(tgt_node_t *x, ucred_t *cred)
{
	char		*prop;
	char		*msg		= NULL;
	tgt_node_t		*targ = NULL;
	libzfs_handle_t		*zh = NULL;
	const priv_set_t	*eset;

	if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME);
		return (msg);
	}

	if ((zh = libzfs_init()) == NULL) {
		xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
		free(prop);
		return (msg);
	}

	eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
	if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) :
	    ucred_geteuid(cred) != 0) {
		/*
		 * See if user has ZFS dataset permissions to do operation
		 */
		if (zfs_iscsi_perm_check(zh, prop, cred) != 0) {
			xml_rtn_msg(&msg, ERR_NO_PERMISSION);
			free(prop);
			libzfs_fini(zh);
			return (msg);
		}
	}

	libzfs_fini(zh);

	while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ))
	    != NULL) {
		if (strcmp(targ->x_value, prop) == 0)
			break;
	}
	free(prop);
	if (targ == NULL) {
		/*
		 * We're unsharing a target. If we don't have a reference
		 * then there's no problem.
		 */
		xml_rtn_msg(&msg, ERR_SUCCESS);
		return (msg);
	}
	if (tgt_find_value_str(targ, XML_ELEMENT_INAME, &prop) ==
	    False) {
		xml_rtn_msg(&msg, ERR_TARGCFG_MISSING_INAME);
		return (msg);
	}

	tgt_node_remove(targets_config, targ, MatchBoth);

	/*
	 * Wait until here to issue a logout to any initiators that
	 * might be logged into the target. Certain initiators are
	 * sneaky in that if asked to logout they will, but turn right
	 * around and log back into the target. By waiting until here
	 * to issue the logout we'll have removed reference to the target
	 * such that this can't happen.
	 */
	if (isns_enabled() == True) {
		if (isns_dereg(prop) != 0)
			syslog(LOG_INFO, "ISNS dereg failed\n");
	}
	logout_targ(prop);
	free(prop);

	xml_rtn_msg(&msg, ERR_SUCCESS);
	return (msg);
}
예제 #21
0
파일: mgmt_scf.c 프로젝트: imp/slist
/*
 * Convert legacy (XML) configuration files into an equivalent SCF
 * representation.
 *
 * Read the XML from disk, translate the XML into a tree of nodes of
 * type tgt_node_t, and write the in-memory tree to SCF's persistent
 * data-store using mgmt_config_save2scf().
 *
 * Return Values:
 * CONVERT_OK:	     successfully converted
 * CONVERT_INIT_NEW: configuration files don't exist; created an SCF entry
 * CONVERT_FAIL: some conversion error occurred; no SCF entry created.
 *		 In this case, user has to manually check files and try
 *		 conversion again.
 */
convert_ret_t
mgmt_convert_conf()
{
	targ_scf_t		*h = NULL;
	xmlTextReaderPtr	r;
	convert_ret_t		ret = CONVERT_FAIL;
	int			xml_fd = -1;
	int			n;
	tgt_node_t		*node = NULL;
	tgt_node_t		*next = NULL;
	char			path[MAXPATHLEN];
	char			*target = NULL;

	h = mgmt_handle_init();
	if (h == NULL)
		return (CONVERT_FAIL);

	/*
	 * Check if the "iscsitgt" PropertyGroup has already been added
	 * to the "iscsitgt" SMF Service.  If so, then we have already
	 * converted the legacy configuration files (and there is no work
	 * to do).
	 */
	if (scf_service_get_pg(h->t_service, "iscsitgt", h->t_pg) == 0) {
		ret = CONVERT_OK;
		goto done;
	}

	if (access(config_file, R_OK) != 0) {
		/*
		 * then the Main Config file is not present; initialize
		 * SCF Properties to default values.
		 */
		if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
			ret = CONVERT_INIT_NEW;

			node = tgt_node_alloc(XML_ELEMENT_VERS, String, "1.0");
			new_property(h, node);
			tgt_node_free(node);
			/* "daemonize" is set to true by default */
			node = tgt_node_alloc(XML_ELEMENT_DBGDAEMON, String,
			    "true");
			new_property(h, node);
			tgt_node_free(node);
			node = NULL;
			node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
			    ISCSI_AUTH_MODIFY);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
			    ISCSI_AUTH_VALUE);
			new_property(h, node);
			tgt_node_free(node);
			(void) mgmt_transaction_end(h);
		} else {
			syslog(LOG_ERR, "Creating empty entry failed");
			ret = CONVERT_FAIL;
			goto done;
		}
		if (mgmt_transaction_start(h, "passwords", "application") ==
		    True) {
			node = tgt_node_alloc(ISCSI_READ_AUTHNAME, String,
			    ISCSI_AUTH_READ);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_MODIFY_AUTHNAME, String,
			    ISCSI_AUTH_MODIFY);
			new_property(h, node);
			tgt_node_free(node);
			node = tgt_node_alloc(ISCSI_VALUE_AUTHNAME, String,
			    ISCSI_AUTH_VALUE);
			new_property(h, node);
			tgt_node_free(node);
			(void) mgmt_transaction_end(h);
		} else {
			syslog(LOG_ERR, "Creating empty entry failed");
			ret = CONVERT_FAIL;
		}
		goto done;
	}

	if ((xml_fd = open(config_file, O_RDONLY)) >= 0)
		r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL, 0);

	if (r != NULL) {
		int is_target_config;

		n = xmlTextReaderRead(r);
		while (n == 1) {
			if (tgt_node_process(r, &node) == False) {
				break;
			}
			n = xmlTextReaderRead(r);
		}
		if (n < 0) {
			syslog(LOG_ERR, "Parsing main config failed");
			ret = CONVERT_FAIL;
			goto done;
		}

		main_config = node;

		/*
		 * Initialize the Base Directory (global) variable by
		 * using the value specified in the XML_ELEMENT_BASEDIR
		 * XML tag.  If a tag is not specified, use a default.
		 */
		(void) tgt_find_value_str(node, XML_ELEMENT_BASEDIR,
		    &target_basedir);

		if (target_basedir == NULL)
			target_basedir = strdup(DEFAULT_TARGET_BASEDIR);

		if (xml_fd != -1) {
			(void) close(xml_fd);
			xml_fd = -1;
		}
		(void) xmlTextReaderClose(r);
		xmlFreeTextReader(r);
		xmlCleanupParser();

		/*
		 * If a Target Config file is present, read and translate
		 * its XML representation into a tree of tgt_node_t.
		 * Merge that tree with the tree of tgt_node_t rooted at
		 * 'main_config'.  The merged tree will then be archived
		 * using an SCF representation.
		 */
		(void) snprintf(path, MAXPATHLEN, "%s/%s",
		    target_basedir, "config.xml");

		if ((xml_fd = open(path, O_RDONLY)) >= 0) {
			is_target_config = 1;
			r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd,
			    NULL, NULL, 0);
		} else {
			is_target_config = 0;
			r = NULL;
		}

		if (r != NULL) {
			/* then the Target Config file is available. */

			node = NULL;

			/*
			 * Create a tree of tgt_node_t rooted at 'node' by
			 * processing each XML Tag in the file.
			 */
			n = xmlTextReaderRead(r);
			while (n == 1) {
				if (tgt_node_process(r, &node) == False) {
					break;
				}
				n = xmlTextReaderRead(r);
			}
			if (n < 0) {
				syslog(LOG_ERR, "Parsing target conf failed");
				ret = CONVERT_FAIL;
				goto done;
			}

			/*
			 * Merge the tree at 'node' into the tree rooted at
			 * 'main_config'.
			 */
			if (node != NULL) {
				next = NULL;
				while ((next = tgt_node_next(node,
				    XML_ELEMENT_TARG, next)) != NULL) {
					tgt_node_add(main_config,
					    tgt_node_dup(next));
				}
				tgt_node_free(node);
			}
		}

		/*
		 * Iterate over the in-memory tree rooted at 'main_config'
		 * and write a representation of the appropriate nodes to
		 * SCF's persistent data-store.
		 */
		if (mgmt_config_save2scf() != True) {
			syslog(LOG_ERR, "Converting config failed");
			if (xml_fd != -1) {
				(void) close(xml_fd);
				xml_fd = -1;
			}
			(void) xmlTextReaderClose(r);
			xmlFreeTextReader(r);
			xmlCleanupParser();
			ret = CONVERT_FAIL;
			goto done;
		}

		/*
		 * Move the configuration files into a well-known backup
		 * directory.  This allows a user to restore their
		 * configuration, if they choose.
		 */
		(void) snprintf(path, sizeof (path), "%s/backup",
		    target_basedir);
		if ((mkdir(path, 0755) == -1) && (errno != EEXIST)) {
			syslog(LOG_ERR, "Creating backup dir failed");
			ret = CONVERT_FAIL;
			goto done;
		}
		/* Save the Main Config file. */
		backup(config_file, NULL);

		/* Save the Target Config file, if it was present. */
		if (is_target_config != 0) {
			(void) snprintf(path, MAXPATHLEN, "%s/%s",
			    target_basedir, "config.xml");
			backup(path, NULL);
		}

		/*
		 * For each tgt_node_t node in 'main_config' whose value is
		 * an iSCSI Name as defined in the RFC (3720) standard (eg,
		 * "iqn.1986..."), read its XML-encoded attributes from a
		 * flat-file and write an equivalent representation to SCF's
		 * data-store.
		 */
		while ((next = tgt_node_next(main_config,
		    XML_ELEMENT_TARG, next)) != NULL) {
			if (tgt_find_value_str(next, XML_ELEMENT_INAME,
			    &target) == False) {
				continue;
			}
			(void) snprintf(path, MAXPATHLEN, "%s/%s",
			    target_basedir, target);
			if (mgmt_convert_param(path, next)
			    != True) {
				ret = CONVERT_FAIL;
				goto done;
			}
			free(target);
		}

		ret = CONVERT_OK;
		syslog(LOG_NOTICE, "Conversion succeeded");

		(void) xmlTextReaderClose(r);
		xmlFreeTextReader(r);
		xmlCleanupParser();
	} else {
		syslog(LOG_ERR, "Reading main config failed");
		ret = CONVERT_FAIL;
		goto done;
	}

done:
	if (xml_fd != -1)
		(void) close(xml_fd);
	mgmt_handle_fini(h);
	return (ret);
}