|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Handle iSNS Device Attribute Query
|
|
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 "config.h"
|
|
Packit |
1c819f |
#include <libisns/isns.h>
|
|
Packit |
1c819f |
#include <libisns/attrs.h>
|
|
Packit |
1c819f |
#include <libisns/message.h>
|
|
Packit |
1c819f |
#include "security.h"
|
|
Packit |
1c819f |
#include "objects.h"
|
|
Packit |
1c819f |
#include "db.h"
|
|
Packit |
1c819f |
#include <libisns/util.h>
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Create a query, and set the source name
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static isns_simple_t *
|
|
Packit |
1c819f |
__isns_create_query(isns_source_t *source, const isns_attr_list_t *key)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return isns_simple_create(ISNS_DEVICE_ATTRIBUTE_QUERY, source, key);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_simple_t *
|
|
Packit |
1c819f |
isns_create_query(isns_client_t *clnt, const isns_attr_list_t *key)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return __isns_create_query(clnt->ic_source, key);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_simple_t *
|
|
Packit |
1c819f |
isns_create_query2(isns_client_t *clnt, const isns_attr_list_t *key, isns_source_t *source)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return __isns_create_query(source?: clnt->ic_source, key);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_query_request_attr_tag(isns_simple_t *qry, uint32_t tag)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_attr_list_append_nil(&qry->is_operating_attrs, tag);
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_query_request_attr(isns_simple_t *qry, isns_attr_t *attr)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
if (!ISNS_ATTR_IS_NIL(attr)) {
|
|
Packit |
1c819f |
isns_error("Query operating attribute must be NIL\n");
|
|
Packit |
1c819f |
return ISNS_INVALID_QUERY;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
isns_attr_list_append_attr(&qry->is_operating_attrs, attr);
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static unsigned int
|
|
Packit |
1c819f |
isns_query_get_requested_types(const isns_attr_list_t *attrs)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
unsigned int i, mask = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < attrs->ial_count; ++i) {
|
|
Packit |
1c819f |
uint32_t tag = attrs->ial_data[i]->ia_tag_id;
|
|
Packit |
1c819f |
isns_object_template_t *tmpl;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = isns_object_template_find(tag);
|
|
Packit |
1c819f |
/* Ignore unknown tags */
|
|
Packit |
1c819f |
if (tmpl == NULL)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
mask |= 1 << tmpl->iot_handle;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
return mask;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Get the list of objects matching this query
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
isns_query_get_objects(isns_simple_t *qry, isns_db_t *db, isns_object_list_t *result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_scope_t *scope = NULL;
|
|
Packit |
1c819f |
isns_object_list_t matching = ISNS_OBJECT_LIST_INIT;
|
|
Packit |
1c819f |
isns_attr_list_t *keys = &qry->is_message_attrs;
|
|
Packit |
1c819f |
isns_object_template_t *query_type = NULL;
|
|
Packit |
1c819f |
unsigned int i, qry_mask = 0;
|
|
Packit |
1c819f |
int status;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* 5.6.5.2
|
|
Packit |
1c819f |
* If multiple attributes are used as the Message Key, then they
|
|
Packit |
1c819f |
* MUST all be from the same object type (e.g., IP address and
|
|
Packit |
1c819f |
* TCP/UDP Port are attributes of the Portal object type).
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
for (i = 0; i < keys->ial_count; ++i) {
|
|
Packit |
1c819f |
isns_object_template_t *tmpl;
|
|
Packit |
1c819f |
uint32_t tag = keys->ial_data[i]->ia_tag_id;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = isns_object_template_for_tag(tag);
|
|
Packit |
1c819f |
if (tmpl == NULL)
|
|
Packit |
1c819f |
return ISNS_ATTRIBUTE_NOT_IMPLEMENTED;
|
|
Packit |
1c819f |
if (query_type == NULL)
|
|
Packit |
1c819f |
query_type = tmpl;
|
|
Packit |
1c819f |
else if (tmpl != query_type)
|
|
Packit |
1c819f |
return ISNS_INVALID_QUERY;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.2
|
|
Packit |
1c819f |
* An empty Message Key field indicates the query is scoped to
|
|
Packit |
1c819f |
* the entire database accessible by the source Node.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (keys->ial_count == 0) {
|
|
Packit |
1c819f |
query_type = &isns_entity_template;
|
|
Packit |
1c819f |
keys = NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Policy: check whether the client is allowed to
|
|
Packit |
1c819f |
* query this type of object. */
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_type(qry->is_policy,
|
|
Packit |
1c819f |
query_type, qry->is_function))
|
|
Packit |
1c819f |
return ISNS_SOURCE_UNAUTHORIZED;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* No scope means that the source is not part of
|
|
Packit |
1c819f |
* any discovery domain, and there's no default DD.
|
|
Packit |
1c819f |
* Just return an empty reply. */
|
|
Packit |
1c819f |
scope = isns_scope_for_call(db, qry);
|
|
Packit |
1c819f |
if (scope == NULL)
|
|
Packit |
1c819f |
return ISNS_SUCCESS;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
status = isns_scope_gang_lookup(scope, query_type, keys, &matching);
|
|
Packit |
1c819f |
if (status != ISNS_SUCCESS)
|
|
Packit |
1c819f |
goto out;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Extract the mask of requested objects */
|
|
Packit |
1c819f |
qry_mask = isns_query_get_requested_types(&qry->is_operating_attrs);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.6.5.2
|
|
Packit |
1c819f |
* The DevAttrQry response message returns attributes of objects
|
|
Packit |
1c819f |
* listed in the Operating Attributes that are related to the
|
|
Packit |
1c819f |
* Message Key of the original DevAttrQry message.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
for (i = 0; i < matching.iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *obj = matching.iol_data[i];
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!isns_policy_validate_object_access(qry->is_policy,
|
|
Packit |
1c819f |
qry->is_source, obj,
|
|
Packit |
1c819f |
qry->is_function))
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (obj->ie_container)
|
|
Packit |
1c819f |
isns_object_list_append(result, obj->ie_container);
|
|
Packit |
1c819f |
isns_object_list_append(result, obj);
|
|
Packit |
1c819f |
isns_scope_get_related(scope, obj, qry_mask, result);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
out:
|
|
Packit |
1c819f |
isns_object_list_destroy(&matching);
|
|
Packit |
1c819f |
isns_scope_release(scope);
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Create a Query Response
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static isns_simple_t *
|
|
Packit |
1c819f |
isns_create_query_response(isns_server_t *srv,
|
|
Packit |
1c819f |
const isns_simple_t *qry, const isns_object_list_t *objects)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
const isns_attr_list_t *req_attrs = NULL;
|
|
Packit |
1c819f |
isns_simple_t *resp;
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
resp = __isns_create_query(srv->is_source, &qry->is_message_attrs);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* 5.7.5.2.
|
|
Packit |
1c819f |
* If no Operating Attributes are included in the original
|
|
Packit |
1c819f |
* query, then all Operating Attributes SHALL be returned
|
|
Packit |
1c819f |
* in the response.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (qry->is_operating_attrs.ial_count != 0)
|
|
Packit |
1c819f |
req_attrs = &qry->is_operating_attrs;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < objects->iol_count; ++i) {
|
|
Packit |
1c819f |
isns_object_t *obj = objects->iol_data[i];
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (obj->ie_rebuild)
|
|
Packit |
1c819f |
obj->ie_rebuild(obj, srv->is_db);
|
|
Packit |
1c819f |
isns_object_get_attrlist(obj,
|
|
Packit |
1c819f |
&resp->is_operating_attrs,
|
|
Packit |
1c819f |
req_attrs);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
return resp;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_process_query(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_db_t *db = srv->is_db;
|
|
Packit |
1c819f |
int status;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Get the objects matching the query */
|
|
Packit |
1c819f |
status = isns_query_get_objects(call, db, &objects);
|
|
Packit |
1c819f |
if (status != ISNS_SUCCESS)
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Success: build the response */
|
|
Packit |
1c819f |
reply = isns_create_query_response(srv, call, &objects);
|
|
Packit |
1c819f |
if (reply == NULL) {
|
|
Packit |
1c819f |
status = ISNS_INTERNAL_ERROR;
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* There's nothing in the spec that tells us what to
|
|
Packit |
1c819f |
* return if the query matches no object.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (objects.iol_count == 0) {
|
|
Packit |
1c819f |
status = ISNS_NO_SUCH_ENTRY;
|
|
Packit |
1c819f |
goto done;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
done:
|
|
Packit |
1c819f |
isns_object_list_destroy(&objects);
|
|
Packit |
1c819f |
*result = reply;
|
|
Packit |
1c819f |
return status;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Parse the list of objects in a query response
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_query_response_get_objects(isns_simple_t *qry,
|
|
Packit |
1c819f |
isns_object_list_t *result)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
return isns_simple_response_get_objects(qry, result);
|
|
Packit |
1c819f |
}
|