xref: /illumos-gate/usr/src/cmd/isns/isnsd/dump.c (revision e9344627fd9b13a2a1fe91a37a88c0edbc4e5191)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright 2025 OmniOS Community Edition (OmniOSce) Association.
29  */
30 
31 /* This file is getting large unexpectly, a lex & yacc */
32 /* implementation is expected. */
33 
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <pthread.h>
46 
47 #include "isns_server.h"
48 #include "isns_htab.h"
49 #include "isns_msgq.h"
50 #include "isns_obj.h"
51 #include "isns_func.h"
52 #include "isns_dd.h"
53 #include "isns_cache.h"
54 #include "isns_pdu.h"
55 
56 #ifdef DEBUG
57 /*
58  * external variables
59  */
60 extern const int NUM_OF_CHILD[MAX_OBJ_TYPE];
61 extern const int TYPE_OF_CHILD[MAX_OBJ_TYPE][MAX_CHILD_TYPE];
62 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
63 extern const int NUM_OF_REF[MAX_OBJ_TYPE_FOR_SIZE];
64 
65 extern lookup_ctrl_t *setup_ddid_lcp(lookup_ctrl_t *, uint32_t);
66 extern lookup_ctrl_t *setup_ddsid_lcp(lookup_ctrl_t *, uint32_t);
67 
68 /*
69  * global variables
70  */
71 int verbose_mc = 0;
72 int verbose_tc = 0;
73 int verbose_lock = 0;
74 int verbose_net = 0;
75 int verbose_parser = 0;
76 
77 /*
78  * local variables
79  */
80 static void print_entity(char *, isns_obj_t *);
81 static void print_iscsi(char *, isns_obj_t *);
82 static void print_portal(char *, isns_obj_t *);
83 static void print_pg(char *, isns_obj_t *);
84 static void print_dd(char *, isns_obj_t *);
85 static void print_dds(char *, isns_obj_t *);
86 static void (*const print_func[MAX_OBJ_TYPE])(char *, isns_obj_t *) = {
87 	NULL,
88 	&print_entity,
89 	&print_iscsi,
90 	&print_portal,
91 	&print_pg,
92 	&print_dd,
93 	&print_dds
94 };
95 static int run_cmd(char *);
96 
97 typedef struct {
98 	uint16_t func_id;
99 	char *fname;
100 } isnsp_fnames_t;
101 isnsp_fnames_t fnames[] = {
102 { ISNS_DEV_ATTR_REG, "DevAttrReg" },
103 { ISNS_DEV_ATTR_QRY, "DevAttrQry" },
104 { ISNS_DEV_GET_NEXT, "DevGetNext" },
105 { ISNS_DEV_DEREG, "DevDereg" },
106 { ISNS_SCN_REG, "SCNReg" },
107 { ISNS_SCN_DEREG, "SCNDereg" },
108 { ISNS_DD_REG, "DDReg" },
109 { ISNS_DD_DEREG, "DDDereg" },
110 { ISNS_DDS_REG, "DDSReg" },
111 { ISNS_DDS_DEREG, "DDSDereg" },
112 { ISNS_SCN, "SCN" },
113 { ISNS_ESI, "ESI" },
114 { ISNS_HEARTBEAT, "Heartbeat" },
115 { ISNS_DEV_ATTR_REG_RSP, "DevAttrRegRsp" },
116 { ISNS_DEV_ATTR_QRY_RSP, "DevAttrQryRsp" },
117 { ISNS_DEV_GET_NEXT_RSP, "DevGetNextRsp" },
118 { ISNS_DEV_DEREG_RSP, "DevDeregRsp" },
119 { ISNS_SCN_REG_RSP, "SCNRegRsp" },
120 { ISNS_SCN_DEREG_RSP, "SCNDeregRsp" },
121 { ISNS_SCN_RSP, "SCNRsp" },
122 { ISNS_ESI_RSP, "ESIRsp" },
123 { 0xFFFF, "Unknown" } };
124 
125 static char *
get_func_name(uint16_t id)126 get_func_name(
127 	uint16_t id
128 )
129 {
130 	int i = 0;
131 	isnsp_fnames_t *fp = &fnames[i ++];
132 	while (fp->func_id != 0xFFFF) {
133 		if (fp->func_id == id) {
134 			return (fp->fname);
135 		}
136 		fp = &fnames[i ++];
137 	}
138 
139 	return ("UNKNOWN");
140 }
141 
142 static char *
get_tlv_tag_name(uint32_t tag)143 get_tlv_tag_name(
144 	uint32_t tag
145 )
146 {
147 	switch (tag) {
148 		case ISNS_DELIMITER_ATTR_ID:
149 			return ("Delimiter");
150 		case ISNS_EID_ATTR_ID:
151 			return ("Entity Identifier");
152 		case ISNS_ENTITY_PROTOCOL_ATTR_ID:
153 			return ("Entity Protocol");
154 		case ISNS_ENTITY_REG_PERIOD_ATTR_ID:
155 			return ("Registration Period");
156 		case ISNS_TIMESTAMP_ATTR_ID:
157 			return ("Timestamp");
158 		case ISNS_PORTAL_IP_ADDR_ATTR_ID:
159 			return ("Portal IP Address");
160 		case ISNS_PORTAL_PORT_ATTR_ID:
161 			return ("Portal TCP/UDP Port");
162 		case ISNS_PORTAL_NAME_ATTR_ID:
163 			return ("Portal Symbolic Name");
164 		case ISNS_ESI_INTERVAL_ATTR_ID:
165 			return ("ESI Interval");
166 		case ISNS_ESI_PORT_ATTR_ID:
167 			return ("ESI Port");
168 		case ISNS_SCN_PORT_ATTR_ID:
169 			return ("SCN Port");
170 		case ISNS_PORTAL_SEC_BMP_ATTR_ID:
171 			return ("Portal Security Bitmap");
172 		case ISNS_ISCSI_NAME_ATTR_ID:
173 			return ("iSCSI Name");
174 		case ISNS_ISCSI_NODE_TYPE_ATTR_ID:
175 			return ("iSCSI Node Type");
176 		case ISNS_ISCSI_ALIAS_ATTR_ID:
177 			return ("iSCSI Alias");
178 		case ISNS_ISCSI_AUTH_METHOD_ATTR_ID:
179 			return ("iSCSI Auth Method");
180 		case ISNS_ISCSI_SCN_BITMAP_ATTR_ID:
181 			return ("iSCSI SCN Bitmap");
182 		case ISNS_PG_ISCSI_NAME_ATTR_ID:
183 			return ("PG iSCSI Name");
184 		case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
185 			return ("PG Portal IP Addr");
186 		case ISNS_PG_PORTAL_PORT_ATTR_ID:
187 			return ("PG Portal TCP/UDP Port");
188 		case ISNS_PG_TAG_ATTR_ID:
189 			return ("PG Tag (PGT)");
190 		case ISNS_PG_INDEX_ATTR_ID:
191 			return ("PG Index");
192 		case ISNS_DD_NAME_ATTR_ID:
193 			return ("DD Name");
194 		case ISNS_DD_ID_ATTR_ID:
195 			return ("DD Index");
196 		case ISNS_DD_ISCSI_INDEX_ATTR_ID:
197 			return ("DD ISCSI Node Index");
198 		case ISNS_DD_ISCSI_NAME_ATTR_ID:
199 			return ("DD ISCSI Node Name");
200 		case ISNS_DD_SET_NAME_ATTR_ID:
201 			return ("DDS Name");
202 		case ISNS_DD_SET_ID_ATTR_ID:
203 			return ("DDS Index");
204 		case ISNS_DD_SET_STATUS_ATTR_ID:
205 			return ("DDS Status");
206 		default:
207 			return ("Unknown");
208 	}
209 }
210 
211 static void
dump_pdu(isns_pdu_t * pdu,int flag)212 dump_pdu(
213 	isns_pdu_t *pdu,
214 	int flag
215 )
216 {
217 	short ver, id, len, flags, xid, seq;
218 
219 	uint8_t *payload = pdu->payload;
220 	isns_resp_t *resp;
221 
222 	/* convert the data */
223 	if (flag) {
224 		ver = ntohs(pdu->version);
225 		id = ntohs(pdu->func_id);
226 		len = ntohs(pdu->payload_len);
227 		flags = ntohs(pdu->flags) & 0xFFFF;
228 		xid = ntohs(pdu->xid);
229 		seq = ntohs(pdu->seq);
230 	} else {
231 		ver = pdu->version;
232 		id = pdu->func_id;
233 		len = pdu->payload_len;
234 		flags = pdu->flags & 0xFFFF;
235 		xid = pdu->xid;
236 		seq = pdu->seq;
237 	}
238 
239 	/* print the pdu header */
240 	printf("iSNSP Version: %d\n", ver);
241 	printf("Function ID: %s\n", get_func_name(id));
242 	printf("PDU Length: %d\n", len);
243 	printf("Flags: %x\n", flags);
244 	printf("    %d... .... .... .... : ISNS_FLAG_CLIENT\n",
245 	    ((flags & ISNS_FLAG_CLIENT) == 0) ? 0 : 1);
246 	printf("    .%d.. .... .... .... : ISNS_FLAG_SERVER\n",
247 	    ((flags & ISNS_FLAG_SERVER) == 0) ? 0 : 1);
248 	printf("    ..%d. .... .... .... : ISNS_FLAG_AUTH_BLK_PRESENTED\n",
249 	    ((flags & ISNS_FLAG_AUTH_BLK_PRESENTED) == 0) ? 0 : 1);
250 	printf("    ...%d .... .... .... : ISNS_FLAG_REPLACE_REG\n",
251 	    ((flags & ISNS_FLAG_REPLACE_REG) == 0) ? 0 : 1);
252 	printf("    .... %d... .... .... : ISNS_FLAG_LAST_PDU\n",
253 	    ((flags & ISNS_FLAG_LAST_PDU) == 0) ? 0 : 1);
254 	printf("    .... .%d.. .... .... : ISNS_FLAG_FIRST_PDU\n",
255 	    ((flags & ISNS_FLAG_FIRST_PDU) == 0) ? 0 : 1);
256 	printf("Transaction ID: %d\n", xid);
257 	printf("Sequence ID: %d\n", seq);
258 
259 	printf("Payload: ...\n");
260 	if (id & ISNS_RSP_MASK) {
261 		resp = (isns_resp_t *)payload;
262 		printf("    ErrorCode: %d\n", ntohl(resp->status));
263 		len -= 4;
264 		payload += 4;
265 	}
266 
267 	/* print the payload */
268 	while (len > 0) {
269 		isns_tlv_t *tlvp;
270 		int t, l;
271 		uint8_t *v;
272 		char *s;
273 		int i;
274 		in6_addr_t *ip;
275 		char pbuff[256] = { 0 };
276 
277 		tlvp = (isns_tlv_t *)payload;
278 
279 		/* convert the data */
280 		t = ntohl(tlvp->attr_id);
281 		l = ntohl(tlvp->attr_len);
282 		v = &(tlvp->attr_value[0]);
283 
284 		/* print payload */
285 		if (l > 0) {
286 			printf("%s: ", get_tlv_tag_name(t));
287 			switch (t) {
288 				case ISNS_EID_ATTR_ID:
289 				case ISNS_ISCSI_NAME_ATTR_ID:
290 				case ISNS_ISCSI_ALIAS_ATTR_ID:
291 				case ISNS_ISCSI_AUTH_METHOD_ATTR_ID:
292 				case ISNS_PG_ISCSI_NAME_ATTR_ID:
293 				case ISNS_DD_NAME_ATTR_ID:
294 				case ISNS_DD_SET_NAME_ATTR_ID:
295 					s = (char *)v;
296 					printf("%s\n", s);
297 					break;
298 				case ISNS_ENTITY_PROTOCOL_ATTR_ID:
299 					i = ntohl(*(uint32_t *)v);
300 					printf("%s (%d)\n",
301 					    ((i == 1) ? "No Protocol" :
302 					    ((i == 2) ? "iSCSI" :
303 					    ((i == 3) ? "iFCP" :
304 					    "Others"))),
305 					    i);
306 					break;
307 				case ISNS_PORTAL_IP_ADDR_ATTR_ID:
308 				case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
309 					ip = (in6_addr_t *)v;
310 					inet_ntop(AF_INET6, (void *)ip,
311 					    pbuff, sizeof (pbuff));
312 					printf("%s\n", pbuff);
313 					break;
314 				case ISNS_PORTAL_PORT_ATTR_ID:
315 				case ISNS_ESI_PORT_ATTR_ID:
316 				case ISNS_SCN_PORT_ATTR_ID:
317 					i = ntohl(*(uint32_t *)v);
318 					printf("%d\n", (i & 0x0000FFFF));
319 					printf("    .... .... %d... .... : "
320 					    "0=TCP\n",
321 					    ((i & 0x10000) == 0) ? 0 : 1);
322 					break;
323 				case ISNS_ISCSI_NODE_TYPE_ATTR_ID:
324 					i = ntohl(*(uint32_t *)v);
325 					printf("0x%x\t", i);
326 					if (i & ISNS_CONTROL_NODE_TYPE) {
327 						printf("Control ");
328 					}
329 					if (i & ISNS_INITIATOR_NODE_TYPE) {
330 						printf("Initiator ");
331 					}
332 					if (i & ISNS_TARGET_NODE_TYPE) {
333 						printf("Target ");
334 					}
335 					printf("\n");
336 					break;
337 				case ISNS_PG_TAG_ATTR_ID:
338 				default:
339 					i = ntohl(*(uint32_t *)v);
340 					printf("%d\n", i);
341 					break;
342 			}
343 			printf("    Attribute Tag: %s (%d)\n",
344 			    get_tlv_tag_name(t), t);
345 			printf("    Attribute Length: %d\n", l);
346 		} else {
347 			printf("%s: (%d)\n", get_tlv_tag_name(t), t);
348 		}
349 
350 		len -= (sizeof (uint32_t) * 2 + l);
351 		payload += (sizeof (uint32_t) * 2 + l);
352 	}
353 }
354 
355 void
dump_pdu1(isns_pdu_t * pdu)356 dump_pdu1(
357 	isns_pdu_t *pdu
358 )
359 {
360 	if (verbose_net) {
361 		printf("### PDU RECEIVED ###\n");
362 		dump_pdu(pdu, 0);
363 	}
364 }
365 
366 void
dump_pdu2(isns_pdu_t * pdu)367 dump_pdu2(
368 	isns_pdu_t *pdu
369 )
370 {
371 	if (verbose_net) {
372 		printf("### PDU SENT ###\n");
373 		dump_pdu(pdu, 1);
374 	}
375 }
376 
377 void
dump_db()378 dump_db(
379 )
380 {
381 #if 0
382 	isns_list_t *list, *lista, *listb;
383 	isns_dds_t *dds;
384 	isns_dd_t *dd;
385 	isns_iscsi2_t *iscsi2;
386 
387 	printf("### DUMP DATABASE ###\n");
388 	/* dump dds(s) */
389 	list = dds_list;
390 	while (list != NULL) {
391 		dds = list->obj.dds;
392 		printf("[DDS:%d]%s(%s)\n", dds->id, dds->name,
393 		    dds->status ? "enabled" : "disabled");
394 		lista = dds->dd_list;
395 		/* dd(s) that belong to this dds */
396 		while (lista != NULL) {
397 			dd = lista->obj.dd;
398 			printf("\t[DD:%d]%s\n", dd->id, dd->name);
399 			lista = lista->next;
400 		}
401 		list = list->next;
402 	}
403 	/* dump dd(s) */
404 	list = dd_list;
405 	while (list != NULL) {
406 		dd = list->obj.dd;
407 		printf("[DD:%d]%s\n", dd->id, dd->name);
408 		/* dds(s) this dd belongs to */
409 		lista = dd->dds_list;
410 		while (lista != NULL) {
411 			dds = lista->obj.dds;
412 			printf("\t[DDS:%d]%s\n", dds->id, dds->name);
413 			lista = lista->next;
414 		}
415 		/* node(s) that this dd have */
416 		listb = dd->iscsi_list;
417 		while (listb != NULL) {
418 			iscsi2 = listb->obj.iscsi2;
419 			printf("\t[ISCSI:%d]%s\n", iscsi2->id, iscsi2->name);
420 			listb = listb->next;
421 		}
422 		list = list->next;
423 	}
424 	/* dump node(s) */
425 	list = iscsi_list;
426 	while (list != NULL) {
427 		iscsi2 = list->obj.iscsi2;
428 		printf("[ISCSI:%d]%s\n", iscsi2->id, iscsi2->name);
429 		lista = iscsi2->dd_list;
430 		/* dd(s) that this node belongs to */
431 		while (lista != NULL) {
432 			dd = lista->obj.dd;
433 			printf("\t[DD:%d]%s\n", dd->id, dd->name);
434 			lista = lista->next;
435 		}
436 		list = list->next;
437 	}
438 #endif
439 }
440 
441 static void
test_cli_help()442 test_cli_help(
443 )
444 {
445 	printf("list          - list all of storage node.\n");
446 	printf("list dd  [id] - list all of dd or one with member.\n");
447 	printf("list dds [id] - list all of dd-set or one with member.\n");
448 
449 	printf("\n");
450 	printf("new dd  <name>  - create a dd with name.\n");
451 	printf("new dds <name>  - create a dd-set with name.\n");
452 	printf("new ddn  <id> <name>  - create a dd with id and name.\n");
453 	printf("new ddsn <id> <name>  - create a dd-set with id and name.\n");
454 	printf("del dd   <id>   - delete a dd.\n");
455 	printf("del dds  <id>   - delete a dd-set.\n");
456 
457 	printf("\n");
458 	printf("add dd   <dd_id>  <node_name> - add a node to dd.\n");
459 	printf("add ddn  <dd_id>  <node_id>   - add a node to dd.\n");
460 	printf("add ddsn <dds_id> <dd_id>     - add a dd to dd-set.\n");
461 	printf("remove dd   <dd_id> <node_name> - remove a node from dd.\n");
462 	printf("remove ddn  <dd_id> <node_id>   - remove a node from dd.\n");
463 	printf("remove ddsn <dds_id> <dd_id>    - remove a dd from dd-set.\n");
464 
465 	printf("\n");
466 	printf("enable  <dds_id> - enable a dd-set.\n");
467 	printf("disable <dds_id> - disable a dd-set.\n");
468 
469 	printf("\n");
470 	printf("file <f> - loading command from a file.\n");
471 	printf("pause    - suspend batch until enter key is pressed.\n");
472 
473 	printf("help   - print this help.\n");
474 	printf("quit   - stop iSNS server and quit.\n");
475 }
476 
477 enum {
478 	CMD_LIST, CMD_LISTNE, CMD_LISTP, CMD_LISTPG,
479 	CMD_LISTDD, CMD_LISTDDS, CMD_LISTDDN, CMD_LISTDDSN,
480 	CMD_NEWDD, CMD_NEWDDS, CMD_NEWDDN, CMD_NEWDDSN,
481 	CMD_DELDD, CMD_DELDDS,
482 	CMD_ENABLE, CMD_DISABLE,
483 	CMD_ADDDD, CMD_ADDDDN, CMD_ADDDDSN,
484 	CMD_REMDD, CMD_REMDDN, CMD_REMDDSN,
485 	CMD_VIEW,
486 	CMD_FILE, CMD_PAUSE,
487 	CMD_HELP,
488 	CMD_VERBOSE_MEMORY, CMD_VERBOSE_NET,
489 	CMD_VERBOSE_PARSER, CMD_VERBOSE_TIME,
490 	CMD_VERBOSE_LOCK,
491 	CMD_QUIT,
492 	CMD_NONE, CMD_INVALID
493 };
494 
495 static int
getcmd(int * argc,int * argv,char * cmd)496 getcmd(
497 	int *argc, int *argv, char *cmd
498 )
499 {
500 	int j = 0;
501 	char tmp[256] = { 0 };
502 	*argc = 0;
503 	while (*cmd == ' ') cmd ++;
504 
505 	if (*cmd == 0) {
506 		return (CMD_NONE);
507 	} else if (*cmd == '?') {
508 		return (CMD_HELP);
509 	}
510 
511 	/* list, list dd, list dds, list dd 0 */
512 	if (strncmp(cmd, "list ", 5) == 0) {
513 		cmd += 5;
514 		while (*cmd == ' ') cmd ++;
515 		if (*cmd == 0) {
516 			return (CMD_LIST);
517 		} else if (*cmd == 'p') {
518 			cmd ++;
519 			while (*cmd == ' ') cmd ++;
520 			if (*cmd == 0) {
521 				return (CMD_LISTP);
522 			}
523 		} else if (*cmd == 'g') {
524 			cmd ++;
525 			while (*cmd == ' ') cmd ++;
526 			if (*cmd == 0) {
527 				return (CMD_LISTPG);
528 			}
529 		} else if (*cmd == 'e') {
530 			cmd ++;
531 			while (*cmd == ' ') cmd ++;
532 			if (*cmd == 0) {
533 				return (CMD_LISTNE);
534 			}
535 		} else if (strncmp(cmd, "dds ", 4) == 0) {
536 			cmd += 4;
537 			while (*cmd == ' ') cmd ++;
538 			if (*cmd == 0) {
539 				return (CMD_LISTDDS);
540 			}
541 			j = 0;
542 			while (*cmd >= '0' && *cmd <= '9') {
543 				tmp[j++] = *cmd ++;
544 			}
545 			tmp[j] = 0;
546 			while (*cmd == ' ') cmd ++;
547 			if (*cmd == 0 && j > 0) {
548 				argv[(*argc)++] = atoi(tmp);
549 				return (CMD_LISTDDSN);
550 			}
551 		} else if (strncmp(cmd, "dd ", 3) == 0) {
552 			cmd += 3;
553 			while (*cmd == ' ') cmd ++;
554 			if (*cmd == 0) {
555 				return (CMD_LISTDD);
556 			}
557 			j = 0;
558 			while (*cmd >= '0' && *cmd <= '9') {
559 				tmp[j++] = *cmd ++;
560 			}
561 			tmp[j] = 0;
562 			while (*cmd == ' ') cmd ++;
563 			if (*cmd == 0 && j > 0) {
564 				argv[(*argc)++] = atoi(tmp);
565 				return (CMD_LISTDDN);
566 			}
567 		}
568 		return (CMD_INVALID);
569 	}
570 
571 	/* view 0 */
572 	if (strncmp(cmd, "view ", 5) == 0) {
573 		cmd += 5;
574 		while (*cmd == ' ') cmd ++;
575 		j = 0;
576 		while (*cmd >= '0' && *cmd <= '9') {
577 			tmp[j++] = *cmd ++;
578 		}
579 		tmp[j] = 0;
580 		while (*cmd == ' ') cmd ++;
581 		if (*cmd == 0 && j > 0) {
582 			argv[(*argc)++] = atoi(tmp);
583 			return (CMD_VIEW);
584 		}
585 		return (CMD_INVALID);
586 	}
587 
588 	/* add dd name */
589 	/* add ddn/ddsn id id */
590 	if (strncmp(cmd, "add ", 4) == 0) {
591 		int addcmd = CMD_INVALID;
592 		cmd += 4;
593 		while (*cmd == ' ') cmd ++;
594 		if (strncmp(cmd, "dd ", 3) == 0) {
595 			cmd += 3;
596 			addcmd = CMD_ADDDD;
597 		} else if (strncmp(cmd, "ddn ", 4) == 0) {
598 			cmd += 4;
599 			addcmd = CMD_ADDDDN;
600 		} else if (strncmp(cmd, "ddsn ", 5) == 0) {
601 			cmd += 5;
602 			addcmd = CMD_ADDDDSN;
603 		} else {
604 			return (CMD_INVALID);
605 		}
606 		while (*cmd == ' ') cmd ++;
607 		j = 0;
608 		while (*cmd >= '0' && *cmd <= '9') {
609 			tmp[j++] = *cmd ++;
610 		}
611 		tmp[j] = 0;
612 		if (j > 0) {
613 			argv[(*argc)++] = atoi(tmp);
614 		} else {
615 			return (CMD_INVALID);
616 		}
617 		while (*cmd == ' ') cmd ++;
618 		if (*cmd != 0) {
619 			switch (addcmd) {
620 			case CMD_ADDDDN:
621 			case CMD_ADDDDSN:
622 				j = 0;
623 				while (*cmd >= '0' && *cmd <= '9') {
624 					tmp[j++] = *cmd ++;
625 				}
626 				tmp[j] = 0;
627 				while (*cmd == ' ') cmd ++;
628 				if (*cmd == 0 && j > 0) {
629 					argv[(*argc)++] = atoi(tmp);
630 				} else {
631 					return (CMD_INVALID);
632 				}
633 				break;
634 			case CMD_ADDDD:
635 				j = strlen(cmd);
636 				while (j > 0) {
637 					/* get rid of trail blank space */
638 					if (cmd[j - 1] == ' ') {
639 						cmd[--j] = 0;
640 					} else {
641 						break;
642 					}
643 				}
644 				if (j > 0) {
645 					cmd[j] = 0;
646 					argv[(*argc)++] = (int)cmd;
647 				} else {
648 					return (CMD_INVALID);
649 				}
650 				break;
651 			}
652 			return (addcmd);
653 		}
654 		return (CMD_INVALID);
655 	}
656 
657 	/* remove dd name */
658 	/* remove ddn/ddsn id id */
659 	if (strncmp(cmd, "remove ", 7) == 0) {
660 		int rmcmd = CMD_INVALID;
661 		cmd += 7;
662 		while (*cmd == ' ') cmd ++;
663 		if (strncmp(cmd, "dd ", 3) == 0) {
664 			cmd += 3;
665 			while (*cmd == ' ') cmd ++;
666 			rmcmd = CMD_REMDD;
667 		} else if (strncmp(cmd, "ddn ", 4) == 0) {
668 			cmd += 4;
669 			while (*cmd == ' ') cmd ++;
670 			rmcmd = CMD_REMDDN;
671 		} else if (strncmp(cmd, "ddsn ", 5) == 0) {
672 			cmd += 5;
673 			while (*cmd == ' ') cmd ++;
674 			rmcmd = CMD_REMDDSN;
675 		} else {
676 			return (CMD_INVALID);
677 		}
678 		j = 0;
679 		while (*cmd >= '0' && *cmd <= '9') {
680 			tmp[j++] = *cmd ++;
681 		}
682 		tmp[j] = 0;
683 		if (j > 0) {
684 			argv[(*argc)++] = atoi(tmp);
685 		} else {
686 			return (CMD_INVALID);
687 		}
688 		while (*cmd == ' ') cmd ++;
689 		if (*cmd != 0) {
690 			switch (rmcmd) {
691 			case CMD_REMDDN:
692 			case CMD_REMDDSN:
693 				j = 0;
694 				while (*cmd >= '0' && *cmd <= '9') {
695 					tmp[j++] = *cmd ++;
696 				}
697 				tmp[j] = 0;
698 				while (*cmd == ' ') cmd ++;
699 				if (*cmd == 0 && j > 0) {
700 					argv[(*argc)++] = atoi(tmp);
701 				} else {
702 					return (CMD_INVALID);
703 				}
704 				break;
705 			case CMD_REMDD:
706 				j = strlen(cmd);
707 				while (j > 0) {
708 					/* get rid of trail blank space */
709 					if (cmd[j - 1] == ' ') {
710 						cmd[--j] = 0;
711 					} else {
712 						break;
713 					}
714 				}
715 				if (j > 0) {
716 					cmd[j] = 0;
717 					argv[(*argc)++] = (int)cmd;
718 				} else {
719 					return (CMD_INVALID);
720 				}
721 				break;
722 			}
723 			return (rmcmd);
724 		}
725 		return (CMD_INVALID);
726 	}
727 
728 	/* new dd, new dds */
729 	if (strncmp(cmd, "new ", 4) == 0) {
730 		int newcmd = CMD_INVALID;
731 		cmd += 4;
732 		while (*cmd == ' ') cmd ++;
733 		if (strncmp(cmd, "dd ", 3) == 0) {
734 			cmd += 3;
735 			newcmd = CMD_NEWDD;
736 		} else if (strncmp(cmd, "dds ", 4) == 0) {
737 			cmd += 4;
738 			newcmd = CMD_NEWDDS;
739 		} else if (strncmp(cmd, "ddn ", 4) == 0) {
740 			cmd += 4;
741 			newcmd = CMD_NEWDDN;
742 		} else if (strncmp(cmd, "ddsn ", 5) == 0) {
743 			cmd += 5;
744 			newcmd = CMD_NEWDDSN;
745 		}
746 		if (newcmd != CMD_INVALID) {
747 			while (*cmd == ' ') cmd ++;
748 			if (*cmd == 0) {
749 				return (newcmd);
750 			}
751 			switch (newcmd) {
752 			case CMD_NEWDDN:
753 			case CMD_NEWDDSN:
754 				j = 0;
755 				while (*cmd >= '0' && *cmd <= '9') {
756 					tmp[j++] = *cmd ++;
757 				}
758 				tmp[j] = 0;
759 				if (*cmd == ' ' && j > 0) {
760 					argv[(*argc)++] = atoi(tmp);
761 				} else {
762 					return (CMD_INVALID);
763 				}
764 			case CMD_NEWDD:
765 			case CMD_NEWDDS:
766 				while (*cmd == ' ') cmd ++;
767 				if (*cmd != 0) {
768 					j = strlen(cmd);
769 				} else {
770 					j = 0;
771 				}
772 				while (j > 0) {
773 					/* get rid of trail blank space */
774 					if (cmd[j - 1] == ' ') {
775 						cmd[--j] = 0;
776 					} else {
777 						break;
778 					}
779 				}
780 				if (j > 0) {
781 					cmd[j] = 0;
782 					argv[(*argc)++] = (int)cmd;
783 				}
784 			}
785 			return (newcmd);
786 		}
787 		return (CMD_INVALID);
788 	}
789 
790 	/* del dd, del dds, disable 0 */
791 	if (strncmp(cmd, "del ", 4) == 0) {
792 		int delcmd = CMD_INVALID;
793 		cmd += 4;
794 		while (*cmd == ' ') cmd ++;
795 		if (strncmp(cmd, "dds ", 4) == 0) {
796 			cmd += 4;
797 			delcmd = CMD_DELDDS;
798 		} else if (strncmp(cmd, "dd ", 3) == 0) {
799 			cmd += 3;
800 			delcmd = CMD_DELDD;
801 		}
802 		if (delcmd != CMD_INVALID) {
803 			while (*cmd == ' ') cmd ++;
804 			j = 0;
805 			while (*cmd >= '0' && *cmd <= '9') {
806 				tmp[j++] = *cmd ++;
807 			}
808 			tmp[j] = 0;
809 			while (*cmd == ' ') cmd ++;
810 			if (*cmd == 0 && j > 0) {
811 				argv[(*argc)++] = atoi(tmp);
812 				return (delcmd);
813 			}
814 		}
815 		return (CMD_INVALID);
816 	}
817 
818 	/* enable 0 */
819 	if (strncmp(cmd, "enable ", 7) == 0) {
820 		cmd += 7;
821 		while (*cmd == ' ') cmd ++;
822 		j = 0;
823 		while (*cmd >= '0' && *cmd <= '9') {
824 			tmp[j++] = *cmd ++;
825 		}
826 		tmp[j] = 0;
827 		while (*cmd == ' ') cmd ++;
828 		if (*cmd == 0 && j > 0) {
829 			argv[(*argc)++] = atoi(tmp);
830 			return (CMD_ENABLE);
831 		}
832 		return (CMD_INVALID);
833 	}
834 
835 	/* disable 0 */
836 	if (strncmp(cmd, "disable ", 8) == 0) {
837 		cmd += 8;
838 		while (*cmd == ' ') cmd ++;
839 		j = 0;
840 		while (*cmd >= '0' && *cmd <= '9') {
841 			tmp[j++] = *cmd ++;
842 		}
843 		tmp[j] = 0;
844 		while (*cmd == ' ') cmd ++;
845 		if (*cmd == 0 && j > 0) {
846 			argv[(*argc)++] = atoi(tmp);
847 			return (CMD_DISABLE);
848 		}
849 		return (CMD_INVALID);
850 	}
851 
852 	/* file */
853 	if (strncmp(cmd, "file ", 5) == 0) {
854 		cmd += 5;
855 		while (*cmd == ' ') cmd ++;
856 		if (*cmd != 0) {
857 			j = strlen(cmd);
858 		} else {
859 			j = 0;
860 		}
861 		while (j > 0) {
862 			/* get rid of trail blank space */
863 			if (cmd[j - 1] == ' ') {
864 				cmd[--j] = 0;
865 			} else {
866 				break;
867 			}
868 		}
869 		if (j > 0) {
870 			cmd[j] = 0;
871 			argv[(*argc)++] = (int)cmd;
872 			return (CMD_FILE);
873 		}
874 		return (CMD_INVALID);
875 	}
876 
877 	/* pause */
878 	if (strncmp(cmd, "pause ", 6) == 0) {
879 		cmd += 6;
880 		while (*cmd == ' ') cmd ++;
881 		if (*cmd == 0) {
882 			return (CMD_PAUSE);
883 		}
884 		return (CMD_INVALID);
885 	}
886 
887 	/* help */
888 	if (strncmp(cmd, "help ", 5) == 0) {
889 		cmd += 5;
890 		while (*cmd == ' ') cmd ++;
891 		if (*cmd == 0) {
892 			return (CMD_HELP);
893 		}
894 		return (CMD_INVALID);
895 	}
896 
897 	/* verbose */
898 	if (strncmp(cmd, "verbose ", 8) == 0) {
899 		cmd += 8;
900 		while (*cmd == ' ') cmd ++;
901 		if (*cmd == 0) {
902 			return (CMD_VERBOSE_PARSER);
903 		} else if (*cmd == 'm') {
904 			cmd ++;
905 			while (*cmd == ' ') cmd ++;
906 			if (*cmd == 0) {
907 				return (CMD_VERBOSE_MEMORY);
908 			}
909 		} else if (*cmd == 'n') {
910 			cmd ++;
911 			while (*cmd == ' ') cmd ++;
912 			if (*cmd == 0) {
913 				return (CMD_VERBOSE_NET);
914 			}
915 		} else if (*cmd == 'p') {
916 			cmd ++;
917 			while (*cmd == ' ') cmd ++;
918 			if (*cmd == 0) {
919 				return (CMD_VERBOSE_PARSER);
920 			}
921 		} else if (*cmd == 't') {
922 			cmd ++;
923 			while (*cmd == ' ') cmd ++;
924 			if (*cmd == 0) {
925 				return (CMD_VERBOSE_TIME);
926 			}
927 		} else if (*cmd == 'l') {
928 			cmd ++;
929 			while (*cmd == ' ') cmd ++;
930 			if (*cmd == 0) {
931 				return (CMD_VERBOSE_LOCK);
932 			}
933 		}
934 		return (CMD_INVALID);
935 	}
936 
937 	/* quit */
938 	if (strncmp(cmd, "quit ", 5) == 0) {
939 		cmd += 5;
940 		while (*cmd == ' ') cmd ++;
941 		if (*cmd == 0) {
942 			return (CMD_QUIT);
943 		}
944 		return (CMD_INVALID);
945 	}
946 
947 	return (CMD_INVALID);
948 }
949 
950 static void
print_entity(char * ident,isns_obj_t * obj)951 print_entity(
952 	char *ident,
953 	isns_obj_t *obj
954 )
955 {
956 	uint32_t uid;
957 	uchar_t *eid;
958 	uint32_t *cuid;
959 	int i, num;
960 
961 	eid = obj->attrs[
962 	    ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)].value.ptr;
963 	uid = get_obj_uid(obj);
964 
965 	if (ident != NULL) {
966 		printf("%s%d\t%s\n", ident, uid, (const char *)eid);
967 	} else {
968 		printf("%d\t%s\n", uid, (const char *)eid);
969 	}
970 
971 	i = 0;
972 	while (i < NUM_OF_CHILD[obj->type]) {
973 		cuid = get_child_n(obj, i);
974 		if (ident != NULL) {
975 			printf("%s\t%s%d:", "child", i);
976 		} else {
977 			printf("\t%s%d:", "child", i);
978 		}
979 		if (cuid != NULL) {
980 			num = *cuid ++;
981 		} else {
982 			num = 0;
983 		}
984 		while (num > 0) {
985 			printf("\t%d", *cuid ++);
986 			num --;
987 		}
988 		printf("\n");
989 		i ++;
990 	}
991 }
992 
993 static void
print_iscsi(char * ident,isns_obj_t * obj)994 print_iscsi(
995 	char *ident,
996 	isns_obj_t *obj
997 )
998 {
999 	uchar_t *name = obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)]
1000 	    .value.ptr;
1001 	uchar_t *alias = obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_ALIAS_ATTR_ID)]
1002 	    .value.ptr;
1003 	uint32_t type = obj->attrs[
1004 	    ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui;
1005 	uint32_t uid = get_obj_uid(obj);
1006 	uint32_t puid = get_parent_uid(obj);
1007 
1008 	if (!alias) {
1009 		alias = (uchar_t *)"-";
1010 	}
1011 
1012 	if (ident != NULL) {
1013 		printf("%s%d[%d]\t%s\n", ident,
1014 		    uid, puid, (const char *)name);
1015 		printf("%s\t%s", ident, alias);
1016 	} else {
1017 		printf("%d[%d]\t%s\n",
1018 		    uid, puid, (const char *)name);
1019 		printf("\t%s", alias);
1020 	}
1021 	if (IS_TYPE_TARGET(type)) {
1022 		printf("\tTarget");
1023 	}
1024 	if (IS_TYPE_INITIATOR(type)) {
1025 		printf("\tInitiator");
1026 	}
1027 	if (IS_TYPE_CONTROL(type)) {
1028 		printf("\tControl");
1029 	}
1030 	if (IS_TYPE_UNKNOWN(type)) {
1031 		printf("\t-");
1032 	}
1033 	printf("\n");
1034 }
1035 
1036 static void
print_portal(char * ident,isns_obj_t * obj)1037 print_portal(
1038 	char *ident,
1039 	isns_obj_t *obj
1040 )
1041 {
1042 	char pbuff[256] = { 0 };
1043 	in6_addr_t *ip = obj->attrs[
1044 	    ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)].value.ip;
1045 	uint32_t port = obj->attrs[
1046 	    ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)].value.ui;
1047 	uint32_t uid = get_obj_uid(obj);
1048 	uint32_t puid = get_parent_uid(obj);
1049 
1050 	inet_ntop(AF_INET6, (void *)ip, pbuff, sizeof (pbuff));
1051 	if (ident != NULL) {
1052 		printf("%s%d[%d]\t%s:%d", ident,
1053 		    uid, puid, pbuff, PORT_NUMBER(port));
1054 	} else {
1055 		printf("%d[%d]\t%s:%d",
1056 		    uid, puid, pbuff, PORT_NUMBER(port));
1057 	}
1058 	printf(" %s\n", IS_PORT_UDP(port) ? "UDP" : "TCP");
1059 }
1060 
1061 static void
print_pg(char * ident,isns_obj_t * obj)1062 print_pg(
1063 	char *ident,
1064 	isns_obj_t *obj
1065 )
1066 {
1067 	uint32_t ref;
1068 	int i;
1069 
1070 	char pbuff[256] = { 0 };
1071 	uchar_t *name = obj->attrs[ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID)]
1072 	    .value.ptr;
1073 	in6_addr_t *ip = obj->attrs[
1074 	    ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)].value.ip;
1075 	uint32_t port = obj->attrs[
1076 	    ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID)].value.ui;
1077 	uint32_t tag = obj->attrs[
1078 	    ATTR_INDEX_PG(ISNS_PG_TAG_ATTR_ID)].value.ui;
1079 	uint32_t uid = get_obj_uid(obj);
1080 	uint32_t puid = get_parent_uid(obj);
1081 
1082 	inet_ntop(AF_INET6, (void *)ip, pbuff, sizeof (pbuff));
1083 	if (ident != NULL) {
1084 		printf("%s%d[%d]\t[%d] %s\n", ident,
1085 		    uid, puid, tag, (const char *)name);
1086 		printf("%s\t%s:%d", ident, pbuff, PORT_NUMBER(port));
1087 	} else {
1088 		printf("%d[%d]\t[%d] %s\n",
1089 		    uid, puid, tag, (const char *)name);
1090 		printf("\t%s:%d", pbuff, PORT_NUMBER(port));
1091 	}
1092 	printf(" %s\n", IS_PORT_UDP(port) ? "UDP" : "TCP");
1093 
1094 	if (NUM_OF_REF[obj->type] > 0) {
1095 		if (ident != NULL) {
1096 			printf("%s\t%s:", "ref");
1097 		} else {
1098 			printf("\t%s:", "ref");
1099 		}
1100 	}
1101 	i = 0;
1102 	while (i < NUM_OF_REF[obj->type]) {
1103 		ref = get_ref_n(obj, i);
1104 		printf("\t%d", ref);
1105 		i ++;
1106 	}
1107 	if (i > 0) {
1108 		printf("\n");
1109 	}
1110 }
1111 
1112 static void
print_dd(char * ident,isns_obj_t * obj)1113 print_dd(
1114 	char *ident,
1115 	isns_obj_t *obj
1116 )
1117 {
1118 	uchar_t *name = obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)]
1119 	    .value.ptr;
1120 	uint32_t uid = obj->attrs[UID_ATTR_INDEX[OBJ_DD]].value.ui;
1121 
1122 	if (ident != NULL) {
1123 		printf("%s%d\t%s\n", ident, uid, (const char *)name);
1124 	} else {
1125 		printf("%d\t%s\n", uid, (const char *)name);
1126 	}
1127 }
1128 
1129 static void
print_dds(char * ident,isns_obj_t * obj)1130 print_dds(
1131 	char *ident,
1132 	isns_obj_t *obj
1133 )
1134 {
1135 	uchar_t *name = obj->attrs[ATTR_INDEX_DDS(
1136 	    ISNS_DD_SET_NAME_ATTR_ID)].value.ptr;
1137 	uint32_t uid = obj->attrs[UID_ATTR_INDEX[OBJ_DDS]].value.ui;
1138 	uint32_t enabled = obj->attrs[ATTR_INDEX_DDS(
1139 	    ISNS_DD_SET_STATUS_ATTR_ID)].value.ui;
1140 
1141 	if (ident != NULL) {
1142 		printf("%s%d\t%s\t\t(%s)\n", ident, uid,
1143 		    (const char *)name, enabled ? "enabled" : "disabled");
1144 	} else {
1145 		printf("%d\t%s\t\t(%s)\n", uid,
1146 		    (const char *)name, enabled ? "enabled" : "disabled");
1147 	}
1148 }
1149 
1150 void
print_object(char * ident,isns_obj_t * obj)1151 print_object(
1152 	char *ident,
1153 	isns_obj_t *obj
1154 )
1155 {
1156 	print_func[obj->type](ident, obj);
1157 }
1158 
1159 /*ARGSUSED*/
1160 static int
cb_print_obj_n(void * p1,void * p2)1161 cb_print_obj_n(
1162 	void *p1,
1163 	void *p2
1164 )
1165 {
1166 	isns_obj_t *obj = (isns_obj_t *)p1;
1167 	print_func[obj->type](NULL, obj);
1168 
1169 	return (0);
1170 }
1171 
1172 static void
list_pg()1173 list_pg(
1174 )
1175 {
1176 	cache_dump_htab(OBJ_PG);
1177 }
1178 
1179 static void
list_portal()1180 list_portal(
1181 )
1182 {
1183 	cache_dump_htab(OBJ_PORTAL);
1184 }
1185 
1186 static void
list_node()1187 list_node(
1188 )
1189 {
1190 	cache_dump_htab(OBJ_ISCSI);
1191 }
1192 
1193 static void
list_entity()1194 list_entity(
1195 )
1196 {
1197 	cache_dump_htab(OBJ_ENTITY);
1198 }
1199 
1200 static void
list_dd()1201 list_dd(
1202 )
1203 {
1204 	cache_dump_htab(OBJ_DD);
1205 }
1206 
1207 static void
list_ddn(uint32_t uid)1208 list_ddn(
1209 	uint32_t uid
1210 )
1211 {
1212 	lookup_ctrl_t lc;
1213 
1214 	bmp_t *p;
1215 	uint32_t n;
1216 
1217 	if (uid != 0) {
1218 		setup_ddid_lcp(&lc, uid);
1219 		cache_lookup(&lc, &uid, cb_print_obj_n);
1220 	}
1221 
1222 	if (uid != 0) {
1223 		printf("--------------------------------\n");
1224 		get_dd_matrix(uid, &p, &n);
1225 		SET_UID_LCP(&lc, OBJ_ISCSI, 0);
1226 		FOR_EACH_MEMBER(p, n, uid, {
1227 			lc.data[0].ui = uid;
1228 			cache_lookup(&lc, NULL, cb_print_obj_n);
1229 		});
1230 		free(p);
1231 	} else {
1232 		printf("no such dd.\n");
1233 	}
1234 }
1235 
1236 static void
list_ddsn(uint32_t uid)1237 list_ddsn(
1238 	uint32_t uid
1239 )
1240 {
1241 	lookup_ctrl_t lc;
1242 
1243 	bmp_t *p;
1244 	uint32_t n;
1245 
1246 	if (uid != 0) {
1247 		setup_ddsid_lcp(&lc, uid);
1248 		cache_lookup(&lc, &uid, cb_print_obj_n);
1249 	}
1250 
1251 	if (uid != 0) {
1252 		printf("--------------------------------\n");
1253 		get_dds_matrix(uid, &p, &n);
1254 		SET_UID_LCP(&lc, OBJ_DD, 0);
1255 		FOR_EACH_MEMBER(p, n, uid, {
1256 			lc.data[0].ui = uid;
1257 			cache_lookup(&lc, NULL, cb_print_obj_n);
1258 		});
1259 		free(p);
1260 	} else {
1261 		printf("no such dd-set.\n");
1262 	}
1263 }
1264 
1265 static void
list_dds()1266 list_dds(
1267 )
1268 {
1269 	cache_dump_htab(OBJ_DDS);
1270 }
1271 
1272 static void
new_dd_dds(int cmd_id,int argc,int * argv)1273 new_dd_dds(
1274 	int cmd_id,
1275 	int argc,
1276 	int *argv
1277 )
1278 {
1279 	uint32_t buff[256];
1280 	isns_pdu_t *pdu = (isns_pdu_t *)buff;
1281 	uint8_t *payload = &pdu->payload[0];
1282 	uint16_t payload_len = 0;
1283 	isns_tlv_t *tlv;
1284 
1285 	int len = 0;
1286 	uint32_t uid = 0;
1287 	char *name;
1288 
1289 	conn_arg_t conn;
1290 
1291 	pdu->version = ISNSP_VERSION;
1292 
1293 	/* source attribute */
1294 	tlv = (isns_tlv_t *)payload;
1295 	tlv->attr_id = htonl(ISNS_ISCSI_NAME_ATTR_ID);
1296 	tlv->attr_len = htonl(32);
1297 	strcpy((char *)tlv->attr_value, "i am a control node.");
1298 	payload += 8 + 32;
1299 	payload_len += 8 + 32;
1300 
1301 	/* key attributes */
1302 
1303 	/* delimiter */
1304 	tlv = (isns_tlv_t *)payload;
1305 	tlv->attr_id = htonl(ISNS_DELIMITER_ATTR_ID);
1306 	tlv->attr_len = htonl(0);
1307 	payload += 8 + 0;
1308 	payload_len += 8 + 0;
1309 
1310 	/* operating attributes */
1311 	switch (cmd_id) {
1312 	case CMD_NEWDD:
1313 		pdu->func_id = ISNS_DD_REG;
1314 		if (argc == 1) {
1315 			name = (char *)argv[0];
1316 			len = strlen(name) + 1;
1317 			len += 4 - (len % 4);
1318 		}
1319 		tlv = (isns_tlv_t *)payload;
1320 		tlv->attr_id = htonl(ISNS_DD_NAME_ATTR_ID);
1321 		tlv->attr_len = htonl(len);
1322 		if (len > 0) {
1323 			strcpy((char *)tlv->attr_value, name);
1324 		}
1325 		payload_len += 8 + len;
1326 		break;
1327 	case CMD_NEWDDS:
1328 		pdu->func_id = ISNS_DDS_REG;
1329 		if (argc == 1) {
1330 			name = (char *)argv[0];
1331 			len = strlen(name) + 1;
1332 			len += 4 - (len % 4);
1333 		}
1334 		tlv = (isns_tlv_t *)payload;
1335 		tlv->attr_id = htonl(ISNS_DD_SET_NAME_ATTR_ID);
1336 		tlv->attr_len = htonl(len);
1337 		if (len > 0) {
1338 			strcpy((char *)tlv->attr_value, name);
1339 		}
1340 		payload_len += 8 + len;
1341 		break;
1342 	case CMD_NEWDDN:
1343 		pdu->func_id = ISNS_DD_REG;
1344 		switch (argc) {
1345 		case 2:
1346 			name = (char *)argv[1];
1347 			len = strlen(name) + 1;
1348 			len += 4 - (len % 4);
1349 			/* FALLTHROUGH */
1350 		case 1:
1351 			uid = argv[0];
1352 		}
1353 		tlv = (isns_tlv_t *)payload;
1354 		tlv->attr_id = htonl(ISNS_DD_NAME_ATTR_ID);
1355 		tlv->attr_len = htonl(len);
1356 		if (len > 0) {
1357 			strcpy((char *)tlv->attr_value, name);
1358 		}
1359 		payload += 8 + len;
1360 		payload_len += 8 + len;
1361 		if (uid > 0) {
1362 			tlv = (isns_tlv_t *)payload;
1363 			tlv->attr_id = htonl(ISNS_DD_ID_ATTR_ID);
1364 			tlv->attr_len = htonl(4);
1365 			*(uint32_t *)tlv->attr_value = htonl(uid);
1366 			payload_len += 8 + 4;
1367 		}
1368 		break;
1369 	case CMD_NEWDDSN:
1370 		pdu->func_id = ISNS_DDS_REG;
1371 		switch (argc) {
1372 		case 2:
1373 			name = (char *)argv[1];
1374 			len = strlen(name) + 1;
1375 			len += 4 - (len % 4);
1376 			/* FALLTHROUGH */
1377 		case 1:
1378 			uid = argv[0];
1379 		}
1380 		tlv = (isns_tlv_t *)payload;
1381 		tlv->attr_id = htonl(ISNS_DD_SET_NAME_ATTR_ID);
1382 		tlv->attr_len = htonl(len);
1383 		if (len > 0) {
1384 			strcpy((char *)tlv->attr_value, name);
1385 		}
1386 		payload_len += 8 + len;
1387 		payload += 8 + len;
1388 		if (uid > 0) {
1389 			tlv = (isns_tlv_t *)payload;
1390 			tlv->attr_id = htonl(ISNS_DD_SET_ID_ATTR_ID);
1391 			tlv->attr_len = htonl(4);
1392 			*(uint32_t *)tlv->attr_value = htonl(uid);
1393 			payload_len += 8 + 4;
1394 		}
1395 		break;
1396 	default:
1397 		break;
1398 	}
1399 
1400 	pdu->payload_len = payload_len;
1401 
1402 	dump_pdu1(pdu);
1403 
1404 	conn.in_packet.pdu = pdu;
1405 	conn.out_packet.pdu = NULL;
1406 	conn.out_packet.sz = 0;
1407 
1408 	if (packet_split_verify(&conn) == 0) {
1409 		cache_lock(conn.lock);
1410 		conn.handler(&conn);
1411 		conn.ec = cache_unlock(conn.lock, conn.ec);
1412 	}
1413 
1414 	if (conn.out_packet.pdu != NULL) {
1415 		pdu_update_code(conn.out_packet.pdu,
1416 		    &conn.out_packet.pl, conn.ec);
1417 		dump_pdu2(conn.out_packet.pdu);
1418 		free(conn.out_packet.pdu);
1419 	} else if (conn.ec != 0) {
1420 		printf("operation failed[%d].\n", conn.ec);
1421 	}
1422 }
1423 
1424 static void
del_dd_dds(int cmd_id,int uid)1425 del_dd_dds(
1426 	int cmd_id,
1427 	int uid
1428 )
1429 {
1430 	uint32_t buff[256];
1431 	isns_pdu_t *pdu = (isns_pdu_t *)buff;
1432 	uint8_t *payload = &pdu->payload[0];
1433 	uint16_t payload_len = 0;
1434 	isns_tlv_t *tlv;
1435 
1436 	uint32_t tag;
1437 
1438 	conn_arg_t conn;
1439 
1440 	if (uid == 0) {
1441 		return;
1442 	}
1443 
1444 	pdu->version = ISNSP_VERSION;
1445 
1446 	if (cmd_id == CMD_DELDD) {
1447 		tag = ISNS_DD_ID_ATTR_ID;
1448 		pdu->func_id = ISNS_DD_DEREG;
1449 	} else {
1450 		tag = ISNS_DD_SET_ID_ATTR_ID;
1451 		pdu->func_id = ISNS_DDS_DEREG;
1452 	}
1453 
1454 	/* source attribute */
1455 	tlv = (isns_tlv_t *)payload;
1456 	tlv->attr_id = htonl(ISNS_ISCSI_NAME_ATTR_ID);
1457 	tlv->attr_len = htonl(32);
1458 	strcpy((char *)tlv->attr_value, "i am a control node.");
1459 	payload_len += 8 + 32;
1460 	payload += 8 + 32;
1461 
1462 	/* key attributes */
1463 	tlv = (isns_tlv_t *)payload;
1464 	tlv->attr_id = htonl(tag);
1465 	tlv->attr_len = htonl(4);
1466 	*(uint32_t *)tlv->attr_value = htonl(uid);
1467 	payload_len += 8 + 4;
1468 	payload += 8 + 4;
1469 
1470 	/* delimiter */
1471 	tlv = (isns_tlv_t *)payload;
1472 	tlv->attr_id = htonl(ISNS_DELIMITER_ATTR_ID);
1473 	tlv->attr_len = htonl(0);
1474 	payload_len += 8 + 0;
1475 	payload += 8 + 0;
1476 
1477 	/* operating attributes */
1478 
1479 	pdu->payload_len = payload_len;
1480 
1481 	dump_pdu1(pdu);
1482 
1483 	conn.in_packet.pdu = pdu;
1484 	conn.out_packet.pdu = NULL;
1485 	conn.out_packet.sz = 0;
1486 
1487 	if (packet_split_verify(&conn) == 0) {
1488 		cache_lock(conn.lock);
1489 		conn.handler(&conn);
1490 		conn.ec = cache_unlock(conn.lock, conn.ec);
1491 	}
1492 
1493 	if (conn.out_packet.pdu != NULL) {
1494 		pdu_update_code(conn.out_packet.pdu,
1495 		    &conn.out_packet.pl, conn.ec);
1496 		dump_pdu2(conn.out_packet.pdu);
1497 		free(conn.out_packet.pdu);
1498 	} else if (conn.ec != 0) {
1499 		printf("operation failed[%d].\n", conn.ec);
1500 	}
1501 }
1502 
1503 static void
update_dds(int cmd_id,int uid)1504 update_dds(
1505 	int cmd_id,
1506 	int uid
1507 )
1508 {
1509 	uint32_t buff[256];
1510 	isns_pdu_t *pdu = (isns_pdu_t *)buff;
1511 	uint8_t *payload = &pdu->payload[0];
1512 	uint16_t payload_len = 0;
1513 	isns_tlv_t *tlv;
1514 
1515 	conn_arg_t conn;
1516 
1517 	if (uid == 0) {
1518 		return;
1519 	}
1520 
1521 	pdu->version = ISNSP_VERSION;
1522 
1523 	pdu->func_id = ISNS_DDS_REG;
1524 
1525 	/* source attribute */
1526 	tlv = (isns_tlv_t *)payload;
1527 	tlv->attr_id = htonl(ISNS_ISCSI_NAME_ATTR_ID);
1528 	tlv->attr_len = htonl(32);
1529 	strcpy((char *)tlv->attr_value, "i am a control node.");
1530 	payload_len += 8 + 32;
1531 	payload += 8 + 32;
1532 
1533 	/* key attributes */
1534 	tlv = (isns_tlv_t *)payload;
1535 	tlv->attr_id = htonl(ISNS_DD_SET_ID_ATTR_ID);
1536 	tlv->attr_len = htonl(4);
1537 	*(uint32_t *)tlv->attr_value = htonl(uid);
1538 	payload_len += 8 + 4;
1539 	payload += 8 + 4;
1540 
1541 	/* delimiter */
1542 	tlv = (isns_tlv_t *)payload;
1543 	tlv->attr_id = htonl(ISNS_DELIMITER_ATTR_ID);
1544 	tlv->attr_len = htonl(0);
1545 	payload_len += 8 + 0;
1546 	payload += 8 + 0;
1547 
1548 	/* operating attributes */
1549 	tlv = (isns_tlv_t *)payload;
1550 	tlv->attr_id = htonl(ISNS_DD_SET_STATUS_ATTR_ID);
1551 	tlv->attr_len = htonl(4);
1552 	if (cmd_id == CMD_ENABLE) {
1553 		*(uint32_t *)tlv->attr_value = htonl(1);
1554 	} else {
1555 		*(uint32_t *)tlv->attr_value = htonl(0);
1556 	}
1557 	payload_len += 8 + 4;
1558 
1559 	pdu->payload_len = payload_len;
1560 
1561 	dump_pdu1(pdu);
1562 
1563 	conn.in_packet.pdu = pdu;
1564 	conn.out_packet.pdu = NULL;
1565 	conn.out_packet.sz = 0;
1566 
1567 	if (packet_split_verify(&conn) == 0) {
1568 		cache_lock(conn.lock);
1569 		conn.handler(&conn);
1570 		conn.ec = cache_unlock(conn.lock, conn.ec);
1571 	}
1572 
1573 	if (conn.out_packet.pdu != NULL) {
1574 		pdu_update_code(conn.out_packet.pdu,
1575 		    &conn.out_packet.pl, conn.ec);
1576 		dump_pdu2(conn.out_packet.pdu);
1577 		free(conn.out_packet.pdu);
1578 	} else if (conn.ec != 0) {
1579 		printf("operation failed[%d].\n", conn.ec);
1580 	}
1581 }
1582 
1583 static void
update_member(int cmd_id,int * argv)1584 update_member(
1585 	int cmd_id,
1586 	int *argv
1587 )
1588 {
1589 	uint32_t buff[256];
1590 	isns_pdu_t *pdu = (isns_pdu_t *)buff;
1591 	uint8_t *payload = &pdu->payload[0];
1592 	uint16_t payload_len = 0;
1593 	isns_tlv_t *tlv;
1594 	uint32_t key_tag, op_tag, op_len;
1595 
1596 	uint32_t uid = argv[0];
1597 	uint32_t m_id;
1598 	char *m_name;
1599 
1600 	conn_arg_t conn;
1601 
1602 	if (uid == 0) {
1603 		printf("operation failed.\n");
1604 		return;
1605 	}
1606 
1607 	pdu->version = ISNSP_VERSION;
1608 
1609 	switch (cmd_id) {
1610 	case CMD_ADDDD:
1611 	case CMD_ADDDDN:
1612 		pdu->func_id = ISNS_DD_REG;
1613 		break;
1614 	case CMD_REMDD:
1615 	case CMD_REMDDN:
1616 		pdu->func_id = ISNS_DD_DEREG;
1617 		break;
1618 	case CMD_ADDDDSN:
1619 		pdu->func_id = ISNS_DDS_REG;
1620 		break;
1621 	case CMD_REMDDSN:
1622 		pdu->func_id = ISNS_DDS_DEREG;
1623 		break;
1624 	}
1625 	switch (cmd_id) {
1626 	case CMD_ADDDD:
1627 	case CMD_REMDD:
1628 		key_tag = ISNS_DD_ID_ATTR_ID;
1629 		op_tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1630 		m_name = (char *)argv[1];
1631 		op_len = strlen(m_name);
1632 		op_len += 4 - (op_len % 4);
1633 		break;
1634 	case CMD_ADDDDN:
1635 	case CMD_REMDDN:
1636 		key_tag = ISNS_DD_ID_ATTR_ID;
1637 		op_tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1638 		m_id = argv[1];
1639 		op_len = 4;
1640 		break;
1641 	case CMD_ADDDDSN:
1642 	case CMD_REMDDSN:
1643 		key_tag = ISNS_DD_SET_ID_ATTR_ID;
1644 		op_tag = ISNS_DD_ID_ATTR_ID;
1645 		m_id = argv[1];
1646 		op_len = 4;
1647 		break;
1648 	}
1649 
1650 	/* source attribute */
1651 	tlv = (isns_tlv_t *)payload;
1652 	tlv->attr_id = htonl(ISNS_ISCSI_NAME_ATTR_ID);
1653 	tlv->attr_len = htonl(32);
1654 	strcpy((char *)tlv->attr_value, "i am a control node.");
1655 	payload_len += 8 + 32;
1656 	payload += 8 + 32;
1657 
1658 	/* key attributes */
1659 	tlv = (isns_tlv_t *)payload;
1660 	tlv->attr_id = htonl(key_tag);
1661 	tlv->attr_len = htonl(4);
1662 	*(uint32_t *)tlv->attr_value = htonl(uid);
1663 	payload_len += 8 + 4;
1664 	payload += 8 + 4;
1665 
1666 	/* delimiter */
1667 	tlv = (isns_tlv_t *)payload;
1668 	tlv->attr_id = htonl(ISNS_DELIMITER_ATTR_ID);
1669 	tlv->attr_len = htonl(0);
1670 	payload_len += 8 + 0;
1671 	payload += 8 + 0;
1672 
1673 	/* operating attributes */
1674 	tlv = (isns_tlv_t *)payload;
1675 	tlv->attr_id = htonl(op_tag);
1676 	tlv->attr_len = htonl(op_len);
1677 	switch (cmd_id) {
1678 	case CMD_ADDDD:
1679 	case CMD_REMDD:
1680 		strcpy((char *)tlv->attr_value, m_name);
1681 		break;
1682 	case CMD_ADDDDN:
1683 	case CMD_ADDDDSN:
1684 	case CMD_REMDDN:
1685 	case CMD_REMDDSN:
1686 		*(uint32_t *)tlv->attr_value = htonl(m_id);
1687 		break;
1688 	}
1689 	payload_len += 8 + op_len;
1690 
1691 	pdu->payload_len = payload_len;
1692 
1693 	dump_pdu1(pdu);
1694 
1695 	conn.in_packet.pdu = pdu;
1696 	conn.out_packet.pdu = NULL;
1697 	conn.out_packet.sz = 0;
1698 
1699 	if (packet_split_verify(&conn) == 0) {
1700 		cache_lock(conn.lock);
1701 		conn.handler(&conn);
1702 		conn.ec = cache_unlock(conn.lock, conn.ec);
1703 	}
1704 
1705 	if (conn.out_packet.pdu != NULL) {
1706 		pdu_update_code(conn.out_packet.pdu,
1707 		    &conn.out_packet.pl, conn.ec);
1708 		dump_pdu2(conn.out_packet.pdu);
1709 		free(conn.out_packet.pdu);
1710 	} else if (conn.ec != 0) {
1711 		printf("operation failed[%d].\n", conn.ec);
1712 	}
1713 }
1714 
1715 static void
cmd_file(char * file)1716 cmd_file(
1717 	char *file
1718 )
1719 {
1720 	char i = 0, ch, cmd[256];
1721 	FILE *f = fopen(file, "r");
1722 	if (f != NULL) {
1723 		while ((ch = fgetc(f)) != 0 && ch != EOF) {
1724 			if (ch == '\t') {
1725 				cmd[i++] = ' ';
1726 			} else if (ch != '\n') {
1727 				cmd[i++] = ch;
1728 			} else {
1729 				cmd[i ++] = ' ';
1730 				cmd[i] = 0;
1731 				i = 0;
1732 				printf("%s\n", cmd);
1733 				if (run_cmd(cmd) != 0) {
1734 					break;
1735 				}
1736 			}
1737 		}
1738 		fclose(f);
1739 	} else {
1740 		printf("Cannot open file %s.\n", file);
1741 	}
1742 }
1743 
1744 static int
run_cmd(char * cmd)1745 run_cmd(
1746 	char *cmd
1747 )
1748 {
1749 	int argc, argv[32];
1750 	int cmd_id;
1751 	cmd_id = getcmd(&argc, argv, cmd);
1752 	switch (cmd_id) {
1753 		case CMD_LIST:
1754 			list_node();
1755 			break;
1756 		case CMD_LISTNE:
1757 			list_entity();
1758 			break;
1759 		case CMD_LISTP:
1760 			list_portal();
1761 			break;
1762 		case CMD_LISTPG:
1763 			list_pg();
1764 			break;
1765 		case CMD_LISTDD:
1766 			list_dd();
1767 			break;
1768 		case CMD_LISTDDS:
1769 			list_dds();
1770 			break;
1771 		case CMD_LISTDDN:
1772 			list_ddn(argv[0]);
1773 			break;
1774 		case CMD_LISTDDSN:
1775 			list_ddsn(argv[0]);
1776 			break;
1777 		case CMD_NEWDD:
1778 		case CMD_NEWDDS:
1779 		case CMD_NEWDDN:
1780 		case CMD_NEWDDSN:
1781 			new_dd_dds(cmd_id, argc, argv);
1782 			break;
1783 		case CMD_DELDD:
1784 		case CMD_DELDDS:
1785 			del_dd_dds(cmd_id, argv[0]);
1786 			break;
1787 		case CMD_ENABLE:
1788 		case CMD_DISABLE:
1789 			update_dds(cmd_id, argv[0]);
1790 			break;
1791 		case CMD_ADDDD:
1792 		case CMD_ADDDDN:
1793 		case CMD_ADDDDSN:
1794 		case CMD_REMDD:
1795 		case CMD_REMDDN:
1796 		case CMD_REMDDSN:
1797 			update_member(cmd_id, argv);
1798 			break;
1799 		case CMD_PAUSE:
1800 			printf("Press enter to continue...");
1801 			getchar();
1802 			break;
1803 		case CMD_FILE:
1804 			cmd_file((char *)argv[0]);
1805 			break;
1806 		case CMD_HELP:
1807 			test_cli_help();
1808 			break;
1809 		case CMD_VERBOSE_MEMORY:
1810 			verbose_mc = !verbose_mc;
1811 			break;
1812 		case CMD_VERBOSE_NET:
1813 			verbose_net = !verbose_net;
1814 			break;
1815 		case CMD_VERBOSE_TIME:
1816 			verbose_tc = !verbose_tc;
1817 			break;
1818 		case CMD_VERBOSE_LOCK:
1819 			verbose_lock = !verbose_lock;
1820 			break;
1821 		case CMD_VERBOSE_PARSER:
1822 			verbose_parser = !verbose_parser;
1823 			break;
1824 		case CMD_QUIT:
1825 			/* clean up cli */
1826 			/* notify sys control */
1827 			shutdown_server();
1828 			return (1);
1829 		case CMD_NONE:
1830 			break;
1831 		default:
1832 			printf("invalid command\n");
1833 			break;
1834 	}
1835 	if (cmd_id != CMD_NONE) {
1836 		printf("\n>");
1837 	} else {
1838 		printf(">");
1839 	}
1840 	return (0);
1841 }
1842 
1843 /*ARGSUSED*/
cli_test(void * arg)1844 void *cli_test(void *arg) {
1845 	char i = 0, ch, cmd[256];
1846 
1847 	printf("iSNS Server test CLI.\n");
1848 	printf("Copyright 2007 Sun Microsystems, Inc.\n");
1849 
1850 	printf("\n>");
1851 	while ((ch = getchar()) != 0 && ch != EOF) {
1852 		if (ch == '\t') {
1853 			cmd[i++] = ' ';
1854 		} else if (ch != '\n') {
1855 			cmd[i++] = ch;
1856 		} else {
1857 			cmd[i ++] = ' ';
1858 			cmd[i] = 0;
1859 			i = 0;
1860 			if (run_cmd(cmd) != 0) {
1861 				break;
1862 			}
1863 		}
1864 	}
1865 
1866 	return (NULL);
1867 }
1868 #endif
1869