|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Helper functions to represent iSNS objects as text,
|
|
Packit |
1c819f |
* and/or to parse objects represented in textual form.
|
|
Packit |
1c819f |
* These functions can be used by command line utilities
|
|
Packit |
1c819f |
* such as isnsadm, as well as applications like iscsid
|
|
Packit |
1c819f |
* or stgtd when talking to the iSNS discovery daemon.
|
|
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 <stdio.h>
|
|
Packit |
1c819f |
#include <string.h>
|
|
Packit |
1c819f |
#include <unistd.h>
|
|
Packit |
1c819f |
#include <ctype.h>
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
#include "config.h"
|
|
Packit |
1c819f |
#include <libisns/isns.h>
|
|
Packit |
1c819f |
#include <libisns/util.h>
|
|
Packit |
1c819f |
#include "vendor.h"
|
|
Packit |
1c819f |
#include <libisns/attrs.h>
|
|
Packit |
1c819f |
#include "security.h"
|
|
Packit |
1c819f |
#include "objects.h"
|
|
Packit |
1c819f |
#include <libisns/paths.h>
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
#define MAX_ALIASES 4
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
struct isns_tag_prefix {
|
|
Packit |
1c819f |
const char * name;
|
|
Packit |
1c819f |
unsigned int name_len;
|
|
Packit |
1c819f |
isns_object_template_t *context;
|
|
Packit |
1c819f |
};
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
struct tag_name {
|
|
Packit |
1c819f |
const char * name;
|
|
Packit |
1c819f |
uint32_t tag;
|
|
Packit |
1c819f |
struct isns_tag_prefix *prefix;
|
|
Packit |
1c819f |
const char * alias[MAX_ALIASES];
|
|
Packit |
1c819f |
};
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static struct isns_tag_prefix all_prefixes[__ISNS_OBJECT_TYPE_MAX] = {
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_ENTITY] = { "entity-", 7, &isns_entity_template },
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_NODE] = { "iscsi-", 6, &isns_iscsi_node_template },
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_PORTAL] = { "portal-", 7, &isns_portal_template },
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_PG] = { "pg-", 3, &isns_iscsi_pg_template },
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_DD] = { "dd-", 3, &isns_dd_template },
|
|
Packit |
1c819f |
[ISNS_OBJECT_TYPE_POLICY] = { "policy-", 7, &isns_policy_template },
|
|
Packit |
1c819f |
};
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static struct tag_name all_attrs[] = {
|
|
Packit |
1c819f |
{ "id", ISNS_TAG_ENTITY_IDENTIFIER,
|
|
Packit |
1c819f |
.alias = { "eid", },
|
|
Packit |
1c819f |
},
|
|
Packit |
1c819f |
{ "prot", ISNS_TAG_ENTITY_PROTOCOL },
|
|
Packit |
1c819f |
{ "idx", ISNS_TAG_ENTITY_INDEX },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ "name", ISNS_TAG_ISCSI_NAME },
|
|
Packit |
1c819f |
{ "node-type", ISNS_TAG_ISCSI_NODE_TYPE },
|
|
Packit |
1c819f |
{ "alias", ISNS_TAG_ISCSI_ALIAS },
|
|
Packit |
1c819f |
{ "authmethod", ISNS_TAG_ISCSI_AUTHMETHOD },
|
|
Packit |
1c819f |
{ "idx", ISNS_TAG_ISCSI_NODE_INDEX },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ "addr", ISNS_TAG_PORTAL_IP_ADDRESS },
|
|
Packit |
1c819f |
{ "port", ISNS_TAG_PORTAL_TCP_UDP_PORT },
|
|
Packit |
1c819f |
{ "name", ISNS_TAG_PORTAL_SYMBOLIC_NAME },
|
|
Packit |
1c819f |
{ "esi-port", ISNS_TAG_ESI_PORT },
|
|
Packit |
1c819f |
{ "esi-interval", ISNS_TAG_ESI_INTERVAL },
|
|
Packit |
1c819f |
{ "scn-port", ISNS_TAG_SCN_PORT },
|
|
Packit |
1c819f |
{ "idx", ISNS_TAG_PORTAL_INDEX },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ "name", ISNS_TAG_PG_ISCSI_NAME },
|
|
Packit |
1c819f |
{ "addr", ISNS_TAG_PG_PORTAL_IP_ADDR },
|
|
Packit |
1c819f |
{ "port", ISNS_TAG_PG_PORTAL_TCP_UDP_PORT },
|
|
Packit |
1c819f |
{ "tag", ISNS_TAG_PG_TAG },
|
|
Packit |
1c819f |
{ "pgt", ISNS_TAG_PG_TAG },
|
|
Packit |
1c819f |
{ "idx", ISNS_TAG_PG_INDEX },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ "id", ISNS_TAG_DD_ID },
|
|
Packit |
1c819f |
{ "name", ISNS_TAG_DD_SYMBOLIC_NAME },
|
|
Packit |
1c819f |
{ "member-name", ISNS_TAG_DD_MEMBER_ISCSI_NAME },
|
|
Packit |
1c819f |
{ "member-iscsi-idx", ISNS_TAG_DD_MEMBER_ISCSI_INDEX },
|
|
Packit |
1c819f |
{ "member-fc-name", ISNS_TAG_DD_MEMBER_FC_PORT_NAME },
|
|
Packit |
1c819f |
{ "member-portal-idx", ISNS_TAG_DD_MEMBER_PORTAL_INDEX },
|
|
Packit |
1c819f |
{ "member-addr", ISNS_TAG_DD_MEMBER_PORTAL_IP_ADDR },
|
|
Packit |
1c819f |
{ "member-port", ISNS_TAG_DD_MEMBER_PORTAL_TCP_UDP_PORT },
|
|
Packit |
1c819f |
{ "features", ISNS_TAG_DD_FEATURES },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ "name", OPENISNS_TAG_POLICY_SPI,
|
|
Packit |
1c819f |
.alias = { "spi" },
|
|
Packit |
1c819f |
},
|
|
Packit |
1c819f |
{ "key", OPENISNS_TAG_POLICY_KEY },
|
|
Packit |
1c819f |
{ "entity", OPENISNS_TAG_POLICY_ENTITY },
|
|
Packit |
1c819f |
{ "object-type", OPENISNS_TAG_POLICY_OBJECT_TYPE },
|
|
Packit |
1c819f |
{ "node-type", OPENISNS_TAG_POLICY_NODE_TYPE },
|
|
Packit |
1c819f |
{ "node-name", OPENISNS_TAG_POLICY_NODE_NAME },
|
|
Packit |
1c819f |
{ "functions", OPENISNS_TAG_POLICY_FUNCTIONS },
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
{ NULL }
|
|
Packit |
1c819f |
};
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Initialize tag array
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static void
|
|
Packit |
1c819f |
init_tags(void)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct tag_name *t;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (t = all_attrs; t->name; ++t) {
|
|
Packit |
1c819f |
isns_object_template_t *tmpl;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = isns_object_template_for_tag(t->tag);
|
|
Packit |
1c819f |
if (tmpl == NULL)
|
|
Packit |
1c819f |
isns_fatal("Bug: cannot find object type for tag %s\n",
|
|
Packit |
1c819f |
t->name);
|
|
Packit |
1c819f |
t->prefix = &all_prefixes[tmpl->iot_handle];
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Match prefix
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static struct isns_tag_prefix *
|
|
Packit |
1c819f |
find_prefix(const char *name)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct isns_tag_prefix *p;
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0, p = all_prefixes; i < __ISNS_OBJECT_TYPE_MAX; ++i, ++p) {
|
|
Packit |
1c819f |
if (p->name && !strncmp(name, p->name, p->name_len))
|
|
Packit |
1c819f |
return p;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
return NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Look up the tag for a given attribute name.
|
|
Packit |
1c819f |
* By default, attr names come with a disambiguating
|
|
Packit |
1c819f |
* prefix that defines the object type the attribute applies
|
|
Packit |
1c819f |
* to, such as "entity-" or "portal-". Once a context has
|
|
Packit |
1c819f |
* been established (ie we know the object type subsequent
|
|
Packit |
1c819f |
* attributes apply to), specifying the prefix is optional.
|
|
Packit |
1c819f |
*
|
|
Packit |
1c819f |
* For instance, in a portal context, "addr=10.1.1.1 port=616 name=foo"
|
|
Packit |
1c819f |
* specifies three portal related attributes. Whereas in a portal
|
|
Packit |
1c819f |
* group context, the same string would specify three portal group
|
|
Packit |
1c819f |
* related attributes. To disambiguate, the first attribute in
|
|
Packit |
1c819f |
* this list should be prefixed by "portal-" or "pg-", respectively.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
static uint32_t
|
|
Packit |
1c819f |
tag_by_name(const char *name, struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
const char *orig_name = name;
|
|
Packit |
1c819f |
unsigned int nmatch = 0, i;
|
|
Packit |
1c819f |
struct tag_name *t, *match[8];
|
|
Packit |
1c819f |
struct isns_tag_prefix *specific = NULL;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (all_attrs[0].prefix == NULL)
|
|
Packit |
1c819f |
init_tags();
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
specific = find_prefix(name);
|
|
Packit |
1c819f |
if (specific != NULL) {
|
|
Packit |
1c819f |
if (st->prefix
|
|
Packit |
1c819f |
&& st->prefix != specific
|
|
Packit |
1c819f |
&& !st->multi_type_permitted) {
|
|
Packit |
1c819f |
isns_error("Cannot mix attributes of different types\n");
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
name += specific->name_len;
|
|
Packit |
1c819f |
st->prefix = specific;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (t = all_attrs; t->name; ++t) {
|
|
Packit |
1c819f |
if (specific && t->prefix != specific)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
if (!st->multi_type_permitted
|
|
Packit |
1c819f |
&& st->prefix && t->prefix != st->prefix)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
if (!strcmp(name, t->name))
|
|
Packit |
1c819f |
goto match;
|
|
Packit |
1c819f |
for (i = 0; i < MAX_ALIASES && t->alias[i]; ++i) {
|
|
Packit |
1c819f |
if (!strcmp(name, t->alias[i]))
|
|
Packit |
1c819f |
goto match;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
match:
|
|
Packit |
1c819f |
if (nmatch < 8)
|
|
Packit |
1c819f |
match[nmatch++] = t;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (nmatch > 1) {
|
|
Packit |
1c819f |
char conflict[128];
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
conflict[0] = '\0';
|
|
Packit |
1c819f |
for (i = 0; i < nmatch; ++i) {
|
|
Packit |
1c819f |
if (i)
|
|
Packit |
1c819f |
strcat(conflict, ", ");
|
|
Packit |
1c819f |
t = match[i];
|
|
Packit |
1c819f |
strcat(conflict, t->prefix->name);
|
|
Packit |
1c819f |
strcat(conflict, t->name);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
isns_error("tag name \"%s\" not unique in this context "
|
|
Packit |
1c819f |
"(could be one of %s)\n",
|
|
Packit |
1c819f |
orig_name, conflict);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (nmatch == 0) {
|
|
Packit |
1c819f |
isns_error("tag name \"%s\" not known in this context\n",
|
|
Packit |
1c819f |
orig_name);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
st->prefix = match[0]->prefix;
|
|
Packit |
1c819f |
return match[0]->tag;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static const char *
|
|
Packit |
1c819f |
name_by_tag(uint32_t tag, struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct tag_name *t;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (t = all_attrs; t->name; ++t) {
|
|
Packit |
1c819f |
if (st->prefix && t->prefix != st->prefix)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
if (t->tag == tag)
|
|
Packit |
1c819f |
return t->name;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
return NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
static int
|
|
Packit |
1c819f |
parse_one_attr(const char *name, const char *value,
|
|
Packit |
1c819f |
isns_attr_list_t *attrs,
|
|
Packit |
1c819f |
struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_attr_t *attr;
|
|
Packit |
1c819f |
uint32_t tag;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Special case: "portal=<address:port>" is translated to
|
|
Packit |
1c819f |
* addr=<address> port=<port>
|
|
Packit |
1c819f |
* If no context has been set, assume portal context.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
if (!strcasecmp(name, "portal")) {
|
|
Packit |
1c819f |
isns_portal_info_t portal_info;
|
|
Packit |
1c819f |
uint32_t addr_tag, port_tag;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (st->prefix == NULL) {
|
|
Packit |
1c819f |
addr_tag = tag_by_name("portal-addr", st);
|
|
Packit |
1c819f |
port_tag = tag_by_name("portal-port", st);
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
addr_tag = tag_by_name("addr", st);
|
|
Packit |
1c819f |
port_tag = tag_by_name("port", st);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!addr_tag || !port_tag) {
|
|
Packit |
1c819f |
isns_error("portal=... not supported in this context\n");
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
if (value == NULL) {
|
|
Packit |
1c819f |
isns_attr_list_append_nil(attrs, addr_tag);
|
|
Packit |
1c819f |
isns_attr_list_append_nil(attrs, port_tag);
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
if (!isns_portal_parse(&portal_info, value, st->default_port))
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
isns_portal_to_attr_list(&portal_info, addr_tag, port_tag, attrs);
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!(tag = tag_by_name(name, st)))
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/* Special handling for key objects */
|
|
Packit |
1c819f |
if (tag == OPENISNS_TAG_POLICY_KEY) {
|
|
Packit |
1c819f |
if (!value || !strcasecmp(value, "gen")) {
|
|
Packit |
1c819f |
if (st->generate_key == NULL) {
|
|
Packit |
1c819f |
isns_error("Key generation not supported in this context\n");
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
attr = st->generate_key();
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
if (st->load_key == NULL) {
|
|
Packit |
1c819f |
isns_error("Policy-key attribute not supported in this context\n");
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
attr = st->load_key(value);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
goto append_attr;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (value == NULL) {
|
|
Packit |
1c819f |
isns_attr_list_append_nil(attrs, tag);
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
attr = isns_attr_from_string(tag, value);
|
|
Packit |
1c819f |
if (!attr)
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
append_attr:
|
|
Packit |
1c819f |
isns_attr_list_append_attr(attrs, attr);
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
void
|
|
Packit |
1c819f |
isns_attr_list_parser_init(struct isns_attr_list_parser *st,
|
|
Packit |
1c819f |
isns_object_template_t *tmpl)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
if (all_attrs[0].prefix == NULL)
|
|
Packit |
1c819f |
init_tags();
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
memset(st, 0, sizeof(*st));
|
|
Packit |
1c819f |
if (tmpl)
|
|
Packit |
1c819f |
st->prefix = &all_prefixes[tmpl->iot_handle];
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_attr_list_split(char *line, char **argv, unsigned int argc_max)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
char *src = line;
|
|
Packit |
1c819f |
unsigned int argc = 0, quoted = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!line)
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
while (1) {
|
|
Packit |
1c819f |
char *dst;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
while (isspace(*src))
|
|
Packit |
1c819f |
++src;
|
|
Packit |
1c819f |
if (!*src)
|
|
Packit |
1c819f |
break;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
argv[argc] = dst = src;
|
|
Packit |
1c819f |
while (*src) {
|
|
Packit |
1c819f |
char cc = *src++;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (cc == '"') {
|
|
Packit |
1c819f |
quoted = !quoted;
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
if (!quoted && isspace(cc)) {
|
|
Packit |
1c819f |
*dst = '\0';
|
|
Packit |
1c819f |
break;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
*dst++ = cc;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (quoted) {
|
|
Packit |
1c819f |
isns_error("%s: Unterminated quoted string: \"%s\"\n",
|
|
Packit |
1c819f |
__FUNCTION__, argv[argc]);
|
|
Packit |
1c819f |
return -1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
argc++;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return argc;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_parse_attrs(unsigned int argc, char **argv,
|
|
Packit |
1c819f |
isns_attr_list_t *attrs,
|
|
Packit |
1c819f |
struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < argc; ++i) {
|
|
Packit |
1c819f |
char *name, *value;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
name = argv[i];
|
|
Packit |
1c819f |
if ((value = strchr(name, '=')) != NULL)
|
|
Packit |
1c819f |
*value++ = '\0';
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!value && !st->nil_permitted) {
|
|
Packit |
1c819f |
isns_error("Missing value for atribute %s\n", name);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (!parse_one_attr(name, value, attrs, st)) {
|
|
Packit |
1c819f |
isns_error("Unable to parse %s=%s\n", name, value);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
/*
|
|
Packit |
1c819f |
* Query strings may contain a mix of query keys (foo=bar),
|
|
Packit |
1c819f |
* and requested attributes (?foo). The former are used by
|
|
Packit |
1c819f |
* the server in its object search, whereas the latter instruct
|
|
Packit |
1c819f |
* it which attributes to return.
|
|
Packit |
1c819f |
*/
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_parse_query_attrs(unsigned int argc, char **argv,
|
|
Packit |
1c819f |
isns_attr_list_t *keys,
|
|
Packit |
1c819f |
isns_attr_list_t *requested_attrs,
|
|
Packit |
1c819f |
struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct isns_attr_list_parser query_state;
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
query_state = *st;
|
|
Packit |
1c819f |
query_state.multi_type_permitted = 1;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < argc; ++i) {
|
|
Packit |
1c819f |
char *name, *value;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
name = argv[i];
|
|
Packit |
1c819f |
if ((value = strchr(name, '=')) != NULL)
|
|
Packit |
1c819f |
*value++ = '\0';
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (name[0] == '?') {
|
|
Packit |
1c819f |
uint32_t tag;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (value) {
|
|
Packit |
1c819f |
isns_error("No value allowed for query attribute %s\n",
|
|
Packit |
1c819f |
name);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if ((tag = tag_by_name(name + 1, &query_state)) != 0) {
|
|
Packit |
1c819f |
isns_attr_list_append_nil(requested_attrs, tag);
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
} else {
|
|
Packit |
1c819f |
if (!value && !st->nil_permitted) {
|
|
Packit |
1c819f |
isns_error("Missing value for atribute %s\n", name);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (parse_one_attr(name, value, keys, st))
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_error("Unable to parse %s=%s\n", name, value);
|
|
Packit |
1c819f |
return 0;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
return 1;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
void
|
|
Packit |
1c819f |
isns_attr_list_parser_help(struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
isns_object_template_t *tmpl, *current = NULL;
|
|
Packit |
1c819f |
struct tag_name *t;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (all_attrs[0].prefix == NULL)
|
|
Packit |
1c819f |
init_tags();
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (t = all_attrs; t->name; ++t) {
|
|
Packit |
1c819f |
const isns_tag_type_t *tag_type;
|
|
Packit |
1c819f |
char namebuf[64];
|
|
Packit |
1c819f |
const char *help;
|
|
Packit |
1c819f |
unsigned int i;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (st && !st->multi_type_permitted
|
|
Packit |
1c819f |
&& st->prefix && t->prefix != st->prefix)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tmpl = t->prefix->context;
|
|
Packit |
1c819f |
if (tmpl != current) {
|
|
Packit |
1c819f |
printf("\nAttributes for object type %s; using prefix %s\n",
|
|
Packit |
1c819f |
tmpl->iot_name, t->prefix->name);
|
|
Packit |
1c819f |
current = tmpl;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
snprintf(namebuf, sizeof(namebuf), "%s%s", t->prefix->name, t->name);
|
|
Packit |
1c819f |
printf(" %-20s ", namebuf);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
tag_type = isns_tag_type_by_id(t->tag);
|
|
Packit |
1c819f |
if (tag_type == NULL) {
|
|
Packit |
1c819f |
printf("Unknown\n");
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
printf("%s (%s", tag_type->it_name,
|
|
Packit |
1c819f |
tag_type->it_type->it_name);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (tag_type->it_readonly)
|
|
Packit |
1c819f |
printf("; readonly");
|
|
Packit |
1c819f |
if (tag_type->it_multiple)
|
|
Packit |
1c819f |
printf("; multiple instances");
|
|
Packit |
1c819f |
printf(")");
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
help = NULL;
|
|
Packit |
1c819f |
if (t->tag == OPENISNS_TAG_POLICY_KEY) {
|
|
Packit |
1c819f |
help = "name of key file, or \"gen\" for key generation";
|
|
Packit |
1c819f |
} else
|
|
Packit |
1c819f |
if (tag_type->it_help)
|
|
Packit |
1c819f |
help = tag_type->it_help();
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (help) {
|
|
Packit |
1c819f |
if (strlen(help) < 20)
|
|
Packit |
1c819f |
printf(" [%s]", help);
|
|
Packit |
1c819f |
else
|
|
Packit |
1c819f |
printf("\n%25s[%s]", "", help);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
printf("\n");
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
if (t->alias[0]) {
|
|
Packit |
1c819f |
printf("%25sAliases:", "");
|
|
Packit |
1c819f |
for (i = 0; i < MAX_ALIASES && t->alias[i]; ++i)
|
|
Packit |
1c819f |
printf(" %s", t->alias[i]);
|
|
Packit |
1c819f |
printf("\n");
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_object_template_t *
|
|
Packit |
1c819f |
isns_attr_list_parser_context(const struct isns_attr_list_parser *st)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
if (st->prefix)
|
|
Packit |
1c819f |
return st->prefix->context;
|
|
Packit |
1c819f |
return NULL;
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
int
|
|
Packit |
1c819f |
isns_print_attrs(isns_object_t *obj, char **argv, unsigned int argsmax)
|
|
Packit |
1c819f |
{
|
|
Packit |
1c819f |
struct isns_attr_list_parser st;
|
|
Packit |
1c819f |
unsigned int i, argc = 0;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
isns_attr_list_parser_init(&st, obj->ie_template);
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
for (i = 0; i < obj->ie_attrs.ial_count; ++i) {
|
|
Packit |
1c819f |
isns_attr_t *attr = obj->ie_attrs.ial_data[i];
|
|
Packit |
1c819f |
char argbuf[512], value[512];
|
|
Packit |
1c819f |
const char *name;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
name = name_by_tag(attr->ia_tag_id, &st);
|
|
Packit |
1c819f |
if (name == NULL)
|
|
Packit |
1c819f |
continue;
|
|
Packit |
1c819f |
if (argc + 1 >= argsmax)
|
|
Packit |
1c819f |
break;
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
snprintf(argbuf, sizeof(argbuf), "%s%s=%s",
|
|
Packit |
1c819f |
st.prefix->name, name,
|
|
Packit |
1c819f |
isns_attr_print_value(attr, value, sizeof(value)));
|
|
Packit |
1c819f |
argv[argc++] = isns_strdup(argbuf);
|
|
Packit |
1c819f |
}
|
|
Packit |
1c819f |
|
|
Packit |
1c819f |
argv[argc] = NULL;
|
|
Packit |
1c819f |
return argc;
|
|
Packit |
1c819f |
}
|