~ubuntu-branches/ubuntu/quantal/open-iscsi/quantal-proposed

« back to all changes in this revision

Viewing changes to utils/open-isns/isnsadm.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-07-10 13:53:52 UTC
  • mfrom: (1.1.5) (4.1.15 sid)
  • Revision ID: package-import@ubuntu.com-20120710135352-8pw2po02ka51y2g2
Tags: 2.0.873-3ubuntu1
* Merge from Debian. Remaining changes: (LP: #961114, LP: #677333)
  - Add upstart job iscsi-network-interface
  - Migrate from /var/run and /lib/init/rw to /run, from /var/lock to
    /run/lock.
* Turn open-iscsi-utils into a transitional package

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * isnsadm - helper utility
 
3
 *
 
4
 * Copyright (C) 2007 Olaf Kirch <olaf.kirch@oracle.com>
 
5
 */
 
6
 
 
7
#include <getopt.h>
 
8
#include <stdlib.h>
 
9
#include <stdio.h>
 
10
#include <string.h>
 
11
#include <unistd.h>
 
12
#include <limits.h>
 
13
 
 
14
#include "isns.h"
 
15
#include "util.h"
 
16
#include "vendor.h"
 
17
#include "attrs.h"
 
18
#include "security.h"
 
19
#include "objects.h"
 
20
#include "paths.h"
 
21
#include "config.h"
 
22
 
 
23
#define ISNS_DEFAULT_PORT_INITIATOR     860
 
24
#define ISNS_DEFAULT_PORT_TARGET        3260
 
25
 
 
26
 
 
27
enum {
 
28
        DO_REGISTER = 1024,
 
29
        DO_QUERY,
 
30
        DO_QUERY_EID,
 
31
        DO_LIST,
 
32
        DO_DEREGISTER,
 
33
        DO_DD_REGISTER,
 
34
        DO_DD_DEREGISTER,
 
35
        DO_ENROLL,
 
36
        DO_EDIT_POLICY,
 
37
        DO_DELETE_POLICY,
 
38
};
 
39
 
 
40
static struct option    options[] = {
 
41
      { "help",                 no_argument,            NULL,   'h'             },
 
42
      { "config",               required_argument,      NULL,   'c'             },
 
43
      { "debug",                required_argument,      NULL,   'd'             },
 
44
      { "keyfile",              required_argument,      NULL,   'K',            },
 
45
      { "key",                  required_argument,      NULL,   'k',            },
 
46
      { "local",                no_argument,            NULL,   'l'             },
 
47
      { "control",              no_argument,            NULL,   'C'             },
 
48
      { "replace",              no_argument,            NULL,   'r'             },
 
49
      { "query",                no_argument,            NULL,   DO_QUERY        },
 
50
      { "query-eid",            no_argument,            NULL,   DO_QUERY_EID    },
 
51
      { "list",                 no_argument,            NULL,   DO_LIST         },
 
52
      { "register",             no_argument,            NULL,   DO_REGISTER     },
 
53
      { "deregister",           no_argument,            NULL,   DO_DEREGISTER   },
 
54
      { "dd-register",          no_argument,            NULL,   DO_DD_REGISTER  },
 
55
      { "dd-deregister",        no_argument,            NULL,   DO_DD_DEREGISTER},
 
56
 
 
57
      { "enroll",               no_argument,            NULL,   DO_ENROLL       },
 
58
      { "edit-policy",          no_argument,            NULL,   DO_EDIT_POLICY  },
 
59
      { "delete-policy",        no_argument,            NULL,   DO_DELETE_POLICY },
 
60
 
 
61
      { "version",              no_argument,            NULL,   'V'             },
 
62
      { NULL }
 
63
};
 
64
 
 
65
 
 
66
static const char *     opt_configfile = ISNS_DEFAULT_ISNSADM_CONFIG;
 
67
static int              opt_af = AF_UNSPEC;
 
68
static int              opt_action = 0;
 
69
static int              opt_local = 0;
 
70
static int              opt_control = 0;
 
71
static int              opt_replace = 0;
 
72
static const char *     opt_keyfile = NULL;
 
73
static char *           opt_key = NULL;
 
74
static struct sockaddr_storage opt_myaddr;
 
75
 
 
76
static void     usage(int, const char *);
 
77
 
 
78
static int      register_objects(isns_client_t *, int, char **);
 
79
static int      query_objects(isns_client_t *, int, char **);
 
80
static int      query_entity_id(isns_client_t *, int, char **);
 
81
static int      list_objects(isns_client_t *, int, char **);
 
82
static int      deregister_objects(isns_client_t *, int, char **);
 
83
static int      register_domain(isns_client_t *, int, char **);
 
84
static int      deregister_domain(isns_client_t *, int, char **);
 
85
static int      enroll_client(isns_client_t *, int, char **);
 
86
static int      edit_policy(isns_client_t *, int, char **);
 
87
 
 
88
static isns_attr_t *    load_key_callback(const char *);
 
89
static isns_attr_t *    generate_key_callback(void);
 
90
 
 
91
int
 
92
main(int argc, char **argv)
 
93
{
 
94
        isns_client_t   *clnt;
 
95
        isns_security_t *security = NULL;
 
96
        int             c, status;
 
97
 
 
98
        while ((c = getopt_long(argc, argv, "46Cc:d:hK:k:l", options, NULL)) != -1) {
 
99
                switch (c) {
 
100
                case '4':
 
101
                        opt_af = AF_INET;
 
102
                        break;
 
103
 
 
104
                case '6':
 
105
                        opt_af = AF_INET6;
 
106
                        break;
 
107
 
 
108
                case 'C':
 
109
                        opt_control = 1;
 
110
                        break;
 
111
 
 
112
                case 'c':
 
113
                        opt_configfile = optarg;
 
114
                        break;
 
115
 
 
116
                case 'd':
 
117
                        isns_enable_debugging(optarg);
 
118
                        break;
 
119
 
 
120
                case 'h':
 
121
                        usage(0, NULL);
 
122
                        break;
 
123
 
 
124
                case 'K':
 
125
                        opt_keyfile = optarg;
 
126
                        break;
 
127
 
 
128
                case 'k':
 
129
                        opt_key = optarg;
 
130
                        break;
 
131
 
 
132
                case 'l':
 
133
                        opt_local = 1;
 
134
                        break;
 
135
 
 
136
                case 'r':
 
137
                        opt_replace = 1;
 
138
                        break;
 
139
 
 
140
                case 'V':
 
141
                        printf("Open-iSNS version %s\n"
 
142
                               "Copyright (C) 2007, Olaf Kirch <olaf.kirch@oracle.com>\n",
 
143
                               OPENISNS_VERSION_STRING);
 
144
                        return 0;
 
145
 
 
146
                case DO_REGISTER:
 
147
                case DO_QUERY:
 
148
                case DO_QUERY_EID:
 
149
                case DO_LIST:
 
150
                case DO_DEREGISTER:
 
151
                case DO_DD_REGISTER:
 
152
                case DO_DD_DEREGISTER:
 
153
                case DO_ENROLL:
 
154
                case DO_EDIT_POLICY:
 
155
                case DO_DELETE_POLICY:
 
156
                        if (opt_action)
 
157
                                usage(1, "You cannot specify more than one mode\n");
 
158
                        opt_action = c;
 
159
                        break;
 
160
 
 
161
                default:
 
162
                        usage(1, "Unknown option");
 
163
                }
 
164
        }
 
165
        
 
166
        isns_read_config(opt_configfile);
 
167
 
 
168
        if (!isns_config.ic_source_name)
 
169
                usage(1, "Please specify an iSNS source name");
 
170
        if (!isns_config.ic_server_name)
 
171
                usage(1, "Please specify an iSNS server name");
 
172
        if (!opt_action)
 
173
                usage(1, "Please specify an operating mode");
 
174
 
 
175
        if (opt_control) {
 
176
                if (!isns_config.ic_security)
 
177
                        isns_fatal("Cannot use control mode, security disabled\n");
 
178
                security = isns_control_security_context(0);
 
179
                if (!security)
 
180
                        isns_fatal("Unable to create control security context\n");
 
181
 
 
182
                /* Create a networked client, using isns.control as
 
183
                 * the source name */
 
184
                clnt = isns_create_client(security, isns_config.ic_control_name);
 
185
        } else if (opt_local) {
 
186
                /* Create a local client, using isns.control as
 
187
                 * the source name */
 
188
                clnt = isns_create_local_client(security,
 
189
                                isns_config.ic_control_name);
 
190
        } else {
 
191
                /* Create a networked client, using the configured
 
192
                 * source name */
 
193
                clnt = isns_create_default_client(security);
 
194
        }
 
195
 
 
196
        if (clnt == NULL)
 
197
                return 1;
 
198
 
 
199
        /* We're an interactive app, and don't want to retry
 
200
         * forever if the server refuses us. */
 
201
        isns_socket_set_disconnect_fatal(clnt->ic_socket);
 
202
 
 
203
        /* Get the IP address we use to talk to the iSNS server */
 
204
        if (opt_myaddr.ss_family == AF_UNSPEC && !opt_local) {
 
205
                if (!isns_socket_get_local_addr(clnt->ic_socket, &opt_myaddr))
 
206
                        isns_fatal("Unable to obtain my IP address\n");
 
207
                isns_addr_set_port((struct sockaddr *) &opt_myaddr, 860);
 
208
        }
 
209
 
 
210
        argv += optind; argc -= optind;
 
211
        switch (opt_action) {
 
212
        case DO_REGISTER:
 
213
                status = register_objects(clnt, argc, argv);
 
214
                break;
 
215
 
 
216
        case DO_QUERY:
 
217
                status = query_objects(clnt, argc, argv);
 
218
                break;
 
219
 
 
220
        case DO_QUERY_EID:
 
221
                status = query_entity_id(clnt, argc, argv);
 
222
                break;
 
223
 
 
224
        case DO_LIST:
 
225
                status = list_objects(clnt, argc, argv);
 
226
                break;
 
227
 
 
228
        case DO_DEREGISTER:
 
229
                status = deregister_objects(clnt, argc, argv);
 
230
                break;
 
231
 
 
232
        case DO_DD_REGISTER:
 
233
                status = register_domain(clnt, argc, argv);
 
234
                break;
 
235
 
 
236
        case DO_DD_DEREGISTER:
 
237
                status = deregister_domain(clnt, argc, argv);
 
238
                break;
 
239
 
 
240
 
 
241
        case DO_ENROLL:
 
242
                status = enroll_client(clnt, argc, argv);
 
243
                break;
 
244
 
 
245
        case DO_EDIT_POLICY:
 
246
                status = edit_policy(clnt, argc, argv);
 
247
                break;
 
248
 
 
249
        // case DO_DELETE_POLICY:
 
250
 
 
251
        default:
 
252
                isns_fatal("Not yet implemented\n");
 
253
                status = 1; /* compiler food */
 
254
        }
 
255
 
 
256
        return status != ISNS_SUCCESS;
 
257
}
 
258
 
 
259
void
 
260
usage(int exval, const char *msg)
 
261
{
 
262
        if (msg)
 
263
                fprintf(stderr, "Error: %s\n", msg);
 
264
        fprintf(stderr,
 
265
        "Usage: isnsadm [options] --action ...\n"
 
266
        "  --config        Specify alternative config fille\n"
 
267
        "  --debug         Enable debugging (list of debug flags)\n"
 
268
        "  --keyfile       Where to store newly generated private key\n"
 
269
        "  --local         Use local Unix socket to talk to isnsd\n"
 
270
        "  --control       Assume control node identity for authentication\n"
 
271
        "  --replace       Use replace mode (--register only)\n"
 
272
        "\nThe following actions are supported:\n"
 
273
        "  --register      Register one or more objects\n"
 
274
        "  --deregister    Deregister an object (and children)\n"
 
275
        "  --query         Query iSNS server for objects\n"
 
276
        "  --list          List all objects of a given type\n"
 
277
        "  --enroll        Create a new policy object for a client\n"
 
278
        "  --edit-policy   Edit a policy object\n"
 
279
        "  --delete-policy Edit a policy object\n"
 
280
        "  --help          Display this message\n"
 
281
        "\nUse \"--query help\" to get help on e.g. the query action\n"
 
282
        );
 
283
        exit(exval);
 
284
}
 
285
 
 
286
int
 
287
parse_registration(char **argv, int argc, isns_object_list_t *objs, isns_object_t *key_obj)
 
288
{
 
289
        struct sockaddr_storage def_addr;
 
290
        isns_object_t   *entity = NULL, *last_portal = NULL, *last_node = NULL;
 
291
        const char      *def_port = NULL;
 
292
        int             i;
 
293
 
 
294
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
295
                printf("Object registration:\n"
 
296
                       " isnsadm [-key attr=value] --register type,attr=value,... type,attr=value,...\n"
 
297
                       "Where type can be one of:\n"
 
298
                       "  entity         create/update network entity\n"
 
299
                       "  initiator      create iSCSI initiator storage node\n"
 
300
                       "  target         create iSCSI target storage node\n"
 
301
                       "  control        create control node\n"
 
302
                       "  portal         create portal\n"
 
303
                       "  pg             create portal group\n"
 
304
                       "\nThe following attributes are recognized:\n");
 
305
 
 
306
                isns_attr_list_parser_help(NULL);
 
307
                exit(0);
 
308
        }
 
309
 
 
310
        if (argc == 0)
 
311
                usage(1, "Missing object list\n");
 
312
 
 
313
        if (key_obj) {
 
314
                //isns_object_list_append(objs, key_obj);
 
315
                if (isns_object_is_entity(key_obj))
 
316
                        entity = key_obj;
 
317
        }
 
318
 
 
319
        def_addr = opt_myaddr;
 
320
 
 
321
        for (i = 0; i < argc; ++i) {
 
322
                isns_attr_list_t attrlist = ISNS_ATTR_LIST_INIT;
 
323
                struct isns_attr_list_parser state;
 
324
                isns_object_t   *obj;
 
325
                char            *type, *name, *value, *next_attr;
 
326
                char            *attrs[128];
 
327
                unsigned int    nattrs = 0;
 
328
 
 
329
                name = argv[i];
 
330
 
 
331
                if ((next_attr = strchr(name, ',')) != NULL)
 
332
                        *next_attr++ = '\0';
 
333
 
 
334
                while (next_attr && *next_attr) {
 
335
                        if (nattrs > 128)
 
336
                                isns_fatal("Too many attributes\n");
 
337
 
 
338
                        /* Show mercy with fat fingered
 
339
                         * people,,,,who,cannot,,,type,properly */
 
340
                        if (next_attr[0] != ',')
 
341
                                attrs[nattrs++] = next_attr;
 
342
                        if ((next_attr = strchr(next_attr, ',')) != NULL)
 
343
                                *next_attr++ = '\0';
 
344
                }
 
345
 
 
346
                if ((value = strchr(name, '=')) != NULL)
 
347
                        *value++ = '\0';
 
348
 
 
349
                type = name;
 
350
                if (!strcmp(name, "entity")) {
 
351
                        if (entity == NULL) {
 
352
                                isns_error("Cannot create entity object "
 
353
                                        "within this key object\n");
 
354
                                return 0;
 
355
                        }
 
356
 
 
357
                        if (value != NULL)
 
358
                                isns_object_set_string(entity,
 
359
                                                ISNS_TAG_ENTITY_IDENTIFIER,
 
360
                                                value);
 
361
                        obj = isns_object_get(entity);
 
362
                        goto handle_attributes;
 
363
                } else
 
364
                if (!strcmp(name, "node")
 
365
                 || !strcmp(name, "initiator")) {
 
366
                        const char *node_name;
 
367
 
 
368
                        node_name = isns_config.ic_source_name;
 
369
                        if (value)
 
370
                                node_name = value;
 
371
 
 
372
                        obj = isns_create_storage_node(node_name,
 
373
                                        ISNS_ISCSI_INITIATOR_MASK,
 
374
                                        entity);
 
375
                        last_node = obj;
 
376
 
 
377
                        isns_addr_set_port((struct sockaddr *) &def_addr,
 
378
                                        ISNS_DEFAULT_PORT_INITIATOR);
 
379
                        def_port = "iscsi";
 
380
                } else
 
381
                if (!strcmp(name, "target")) {
 
382
                        const char *node_name;
 
383
 
 
384
                        node_name = isns_config.ic_source_name;
 
385
                        if (value)
 
386
                                node_name = value;
 
387
                        obj = isns_create_storage_node(node_name,
 
388
                                        ISNS_ISCSI_TARGET_MASK,
 
389
                                        entity);
 
390
                        last_node = obj;
 
391
 
 
392
                        isns_addr_set_port((struct sockaddr *) &def_addr,
 
393
                                        ISNS_DEFAULT_PORT_TARGET);
 
394
                        def_port = "iscsi-target";
 
395
                } else
 
396
                if (!strcmp(name, "control")) {
 
397
                        const char *node_name;
 
398
 
 
399
                        node_name = isns_config.ic_control_name;
 
400
                        if (value)
 
401
                                node_name = value;
 
402
                        obj = isns_create_storage_node(node_name,
 
403
                                        ISNS_ISCSI_CONTROL_MASK,
 
404
                                        entity);
 
405
                        last_node = obj;
 
406
 
 
407
                        def_port = NULL;
 
408
                } else
 
409
                if (!strcmp(name, "portal")) {
 
410
                        isns_portal_info_t portal_info;
 
411
 
 
412
                        if (value == NULL) {
 
413
                                if (def_port == NULL)
 
414
                                        isns_fatal("portal must follow initiator or target\n");
 
415
                                isns_portal_init(&portal_info,
 
416
                                                (struct sockaddr *) &def_addr,
 
417
                                                IPPROTO_TCP);
 
418
                        } else
 
419
                        if (!isns_portal_parse(&portal_info, value, def_port))
 
420
                                isns_fatal("Unable to parse portal=%s\n", value);
 
421
                        obj = isns_create_portal(&portal_info, entity);
 
422
                        last_portal = obj;
 
423
                } else
 
424
                if (!strcmp(name, "pg")) {
 
425
                        if (value)
 
426
                                isns_fatal("Unexpected value for portal group\n");
 
427
                        if (!last_portal || !last_node)
 
428
                                isns_fatal("Portal group registration must follow portal and node\n");
 
429
                        obj = isns_create_portal_group(last_portal, last_node, 10);
 
430
                } else {
 
431
                        isns_error("Unknown object type \"%s\"\n", name);
 
432
                        return 0;
 
433
                }
 
434
 
 
435
                if (obj == NULL) {
 
436
                        isns_error("Failure to create %s object\n", name);
 
437
                        return 0;
 
438
                }
 
439
                isns_object_list_append(objs, obj);
 
440
 
 
441
handle_attributes:
 
442
                isns_attr_list_parser_init(&state, obj->ie_template);
 
443
                state.default_port = def_port;
 
444
 
 
445
                if (!isns_parse_attrs(nattrs, attrs, &attrlist, &state)
 
446
                 || !isns_object_set_attrlist(obj, &attrlist)) {
 
447
                        isns_error("Failure to set all %s attributes\n", name);
 
448
                        isns_attr_list_destroy(&attrlist);
 
449
                        return 0;
 
450
                }
 
451
 
 
452
                isns_attr_list_destroy(&attrlist);
 
453
                isns_object_release(obj);
 
454
        }
 
455
 
 
456
        return 1;
 
457
}
 
458
 
 
459
static int
 
460
__register_objects(isns_client_t *clnt,
 
461
                isns_object_t *key_obj,
 
462
                const isns_object_list_t *objects)
 
463
{
 
464
        isns_source_t   *source = NULL;
 
465
        isns_simple_t   *reg;
 
466
        uint32_t        status;
 
467
        unsigned int    i;
 
468
 
 
469
        for (i = 0; i < objects->iol_count && !source; ++i) {
 
470
                isns_object_t *obj = objects->iol_data[i];
 
471
 
 
472
                if (!isns_object_is_iscsi_node(obj))
 
473
                        continue;
 
474
                source = isns_source_from_object(obj);
 
475
        }
 
476
 
 
477
        reg = isns_create_registration2(clnt, key_obj, source);
 
478
        isns_registration_set_replace(reg, opt_replace);
 
479
 
 
480
        /* Add all objects to be registered */
 
481
        for (i = 0; i < objects->iol_count; ++i)
 
482
                isns_registration_add_object(reg, objects->iol_data[i]);
 
483
 
 
484
        status = isns_client_call(clnt, &reg);
 
485
        isns_simple_free(reg);
 
486
 
 
487
        if (status == ISNS_SUCCESS)
 
488
                printf("Successfully registered object(s)\n");
 
489
        else
 
490
                isns_error("Failed to register object(s): %s\n",
 
491
                                isns_strerror(status));
 
492
 
 
493
        if (source)
 
494
                isns_source_release(source);
 
495
        return status;
 
496
}
 
497
 
 
498
int
 
499
register_objects(isns_client_t *clnt,
 
500
                int argc, char **argv)
 
501
{
 
502
        isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
 
503
        isns_object_t   *key_obj = NULL;
 
504
        uint32_t        status;
 
505
 
 
506
        if (opt_key != NULL) {
 
507
                isns_attr_list_t key_attrs = ISNS_ATTR_LIST_INIT;
 
508
                struct isns_attr_list_parser state;
 
509
 
 
510
                isns_attr_list_parser_init(&state, NULL);
 
511
 
 
512
                if (!isns_parse_attrs(1, &opt_key, &key_attrs, &state)) {
 
513
                        isns_error("Cannot parse registration key \"%s\"\n",
 
514
                                        opt_key);
 
515
                        return 0;
 
516
                }
 
517
 
 
518
                key_obj = isns_create_object(isns_attr_list_parser_context(&state),
 
519
                                &key_attrs, NULL);
 
520
                isns_attr_list_destroy(&key_attrs);
 
521
 
 
522
                if (!key_obj) {
 
523
                        isns_error("Cannot create registration key object\n");
 
524
                        return 0;
 
525
                }
 
526
        } else {
 
527
                /* If the user does not provide a key object, 
 
528
                 * create/update an entity.
 
529
                 */
 
530
                key_obj = isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI, NULL);
 
531
        }
 
532
 
 
533
        if (!parse_registration(argv, argc, &objects, key_obj))
 
534
                isns_fatal("Unable to parse registration\n");
 
535
 
 
536
        status = __register_objects(clnt, key_obj, &objects);
 
537
        isns_object_list_destroy(&objects);
 
538
 
 
539
        isns_object_release(key_obj);
 
540
        return status;
 
541
}
 
542
 
 
543
/*
 
544
 * Parse the query string given by the user
 
545
 *
 
546
 * 5.6.5.2
 
547
 * The Message Key may contain key or non-key attributes or no
 
548
 * attributes at all.  If multiple attributes are used as the
 
549
 * Message Key, then they MUST all be from the same object type
 
550
 * (e.g., IP address and TCP/UDP Port are attributes of the
 
551
 * Portal object type).
 
552
 */
 
553
int
 
554
parse_query(char **argv, int argc, isns_attr_list_t *keys, isns_attr_list_t *query)
 
555
{
 
556
        struct isns_attr_list_parser state;
 
557
 
 
558
        isns_attr_list_parser_init(&state, NULL);
 
559
        state.nil_permitted = 1;
 
560
 
 
561
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
562
                printf("Object query:\n"
 
563
                       " isnsadm --query attr=value attr=value ... ?query-attr ?query-attr ...\n"
 
564
                       "All key attributes must refer to a common object type.\n"
 
565
                       "Query attributes specify the attributes the server should return,"
 
566
                       "and can refer to any object type.\n"
 
567
                       "The following attributes are recognized:\n");
 
568
                isns_attr_list_parser_help(&state);
 
569
                exit(0);
 
570
        }
 
571
 
 
572
        if (argc == 0)
 
573
                isns_fatal("Missing query attributes\n");
 
574
 
 
575
        return isns_parse_query_attrs(argc, argv, keys, query, &state);
 
576
}
 
577
 
 
578
int
 
579
query_objects(isns_client_t *clnt, int argc, char **argv)
 
580
{
 
581
        isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
 
582
        isns_attr_list_t oper_attrs = ISNS_ATTR_LIST_INIT;
 
583
        isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
 
584
        uint32_t        status;
 
585
        isns_simple_t   *qry;
 
586
        unsigned int    i;
 
587
 
 
588
        if (!parse_query(argv, argc, &query_key, &oper_attrs))
 
589
                isns_fatal("Unable to parse query\n");
 
590
 
 
591
        qry = isns_create_query(clnt, &query_key);
 
592
        isns_attr_list_destroy(&query_key);
 
593
 
 
594
        /* Add the list of attributes we request */
 
595
        for (i = 0; i < oper_attrs.ial_count; ++i)
 
596
                isns_query_request_attr(qry, oper_attrs.ial_data[i]);
 
597
        isns_attr_list_destroy(&oper_attrs);
 
598
 
 
599
        status = isns_client_call(clnt, &qry);
 
600
        if (status != ISNS_SUCCESS) {
 
601
                isns_error("Query failed: %s\n", isns_strerror(status));
 
602
                return status;
 
603
        }
 
604
 
 
605
        status = isns_query_response_get_objects(qry, &objects);
 
606
        if (status) {
 
607
                isns_error("Unable to extract object list from query response: %s\n",
 
608
                                isns_strerror(status), status);
 
609
                return status;
 
610
        }
 
611
 
 
612
        isns_object_list_print(&objects, isns_print_stdout);
 
613
        isns_object_list_destroy(&objects);
 
614
        isns_simple_free(qry);
 
615
 
 
616
        return status;
 
617
}
 
618
 
 
619
int
 
620
query_entity_id(isns_client_t *clnt, int argc, char **argv)
 
621
{
 
622
        isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
 
623
        isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
 
624
        uint32_t        status;
 
625
        isns_simple_t   *qry;
 
626
        const char      *eid;
 
627
 
 
628
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
629
                printf("Query iSNS for own entity ID.\n"
 
630
                       "No arguments allowed\n");
 
631
                exit(0);
 
632
        }
 
633
        if (argc != 0)
 
634
                isns_fatal("EID query - no arguments accepted\n");
 
635
 
 
636
        isns_attr_list_append_string(&query_key,
 
637
                        ISNS_TAG_ISCSI_NAME,
 
638
                        isns_config.ic_source_name);
 
639
        qry = isns_create_query(clnt, &query_key);
 
640
        isns_attr_list_destroy(&query_key);
 
641
 
 
642
        isns_query_request_attr_tag(qry, ISNS_TAG_ENTITY_IDENTIFIER);
 
643
 
 
644
        status = isns_client_call(clnt, &qry);
 
645
        if (status != ISNS_SUCCESS) {
 
646
                isns_error("Query failed: %s\n", isns_strerror(status));
 
647
                return status;
 
648
        }
 
649
 
 
650
        status = isns_query_response_get_objects(qry, &objects);
 
651
        if (status) {
 
652
                isns_error("Unable to extract object list from query response: %s\n",
 
653
                                isns_strerror(status), status);
 
654
                return status;
 
655
        }
 
656
 
 
657
        status = ISNS_NO_SUCH_ENTRY;
 
658
        if (objects.iol_count == 0) {
 
659
                isns_error("Node %s not registered with iSNS\n",
 
660
                                isns_config.ic_source_name);
 
661
        } else
 
662
        if (!isns_object_get_string(objects.iol_data[0],
 
663
                                ISNS_TAG_ENTITY_IDENTIFIER, &eid)) {
 
664
                isns_error("Query for %s returned an object without EID\n",
 
665
                                isns_config.ic_source_name);
 
666
        } else {
 
667
                printf("%s\n", eid);
 
668
                status = ISNS_SUCCESS;
 
669
        }
 
670
 
 
671
        isns_object_list_destroy(&objects);
 
672
        isns_simple_free(qry);
 
673
 
 
674
        return status;
 
675
}
 
676
 
 
677
/*
 
678
 * Parse the list query string given by the user
 
679
 */
 
680
int
 
681
parse_list(int argc, char **argv, isns_object_template_t **type_p, isns_attr_list_t *keys)
 
682
{
 
683
        struct isns_attr_list_parser state;
 
684
        isns_object_template_t *query_type = NULL;
 
685
        char    *type_name;
 
686
 
 
687
        if (argc == 0)
 
688
                usage(1, "Missing object type");
 
689
 
 
690
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
691
                printf("Object query:\n"
 
692
                       " isnsadm --list type attr=value attr=value ...\n"
 
693
                       "Possible value for <type>:\n"
 
694
                       " entities           - list all network entites\n"
 
695
                       " nodes              - list all storage nodes\n"
 
696
                       " portals            - list all portals\n"
 
697
                       " portal-groups      - list all portal groups\n"
 
698
                       " dds                - list all discovery domains\n"
 
699
                       " ddsets             - list all discovery domains sets\n"
 
700
                       " policies           - list all policies (privileged)\n"
 
701
                       "Additional attributes can be specified to scope the\n"
 
702
                       "search. They must match the specified object type.\n"
 
703
                       "\nThe following attributes are recognized:\n");
 
704
                isns_attr_list_parser_help(NULL);
 
705
                exit(0);
 
706
        }
 
707
 
 
708
        type_name = *argv++; --argc;
 
709
        if (!strcasecmp(type_name, "entities"))
 
710
                query_type = &isns_entity_template;
 
711
        else
 
712
        if (!strcasecmp(type_name, "nodes"))
 
713
                query_type = &isns_iscsi_node_template;
 
714
        else
 
715
        if (!strcasecmp(type_name, "portals"))
 
716
                query_type = &isns_portal_template;
 
717
        else
 
718
        if (!strcasecmp(type_name, "portal-groups"))
 
719
                query_type = &isns_iscsi_pg_template;
 
720
        else
 
721
        if (!strcasecmp(type_name, "dds"))
 
722
                query_type = &isns_dd_template;
 
723
        else
 
724
        if (!strcasecmp(type_name, "ddsets"))
 
725
                query_type = &isns_ddset_template;
 
726
        else
 
727
        if (!strcasecmp(type_name, "policies"))
 
728
                query_type = &isns_policy_template;
 
729
        else {
 
730
                isns_error("Unknown object type \"%s\"\n",
 
731
                                type_name);
 
732
                return 0;
 
733
        }
 
734
 
 
735
        *type_p = query_type;
 
736
 
 
737
        isns_attr_list_parser_init(&state, query_type);
 
738
        state.nil_permitted = 1;
 
739
 
 
740
        return isns_parse_attrs(argc, argv, keys, &state);
 
741
}
 
742
 
 
743
int
 
744
list_objects(isns_client_t *clnt, int argc, char **argv)
 
745
{
 
746
        isns_attr_list_t        query_keys = ISNS_ATTR_LIST_INIT;
 
747
        isns_object_template_t  *query_type = NULL;
 
748
        isns_simple_t           *simp;
 
749
        int                     status, count = 0;
 
750
 
 
751
        if (!parse_list(argc, argv, &query_type, &query_keys))
 
752
                isns_fatal("Unable to parse parameters\n");
 
753
 
 
754
        simp = isns_create_getnext(clnt, query_type, &query_keys);
 
755
        while (1) {
 
756
                isns_object_t   *obj = NULL;
 
757
                isns_simple_t   *followup;
 
758
 
 
759
                status = isns_client_call(clnt, &simp);
 
760
                if (status)
 
761
                        break;
 
762
 
 
763
                status = isns_getnext_response_get_object(simp, &obj);
 
764
                if (status)
 
765
                        break;
 
766
 
 
767
                printf("Object %u:\n", count++);
 
768
                isns_object_print(obj, isns_print_stdout);
 
769
                isns_object_release(obj);
 
770
 
 
771
                followup = isns_create_getnext_followup(clnt,
 
772
                                simp, &query_keys);
 
773
                isns_simple_free(simp);
 
774
                simp = followup;
 
775
        }
 
776
 
 
777
        if (status == ISNS_SOURCE_UNAUTHORIZED
 
778
         && query_type == &isns_policy_template
 
779
         && !opt_local)
 
780
                isns_warning("Please use --local trying to list policies\n");
 
781
 
 
782
        if (status != ISNS_NO_SUCH_ENTRY) {
 
783
                isns_error("GetNext call failed: %s\n",
 
784
                                isns_strerror(status));
 
785
                return status;
 
786
        }
 
787
        return ISNS_SUCCESS;
 
788
}
 
789
 
 
790
/*
 
791
 * Parse the deregistration string given by the user
 
792
 *
 
793
 * 5.6.5.2
 
794
 * The Message Key may contain key or non-key attributes or no
 
795
 * attributes at all.  If multiple attributes are used as the
 
796
 * Message Key, then they MUST all be from the same object type
 
797
 * (e.g., IP address and TCP/UDP Port are attributes of the
 
798
 * Portal object type).
 
799
 */
 
800
int
 
801
parse_deregistration(char **argv, int argc, isns_attr_list_t *keys)
 
802
{
 
803
        struct isns_attr_list_parser state;
 
804
 
 
805
        isns_attr_list_parser_init(&state, NULL);
 
806
        state.multi_type_permitted = 1;
 
807
        state.nil_permitted = 1;
 
808
 
 
809
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
810
                printf("Object deregistration:\n"
 
811
                       " isnsadm --deregister attr=value attr=value ...\n"
 
812
                       "All attributes must refer to a common object type.\n"
 
813
                       "\nThe following attributes are recognized:\n");
 
814
                isns_attr_list_parser_help(&state);
 
815
                exit(0);
 
816
        }
 
817
 
 
818
        return isns_parse_attrs(argc, argv, keys, &state);
 
819
}
 
820
 
 
821
int
 
822
deregister_objects(isns_client_t *clnt, int argc, char **argv)
 
823
{
 
824
        isns_attr_list_t query_key = ISNS_ATTR_LIST_INIT;
 
825
        isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
 
826
        isns_simple_t   *dereg;
 
827
        uint32_t        status;
 
828
 
 
829
        if (!parse_deregistration(argv, argc, &query_key))
 
830
                isns_fatal("Unable to parse unregistration\n");
 
831
 
 
832
        dereg = isns_create_deregistration(clnt, &query_key);
 
833
        isns_attr_list_destroy(&query_key);
 
834
 
 
835
        status = isns_client_call(clnt, &dereg);
 
836
        if (status != ISNS_SUCCESS) {
 
837
                isns_error("Deregistration failed: %s\n",
 
838
                                isns_strerror(status));
 
839
                return status;
 
840
        }
 
841
 
 
842
#if 0
 
843
        status = isns_dereg_msg_response_get_objects(dereg, &objects);
 
844
        if (status) {
 
845
                isns_error("Unable to extract object list from deregistration response: %s\n",
 
846
                                isns_strerror(status), status);
 
847
                goto done;
 
848
        }
 
849
        isns_object_list_print(&objects, isns_print_stdout);
 
850
#endif
 
851
 
 
852
        isns_object_list_destroy(&objects);
 
853
        isns_simple_free(dereg);
 
854
 
 
855
        return status;
 
856
}
 
857
 
 
858
/*
 
859
 * Handle discovery domain registration/deregistration
 
860
 */
 
861
int
 
862
parse_dd_registration(char **argv, int argc, isns_attr_list_t *keys)
 
863
{
 
864
        struct isns_attr_list_parser state;
 
865
 
 
866
        isns_attr_list_parser_init(&state, &isns_dd_template);
 
867
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
868
                printf("Object query:\n"
 
869
                       " isnsadm --dd-register attr=value attr=value ...\n"
 
870
                       "You cannot specify more than one domain.\n"
 
871
                       "If you want to modify an existing domain, you must specify its ID.\n"
 
872
                       "The following attributes are recognized:\n");
 
873
                isns_attr_list_parser_help(&state);
 
874
                exit(0);
 
875
        }
 
876
 
 
877
        return isns_parse_attrs(argc, argv, keys, &state);
 
878
}
 
879
 
 
880
int
 
881
register_domain(isns_client_t *clnt, int argc, char **argv)
 
882
{
 
883
        isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
 
884
        isns_simple_t   *msg;
 
885
        uint32_t        status;
 
886
 
 
887
        if (!parse_dd_registration(argv, argc, &attrs))
 
888
                isns_fatal("Unable to parse DD registration\n");
 
889
 
 
890
        msg = isns_create_dd_registration(clnt, &attrs);
 
891
        isns_attr_list_destroy(&attrs);
 
892
 
 
893
        if (msg == NULL) {
 
894
                isns_error("Cannot create message\n");
 
895
                return ISNS_INTERNAL_ERROR;
 
896
        }
 
897
 
 
898
        status = isns_client_call(clnt, &msg);
 
899
        if (status != ISNS_SUCCESS) {
 
900
                isns_error("Registration failed: %s\n",
 
901
                                isns_strerror(status));
 
902
                return status;
 
903
        }
 
904
 
 
905
        if (status == ISNS_SUCCESS) {
 
906
                printf("Registered DD:\n");
 
907
                isns_attr_list_print(
 
908
                                isns_simple_get_attrs(msg),
 
909
                                isns_print_stdout);
 
910
        }
 
911
        isns_simple_free(msg);
 
912
 
 
913
        return status;
 
914
}
 
915
 
 
916
int
 
917
parse_dd_deregistration(char **argv, int argc,
 
918
                uint32_t *dd_id, isns_attr_list_t *keys)
 
919
{
 
920
        struct isns_attr_list_parser state;
 
921
 
 
922
        isns_attr_list_parser_init(&state, &isns_dd_template);
 
923
        if (argc == 0 || (argc == 1 && !strcmp(argv[0], "help"))) {
 
924
                printf("DD deregistration:\n"
 
925
                       " isnsadm --dd-deregister dd-id attr=value attr=value ...\n"
 
926
                       "You cannot specify more than one domain.\n"
 
927
                       "The following attributes are recognized:\n");
 
928
                isns_attr_list_parser_help(&state);
 
929
                exit(0);
 
930
        }
 
931
 
 
932
        *dd_id = parse_count(argv[0]);
 
933
 
 
934
        return isns_parse_attrs(argc - 1, argv + 1, keys, &state);
 
935
}
 
936
 
 
937
int
 
938
deregister_domain(isns_client_t *clnt, int argc, char **argv)
 
939
{
 
940
        isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
 
941
        isns_simple_t   *msg;
 
942
        uint32_t        dd_id, status;
 
943
 
 
944
        if (!parse_dd_deregistration(argv, argc, &dd_id, &attrs))
 
945
                isns_fatal("Unable to parse DD registration\n");
 
946
 
 
947
        msg = isns_create_dd_deregistration(clnt, dd_id, &attrs);
 
948
        isns_attr_list_destroy(&attrs);
 
949
 
 
950
        if (msg == NULL) {
 
951
                isns_error("Cannot create message\n");
 
952
                return ISNS_INTERNAL_ERROR;
 
953
        }
 
954
 
 
955
        status = isns_client_call(clnt, &msg);
 
956
        if (status != ISNS_SUCCESS) {
 
957
                isns_error("Deregistration failed: %s\n",
 
958
                                isns_strerror(status));
 
959
                return status;
 
960
        }
 
961
 
 
962
        isns_simple_free(msg);
 
963
        return status;
 
964
}
 
965
 
 
966
/*
 
967
 * Parse a policy
 
968
 */
 
969
int
 
970
parse_policy(int argc, char **argv, isns_attr_list_t *attrs,
 
971
                const char *help_title, const char *help_action)
 
972
{
 
973
        struct isns_attr_list_parser state;
 
974
 
 
975
        isns_attr_list_parser_init(&state, &isns_policy_template);
 
976
        state.nil_permitted = 0;
 
977
        state.load_key = load_key_callback;
 
978
        state.generate_key = generate_key_callback;
 
979
 
 
980
        if (argc == 1 && !strcmp(argv[0], "help")) {
 
981
                printf("%s:\n"
 
982
                       " isnsadm %s attr=value attr=value ...\n"
 
983
                       "Specifying a Security Policy Index is mandatory.\n"
 
984
                       "\nThe following attributes are recognized:\n",
 
985
                       help_title, help_action);
 
986
                isns_attr_list_parser_help(&state);
 
987
                exit(0);
 
988
        }
 
989
 
 
990
        return isns_parse_attrs(argc, argv, attrs, &state);
 
991
}
 
992
 
 
993
static int
 
994
__create_policy(isns_client_t *clnt, const isns_attr_list_t *attrs)
 
995
{
 
996
        isns_object_list_t objects = ISNS_OBJECT_LIST_INIT;
 
997
        isns_object_t   *obj;
 
998
        int             status;
 
999
 
 
1000
        obj = isns_create_object(&isns_policy_template, attrs, NULL);
 
1001
        if (!obj)
 
1002
                isns_fatal("Cannot create policy object\n");
 
1003
        isns_object_list_append(&objects, obj);
 
1004
 
 
1005
        status = __register_objects(clnt, NULL, &objects);
 
1006
        isns_object_list_destroy(&objects);
 
1007
        return status;
 
1008
}
 
1009
 
 
1010
/*
 
1011
 * Enroll a new client
 
1012
 */
 
1013
int
 
1014
enroll_client(isns_client_t *clnt, int argc, char **argv)
 
1015
{
 
1016
        isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
 
1017
        const char      *client_name;
 
1018
        int             status;
 
1019
 
 
1020
        if (argc == 0)
 
1021
                usage(1, "Missing client name");
 
1022
 
 
1023
        client_name = *argv++; --argc;
 
1024
 
 
1025
        isns_attr_list_append_string(&attrs,
 
1026
                        OPENISNS_TAG_POLICY_SPI,
 
1027
                        client_name);
 
1028
#if 0
 
1029
        isns_attr_list_append_string(&attrs,
 
1030
                        OPENISNS_TAG_POLICY_SOURCE_NAME,
 
1031
                        client_name);
 
1032
#endif
 
1033
 
 
1034
        if (!opt_keyfile) {
 
1035
                static char     namebuf[PATH_MAX];
 
1036
 
 
1037
                snprintf(namebuf, sizeof(namebuf), "%s.key", client_name);
 
1038
                opt_keyfile = namebuf;
 
1039
        }
 
1040
 
 
1041
        if (argc && !parse_policy(argc, argv, &attrs,
 
1042
                                "Enroll an iSNS client",
 
1043
                                "--enroll hostname"))
 
1044
                isns_fatal("Cannot parse policy\n");
 
1045
 
 
1046
        /* If no key is given, generate one */
 
1047
        if (!isns_attr_list_contains(&attrs, OPENISNS_TAG_POLICY_KEY)) {
 
1048
                printf("No key given, generating one\n");
 
1049
                isns_attr_list_append_attr(&attrs,
 
1050
                                generate_key_callback());
 
1051
        }
 
1052
 
 
1053
        status = __create_policy(clnt, &attrs);
 
1054
        isns_attr_list_destroy(&attrs);
 
1055
        return status;
 
1056
}
 
1057
 
 
1058
 
 
1059
/*
 
1060
 * Create a new policy
 
1061
 */
 
1062
int
 
1063
edit_policy(isns_client_t *clnt, int argc, char **argv)
 
1064
{
 
1065
        isns_attr_list_t attrs = ISNS_ATTR_LIST_INIT;
 
1066
        int             status;
 
1067
 
 
1068
        if (!parse_policy(argc, argv, &attrs,
 
1069
                                "Edit an existing policy",
 
1070
                                "--edit-policy"))
 
1071
                isns_fatal("Cannot parse policy\n");
 
1072
 
 
1073
        status = __create_policy(clnt, &attrs);
 
1074
        isns_attr_list_destroy(&attrs);
 
1075
 
 
1076
        return status;
 
1077
}
 
1078
 
 
1079
#ifdef WITH_SECURITY
 
1080
static isns_attr_t *
 
1081
__key_to_attr(EVP_PKEY *pkey)
 
1082
{
 
1083
        struct __isns_opaque key;
 
1084
        isns_value_t    value;
 
1085
        isns_attr_t     *attr = NULL;
 
1086
 
 
1087
        if (!isns_dsa_encode_public(pkey, &key.ptr, &key.len))
 
1088
                goto out;
 
1089
 
 
1090
        /* Must pad key. This means we may end up encoding a few
 
1091
         * bytes of trash. Oh well. */
 
1092
        key.len = ISNS_PAD(key.len);
 
1093
 
 
1094
        value = ISNS_VALUE_INIT(opaque, key);
 
1095
        attr = isns_attr_alloc(OPENISNS_TAG_POLICY_KEY, NULL, &value);
 
1096
 
 
1097
        isns_free(key.ptr);
 
1098
 
 
1099
out:
 
1100
        EVP_PKEY_free(pkey);
 
1101
        return attr;
 
1102
}
 
1103
 
 
1104
isns_attr_t *
 
1105
generate_key_callback(void)
 
1106
{
 
1107
        EVP_PKEY        *pkey;
 
1108
 
 
1109
        if (opt_keyfile == NULL)
 
1110
                isns_fatal("Key generation requires --keyfile option\n");
 
1111
 
 
1112
        if (!(pkey = isns_dsa_generate_key()))
 
1113
                isns_fatal("Key generation failed\n");
 
1114
 
 
1115
        if (!isns_dsa_store_private(opt_keyfile, pkey))
 
1116
                isns_fatal("Unable to write private key to %s\n",
 
1117
                                opt_keyfile);
 
1118
 
 
1119
        printf("Stored DSA private key in %s\n", opt_keyfile);
 
1120
        return __key_to_attr(pkey);
 
1121
}
 
1122
 
 
1123
isns_attr_t *
 
1124
load_key_callback(const char *pathname)
 
1125
{
 
1126
        EVP_PKEY        *pkey;
 
1127
 
 
1128
        if (!(pkey = isns_dsa_load_public(pathname)))
 
1129
                isns_fatal("Unable to load public key from file %s\n", pathname);
 
1130
 
 
1131
        return __key_to_attr(pkey);
 
1132
}
 
1133
 
 
1134
#else /* WITH_SECURITY */
 
1135
isns_attr_t *
 
1136
generate_key_callback(void)
 
1137
{
 
1138
        isns_fatal("Authentication disabled in this build\n");
 
1139
        return NULL;
 
1140
}
 
1141
 
 
1142
isns_attr_t *
 
1143
load_key_callback(const char *pathname)
 
1144
{
 
1145
        isns_fatal("Authentication disabled in this build\n");
 
1146
        return NULL;
 
1147
}
 
1148
 
 
1149
#endif