コード例 #1
0
ファイル: isns_client.c プロジェクト: imp/slist
/*
 * 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);
}
コード例 #2
0
ファイル: isns_client.c プロジェクト: imp/slist
/*
 * This thread sit's in a loop and ensures that it keeps checking for
 * connection to isns_server. Once the connection works it registers
 * with the isns and bails out.
 * We expect the isns server to be fault taulerant and has persistence
 * for the registered entries.
 */
static void *
isns_server_connection_thr(void *arg)
{
	Boolean_t registered_targets = False;
	char server[MAXHOSTNAMELEN + 1] = {0};

	while (isns_shutdown == False &&
	    connection_thr_bail_out == False) {
		/* current server */
		(void) strcpy(server, isns_args.server);

		if (is_isns_server_up(server) == 0) {
			if (registered_targets == False) {
				/*
				 * register all targets, what happens if
				 * no targets are created yet? this should
				 * not be a failure, when new target gets
				 * created, update gets call. what if SCN
				 * register fails?
				 */
				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);
						registered_targets = False;
					} else {
						registered_targets = True;
						break;
					}
				}
			}
		} else {
			syslog(LOG_INFO,
			    "isns server %s is not reachable",
			    server);
			registered_targets = False;
		}
		(void) sleep(ISNS_SLEEP_SECS);
		/* If isns was disabled, deregister and close the thread */
		if (isns_enabled() == False) {
			syslog(LOG_INFO,
			    "isns server is disabled, dergister target");
			isns_fini();
			break;
		}

	}
	queue_message_set(mgmtq, 0, msg_pthread_join,
	    (void *)(uintptr_t)pthread_self());

	return (NULL);
}
コード例 #3
0
ファイル: isns_client.c プロジェクト: imp/slist
/*
 * isns_update gets call on modify_admin, this is changes to
 * isns access and/or isns server
 */
int
isns_update()
{
	Boolean_t is_isns_enabled = isns_enabled();
	/*
	 * If the isns thread was not started before and we are going
	 * enabled from disabled start the threads.
	 */
	if (isns_server_connection_thr_running == False) {
		if (is_isns_enabled == True) {
			if (isns_init(NULL) != 0) {
				return (-1);
			} else {
				return (0);
			}
		} else {
			syslog(LOG_INFO,
			    "isns_update: isns is disabled");
		}
	} else {
		/*
		 * isns is disabled after enabled,
		 * log off all targets and fini isns service
		 */
		if (is_isns_enabled == False) {
			isns_shutdown = True;
			/* pthread_join for the isns thread */
			(void) pthread_join(isns_tid, NULL);
			(void) pthread_join(scn_tid, NULL);
			isns_server_connection_thr_running = False;
		} else {
			/*
			 * Incase the original thread is still running
			 * we should reap it
			 */
			connection_thr_bail_out = True;
			(void) pthread_join(isns_tid, NULL);
			connection_thr_bail_out = False;

			/*
			 * Read the configuration file incase the server
			 * has changed.
			 */
			if (isns_populate_and_update_server_info(True) == -1) {
				return (-1);
			}
		}
	}
	return (0);
}
コード例 #4
0
ファイル: mgmt_modify.c プロジェクト: CoryXie/opensolaris
/*
 * []----
 * | validate_isns_server -- validate that server[:port] are valid
 * []----
 */
char *
valid_isns_srv(char *name, char *prop)
{
	char		*msg	= NULL;
	char		*sp, *p;
	int		so;
	int		port;

	if (strlen(prop) > MAXHOSTNAMELEN) {
		xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
		return (msg);
	}

	if ((sp = strdup(prop)) == NULL) {
		xml_rtn_msg(&msg, ERR_NO_MEM);
		return (msg);
	}
	if ((p = strrchr(sp, ':')) != NULL) {
		*p++ = '\0';
		port = atoi(p);
		if ((port < 1) || (port > 65535)) {
			xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
			free(sp);
			return (msg);
		}
	}

	so = isns_open(sp);
	if (so < 0) {
		if (isns_enabled() == True) {
			xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV);
		} else { /* Just print a warning and accept the server */
			syslog(LOG_ALERT,
			    "Check if the server:%s is valid", sp);
		}
	} else {
		isns_close(so);
	}
	free(sp);
	return (msg);
}
コード例 #5
0
ファイル: mgmt_remove.c プロジェクト: alhazred/onarm
/*
 * 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);
}
コード例 #6
0
ファイル: mgmt_remove.c プロジェクト: alhazred/onarm
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);
}
コード例 #7
0
ファイル: mgmt_remove.c プロジェクト: alhazred/onarm
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);
}
コード例 #8
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);
}
コード例 #9
0
ファイル: mgmt_modify.c プロジェクト: CoryXie/opensolaris
/*
 * []----
 * | 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);
}
コード例 #10
0
ファイル: mgmt_modify.c プロジェクト: CoryXie/opensolaris
/*
 * []----
 * | 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);
}
コード例 #11
0
ファイル: isns_client.c プロジェクト: imp/slist
/*
 * esi_scn_thr() is the thread creates an end point to receive and process
 * ESI & SCN messages.  This thread is created when isns_access is enabled
 * and for the duration of the iscsi daemon
 */
static void *
esi_scn_thr(void *arg)
{
	struct sockaddr		sa, *ai;
	struct sockaddr_in	sin;
	struct sockaddr_in6	sin6;
	int			so, fd, pf;
	socklen_t		len;
	char			strport[NI_MAXSERV];
	isns_pdu_t		*scn = NULL;
	struct timeval timeout;
	fd_set fdset;
	int socket_ready = 0;

	pf = get_addr_family(isns_args.entity);
	if (pf == PF_INET) {
		bzero(&sin, sizeof (sin));
		sin.sin_family = PF_INET;
		sin.sin_port = htons(0);
		sin.sin_addr.s_addr = INADDR_ANY;
		ai = (struct sockaddr *)&sin;
		len = sizeof (sin);
	} else if (pf == PF_INET6) {
		bzero(&sin6, sizeof (sin6));
		sin6.sin6_family = PF_INET6;
		sin6.sin6_port = htons(0);
		sin6.sin6_addr = in6addr_any;
		ai = (struct sockaddr *)&sin6;
		len = sizeof (sin6);
	} else {
		syslog(LOG_ERR, "Bad address family. Exit esi_scn_thr");
		return (NULL);
	}

	/*
	 * create and bind SCN socket
	 * save the scn port info
	 */
	if ((so = socket(pf, SOCK_STREAM, 0)) == -1) {
		syslog(LOG_ALERT, "create isns socket failed");
		return (NULL);
	}

	(void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0);

	if (bind(so, ai, len) < 0) {
		syslog(LOG_ALERT, "esi_scn_thr: bind failed");
		(void) close(so);
		return (NULL);
	}

	/* get scn port info */
	len = sizeof (sa);
	if (getsockname(so, &sa, &len) < 0) {
		syslog(LOG_ALERT, "isns getsockname failed");
		(void) close(so);
		return (NULL);
	}
	if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV,
	    NI_NUMERICSERV) != 0) {
		syslog(LOG_ALERT, "isns getnameinfo failed");
		(void) close(so);
		return (NULL);
	}
	scn_port = atoi(strport);


	if (listen(so, 5) < 0) {
		syslog(LOG_ALERT, "esi_scn_thr: failed listen");
		(void) close(so);
		return (NULL);
	}

	/* listen for esi or scn messages */
	while (isns_shutdown == False) {
		/* ISNS_ESI_INTERVAL_ATTR_ID is set to 10s */
		timeout.tv_sec = 10;
		timeout.tv_usec = 0;
		FD_ZERO(&fdset);
		FD_SET(so, &fdset);

		socket_ready = select(so + 1, &fdset, NULL, NULL, &timeout);

		/* If disabled bail out, dont care about packets */
		if (isns_enabled() == False) {
			syslog(LOG_INFO,
			    "isns server is disabled, dergister target");
			isns_fini();
			(void) close(so);
			return (NULL);
		}

		if (socket_ready < 0) {
			syslog(LOG_ERR,
			    "esi_scn_thr: select failed, retrying.");
			continue;
		} else if (socket_ready == 0) { /* timeout */
			continue;
		} else {
			/* Socket is ready */
			if ((fd = accept(so, &sa, &len)) < 0) {
				syslog(LOG_ALERT, "esi_scn_thr: failed accept");
				continue;
			}
		}
		if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) {
			/* Just return success for ESI */
			switch (scn->func_id) {
				case ISNS_ESI:
					process_esi(fd, scn);
					break;
				case ISNS_SCN:
					/* call the SCN process function */
					process_scn(fd, scn);
					break;
				default:
					syslog(LOG_ERR,
					    "esi_scn_thr: Invalid funcid %d\n",
					    scn->func_id);
					break;
			}
			/* free response resource */
			isns_free_pdu(scn);
		} else {
			syslog(LOG_ALERT, "esi_scn_thr fails isns_recv ");
		}

		(void) close(fd);
	}
	(void) close(so);
	return (NULL);
}