Beispiel #1
0
isns_object_t *
isns_create_storage_node2(const isns_source_t *source,
				uint32_t type,
				isns_object_t *parent)
{
	isns_attr_t	*name_attr;
	isns_object_t	*obj;

	if (parent && !ISNS_IS_ENTITY(parent)) {
		isns_warning("Invalid container type \"%s\" for storage node: "
			"should be \"%s\"\n",
			parent->ie_template->iot_name,
			isns_entity_template.iot_name);
		return NULL;
	}
	if ((name_attr = isns_source_attr(source)) == NULL) {
		isns_warning("No source attribute\n");
		return NULL;
	}

	if (name_attr->ia_tag_id == ISNS_TAG_ISCSI_NAME) {
		obj = isns_create_object(&isns_iscsi_node_template, NULL, parent);
		isns_attr_list_update_attr(&obj->ie_attrs, name_attr);
		isns_object_set_uint32(obj,
				ISNS_TAG_ISCSI_NODE_TYPE, type);
	} else {
		/* No iFCP yet, sorry */
		isns_warning("%s: source tag type %u not supported\n",
				__FUNCTION__);
		return NULL;
	}

	return obj;
}
Beispiel #2
0
/*
 * Callback function which builds an iSNS object from the
 * list of attr=tag values.
 */
static int
__isns_local_registry_load_object(const char *line,
		int argc, char **argv, void *user_data)
{
	isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
	struct isns_attr_list_parser state;
	isns_object_list_t *list = user_data;
	isns_object_t *obj, *entity = NULL;

	for (; argc > 0; --argc) {
		char	*attr = argv[argc-1];

		if (!strncasecmp(attr, "owner=", 6)) {
			char *eid = __isns_local_registry_entity_name(attr + 6);
			ISNS_QUICK_ATTR_LIST_DECLARE(key_attrs,
					ISNS_TAG_ENTITY_IDENTIFIER,
					string, eid);

			if (entity) {
				isns_error("Duplicate owner entry in registry\n");
				continue;
			}
			isns_attr_print(&key_attrs.iqa_attr, isns_print_stdout);
			entity = isns_object_list_lookup(list,
					&isns_entity_template,
					&key_attrs.iqa_list);
			if (entity != NULL)
				continue;

			isns_debug_state("Creating fake entity %s\n", eid);
			entity = isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI, eid);
			isns_object_list_append(list, entity);
		} else {
			break;
		}
	}

	isns_attr_list_parser_init(&state, NULL);
	if (!isns_parse_attrs(argc, argv, &attrs, &state)) {
		isns_error("Unable to parse attrs\n");
		isns_attr_list_destroy(&attrs);
		return 0;
	}

	obj = isns_create_object(isns_attr_list_parser_context(&state),
					&attrs, entity);
	isns_attr_list_destroy(&attrs);

	if (obj == NULL) {
		isns_error("Unable to create object\n");
		return 0;
	}

	isns_object_list_append(list, obj);
	return 1;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
0
/*
 * Portal Group
 */
static isns_object_t *
__isns_pg_create(const isns_attr_list_t *attrs, uint32_t pg_tag,
                 isns_object_t *portal, isns_object_t *node)
{
    isns_object_t	*obj;

    obj = isns_create_object(&isns_iscsi_pg_template, attrs,
                             isns_object_get_entity(portal));

    /*
     * 3.4
     *
     * Each Portal and iSCSI Storage Node registered in an Entity can
     * be associated using a Portal Group (PG) object.  The PG Tag
     * (PGT), if non-NULL, indicates that the associated Portal
     * provides access to the associated iSCSI Storage Node in
     * the Entity.	All Portals that have the same PGT value for
     * a specific iSCSI Storage Node allow coordinated access to
     * that node.
     *
     * 5.6.5.2
     *
     * If the PGT of the Portal Group is not NULL, then a relationship
     * exists between the indicated Storage Node and Portal; if the
     * PGT is NULL, then no relationship exists.
     */
    if (pg_tag != 0) {
        isns_object_set_uint32(obj,
                               ISNS_TAG_PG_TAG, pg_tag);
    } else {
        /* A NULL PGT indicates that the
         * storage node cannot be accessed through
         * this portal. */
        isns_object_set_nil(obj, ISNS_TAG_PG_TAG);
    }

    /* This object represents a relationship between portal
       and storage node. Create a relation. */
    obj->ie_relation = isns_create_relation(obj,
                                            ISNS_RELATION_PORTAL_GROUP,
                                            portal, node);

    return obj;
}
Beispiel #6
0
isns_object_t *
isns_create_storage_node(const char *name, uint32_t type,
			isns_object_t *parent)
{
	isns_object_t	*obj;

	if (parent && !ISNS_IS_ENTITY(parent)) {
		isns_warning("Invalid container type \"%s\" for storage node: "
			"should be \"%s\"\n",
			parent->ie_template->iot_name,
			isns_entity_template.iot_name);
		return NULL;
	}

	obj = isns_create_object(&isns_iscsi_node_template, NULL, parent);
	isns_object_set_string(obj,
			ISNS_TAG_ISCSI_NAME, name);
	isns_object_set_uint32(obj,
			ISNS_TAG_ISCSI_NODE_TYPE, type);

	return obj;
}
Beispiel #7
0
static int
isns_registration_get_next_object(isns_db_t *db,
				struct isns_attr_list_scanner *st,
				isns_object_list_t *result)
{
	isns_object_t	*current;
	int		status, esi = 0;

	status = isns_attr_list_scanner_next(st);
	/* We get here if the registration has a trailing PGT */
	if (status == ISNS_NO_SUCH_ENTRY)
		return ISNS_SUCCESS;
	if (status)
		return status;

	/*
	 * Validate the attrlist.
	 * This makes sure the client does not include
	 * duplicate attributes, readonly attributes
	 * such as Registration Timestamp, Index and Next Index,
	 * or privileged data (such as marking a storage node as
	 * control node).
	 */
	status = isns_attr_list_validate(&st->attrs,
			st->policy,
			ISNS_DEVICE_ATTRIBUTE_REGISTER);
	if (status) {
		isns_debug_protocol("invalid attr in message\n");
		return status;
	}

	/*
	 * 6.3.4.  Entity Status Inquiry Interval
	 *
	 * If the iSNS server is unable to support ESI messages
	 * or the ESI Interval requested, it SHALL [...] reject
	 * the ESI request by returning an "ESI Not Available"
	 * Status Code [...]
	 *
	 * Implementer's note: In section 5.7.5.1, the RFC talks
	 * about modifying the requested ESI interval; so it seems
	 * it's okay to be liberal about the ESI intervals we accept,
	 * and update them quietly.
	 */
	if (isns_attr_list_contains(&st->attrs, ISNS_TAG_ESI_PORT)) {
		if (!isns_esi_enabled) {
			isns_debug_esi("Refusing to accept portal "
					"registration with ESI port\n");
			return ISNS_ESI_NOT_AVAILABLE;
		}
		esi = 1;
	}

	/*
	 * Override any registration period specified by the client.
	 */
	if (isns_attr_list_contains(&st->attrs, ISNS_TAG_REGISTRATION_PERIOD)) {
		isns_value_t value = ISNS_VALUE_INIT(uint32,
					isns_config.ic_registration_period);

		isns_attr_list_update_value(&st->attrs,
				ISNS_TAG_REGISTRATION_PERIOD, NULL,
				&value);
	}

	if (st->tmpl == &isns_entity_template) {
		/*
		 * 5.6.5.1.
		 * A maximum of one Network Entity object can be
		 * created or updated with a single DevAttrReg
		 * message.  Consequently, the Operating Attributes
		 * MUST NOT contain more than one Network Entity
		 * object.
		 */
		if (st->entities++) {
			isns_debug_protocol("More than one entity in DevAttrReg msg\n");
			return ISNS_INVALID_REGISTRATION;
		}

		/* This should be the key object.
		 * The EID specified by by the client may be
		 * empty, so don't overwrite the value we
		 * assigned with something else.
		 */
		if (!isns_object_match(st->key_obj, &st->keys)) {
			isns_debug_protocol("Entity mismatch in message vs. operating attrs\n");
			return ISNS_INVALID_REGISTRATION;
		}
		current = isns_object_get(st->key_obj);
	} else
	if (st->tmpl == &isns_dd_template || st->tmpl == &isns_ddset_template) {
		isns_debug_protocol("DevAttrReg of type %s not allowed\n",
				st->tmpl->iot_name);
		return ISNS_INVALID_REGISTRATION;
	} else {
		/* This will also catch objects in limbo. */
		current = isns_db_lookup(db, st->tmpl, &st->keys);
	}

	if (current != NULL) {
		/* 
		 * If the replace bit is not set, then the message updates
		 * the attributes of the object identified by the Message Key
		 * and its subordinate objects.  Existing object containment
		 * relationships MUST NOT be changed.  For existing objects,
		 * key attributes MUST NOT be modified, but new subordinate
		 * objects MAY be added.
		 */

		/*
		 * [...]
		 * If the Node identified by the Source Attribute is
		 * not a Control Node, then the objects in the operating
		 * attributes MUST be members of the same Network Entity
		 * as the Source Node.
		 */
		if (!isns_policy_validate_object_update(st->policy,
					st->source, current, &st->attrs,
					ISNS_DEVICE_ATTRIBUTE_REGISTER)) {
			isns_object_release(current);
			return ISNS_SOURCE_UNAUTHORIZED;
		}

		/* We shouldn't allow messages affecting one Entity
		 * to modify objects owned by a different Entity.
		 *
		 * However, there may be orphan objects (created
		 * while populating discovery domains). These will
		 * not be associated with any Network Entity, so
		 * they're up for grabs.
		 */
		if (st->key_obj == current
		 || st->key_obj == current->ie_container) {
			/* All is well. The current object is the
			 * key object itself, or a direct descendant of the
			 * key object. */
			/* FIXME: with FC we can get deeper nesting;
			 * this needs work. */
		} else
		if (!isns_object_is_valid_container(st->key_obj, st->tmpl)) {
			isns_error("Client attempts to add %s object to a %s - tsk tsk.\n",
					st->tmpl->iot_name,
					st->key_obj->ie_template->iot_name);
			goto invalid_registration;
		} else if (current->ie_container) {
			/* We shouldn't get here in authenticated mode,
			 * but in insecure mode we still may. */
			isns_error("Client attempts to move %s %u to a different %s\n",
					current->ie_template->iot_name,
					current->ie_index,
					st->key_obj->ie_template->iot_name);
			goto invalid_registration;
		}
	} else {
		if (!isns_object_is_valid_container(st->key_obj, st->tmpl)) {
			isns_error("Client attempts to add %s object to a %s - tsk tsk.\n",
					st->tmpl->iot_name,
					st->key_obj->ie_template->iot_name);
			goto invalid_registration;
		}

		if (!isns_policy_validate_object_creation(st->policy,
					st->source, st->tmpl,
					&st->keys, &st->attrs,
					ISNS_DEVICE_ATTRIBUTE_REGISTER)) {
			return ISNS_SOURCE_UNAUTHORIZED;
		}
		current = isns_create_object(st->tmpl, &st->keys,
				isns_object_get_entity(st->key_obj));

		/* We do not insert the new object into the database yet.
		 * That happens after we're done with parsing *all*
		 * objects. */
	}

	if (!isns_object_set_attrlist(current, &st->attrs)) {
		isns_debug_state("Error updating object's attrlist\n");
		isns_object_release(current);
		return ISNS_INTERNAL_ERROR;
	}

	/* If the client specifies an ESI port, make sure the
	 * ESI interval is set and within bounds. */
	if (esi) {
		uint32_t	esi_interval;

		if (!isns_object_get_uint32(current,
					ISNS_TAG_ESI_INTERVAL, &esi_interval)) {
			esi_interval = isns_config.ic_esi_min_interval;
		} else
		if (esi_interval < isns_config.ic_esi_min_interval) {
			esi_interval = isns_config.ic_esi_min_interval;
		} else
		if (esi_interval > isns_config.ic_esi_max_interval) {
			esi_interval = isns_config.ic_esi_max_interval;
		} else {
			esi_interval = 0;
		}

		if (esi_interval)
			isns_object_set_uint32(current,
					ISNS_TAG_ESI_INTERVAL, esi_interval);
	}

	/* Append it to the result list.
	 * We do not return the key object, otherwise
	 * we end up putting it into the response twice.
	 */
	if (current != st->key_obj)
		isns_object_list_append(result, current);

	/*
	 * When a Portal is registered, the Portal attributes MAY immediately be
	 * followed by a PGT attribute. 
	 * [...]
	 * When an iSCSI Storage Node is registered, the Storage Node attributes
	 * MAY immediately be followed by a PGT attribute.
	 */
	if (st->tmpl == &isns_portal_template
	 || st->tmpl == &isns_iscsi_node_template) {
		st->pgt_next_attr = ISNS_TAG_PG_TAG;
		st->pgt_base_object = current;
	} else if (st->tmpl != &isns_iscsi_pg_template) {
		st->pgt_next_attr = 0;
		st->pgt_base_object = NULL;
	}

	isns_object_release(current);
	return ISNS_SUCCESS;

invalid_registration:
	if (current)
		isns_object_release(current);
	return ISNS_INVALID_REGISTRATION;
}