|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Handle iSNS Device Attribute Registration
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
#include <stdlib.h>
|
|
Packit |
1c819f |
#include <string.h>
|
|
Packit |
1c819f |
#include <time.h>
|
|
Packit |
1c819f |
#include "config.h"
|
|
Packit |
1c819f |
#include <libisns/isns.h>
|
|
Packit |
1c819f |
#include <libisns/attrs.h>
|
|
Packit |
1c819f |
#include "objects.h"
|
|
Packit |
1c819f |
#include <libisns/message.h>
|
|
Packit |
1c819f |
#include "security.h"
|
|
Packit |
1c819f |
#include <libisns/util.h>
|
|
Packit |
1c819f |
#include "db.h"
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static int isns_create_default_pgs_for_object(isns_db_t *, isns_object_t *);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Create a registration, and set the source name
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static isns_simple_t *
|
|
Packit |
1c819f |
__isns_create_registration(isns_source_t *source, isns_object_t *key_obj)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_simple_t *reg;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
reg = isns_simple_create(ISNS_DEVICE_ATTRIBUTE_REGISTER, source, NULL);
|
|
Packit |
1c819f |
if (reg == NULL)
|
|
Packit |
1c819f |
return NULL;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* When sending a registration, you can either specify
|
|
Packit |
1c819f |
* the object to be modified in the key attrs, or leave
|
|
Packit |
1c819f |
* the key empty.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (key_obj == NULL)
|
|
Packit |
1c819f |
return reg;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* User gave us a key object. We need to put the key
|
|
Packit |
1c819f |
* attributes into the message attrs, and *all* attrs
|
|
Packit |
1c819f |
* into the operating attrs. */
|
|
Packit |
1c819f |
if (!isns_object_extract_keys(key_obj, ®->is_message_attrs)) {
|
|
Packit |
1c819f |
/* bummer - seems the object is missing some
|
|
Packit |
1c819f |
* vital organs. */
|
|
Packit |
1c819f |
isns_warning("%s: object not fully specified, key attrs missing\n",
|
|
Packit |
1c819f |
__FUNCTION__);
|
|
Packit |
1c819f |
goto failed;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* The Message Key identifies the object the DevAttrReg message
|
|
Packit |
1c819f |
* acts upon. [...] The key attribute(s) identifying this object
|
|
Packit |
1c819f |
* MUST also be included among the Operating Attributes.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* We do not enforce this here, we rely on the caller to get this
|
|
Packit |
1c819f |
* right.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
#if 0
|
|
Packit |
1c819f |
if (!isns_object_extract_all(key_obj, ®->is_operating_attrs)) {
|
|
Packit |
1c819f |
isns_warning("%s: unable to extract attrs from key objects\n",
|
|
Packit |
1c819f |
__FUNCTION__);
|
|
Packit |
1c819f |
goto failed;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
#endif
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return reg;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
failed:
|
|
Packit |
1c819f |
isns_simple_free(reg);
|
|
Packit |
1c819f |
return NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_simple_t *
|
|
Packit |
1c819f |
isns_create_registration(isns_client_t *clnt, isns_object_t *key_obj)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return __isns_create_registration(clnt->ic_source, key_obj);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_simple_t *
|
|
Packit |
1c819f |
isns_create_registration2(isns_client_t *clnt, isns_object_t *key_obj,
|
|
Packit |
1c819f |
isns_source_t *source)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return __isns_create_registration(source?: clnt->ic_source, key_obj);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Set the replace flag
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
void
|
|
Packit |
1c819f |
isns_registration_set_replace(isns_simple_t *reg, int replace)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
reg->is_replace = !!replace;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Add an object to the registration
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
void
|
|
Packit |
1c819f |
isns_registration_add_object(isns_simple_t *reg, isns_object_t *obj)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_object_extract_writable(obj, ®->is_operating_attrs);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
void
|
|
Packit |
1c819f |
isns_registration_add_object_list(isns_simple_t *reg, isns_object_list_t *list)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < list->iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_extract_writable(list->iol_data[i],
|
|
Packit |
1c819f |
®->is_operating_attrs);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Get the key object given in this message
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* It doesn't say anywhere explicitly in the RFC, but
|
|
Packit |
1c819f |
* the message key can contain both key and non-key
|
|
Packit |
1c819f |
* attributes. For instance, you can search by
|
|
Packit |
1c819f |
* Portal Group Index (section 3.4).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_registration_get_key(isns_simple_t *reg, isns_db_t *db, isns_object_t **key_obj)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_attr_list_t *keys = ®->is_message_attrs;
|
|
Packit |
1c819f |
isns_attr_list_t dummy_keys = ISNS_ATTR_LIST_INIT;
|
|
Packit |
1c819f |
isns_attr_t *attr;
|
|
Packit |
1c819f |
isns_object_t *obj = NULL;
|
|
Packit |
1c819f |
const char *eid = NULL;
|
|
Packit |
1c819f |
char eidbuf[128];
|
|
Packit |
1c819f |
int status = ISNS_SUCCESS;
|
|
Packit |
1c819f |
int obj_must_exist = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* If the Message Key is not present, then the DevAttrReg message
|
|
Packit |
1c819f |
* implicitly registers a new Network Entity. In this case,
|
|
Packit |
1c819f |
* the replace bit SHALL be ignored; a new Network Entity SHALL
|
|
Packit |
1c819f |
* be created.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Note that some clients seem to leave the message key
|
|
Packit |
1c819f |
* empty, but hide the entity identifier in the operating
|
|
Packit |
1c819f |
* attrs.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (keys->ial_count != 0) {
|
|
Packit |
1c819f |
attr = keys->ial_data[0];
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* If the Message Key does not contain an EID, and no
|
|
Packit |
1c819f |
* pre-existing objects match the Message Key, then the
|
|
Packit |
1c819f |
* DevAttrReg message SHALL be rejected with a status
|
|
Packit |
1c819f |
* code of 3 (Invalid Registration).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (keys->ial_count != 1
|
|
Packit |
1c819f |
|| attr->ia_tag_id != ISNS_TAG_ENTITY_IDENTIFIER)
|
|
Packit |
1c819f |
obj_must_exist = 1;
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
/* Empty message key. But the client may have hidden
|
|
Packit |
1c819f |
* the EID in the operating attrs :-/
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (reg->is_operating_attrs.ial_count == 0)
|
|
Packit |
1c819f |
goto create_entity;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
attr = reg->is_operating_attrs.ial_data[0];
|
|
Packit |
1c819f |
if (attr->ia_tag_id != ISNS_TAG_ENTITY_IDENTIFIER)
|
|
Packit |
1c819f |
goto create_entity;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_append_attr(&dummy_keys, attr);
|
|
Packit |
1c819f |
keys = &dummy_keys;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* If the caller specifies an EID, extract it while
|
|
Packit |
1c819f |
* we know what we're doing :-) */
|
|
Packit |
1c819f |
if (attr->ia_tag_id == ISNS_TAG_ENTITY_IDENTIFIER
|
|
Packit |
1c819f |
&& ISNS_ATTR_IS_STRING(attr))
|
|
Packit |
1c819f |
eid = attr->ia_value.iv_string;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Look up the object identified by the keys.
|
|
Packit |
1c819f |
* We do not scope the lookup, as the client
|
|
Packit |
1c819f |
* may want to add nodes to an entity that's
|
|
Packit |
1c819f |
* currently empty - and hence not visible to
|
|
Packit |
1c819f |
* any DD. */
|
|
Packit |
1c819f |
if (!ISNS_ATTR_IS_NIL(attr))
|
|
Packit |
1c819f |
obj = isns_db_lookup(db, NULL, keys);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (obj == NULL && obj_must_exist)
|
|
Packit |
1c819f |
goto err_invalid;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (obj != NULL) {
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Policy: verify that the client is permitted
|
|
Packit |
1c819f |
* to access this object.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* This includes
|
|
Packit |
1c819f |
* - the client node must be the object owner,
|
|
Packit |
1c819f |
* or a control node.
|
|
Packit |
1c819f |
* - the policy must allow modification of
|
|
Packit |
1c819f |
* this object type.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_access(reg->is_policy,
|
|
Packit |
1c819f |
reg->is_source,
|
|
Packit |
1c819f |
obj, reg->is_function))
|
|
Packit |
1c819f |
goto err_unauthorized;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
found_object:
|
|
Packit |
1c819f |
if (reg->is_replace) {
|
|
Packit |
1c819f |
isns_object_t *container = NULL;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!ISNS_IS_ENTITY(obj)) {
|
|
Packit |
1c819f |
container = isns_object_get_entity(obj);
|
|
Packit |
1c819f |
if (container == NULL) {
|
|
Packit |
1c819f |
isns_error("Trying to replace %s (id %u) "
|
|
Packit |
1c819f |
"which has no container\n",
|
|
Packit |
1c819f |
obj->ie_template->iot_name,
|
|
Packit |
1c819f |
obj->ie_index);
|
|
Packit |
1c819f |
goto err_invalid;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_debug_state("Replacing %s (id %u)\n",
|
|
Packit |
1c819f |
obj->ie_template->iot_name,
|
|
Packit |
1c819f |
obj->ie_index);
|
|
Packit |
1c819f |
isns_db_remove(db, obj);
|
|
Packit |
1c819f |
isns_object_release(obj);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Purge the deleted objects from the database now */
|
|
Packit |
1c819f |
isns_db_purge(db);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* We need to flush pending SCNs because the
|
|
Packit |
1c819f |
* objects may be resurrected from limbo,
|
|
Packit |
1c819f |
* and we might be looking at stale data. */
|
|
Packit |
1c819f |
isns_scn_transmit_all();
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* It's an entity. Nuke it and create
|
|
Packit |
1c819f |
* a new one. */
|
|
Packit |
1c819f |
if (container == NULL) {
|
|
Packit |
1c819f |
isns_source_set_entity(reg->is_source, NULL);
|
|
Packit |
1c819f |
goto create_entity;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
obj = isns_object_get(container);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
goto out;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* If the Message Key contains an EID and no pre-existing objects
|
|
Packit |
1c819f |
* match the Message Key, then the DevAttrReg message SHALL create a
|
|
Packit |
1c819f |
* new Entity with the specified EID and any new object(s) specified
|
|
Packit |
1c819f |
* by the Operating Attributes. The replace bit SHALL be ignored.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Implementer's note: the EID attribute may be empty, in which case
|
|
Packit |
1c819f |
* we also create a new entity.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
create_entity:
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_creation(reg->is_policy,
|
|
Packit |
1c819f |
reg->is_source,
|
|
Packit |
1c819f |
&isns_entity_template, keys, NULL,
|
|
Packit |
1c819f |
reg->is_function))
|
|
Packit |
1c819f |
goto err_unauthorized;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* A registration message that creates a new Network Entity object
|
|
Packit |
1c819f |
* MUST contain at least one Portal or one Storage Node. If the
|
|
Packit |
1c819f |
* message does not, then it SHALL be considered invalid and result
|
|
Packit |
1c819f |
* in a response with Status Code of 3 (Invalid Registration).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
/* FIXME: Implement this check */
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* We try to play nice with lazy clients and attempt to
|
|
Packit |
1c819f |
* look up the network entity given the source name.
|
|
Packit |
1c819f |
* But we don't do this if a non-NULL EID was given,
|
|
Packit |
1c819f |
* because the client may explicitly want to specify more
|
|
Packit |
1c819f |
* than one Network Entity.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (eid == NULL) {
|
|
Packit |
1c819f |
obj = reg->is_source->is_entity;
|
|
Packit |
1c819f |
if (obj != NULL) {
|
|
Packit |
1c819f |
isns_object_get(obj);
|
|
Packit |
1c819f |
goto found_object;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* The policy may define a default entity name.
|
|
Packit |
1c819f |
* If that is the case, use it.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
eid = isns_policy_default_entity(reg->is_policy);
|
|
Packit |
1c819f |
if (eid) {
|
|
Packit |
1c819f |
obj = isns_db_vlookup(db, &isns_entity_template,
|
|
Packit |
1c819f |
ISNS_TAG_ENTITY_IDENTIFIER, eid,
|
|
Packit |
1c819f |
0);
|
|
Packit |
1c819f |
if (obj) {
|
|
Packit |
1c819f |
reg->is_source->is_entity = isns_object_get(obj);
|
|
Packit |
1c819f |
goto found_object;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* If the Message Key and Operating Attributes do not contain
|
|
Packit |
1c819f |
* an EID attribute, or if the EID attribute has a length of 0,
|
|
Packit |
1c819f |
* then a new Network Entity object SHALL be created and the iSNS
|
|
Packit |
1c819f |
* server SHALL supply a unique EID value for it.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (eid == NULL)
|
|
Packit |
1c819f |
eid = isns_db_generate_eid(db, eidbuf, sizeof(eidbuf));
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 6.2.2. Entity Protocol
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* This attribute is required during initial registration of
|
|
Packit |
1c819f |
* the Network Entity.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Implementer's note: we don't rely on this. Instead, the
|
|
Packit |
1c819f |
* Entity Protocol is selected based on the source type.
|
|
Packit |
1c819f |
* If the client specifies the protocol, the auto-selected
|
|
Packit |
1c819f |
* value is overwritten.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
obj = isns_create_entity_for_source(reg->is_source, eid);
|
|
Packit |
1c819f |
if (obj == NULL)
|
|
Packit |
1c819f |
goto err_invalid;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_source_set_entity(reg->is_source, obj);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 6.2.6
|
|
Packit |
1c819f |
* If a Registration Period is not requested by the iSNS
|
|
Packit |
1c819f |
* client and Entity Status Inquiry (ESI) messages are not
|
|
Packit |
1c819f |
* enabled for that client, then the Registration Period
|
|
Packit |
1c819f |
* SHALL be set to a non-zero value by the iSNS server.
|
|
Packit |
1c819f |
* This implementation-specific value for the Registration
|
|
Packit |
1c819f |
* Period SHALL be returned in the registration response to the
|
|
Packit |
1c819f |
* iSNS client. The Registration Period may be set to zero,
|
|
Packit |
1c819f |
* indicating its non-use, only if ESI messages are enabled for
|
|
Packit |
1c819f |
* that Network Entity.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Implementer's note: we diverge from this in two ways:
|
|
Packit |
1c819f |
* - the admin may choose to disable registration timeout,
|
|
Packit |
1c819f |
* by setting RegistrationPeriod=0 in the config file
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* - When a new entity is created, we always set the
|
|
Packit |
1c819f |
* registration interval because we cannot know yet
|
|
Packit |
1c819f |
* whether the client will subsequently enable ESI or
|
|
Packit |
1c819f |
* not.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* - The control entity (holding policy objects) will
|
|
Packit |
1c819f |
* not expire.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (isns_config.ic_registration_period
|
|
Packit |
1c819f |
&& strcasecmp(eid, ISNS_ENTITY_CONTROL)) {
|
|
Packit |
1c819f |
isns_object_set_uint32(obj,
|
|
Packit |
1c819f |
ISNS_TAG_REGISTRATION_PERIOD,
|
|
Packit |
1c819f |
isns_config.ic_registration_period);
|
|
Packit |
1c819f |
isns_object_set_uint64(obj,
|
|
Packit |
1c819f |
ISNS_TAG_TIMESTAMP,
|
|
Packit |
1c819f |
time(NULL));
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Insert into database, and set the object's owner */
|
|
Packit |
1c819f |
isns_db_insert(db, obj);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
reg->is_replace = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
out:
|
|
Packit |
1c819f |
*key_obj = obj;
|
|
Packit |
1c819f |
isns_attr_list_destroy(&dummy_keys);
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
error:
|
|
Packit |
1c819f |
if (obj)
|
|
Packit |
1c819f |
isns_object_release(obj);
|
|
Packit |
1c819f |
isns_attr_list_destroy(&dummy_keys);
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
err_unauthorized:
|
|
Packit |
1c819f |
status = ISNS_SOURCE_UNAUTHORIZED;
|
|
Packit |
1c819f |
goto error;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
err_invalid:
|
|
Packit |
1c819f |
status = ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
goto error;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_registration_get_next_object(isns_db_t *db,
|
|
Packit |
1c819f |
struct isns_attr_list_scanner *st,
|
|
Packit |
1c819f |
isns_object_list_t *result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_object_t *current;
|
|
Packit |
1c819f |
int status, esi = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
status = isns_attr_list_scanner_next(st);
|
|
Packit |
1c819f |
/* We get here if the registration has a trailing PGT */
|
|
Packit |
1c819f |
if (status == ISNS_NO_SUCH_ENTRY)
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
if (status)
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Validate the attrlist.
|
|
Packit |
1c819f |
* This makes sure the client does not include
|
|
Packit |
1c819f |
* duplicate attributes, readonly attributes
|
|
Packit |
1c819f |
* such as Registration Timestamp, Index and Next Index,
|
|
Packit |
1c819f |
* or privileged data (such as marking a storage node as
|
|
Packit |
1c819f |
* control node).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
status = isns_attr_list_validate(&st->attrs,
|
|
Packit |
1c819f |
st->policy,
|
|
Packit |
1c819f |
ISNS_DEVICE_ATTRIBUTE_REGISTER);
|
|
Packit |
1c819f |
if (status) {
|
|
Packit |
1c819f |
isns_debug_protocol("invalid attr in message\n");
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 6.3.4. Entity Status Inquiry Interval
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* If the iSNS server is unable to support ESI messages
|
|
Packit |
1c819f |
* or the ESI Interval requested, it SHALL [...] reject
|
|
Packit |
1c819f |
* the ESI request by returning an "ESI Not Available"
|
|
Packit |
1c819f |
* Status Code [...]
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Implementer's note: In section 5.7.5.1, the RFC talks
|
|
Packit |
1c819f |
* about modifying the requested ESI interval; so it seems
|
|
Packit |
1c819f |
* it's okay to be liberal about the ESI intervals we accept,
|
|
Packit |
1c819f |
* and update them quietly.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (isns_attr_list_contains(&st->attrs, ISNS_TAG_ESI_PORT)) {
|
|
Packit |
1c819f |
if (!isns_esi_enabled) {
|
|
Packit |
1c819f |
isns_debug_esi("Refusing to accept portal "
|
|
Packit |
1c819f |
"registration with ESI port\n");
|
|
Packit |
1c819f |
return ISNS_ESI_NOT_AVAILABLE;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
esi = 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Override any registration period specified by the client.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (isns_attr_list_contains(&st->attrs, ISNS_TAG_REGISTRATION_PERIOD)) {
|
|
Packit |
1c819f |
isns_value_t value = ISNS_VALUE_INIT(uint32,
|
|
Packit |
1c819f |
isns_config.ic_registration_period);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_update_value(&st->attrs,
|
|
Packit |
1c819f |
ISNS_TAG_REGISTRATION_PERIOD, NULL,
|
|
Packit |
1c819f |
&value);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (st->tmpl == &isns_entity_template) {
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1.
|
|
Packit |
1c819f |
* A maximum of one Network Entity object can be
|
|
Packit |
1c819f |
* created or updated with a single DevAttrReg
|
|
Packit |
1c819f |
* message. Consequently, the Operating Attributes
|
|
Packit |
1c819f |
* MUST NOT contain more than one Network Entity
|
|
Packit |
1c819f |
* object.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (st->entities++) {
|
|
Packit |
1c819f |
isns_debug_protocol("More than one entity in DevAttrReg msg\n");
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* This should be the key object.
|
|
Packit |
1c819f |
* The EID specified by by the client may be
|
|
Packit |
1c819f |
* empty, so don't overwrite the value we
|
|
Packit |
1c819f |
* assigned with something else.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (!isns_object_match(st->key_obj, &st->keys)) {
|
|
Packit |
1c819f |
isns_debug_protocol("Entity mismatch in message vs. operating attrs\n");
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
current = isns_object_get(st->key_obj);
|
|
Packit |
1c819f |
} else
|
|
Packit |
1c819f |
if (st->tmpl == &isns_dd_template || st->tmpl == &isns_ddset_template) {
|
|
Packit |
1c819f |
isns_debug_protocol("DevAttrReg of type %s not allowed\n",
|
|
Packit |
1c819f |
st->tmpl->iot_name);
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
/* This will also catch objects in limbo. */
|
|
Packit |
1c819f |
current = isns_db_lookup(db, st->tmpl, &st->keys);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (current != NULL) {
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* If the replace bit is not set, then the message updates
|
|
Packit |
1c819f |
* the attributes of the object identified by the Message Key
|
|
Packit |
1c819f |
* and its subordinate objects. Existing object containment
|
|
Packit |
1c819f |
* relationships MUST NOT be changed. For existing objects,
|
|
Packit |
1c819f |
* key attributes MUST NOT be modified, but new subordinate
|
|
Packit |
1c819f |
* objects MAY be added.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* [...]
|
|
Packit |
1c819f |
* If the Node identified by the Source Attribute is
|
|
Packit |
1c819f |
* not a Control Node, then the objects in the operating
|
|
Packit |
1c819f |
* attributes MUST be members of the same Network Entity
|
|
Packit |
1c819f |
* as the Source Node.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_update(st->policy,
|
|
Packit |
1c819f |
st->source, current, &st->attrs,
|
|
Packit |
1c819f |
ISNS_DEVICE_ATTRIBUTE_REGISTER)) {
|
|
Packit |
1c819f |
isns_object_release(current);
|
|
Packit |
1c819f |
return ISNS_SOURCE_UNAUTHORIZED;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* We shouldn't allow messages affecting one Entity
|
|
Packit |
1c819f |
* to modify objects owned by a different Entity.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* However, there may be orphan objects (created
|
|
Packit |
1c819f |
* while populating discovery domains). These will
|
|
Packit |
1c819f |
* not be associated with any Network Entity, so
|
|
Packit |
1c819f |
* they're up for grabs.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (st->key_obj == current
|
|
Packit |
1c819f |
|| st->key_obj == current->ie_container) {
|
|
Packit |
1c819f |
/* All is well. The current object is the
|
|
Packit |
1c819f |
* key object itself, or a direct descendant of the
|
|
Packit |
1c819f |
* key object. */
|
|
Packit |
1c819f |
/* FIXME: with FC we can get deeper nesting;
|
|
Packit |
1c819f |
* this needs work. */
|
|
Packit |
1c819f |
} else
|
|
Packit |
1c819f |
if (!isns_object_is_valid_container(st->key_obj, st->tmpl)) {
|
|
Packit |
1c819f |
isns_error("Client attempts to add %s object to a %s - tsk tsk.\n",
|
|
Packit |
1c819f |
st->tmpl->iot_name,
|
|
Packit |
1c819f |
st->key_obj->ie_template->iot_name);
|
|
Packit |
1c819f |
goto invalid_registration;
|
|
Packit |
1c819f |
} else if (current->ie_container) {
|
|
Packit |
1c819f |
/* We shouldn't get here in authenticated mode,
|
|
Packit |
1c819f |
* but in insecure mode we still may. */
|
|
Packit |
1c819f |
isns_error("Client attempts to move %s %u to a different %s\n",
|
|
Packit |
1c819f |
current->ie_template->iot_name,
|
|
Packit |
1c819f |
current->ie_index,
|
|
Packit |
1c819f |
st->key_obj->ie_template->iot_name);
|
|
Packit |
1c819f |
goto invalid_registration;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
if (!isns_object_is_valid_container(st->key_obj, st->tmpl)) {
|
|
Packit |
1c819f |
isns_error("Client attempts to add %s object to a %s - tsk tsk.\n",
|
|
Packit |
1c819f |
st->tmpl->iot_name,
|
|
Packit |
1c819f |
st->key_obj->ie_template->iot_name);
|
|
Packit |
1c819f |
goto invalid_registration;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_creation(st->policy,
|
|
Packit |
1c819f |
st->source, st->tmpl,
|
|
Packit |
1c819f |
&st->keys, &st->attrs,
|
|
Packit |
1c819f |
ISNS_DEVICE_ATTRIBUTE_REGISTER)) {
|
|
Packit |
1c819f |
return ISNS_SOURCE_UNAUTHORIZED;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
current = isns_create_object(st->tmpl, &st->keys,
|
|
Packit |
1c819f |
isns_object_get_entity(st->key_obj));
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* We do not insert the new object into the database yet.
|
|
Packit |
1c819f |
* That happens after we're done with parsing *all*
|
|
Packit |
1c819f |
* objects. */
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!isns_object_set_attrlist(current, &st->attrs)) {
|
|
Packit |
1c819f |
isns_debug_state("Error updating object's attrlist\n");
|
|
Packit |
1c819f |
isns_object_release(current);
|
|
Packit |
1c819f |
return ISNS_INTERNAL_ERROR;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* If the client specifies an ESI port, make sure the
|
|
Packit |
1c819f |
* ESI interval is set and within bounds. */
|
|
Packit |
1c819f |
if (esi) {
|
|
Packit |
1c819f |
uint32_t esi_interval;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!isns_object_get_uint32(current,
|
|
Packit |
1c819f |
ISNS_TAG_ESI_INTERVAL, &esi_interval)) {
|
|
Packit |
1c819f |
esi_interval = isns_config.ic_esi_min_interval;
|
|
Packit |
1c819f |
} else
|
|
Packit |
1c819f |
if (esi_interval < isns_config.ic_esi_min_interval) {
|
|
Packit |
1c819f |
esi_interval = isns_config.ic_esi_min_interval;
|
|
Packit |
1c819f |
} else
|
|
Packit |
1c819f |
if (esi_interval > isns_config.ic_esi_max_interval) {
|
|
Packit |
1c819f |
esi_interval = isns_config.ic_esi_max_interval;
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
esi_interval = 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (esi_interval)
|
|
Packit |
1c819f |
isns_object_set_uint32(current,
|
|
Packit |
1c819f |
ISNS_TAG_ESI_INTERVAL, esi_interval);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Append it to the result list.
|
|
Packit |
1c819f |
* We do not return the key object, otherwise
|
|
Packit |
1c819f |
* we end up putting it into the response twice.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (current != st->key_obj)
|
|
Packit |
1c819f |
isns_object_list_append(result, current);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* When a Portal is registered, the Portal attributes MAY immediately be
|
|
Packit |
1c819f |
* followed by a PGT attribute.
|
|
Packit |
1c819f |
* [...]
|
|
Packit |
1c819f |
* When an iSCSI Storage Node is registered, the Storage Node attributes
|
|
Packit |
1c819f |
* MAY immediately be followed by a PGT attribute.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (st->tmpl == &isns_portal_template
|
|
Packit |
1c819f |
|| st->tmpl == &isns_iscsi_node_template) {
|
|
Packit |
1c819f |
st->pgt_next_attr = ISNS_TAG_PG_TAG;
|
|
Packit |
1c819f |
st->pgt_base_object = current;
|
|
Packit |
1c819f |
} else if (st->tmpl != &isns_iscsi_pg_template) {
|
|
Packit |
1c819f |
st->pgt_next_attr = 0;
|
|
Packit |
1c819f |
st->pgt_base_object = NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_object_release(current);
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
invalid_registration:
|
|
Packit |
1c819f |
if (current)
|
|
Packit |
1c819f |
isns_object_release(current);
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Extract the list of objects to be registered from
|
|
Packit |
1c819f |
* the list of operating attributes.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_registration_get_objects(isns_simple_t *reg, isns_db_t *db,
|
|
Packit |
1c819f |
isns_object_t *key_obj,
|
|
Packit |
1c819f |
isns_object_list_t *result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct isns_attr_list_scanner state;
|
|
Packit |
1c819f |
int status = ISNS_SUCCESS;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_scanner_init(&state, key_obj, ®->is_operating_attrs);
|
|
Packit |
1c819f |
state.source = reg->is_source;
|
|
Packit |
1c819f |
state.policy = reg->is_policy;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.4.
|
|
Packit |
1c819f |
* The ordering of Operating Attributes in the message is
|
|
Packit |
1c819f |
* important for determining the relationships among objects
|
|
Packit |
1c819f |
* and their ownership of non-key attributes. iSNS protocol
|
|
Packit |
1c819f |
* messages that violate these ordering rules SHALL be rejected
|
|
Packit |
1c819f |
* with the Status Code of 2 (Message Format Error).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
/* FIXME: Implement this check */
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
while (state.pos < state.orig_attrs.ial_count) {
|
|
Packit |
1c819f |
status = isns_registration_get_next_object(db,
|
|
Packit |
1c819f |
&state, result);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (status)
|
|
Packit |
1c819f |
break;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_scanner_destroy(&state);
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* New PG objects are registered when an associated Portal or
|
|
Packit |
1c819f |
* iSCSI Node object is registered. An explicit PG object
|
|
Packit |
1c819f |
* registration MAY follow a Portal or iSCSI Node object
|
|
Packit |
1c819f |
* registration in a DevAttrReg message.
|
|
Packit |
1c819f |
* [...]
|
|
Packit |
1c819f |
* If the PGT value is not included in the Storage Node or
|
|
Packit |
1c819f |
* Portal object registration, and if a PGT value was not
|
|
Packit |
1c819f |
* previously registered for the relationship, then the PGT for
|
|
Packit |
1c819f |
* the corresponding PG object SHALL be registered with a value
|
|
Packit |
1c819f |
* of 0x00000001.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_create_registration_pgs(isns_db_t *db,
|
|
Packit |
1c819f |
const isns_object_list_t *list)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
unsigned int i, num_created = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < list->iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *obj = list->iol_data[i];
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (ISNS_IS_ISCSI_NODE(obj) || ISNS_IS_PORTAL(obj))
|
|
Packit |
1c819f |
num_created += isns_create_default_pgs_for_object(db, obj);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
return num_created;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_create_default_pgs_for_object(isns_db_t *db, isns_object_t *this)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_object_template_t *match_tmpl;
|
|
Packit |
1c819f |
isns_object_t *entity;
|
|
Packit |
1c819f |
unsigned int i, num_created = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (ISNS_IS_ISCSI_NODE(this))
|
|
Packit |
1c819f |
match_tmpl = &isns_portal_template;
|
|
Packit |
1c819f |
else
|
|
Packit |
1c819f |
match_tmpl = &isns_iscsi_node_template;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
entity = isns_object_get_entity(this);
|
|
Packit |
1c819f |
for (i = 0; i < entity->ie_children.iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *that = entity->ie_children.iol_data[i], *pg;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (that->ie_template != match_tmpl)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Create the portal group if it does not
|
|
Packit |
1c819f |
* exist.
|
|
Packit |
1c819f |
* Note: we do not return these implicitly
|
|
Packit |
1c819f |
* created portal groups - that's a matter
|
|
Packit |
1c819f |
* of sheer laziness. We would have to
|
|
Packit |
1c819f |
* splice these into the list in the
|
|
Packit |
1c819f |
* appropriate location, and I guess it's
|
|
Packit |
1c819f |
* not really worth the hassle.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (ISNS_IS_ISCSI_NODE(this))
|
|
Packit |
1c819f |
pg = isns_create_default_portal_group(db, that, this);
|
|
Packit |
1c819f |
else
|
|
Packit |
1c819f |
pg = isns_create_default_portal_group(db, this, that);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* There already is a PG linking these two
|
|
Packit |
1c819f |
* objects. */
|
|
Packit |
1c819f |
if (pg == NULL)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_db_insert(db, pg);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_debug_message("--Created default PG:--\n");
|
|
Packit |
1c819f |
isns_object_print(pg, isns_debug_message);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_object_release(pg);
|
|
Packit |
1c819f |
num_created++;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return num_created;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Commit all changes to the DB
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_commit_registration(isns_db_t *db, isns_object_t *key_obj, isns_object_list_t *list)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* If there are any Portal Groups in this registration, build
|
|
Packit |
1c819f |
* the relationship handle:
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* 3.4
|
|
Packit |
1c819f |
* A new PG object can only be registered by referencing
|
|
Packit |
1c819f |
* its associated iSCSI Storage Node or Portal object.
|
|
Packit |
1c819f |
* A pre-existing PG object can be modified or queried
|
|
Packit |
1c819f |
* by using its Portal Group Index as message key, or
|
|
Packit |
1c819f |
* by referencing its associated iSCSI Storage Node or
|
|
Packit |
1c819f |
* Portal object.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* Implementation note: isns_db_create_pg_relation
|
|
Packit |
1c819f |
* checks whether the referenced node and portal exist,
|
|
Packit |
1c819f |
* and belong to the same entity as the PG. If this is
|
|
Packit |
1c819f |
* not the case, NULL is returned, and no relation is
|
|
Packit |
1c819f |
* defined.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
for (i = 0; i < list->iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *obj = list->iol_data[i];
|
|
Packit |
1c819f |
isns_object_template_t *tmpl;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = obj->ie_template;
|
|
Packit |
1c819f |
if (tmpl->iot_build_relation && !obj->ie_relation
|
|
Packit |
1c819f |
&& !tmpl->iot_build_relation(db, obj, list)) {
|
|
Packit |
1c819f |
isns_debug_protocol("Unable to build relation for new %s\n",
|
|
Packit |
1c819f |
tmpl->iot_name);
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < list->iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *obj = list->iol_data[i];
|
|
Packit |
1c819f |
isns_object_template_t *tmpl;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = obj->ie_template;
|
|
Packit |
1c819f |
if (key_obj != obj && !obj->ie_container) {
|
|
Packit |
1c819f |
if (!isns_object_attach(obj, key_obj)) {
|
|
Packit |
1c819f |
/* This should not fail any longer */
|
|
Packit |
1c819f |
isns_debug_protocol("Unable to attach %s %u to %s\n",
|
|
Packit |
1c819f |
tmpl->iot_name, obj->ie_index,
|
|
Packit |
1c819f |
key_obj->ie_template->iot_name);
|
|
Packit |
1c819f |
return ISNS_INVALID_REGISTRATION;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (obj->ie_state != ISNS_OBJECT_STATE_MATURE)
|
|
Packit |
1c819f |
isns_db_insert(db, obj);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Process a registration
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_process_registration(isns_server_t *srv, isns_simple_t *call, isns_simple_t **result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
|
|
Packit |
1c819f |
isns_simple_t *reply = NULL;
|
|
Packit |
1c819f |
isns_object_t *key_obj = NULL;
|
|
Packit |
1c819f |
isns_db_t *db = srv->is_db;
|
|
Packit |
1c819f |
int status;
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.1
|
|
Packit |
1c819f |
* For messages that change the contents of the iSNS database,
|
|
Packit |
1c819f |
* the iSNS server MUST verify that the Source Attribute
|
|
Packit |
1c819f |
* identifies either a Control Node or a Storage Node that is
|
|
Packit |
1c819f |
* a part of the Network Entity containing the added, deleted,
|
|
Packit |
1c819f |
* or modified objects.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* This check happens in isns_registration_get_key by calling
|
|
Packit |
1c819f |
* isns_policy_validate_object_access.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Get the key object (usually a Network Entity) */
|
|
Packit |
1c819f |
status = isns_registration_get_key(call, db, &key_obj);
|
|
Packit |
1c819f |
if (status)
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Get the objects to register */
|
|
Packit |
1c819f |
status = isns_registration_get_objects(call, db, key_obj, &objects);
|
|
Packit |
1c819f |
if (status != ISNS_SUCCESS)
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* We parsed the request alright; all semantic checks passed.
|
|
Packit |
1c819f |
* Now insert the modified/new objects.
|
|
Packit |
1c819f |
* We do this in two passes, by first committing all nodes and
|
|
Packit |
1c819f |
* portals, and then committing the portal groups.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
status = isns_commit_registration(db, key_obj, &objects);
|
|
Packit |
1c819f |
if (status != ISNS_SUCCESS)
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* The client may have registered a bunch of storage nodes,
|
|
Packit |
1c819f |
* and created an entity in the process. However, there's the
|
|
Packit |
1c819f |
* odd chance that the source node name it used was not
|
|
Packit |
1c819f |
* registered. However, we need to be able to later find
|
|
Packit |
1c819f |
* the entity it registered based on its source name.
|
|
Packit |
1c819f |
* So we implicitly create a dummy storage node with the given
|
|
Packit |
1c819f |
* source name and attach it.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
#if 1
|
|
Packit |
1c819f |
if (ISNS_IS_ENTITY(key_obj)
|
|
Packit |
1c819f |
&& !isns_source_set_node(call->is_source, db)) {
|
|
Packit |
1c819f |
isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
|
|
Packit |
1c819f |
isns_source_t *source = call->is_source;
|
|
Packit |
1c819f |
isns_object_t *obj;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_append_attr(&attrs, isns_source_attr(source));
|
|
Packit |
1c819f |
isns_attr_list_append_uint32(&attrs,
|
|
Packit |
1c819f |
ISNS_TAG_ISCSI_NODE_TYPE,
|
|
Packit |
1c819f |
0);
|
|
Packit |
1c819f |
obj = isns_create_object(&isns_iscsi_node_template,
|
|
Packit |
1c819f |
&attrs, key_obj);
|
|
Packit |
1c819f |
if (obj) {
|
|
Packit |
1c819f |
isns_db_insert(db, obj);
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
isns_warning("Unable to create dummy storage node "
|
|
Packit |
1c819f |
"for source %s\n",
|
|
Packit |
1c819f |
isns_source_name(source));
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
isns_attr_list_destroy(&attrs);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
#endif
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.1
|
|
Packit |
1c819f |
* New PG objects are registered when an associated Portal or
|
|
Packit |
1c819f |
* iSCSI Node object is registered. An explicit PG object
|
|
Packit |
1c819f |
* registration MAY follow a Portal or iSCSI Node object
|
|
Packit |
1c819f |
* registration in a DevAttrReg message.
|
|
Packit |
1c819f |
* [...]
|
|
Packit |
1c819f |
* If the PGT value is not included in the Storage Node or
|
|
Packit |
1c819f |
* Portal object registration, and if a PGT value was not
|
|
Packit |
1c819f |
* previously registered for the relationship, then the PGT for
|
|
Packit |
1c819f |
* the corresponding PG object SHALL be registered with a value
|
|
Packit |
1c819f |
* of 0x00000001.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
isns_create_registration_pgs(db, &objects);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Success: create a new registration message, and
|
|
Packit |
1c819f |
* send it in our reply. */
|
|
Packit |
1c819f |
reply = __isns_create_registration(srv->is_source, key_obj);
|
|
Packit |
1c819f |
if (reply == NULL) {
|
|
Packit |
1c819f |
status = ISNS_INTERNAL_ERROR;
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* If the key object was modified (or created)
|
|
Packit |
1c819f |
* include it in the response.
|
|
Packit |
1c819f |
* We really ought to restrict ourselves to the
|
|
Packit |
1c819f |
* key attrs plus those that were modified by this
|
|
Packit |
1c819f |
* registration. But right now have no way of
|
|
Packit |
1c819f |
* finding out.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (key_obj->ie_flags & ISNS_OBJECT_DIRTY)
|
|
Packit |
1c819f |
isns_registration_add_object(reply, key_obj);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < objects.iol_count; ++i) {
|
|
Packit |
1c819f |
isns_registration_add_object(reply,
|
|
Packit |
1c819f |
objects.iol_data[i]);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
done:
|
|
Packit |
1c819f |
isns_object_list_destroy(&objects);
|
|
Packit |
1c819f |
isns_object_release(key_obj);
|
|
Packit |
1c819f |
*result = reply;
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Extract the list of objects from the DevAttrReg response
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_registration_response_get_objects(isns_simple_t *reg,
|
|
Packit |
1c819f |
isns_object_list_t *result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return isns_simple_response_get_objects(reg, result);
|
|
Packit |
1c819f |
}
|