示例#1
0
int
isns_process_query(isns_server_t *srv, isns_simple_t *call, isns_simple_t **result)
{
	isns_object_list_t	objects = ISNS_OBJECT_LIST_INIT;
	isns_simple_t		*reply = NULL;
	isns_db_t		*db = srv->is_db;
	int			status;

	/* Get the objects matching the query */
	status = isns_query_get_objects(call, db, &objects);
	if (status != ISNS_SUCCESS)
		goto done;

	/* Success: build the response */
	reply = isns_create_query_response(srv, call, &objects);
	if (reply == NULL) {
		status = ISNS_INTERNAL_ERROR;
		goto done;
	}

	/* There's nothing in the spec that tells us what to
	 * return if the query matches no object.
	 */
	if (objects.iol_count == 0) {
		status = ISNS_NO_SUCH_ENTRY;
		goto done;
	}

done:
	isns_object_list_destroy(&objects);
	*result = reply;
	return status;
}
示例#2
0
int
query_entity_id(isns_client_t *clnt, int argc, char **argv)
{
	isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
	isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
	uint32_t	status;
	isns_simple_t	*qry;
	const char	*eid;

	if (argc == 1 && !strcmp(argv[0], "help")) {
		printf("Query iSNS for own entity ID.\n"
		       "No arguments allowed\n");
		exit(0);
	}
	if (argc != 0)
		isns_fatal("EID query - no arguments accepted\n");

	isns_attr_list_append_string(&query_key,
			ISNS_TAG_ISCSI_NAME,
			isns_config.ic_source_name);
	qry = isns_create_query(clnt, &query_key);
	isns_attr_list_destroy(&query_key);

	isns_query_request_attr_tag(qry, ISNS_TAG_ENTITY_IDENTIFIER);

	status = isns_client_call(clnt, &qry);
	if (status != ISNS_SUCCESS) {
		isns_error("Query failed: %s\n", isns_strerror(status));
		return status;
	}

	status = isns_query_response_get_objects(qry, &objects);
	if (status) {
		isns_error("Unable to extract object list from query response: %s\n",
				isns_strerror(status), status);
		return status;
	}

	status = ISNS_NO_SUCH_ENTRY;
	if (objects.iol_count == 0) {
		isns_error("Node %s not registered with iSNS\n",
				isns_config.ic_source_name);
	} else
	if (!isns_object_get_string(objects.iol_data[0],
				ISNS_TAG_ENTITY_IDENTIFIER, &eid)) {
		isns_error("Query for %s returned an object without EID\n",
				isns_config.ic_source_name);
	} else {
		printf("%s\n", eid);
		status = ISNS_SUCCESS;
	}

	isns_object_list_destroy(&objects);
	isns_simple_free(qry);

	return status;
}
示例#3
0
文件: scn.c 项目: chris-se/open-isns
/*
 * Set up the SCN object.
 */
static isns_scn_t *
isns_scn_setup(isns_scn_t *scn, isns_object_t *node)
{
	isns_object_list_t portals = ISNS_OBJECT_LIST_INIT;
	isns_object_t	*entity;
	unsigned int	i;

	entity = isns_object_get_entity(node);
	if (entity == NULL
	 || !isns_object_find_descendants(entity,
			 &isns_portal_template, NULL, &portals))
		return NULL;

	for (i = 0; i < portals.iol_count; ++i) {
		isns_object_t	*portal = portals.iol_data[i];
		isns_portal_info_t info;
		isns_scn_funnel_t *funnel;

		/* Extract address and SCN port from portal */
		if (!isns_portal_from_object(&info,
				ISNS_TAG_PORTAL_IP_ADDRESS,
				ISNS_TAG_SCN_PORT,
				portal))
			continue;

		/* We know where to send our notifications! */
		if (scn == NULL) {
			isns_attr_t	*attr;

			if (!isns_object_get_attr(node, ISNS_TAG_ISCSI_NAME, &attr)
			 && !isns_object_get_attr(node, ISNS_TAG_FC_PORT_NAME_WWPN, &attr)) {
				isns_error("Attempt to set up SCN for strange node type\n");
				return NULL;
			}

			scn = isns_calloc(1, sizeof(*scn));
			scn->scn_entity = isns_object_get(entity);
			scn->scn_owner = isns_object_get(node);
			scn->scn_attr = isns_attr_get(attr);
			scn->scn_name = isns_strdup(attr->ia_value.iv_string);
		}

		funnel = isns_calloc(1, sizeof(*funnel));
		funnel->scn_portal = info;
		funnel->scn_next = scn->scn_funnels;
		scn->scn_funnels = funnel;
	}

	isns_object_list_destroy(&portals);
	return scn;
}
示例#4
0
static int
__create_policy(isns_client_t *clnt, const isns_attr_list_t *attrs)
{
	isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
	isns_object_t	*obj;
	int		status;

	obj = isns_create_object(&isns_policy_template, attrs, NULL);
	if (!obj)
		isns_fatal("Cannot create policy object\n");
	isns_object_list_append(&objects, obj);

	status = __register_objects(clnt, NULL, &objects);
	isns_object_list_destroy(&objects);
	return status;
}
示例#5
0
int
register_objects(isns_client_t *clnt,
		int argc, char **argv)
{
	isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
	isns_object_t	*key_obj = NULL;
	uint32_t	status;

	if (opt_key != NULL) {
		isns_attr_list_t key_attrs = ISNS_ATTR_LIST_INIT;
		struct isns_attr_list_parser state;

		isns_attr_list_parser_init(&state, NULL);

		if (!isns_parse_attrs(1, &opt_key, &key_attrs, &state)) {
			isns_error("Cannot parse registration key \"%s\"\n",
					opt_key);
			return 0;
		}

		key_obj = isns_create_object(isns_attr_list_parser_context(&state),
				&key_attrs, NULL);
		isns_attr_list_destroy(&key_attrs);

		if (!key_obj) {
			isns_error("Cannot create registration key object\n");
			return 0;
		}
	} else {
		/* If the user does not provide a key object, 
		 * create/update an entity.
		 */
		key_obj = isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI, NULL);
	}

	if (!parse_registration(argv, argc, &objects, key_obj))
		isns_fatal("Unable to parse registration\n");

	status = __register_objects(clnt, key_obj, &objects);
	isns_object_list_destroy(&objects);

	isns_object_release(key_obj);
	return status;
}
示例#6
0
int
query_objects(isns_client_t *clnt, int argc, char **argv)
{
	isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
	isns_attr_list_t oper_attrs = ISNS_ATTR_LIST_INIT;
	isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
	uint32_t	status;
	isns_simple_t	*qry;
	unsigned int	i;

	if (!parse_query(argv, argc, &query_key, &oper_attrs))
		isns_fatal("Unable to parse query\n");

	qry = isns_create_query(clnt, &query_key);
	isns_attr_list_destroy(&query_key);

	/* Add the list of attributes we request */
	for (i = 0; i < oper_attrs.ial_count; ++i)
		isns_query_request_attr(qry, oper_attrs.ial_data[i]);
	isns_attr_list_destroy(&oper_attrs);

	status = isns_client_call(clnt, &qry);
	if (status != ISNS_SUCCESS) {
		isns_error("Query failed: %s\n", isns_strerror(status));
		return status;
	}

	status = isns_query_response_get_objects(qry, &objects);
	if (status) {
		isns_error("Unable to extract object list from query response: %s\n",
				isns_strerror(status), status);
		return status;
	}

	isns_object_list_print(&objects, isns_print_stdout);
	isns_object_list_destroy(&objects);
	isns_simple_free(qry);

	return status;
}
示例#7
0
int
deregister_objects(isns_client_t *clnt, int argc, char **argv)
{
	isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
	isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
	isns_simple_t	*dereg;
	uint32_t	status;

	if (!parse_deregistration(argv, argc, &query_key))
		isns_fatal("Unable to parse unregistration\n");

	dereg = isns_create_deregistration(clnt, &query_key);
	isns_attr_list_destroy(&query_key);

	status = isns_client_call(clnt, &dereg);
	if (status != ISNS_SUCCESS) {
		isns_error("Deregistration failed: %s\n",
				isns_strerror(status));
		return status;
	}

#if 0
	status = isns_dereg_msg_response_get_objects(dereg, &objects);
	if (status) {
		isns_error("Unable to extract object list from deregistration response: %s\n",
				isns_strerror(status), status);
		goto done;
	}
	isns_object_list_print(&objects, isns_print_stdout);
#endif

	isns_object_list_destroy(&objects);
	isns_simple_free(dereg);

	return status;
}
示例#8
0
/*
 * Get the list of objects matching this query
 */
static int
isns_query_get_objects(isns_simple_t *qry, isns_db_t *db, isns_object_list_t *result)
{
	isns_scope_t		*scope = NULL;
	isns_object_list_t	matching = ISNS_OBJECT_LIST_INIT;
	isns_attr_list_t	*keys = &qry->is_message_attrs;
	isns_object_template_t	*query_type = NULL;
	unsigned int		i, qry_mask = 0;
	int			status;

	/* 5.6.5.2
	 * If multiple attributes are used as the Message Key, then they
	 * MUST all be from the same object type (e.g., IP address and
	 * TCP/UDP Port are attributes of the Portal object type).
	 */
	for (i = 0; i < keys->ial_count; ++i) {
		isns_object_template_t	*tmpl;
		uint32_t tag = keys->ial_data[i]->ia_tag_id;

		tmpl = isns_object_template_for_tag(tag);
		if (tmpl == NULL)
			return ISNS_ATTRIBUTE_NOT_IMPLEMENTED;
		if (query_type == NULL)
			query_type = tmpl;
		else if (tmpl != query_type)
			return ISNS_INVALID_QUERY;
	}

	/*
	 * 5.6.5.2
	 * An empty Message Key field indicates the query is scoped to
	 * the entire database accessible by the source Node.
	 */
	if (keys->ial_count == 0) {
		query_type = &isns_entity_template;
		keys = NULL;
	}

	/* Policy: check whether the client is allowed to
	 * query this type of object. */
	if (!isns_policy_validate_object_type(qry->is_policy,
				query_type, qry->is_function))
		return ISNS_SOURCE_UNAUTHORIZED;

	/* No scope means that the source is not part of
	 * any discovery domain, and there's no default DD.
	 * Just return an empty reply. */
	scope = isns_scope_for_call(db, qry);
	if (scope == NULL)
		return ISNS_SUCCESS;

	status = isns_scope_gang_lookup(scope, query_type, keys, &matching);
	if (status != ISNS_SUCCESS)
		goto out;

	/* Extract the mask of requested objects */
	qry_mask = isns_query_get_requested_types(&qry->is_operating_attrs);

	/*
	 * 5.6.5.2
	 * The DevAttrQry response message returns attributes of objects
	 * listed in the Operating Attributes that are related to the
	 * Message Key of the original DevAttrQry message.
	 */
	for (i = 0; i < matching.iol_count; ++i) {
		isns_object_t	*obj = matching.iol_data[i];

		if (!isns_policy_validate_object_access(qry->is_policy,
					qry->is_source, obj,
					qry->is_function))
			continue;

		if (obj->ie_container)
			isns_object_list_append(result, obj->ie_container);
		isns_object_list_append(result, obj);
		isns_scope_get_related(scope, obj, qry_mask, result);
	}

out:
	isns_object_list_destroy(&matching);
	isns_scope_release(scope);
	return status;
}
示例#9
0
/*
 * Process a deregistration
 *
 * Normally, you would expect that a deregistration removes the
 * object from the database, and that's the end of the story.
 * Unfortunately, someone added Discovery Domains to the protocol,
 * requiring _some_ information to survive as long as an object
 * is referenced by a discovery domain. Specifically, we need to
 * retain the relationship between key attributes (eg iscsi node
 * name) and the object index.
 *
 * Thus, deregistration consists of the following steps
 *  -	the object is removed from the database's global scope,
 *	so that it's no longer visible to DB lookups.
 *
 *  -	the object is detached from its containing Network
 *	Entity.
 *
 *  -	all attributes except the key attr(s) and the index
 *	attribute are removed.
 */
int
isns_process_deregistration(isns_server_t *srv, isns_simple_t *call, isns_simple_t **result)
{
	isns_object_list_t	objects = ISNS_OBJECT_LIST_INIT;
	isns_simple_t		*reply = NULL;
	isns_db_t		*db = srv->is_db;
	int			status, dereg_status;
	unsigned int		i;

	/* Get the objects to deregister */
	status = isns_deregistration_get_objects(call, db, &objects);
	if (status != ISNS_SUCCESS)
		goto done;

	/*
	 * 5.6.5.4
	 *
	 * For messages that change the contents of the iSNS database,
	 * the iSNS server MUST verify that the Source Attribute
	 * identifies either a Control Node or a Storage Node that is
	 * a part of the Network Entity containing the added, deleted,
	 * or modified objects.
	 */
	/*
	 * Implementation note: this can be implemented either by
	 * explicitly checking the object's owner in isns_db_remove
	 * (which is what we do right now), or by matching only
	 * those objects that have the right owner anyway.
	 *
	 * The latter sounds like a better choice if the client
	 * uses NIL attributes, because it limits the scope of
	 * the operation; but then the RFC doesn't say whether
	 * this kind of deregistration would be valid at all.
	 */

	/* Success: create a new simple message, and
	 * send it in our reply. */
	reply = __isns_create_deregistration(srv->is_source, NULL);
	if (reply == NULL) {
		status = ISNS_INTERNAL_ERROR;
		goto done;
	}

	dereg_status = ISNS_SUCCESS;
	for (i = 0; i < objects.iol_count; ++i) {
		isns_object_t	*obj = objects.iol_data[i];

		/* Policy: check that the client is permitted
		 * to deregister this object */
		if (!isns_policy_validate_object_access(call->is_policy,
					call->is_source, obj,
					call->is_function))
			status = ISNS_SOURCE_UNAUTHORIZED;

		if (status == ISNS_SUCCESS)
			status = isns_db_remove(db, obj);
		if (status != ISNS_SUCCESS) {
			/*
			 * 5.7.5.4
			 *
			 * In the event of an error, this response message
			 * contains the appropriate status code as well
			 * as a list of objects from the original DevDereg
			 * message that were not successfully deregistered
			 * from the iSNS database.  This list of objects
			 * is contained in the Operating Attributes
			 * of the DevDeregRsp message.	Note that an
			 * attempted deregistration of a non-existent
			 * object does not constitute an isns_error, and
			 * non-existent entries SHALL not be returned
			 * in the DevDeregRsp message.
			 */
			/*
			 * Implementation: right now this doesn't work
			 * at all, because isns_msg_set_error will
			 * discard the entire message except for the
			 * status word.
			 */
			isns_debug_message("Failed to deregister object: %s (0x%04x)\n",
				isns_strerror(status), status);

			isns_object_extract_all(obj, &reply->is_operating_attrs);
			dereg_status = status;
			continue;
		}

		/*
		 * 5.7.5.4
		 * If all Nodes and Portals associated with a Network
		 * Entity are deregistered, then the Network Entity
		 * SHALL also be removed.
		 * [...]
		 * If both the Portal and iSCSI Storage Node objects
		 * associated with a Portal Group object are removed,
		 * then that Portal Group object SHALL also be removed.
		 * The Portal Group object SHALL remain registered
		 * as long as either of its associated Portal or
		 * iSCSI Storage Node objects remain registered.  If a
		 * deleted Storage Node or Portal object is subsequently
		 * re-registered, then a relationship between the re-
		 * registered object and an existing Portal or Storage
		 * Node object registration, indicated by the PG object,
		 * SHALL be restored.
		 */
		/* isns_db_remove takes care of removing dead entities,
		 * and dead portal groups.
		 */
	}

	if (status == ISNS_SUCCESS)
		status = dereg_status;

done:
	isns_object_list_destroy(&objects);
	*result = reply;
	return status;
}