Beispiel #1
0
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);
}
Beispiel #2
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);
}
Beispiel #3
0
/*
 * isns_init() needs to be call before all ISNS operations.
 * Save the isns_server & entity name.
 * Start esi_scn_thr to receive ESI & SCN messages
 */
int
isns_init(target_queue_t *q)
{
	char	*entity = NULL;

	if (q != NULL)
		mgmtq = q;

	if (isns_enabled() == False)
		return (0);

	/*
	 * get entity from the configuration if it set, alternatively
	 * get local hostname for entity usage. If environment variable
	 * ISCSITGT_ISNS_ENTITY is set it overrides all the other means
	 * of entity definition
	 */

	if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_ENTITY, &entity)) {
		(void) strlcpy(isns_args.entity, entity, MAXHOSTNAMELEN + 1);
		free(entity);
	} else {
		(void) gethostname(isns_args.entity, MAXHOSTNAMELEN);
	}

	/* Try environment variable - it overrides everything else */
	entity = getenv(ISCSITGT_ISNS_ENTITY);
	if (entity != NULL) {
		(void) strlcpy(isns_args.entity, entity, MAXHOSTNAMELEN + 1);
	}

	if ((strlen(isns_args.entity) == 0) ||
	    (get_ip_addr(isns_args.entity, &eid_ip) < 0)) {
		syslog(LOG_ERR, "isns_init: failed to get host name or host ip"
		    " address for ENTITY properties");
		return (-1);
	}

	isns_shutdown = False;

	(void) isns_populate_and_update_server_info(False);
	if (pthread_create(&scn_tid, NULL,
	    esi_scn_thr, (void *)&isns_args) !=
	    0) {
		syslog(LOG_ALERT, "isns_init failed to pthread_create");
		(void) pthread_kill(isns_tid, SIGKILL);
		return (-1);
	}

	if (pthread_create(&isns_tid, NULL, isns_server_connection_thr,
	    (void *)NULL) != 0) {
		syslog(LOG_ALERT,
		    "isns_init failed to create the "
		    "isns connection thr");
		return (-1);
	}

	isns_server_connection_thr_running = True;
	return (0);
}
Beispiel #4
0
Datei: util.c Projekt: imp/slist
/*
 * []----
 * | 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_child(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);
}
Beispiel #5
0
static int
formatErrString(tgt_node_t *node)
{
	int	code	= 0;
	int	rtn	= 0;
	char	*msg	= NULL;

	if (node == NULL) {
		(void) fprintf(stderr, "%s: %s\n", cmdName,
		    gettext("Unable to contact target daemon"));
		return (1);
	}
	if ((strcmp(node->x_name, XML_ELEMENT_ERROR) == 0) &&
	    (tgt_find_value_int(node, XML_ELEMENT_CODE, &code) == B_TRUE) &&
	    (tgt_find_value_str(node, XML_ELEMENT_MESSAGE, &msg) == B_TRUE)) {

		/*
		 * 1000 is the success code, so we don't need to display
		 * the success message.
		 */
		if (code != 1000) {
			(void) fprintf(stderr, "%s: %s %s\n",
			    cmdName, gettext("Error"), msg);
			rtn = 1;
		}
	} else {
		(void) fprintf(stderr, "%s: %s\n", cmdName,
		    gettext("Bad XML response"));
		rtn = 1;
	}
	if (msg)
		free(msg);
	return (rtn);
}
Beispiel #6
0
/*
 * Perform operation on all targets
 */
static int
isns_op_all(uint16_t op)
{
	int		so;
	tgt_node_t	*tgt = NULL;
	char		*iname;

	if (isns_server_connection_thr_running == False) {
		syslog(LOG_ERR,
		    "isns_op_all: iSNS discovery is not running."
		    " Check the previous iSNS initialization error.");
		return (-1);
	}

	if ((so = isns_open(isns_args.server)) == -1) {
		syslog(LOG_ERR, "isns_op_all: failed to open isns server %s",
		    isns_args.server);
		return (-1);
	}

	while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    tgt)) != NULL) {
		if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname)
		    == FALSE) {
			continue;
		}

		switch (op) {
			case ISNS_DEV_DEREG:
				if (isns_dev_attr_dereg(so, iname) == -1) {
					syslog(LOG_ERR,
					    "ISNS de-register failed\n");
				}
				num_reg = 0;
				break;
			case ISNS_SCN_DEREG:
				if (isns_scn_dereg(so, iname) == -1) {
					syslog(LOG_ERR,
					    "ISNS SCN de-register failed\n");
				}
				break;
			case ISNS_SCN_REG:
				if (isns_scn_reg(so, iname) == -1) {
					syslog(LOG_ERR,
					    "ISNS SCN register failed\n");
				}
				break;
			case ISNS_TGT_LOGOUT:
				logout_targ(iname);
				break;
			default:
				break;
		}

		free(iname);
	}
	isns_close(so);
	return (0);
}
Beispiel #7
0
static int
isns_populate_and_update_server_info(Boolean_t update) {
	char		*isns_srv, *isns_port;
	int retcode = 0;

	/* get isns server info */
	(void) tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
	    &isns_srv);
	if (isns_srv == NULL) {
		syslog(LOG_INFO,
		    "The server has not been setup, "
		    "but enabling the isns access");
		retcode = -1;
		return (retcode);
	}
	isns_port = strchr(isns_srv, ':');
	if (isns_port == NULL) {
		isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
	} else {
		isns_args.isns_port = strtoul(isns_port + 1, NULL, 0);
		if (isns_args.isns_port == 0) {
			isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT;
		}
		*isns_port = '\0';
	}

	if (update == True) {
		/* isns_server changed */
		if (strcmp(isns_srv, isns_args.server) != 0) {
			/* de-reg from old iSNS server if it is setup */
			syslog(LOG_INFO,
			    "Detected a new isns server, deregistering"
			    " %s", isns_args.server);
			(void) isns_dereg_all();
			(void) strcpy(isns_args.server, isns_srv);
			/* Register with the new server */
			if (isns_reg_all() == 0) {
				/* scn register all targets */
				if (isns_op_all(ISNS_SCN_REG) != 0) {
					syslog(LOG_ERR,
					    "SCN registrations failed\n");
					(void) isns_op_all(ISNS_DEV_DEREG);
					retcode = -1;
				}
			}
		}
	} else {
		(void) strcpy(isns_args.server, isns_srv);
	}
	free(isns_srv);
	return (retcode);
}
Beispiel #8
0
static tgt_node_t *
find_next_tgt(tgt_node_t *tgt, char **iname)
{
	while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    tgt)) != NULL) {
		if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
		    == FALSE) {
			continue;
		}
		return (tgt);
	}
	return (NULL);
}
Beispiel #9
0
/*
 * Just checking the existance of the given target. Here we check whether
 * both zfs and iscsitarget aware of the given target/volume. It neither
 * care about the credentials nor SHAREISCSI properties.
 */
static char *
validate_zfs_iscsitgt(tgt_node_t *x)
{
	char		*msg		= NULL;
	char		*prop		= NULL;
	char		*dataset	= NULL;
	libzfs_handle_t	*zh		= NULL;
	zfs_handle_t	*zfsh		= NULL;
	tgt_node_t	*n		= NULL;

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

	if (((zh = libzfs_init()) == NULL) ||
	    ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) {
		xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND);
		goto error;
	}

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

	xml_rtn_msg(&msg, ERR_SUCCESS);

error:
	if (zfsh)
		zfs_close(zfsh);
	if (prop)
		free(prop);
	if (zh)
		libzfs_fini(zh);
	if (dataset)
		free(dataset);

	return (msg);

}
Beispiel #10
0
/*
 * []----
 * | raw_init_common -- Initialize LU data which is common to all I_T_Ls
 * []----
 */
Boolean_t
raw_common_init(t10_lu_common_t *lu)
{
	tgt_node_t	*node	= lu->l_root;
	char		*str;
	raw_params_t	*r;

	if ((r = (raw_params_t *)calloc(1, sizeof (*r))) == NULL)
		return (False);

	if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
		r->r_size = strtoll(str, NULL, 0);
		free(str);
	}
	lu->l_dtype_params = (void *)r;
	return (True);
}
Beispiel #11
0
Boolean_t
isns_enabled()
{
	Boolean_t	isns_access = False;
	char		*isns_srv = NULL;

	(void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS,
	    &isns_access);
	/* get isns server info */
	if (isns_access == True) {
		if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV,
		    &isns_srv) == True) {
			free(isns_srv);
			return (True);
		}
	}
	return (False);
}
Beispiel #12
0
Datei: xml.c Projekt: imp/slist
Boolean_t
tgt_find_value_str(tgt_node_t *n, char *name, char **value)
{
	tgt_node_t	*c;

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

	if (strcmp(n->x_name, name) == 0) {
		*value = n->x_value ? strdup(n->x_value) : NULL;
		return (True);
	}
	for (c = n->x_child; c; c = c->x_sibling) {
		if (tgt_find_value_str(c, name, value) == True)
			return (True);
	}
	return (False);
}
Beispiel #13
0
Datei: util.c Projekt: imp/slist
/*
 * []----
 * | 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_child(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);
}
Beispiel #14
0
/*ARGSUSED*/
Boolean_t
osd_common_init(t10_lu_common_t *lu)
{
	osd_params_t	*o;
	char		*str;
	tgt_node_t	*node	= lu->l_root;

	if ((o = (osd_params_t *)calloc(1, sizeof (*o))) == NULL)
		return (False);

	if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &str) == True) {
		o->o_size = strtoll(str, NULL, 0);
		free(str);
	} else {
		free(o);
		return (False);
	}

	lu->l_dtype_params = (void *)o;
	return (True);
}
Beispiel #15
0
/*
 * find_tgt_by_name searches DB by iscsi name or local name, if found
 * returns tgt_node_t.  iname needs to be free by caller.
 */
static tgt_node_t *
find_tgt_by_name(char *targ, char **iname)
{
	tgt_node_t	*tgt = NULL;

	while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    tgt)) != NULL) {
		if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname)
		    == FALSE) {
			syslog(LOG_ALERT, "ISNS: Missing iscsi name\n");
			break;
		}
		/* match either iscsi name or local name */
		if (strcmp(targ, tgt->x_value) == 0 ||
		    strcmp(targ, *iname) == 0) {
			return (tgt);
		}
		free(*iname);
	}
	return (NULL);
}
Beispiel #16
0
Datei: xml.c Projekt: imp/slist
/*
 * []----
 * | xml_find_value_intchk -- if node exists, check to see if value is okay
 * []----
 */
Boolean_t
tgt_find_value_intchk(tgt_node_t *n, char *name, int *value)
{
	char		*str;
	char		chk[32];
	Boolean_t	rval;

	if (tgt_find_value_str(n, name, &str) == True) {

		*value = strtol(str, NULL, 0);
		/*
		 * Validate that the input string hasn't overrun what
		 * what an integer can handle. This is done by simply
		 * printing out the result of the conversion into a buffer
		 * and comparing it to the incoming string. That way when
		 * someone enters 4294967296 which strtol returns as 0
		 * we'll catch it.
		 */
		if ((str[0] == '0') && (str[1] != '\0')) {
			if (str[1] == 'x')
				(void) snprintf(chk, sizeof (chk), "0x%x",
				    *value);
			else if (str[1] == 'X')
				(void) snprintf(chk, sizeof (chk), "0X%x",
				    *value);
			else
				(void) snprintf(chk, sizeof (chk), "0%o",
				    *value);
		} else
			(void) snprintf(chk, sizeof (chk), "%d", *value);
		if (strcmp(chk, str) == 0)
			rval = True;
		else
			rval = False;
		free(str);
		return (rval);
	} else
		return (True);
}
Beispiel #17
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);
}
Beispiel #18
0
/*
 * 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);
}
Beispiel #19
0
/*
 * []----
 * | modify_admin -- modify one or more of the admin related props
 * []----
 */
static char *
modify_admin(tgt_node_t *x)
{
	char		*msg	= NULL;
	char		*prop;
	Boolean_t	changes_made = False;
	Boolean_t	update_isns = False;
	admin_table_t	*ap;

	for (ap = admin_prop_list; ap->name; ap++) {
		if (tgt_find_value_str(x, ap->name, &prop) == True) {

			if ((prop == NULL) || (strlen(prop) == 0))
				break;

			/*
			 * Do the function call first if it exists which
			 * will allow possible checking to be done first.
			 */
			if (ap->func) {
				msg = (*ap->func)(ap->name, prop);
				if (msg != NULL) {
					free(prop);
					return (msg);
				}
			}

			(void) pthread_rwlock_wrlock(&targ_config_mutex);
			if (ap->delete_name == NULL) {
				if (modify_element(ap->name, prop, main_config,
				    MatchName) == False) {
					xml_rtn_msg(&msg, ERR_NO_MEM);
					free(prop);
					(void) pthread_rwlock_unlock(
					    &targ_config_mutex);
					return (msg);
				}
			} else {
				if (strcmp(prop, XML_VALUE_TRUE) != 0) {
					xml_rtn_msg(&msg,
					    ERR_SYNTAX_MISSING_OPERAND);
					free(prop);
					(void) pthread_rwlock_unlock(
					    &targ_config_mutex);
					return (msg);
				}
				if (delete_element(ap->delete_name,
				    main_config, MatchName) == False) {
					xml_rtn_msg(&msg, ERR_NO_MEM);
					free(prop);
					(void) pthread_rwlock_unlock(
					    &targ_config_mutex);
					return (msg);
				}
			}
			(void) pthread_rwlock_unlock(&targ_config_mutex);
			if (0 == strcmp(ap->name, XML_ELEMENT_ISNS_ACCESS) ||
			    0 == strcmp(ap->name, XML_ELEMENT_ISNS_SERV)) {
				update_isns = True;
			}
			free(prop);
			changes_made = True;
		}
	}

	if (changes_made == True) {
		/* isns_update updates isns_access & isns server name */
		if (update_isns == True) {
			if (isns_update() != 0) {
				xml_rtn_msg(&msg, ERR_ISNS_ERROR);
				return (msg);
			}
		}
		if (mgmt_config_save2scf() == True) {
			xml_rtn_msg(&msg, ERR_SUCCESS);
		} else {
			xml_rtn_msg(&msg, ERR_INTERNAL_ERROR);
		}
	} else {
		xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
	}

	return (msg);
}
Beispiel #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);
}
Beispiel #21
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);
}
Beispiel #22
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);
}
Beispiel #23
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);
}
Beispiel #24
0
/*
 * Register all iscsi target nodes from the XML database
 * Alway use the ISNS_FLAG_REPLACE_REG flag
 */
int
isns_reg_all()
{
	int so;
	uint32_t	flags = ISNS_FLAG_REPLACE_REG;
	isns_pdu_t	*cmd = NULL;
	isns_rsp_t	*rsp = NULL;
	char		*n = NULL;
	char		*a = NULL;
	char		alias[MAXNAMELEN];
	char		iname[MAXNAMELEN];
	tgt_node_t	*tgt = NULL;
	int		ret = -1;
	int		tgt_cnt = 0;

	if (isns_server_connection_thr_running == False) {
		syslog(LOG_ERR,
		    "isns_reg_all: iSNS discovery is not running."
		    " Check the previous iSNS initialization error.");
		return (-1);
	}

	/*
	 * get the 1st target and use it for the source attribute
	 */
	if ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, tgt))
	    == NULL) {
		return (0);
	}
	if (tgt->x_value == NULL) {
		syslog(LOG_ALERT, "ISNS: target with NULL local name\n");
		return (-1);
	}
	if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
	    == FALSE) {
		syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n");
		return (-1);
	}
	(void) strcpy(iname, n);
	free(n);
	if ((so = isns_open(isns_args.server)) == -1) {
		syslog(LOG_ALERT, "ISNS: fails to connect to %s\n",
		    isns_args.server);
		return (-1);
	}

	if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) {
		goto error;
	}

	/* source attribute */
	if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
	    STRLEN(iname), iname, 0) != 0) {
		goto error;
	}

	/* add message key attribute */
	if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
	    STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
		goto error;
	}

	/* add delimiter */
	if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) {
		goto error;
	}

	/* entity id */
	if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
	    STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
		goto error;
	}

	/* entity type */
	if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID,
	    ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) {
		goto error;
	}

	/* portal ip-addr */
	if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID,
	    eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr,
	    eid_ip.ip_len) != 0) {
		goto error;
	}

	/* portal port */
	if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID,
	    ISNS_PORT_SZ, NULL, iscsi_port) != 0) {
		goto error;
	}

	/* ESI interval */
	if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID,
	    ISNS_ESI_TICK_SZ, NULL, 10) != 0) {
		goto error;
	}


	/* scn port */
	if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID,
	    ISNS_PORT_SZ, NULL, scn_port) != 0) {
		goto error;
	}

	/* esi port */
	if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID,
	    ISNS_PORT_SZ, NULL, scn_port) != 0) {
		goto error;
	}

	/*
	 * Open targets_config and devAttrReg all nodes
	 */
	tgt = NULL;
	while ((tgt = tgt_node_next_child(targets_config, XML_ELEMENT_TARG,
	    tgt)) != NULL) {
		if (tgt->x_value == NULL) {
			syslog(LOG_ALERT, "ISNS: target with NULL name\n");
			continue;
		}
		/* use this value as alias if alias is not set */
		(void) strcpy(alias, tgt->x_value);

		if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n)
		    == FALSE) {
			continue;
		}
		(void) strcpy(iname, n);
		free(n);

		/* find alias */
		if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a)
		    == TRUE) {
			(void) strcpy(alias, a);
			free(a);
		}

		tgt_cnt++;		/* increment target count */

		/* operation attributes */
		if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
		    STRLEN(iname), iname, 0) != 0) {
			goto error;
		}
		if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
		    4, NULL, ISNS_TARGET_NODE_TYPE) != 0) {
			goto error;
		}
		if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
		    STRLEN(alias), alias, 0) != 0) {
			goto error;
		}

		if (append_tpgt(tgt, cmd) != 0) {
			goto error;
		}

	}

	/* send pdu */
	if (isns_send(so, cmd) == -1) {
		goto error;
	}

	/* get isns response */
	if (isns_recv(so, &rsp) == -1) {
		goto error;
	}

	/* process response */
	if (process_rsp(cmd, rsp) == 0) {
		ret = 0;
		num_reg = tgt_cnt;
		queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful");
	} else {
		syslog(LOG_ALERT, "DevAttrReg failed");
	}

error:
	if (cmd)
		isns_free_pdu(cmd);
	if (rsp)
		isns_free_pdu(rsp);
	isns_close(so);
	return (ret);
}
Beispiel #25
0
/*
 * Update an existing iscsi target property
 */
int
isns_dev_update(char *targ, uint32_t mods)
{
	int		so;
	int		flags = 0;	/* update only */
	char		*iname = NULL;
	char		*dummy = NULL;
	char		alias[MAXNAMELEN];
	tgt_node_t	*tgt = NULL;
	isns_pdu_t	*cmd;
	isns_rsp_t	*rsp;
	int		ret = -1;

	if (mods == 0)
		return (0);

	if (isns_server_connection_thr_running == False) {
		syslog(LOG_ERR,
		    "isns_dev_update: iSNS discovery is not running."
		    " Check the previous iSNS initialization error.");
		return (-1);
	}

	if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) {
		if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) ==
		    True) {
			(void) strcpy(alias, dummy);
			free(dummy);
		} else
			(void) strcpy(alias, tgt->x_value);

		if ((so = isns_open(isns_args.server)) < 0) {
			goto error;
		}

		if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) {
			goto error;
		}
		/* source attr, msg key, delimiter */
		if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
		    STRLEN(iname), iname, 0) != 0) {
			goto error;
		}
		if (isns_append_attr(cmd, ISNS_EID_ATTR_ID,
		    STRLEN(isns_args.entity), isns_args.entity, 0) != 0) {
			goto error;
		}
		if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)
		    != 0) {
			goto error;
		}

		/*
		 * get current operating attributes, alias & portal group
		 * objects, these should be the only things that get change
		 */
		(void) isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID,
		    STRLEN(iname), iname, 0);
		(void) isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID,
		    ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE);

		if (mods & ISNS_MOD_ALIAS)
		if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID,
		    STRLEN(alias), alias, 0) != 0) {
			goto error;
		}

		if (mods & ISNS_MOD_TPGT)
			if (append_tpgt(tgt, cmd) != 0) {
				goto error;
			}

		if (isns_send(so, (isns_pdu_t *)cmd) < 0) {
			goto error;
		}

		if (isns_recv(so, &rsp) == -1) {
			goto error;
		}

		/* process response, if failed do a isns_reg_all */
		if ((ret = process_rsp(cmd, rsp)) == -1) {
			if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) {
				syslog(LOG_ALERT, "ISNS register failed\n");
				goto error;
			}
			ret = 0;
		} else {
			if (isns_scn_reg(so, iname) == -1) {
				syslog(LOG_ERR, "ISNS SCN register failed\n");
				goto error;
			}
			ret = 0;
		}
	} else {
		syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias);
	}

error:
	if (cmd)
		isns_free_pdu(cmd);
	if (rsp)
		isns_free_pdu(rsp);
	if (iname)
		free(iname);
	isns_close(so);
	return (ret);
}
Beispiel #26
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);
}
Beispiel #27
0
Datei: util.c Projekt: 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);
}
Beispiel #28
0
/*
 * 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);
}
Beispiel #29
0
/*
 * []----
 * | modify_initiator -- store the CHAP information for an initiator
 * []----
 */
static char *
modify_initiator(tgt_node_t *x)
{
	char		*msg		= NULL;
	char		*name		= NULL;
	char		*prop		= NULL;
	tgt_node_t	*inode		= NULL;
	Boolean_t	changes_made	= False;

	(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 ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT,
	    inode)) != NULL) {
		if (strcmp(inode->x_value, name) == 0)
			break;
	}

	/*
	 * We no longer need the name since we should have found the node
	 * it refers to and this way we don't have to worry about freeing
	 * the storage later.
	 */
	free(name);

	if (inode == NULL) {
		xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND);
		goto error;
	}

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

		if (modify_element(XML_ELEMENT_CHAPSECRET, prop, inode,
		    MatchName) == False) {
			free(prop);
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		free(prop);
		changes_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPSECRET,
	    &prop) == True) {
		if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
			if (prop != NULL)
				free(prop);
			xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
			goto error;
		}
		free(prop);

		if (delete_element(XML_ELEMENT_CHAPSECRET, inode,
		    MatchName) == False) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		changes_made = True;
	}

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

		if (modify_element(XML_ELEMENT_CHAPNAME, prop, inode,
		    MatchName) == False) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			free(prop);
			goto error;
		}
		free(prop);
		changes_made = True;
	}

	if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPNAME, &prop) == True) {
		if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) {
			if (prop != NULL)
				free(prop);
			xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND);
			goto error;
		}
		free(prop);


		if (delete_element(XML_ELEMENT_CHAPNAME, inode,
		    MatchName) == False) {
			xml_rtn_msg(&msg, ERR_NO_MEM);
			goto error;
		}
		changes_made = True;
	}

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

error:
	(void) pthread_rwlock_unlock(&targ_config_mutex);
	return (msg);
}