1/*	$NetBSD: iscsic_daemonif.c,v 1.1 2011/10/23 21:11:23 agc Exp $	*/
2
3/*-
4 * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31#include "iscsic_globals.h"
32
33/*
34 * do_add_target:
35 *    Handle both the add_target and add_send_target commands.
36 *
37 *    Parameter:
38 *          argc, argv  Shifted arguments
39 *          kind        Which list
40 *
41 *    Returns:    0 if OK - else it doesn't return at all.
42 */
43
44STATIC int
45do_add_target(int argc, char **argv, iscsid_list_kind_t kind)
46{
47	iscsid_add_target_req_t *targ;
48	iscsid_set_target_authentication_req_t auth;
49	iscsid_get_set_target_options_t opt;
50	iscsid_response_t *rsp;
51	iscsid_add_target_rsp_t *res;
52	unsigned		i;
53	int opts, auths, tlen;
54	uint32_t tid;
55
56	tlen = cl_get_target(&targ, argc, argv, kind != SEND_TARGETS_LIST);
57	if (tlen == 0) {
58		arg_missing("Target");
59	}
60	if (kind == SEND_TARGETS_LIST && !targ->num_portals) {
61		arg_missing("Target Address");
62	}
63	opts = cl_get_target_opts(&opt, argc, argv);
64	auths = cl_get_auth_opts(&auth, argc, argv);
65	cl_get_symname(targ->sym_name, argc, argv);
66	check_extra_args(argc, argv);
67
68	targ->list_kind = kind;
69
70	send_request(ISCSID_ADD_TARGET, tlen, targ);
71	rsp = get_response(FALSE);
72
73	if (rsp->status) {
74		status_error(rsp->status);
75	}
76	res = (iscsid_add_target_rsp_t *)(void *)rsp->parameter;
77	tid = res->target_id;
78
79	if (kind == SEND_TARGETS_LIST) {
80		printf("Added Send Target %d\n", res->target_id);
81	} else {
82		printf("Added Target %d", res->target_id);
83		if (res->num_portals) {
84			printf(", Portal ");
85			for (i = 0; i < res->num_portals; i++)
86				printf("%d ", res->portal_id[i]);
87		}
88		printf("\n");
89	}
90
91	free_response(rsp);
92
93	if (opts) {
94		opt.list_kind = kind;
95		opt.target_id.id = tid;
96		send_request(ISCSID_SET_TARGET_OPTIONS, sizeof(opt), &opt);
97		rsp = get_response(FALSE);
98		if (rsp->status) {
99			status_error(rsp->status);
100		}
101		free_response(rsp);
102	}
103
104	if (auths) {
105		auth.list_kind = kind;
106		auth.target_id.id = tid;
107		send_request(ISCSID_SET_TARGET_AUTHENTICATION, sizeof(auth), &auth);
108		rsp = get_response(FALSE);
109		if (rsp->status) {
110			status_error(rsp->status);
111		}
112		free_response(rsp);
113	}
114
115	return 0;
116}
117
118
119/*
120 * do_remove_target:
121 *    Handle both the remove_target and remove_send_target commands.
122 *
123 *    Parameter:
124 *          argc, argv  Shifted arguments
125 *          kind        Which list
126 *
127 *    Returns:    0 if OK - else it doesn't return at all.
128 */
129
130STATIC int
131do_remove_target(int argc, char **argv, iscsid_list_kind_t kind)
132{
133	iscsid_list_id_t req;
134	iscsid_search_list_req_t srch;
135	iscsid_response_t *rsp;
136
137	if (!cl_get_id('I', &req.id, argc, argv)) {
138		if (!cl_get_string('n', (char *)srch.strval, argc, argv)) {
139			arg_missing("Target ID or Name");
140		}
141		check_extra_args(argc, argv);
142
143		srch.search_kind = FIND_TARGET_NAME;
144		srch.list_kind = kind;
145
146		send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
147		rsp = get_response(FALSE);
148		if (rsp->status) {
149			status_error_slist(rsp->status);
150		}
151		GET_SYM_ID(req.id.id, rsp->parameter);
152		free_response(rsp);
153	} else {
154		check_extra_args(argc, argv);
155	}
156	req.list_kind = kind;
157	send_request(ISCSID_REMOVE_TARGET, sizeof(req), &req);
158	rsp = get_response(TRUE);
159	if (rsp->status) {
160		status_error(rsp->status);
161	}
162	free_response(rsp);
163	printf("OK\n");
164	return 0;
165}
166
167
168/*
169 * do_refresh:
170 *    Handle the refresh_targets and refresh_isns commands.
171 *
172 *    Parameter:
173 *          argc, argv  Shifted arguments
174 *          kind        Which list
175 *
176 *    Returns:    0 if OK - else it doesn't return at all.
177 */
178
179STATIC int
180do_refresh(int argc, char **argv, iscsid_list_kind_t kind)
181{
182	iscsid_sym_id_t id;
183	iscsid_response_t *rsp;
184	iscsid_refresh_req_t req;
185
186	req.kind = kind;
187
188	if (cl_get_id('I', &id, argc, argv)) {
189		check_extra_args(argc, argv);
190
191		if (!id.id) {
192			iscsid_search_list_req_t srch;
193
194			srch.search_kind = FIND_NAME;
195			srch.list_kind = kind;
196			strlcpy((char *)srch.strval, (char *)id.name,
197				sizeof(srch.strval));
198
199			send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
200			rsp = get_response(FALSE);
201			if (rsp->status) {
202				status_error_slist(rsp->status);
203			}
204			GET_SYM_ID(req.id[0], rsp->parameter);
205			free_response(rsp);
206		} else {
207			req.id[0] = id.id;
208		}
209		req.num_ids = 1;
210	} else {
211		req.num_ids = 0;
212		check_extra_args(argc, argv);
213	}
214
215	req.kind = kind;
216	send_request(ISCSID_REFRESH_TARGETS, sizeof(req), &req);
217
218	rsp = get_response(FALSE);
219	if (rsp->status) {
220		status_error(rsp->status);
221	}
222	printf("OK\n");
223	free_response(rsp);
224	return 0;
225}
226
227
228/*
229 * add_target:
230 *    Handle the add_target command.
231 *
232 *    Parameter:  argc, argv (shifted)
233 *
234 *    Returns:    0 if OK - else it doesn't return at all.
235 */
236
237int
238add_target(int argc, char **argv)
239{
240	return do_add_target(argc, argv, TARGET_LIST);
241}
242
243
244/*
245 * remove_target:
246 *    Handle the remove_target command.
247 *
248 *    Parameter:  argc, argv (shifted)
249 *
250 *    Returns:    0 if OK - else it doesn't return at all.
251 */
252
253int
254remove_target(int argc, char **argv)
255{
256	return do_remove_target(argc, argv, TARGET_LIST);
257}
258
259
260/*
261 * slp_find_targets:
262 *    Handle the slp_find_targets command.
263 *
264 *    Parameter:  argc, argv (shifted)
265 *
266 *    Returns:    0 if OK - else it doesn't return at all.
267 *
268 *    ToDo: Implement.
269 */
270
271int
272/*ARGSUSED*/
273slp_find_targets(int argc, char **argv)
274{
275	printf("Not implemented\n");
276	return 5;
277}
278
279
280/*
281 * refresh_targets:
282 *    Handle the refresh_targets command.
283 *
284 *    Parameter:  argc, argv (shifted)
285 *
286 *    Returns:    0 if OK - else it doesn't return at all.
287 */
288
289int
290refresh_targets(int argc, char **argv)
291{
292	return do_refresh(argc, argv, SEND_TARGETS_LIST);
293}
294
295
296/*
297 * add_portal:
298 *    Handle the add_portal command.
299 *
300 *    Parameter:
301 *          argc, argv  Shifted arguments
302 *
303 *    Returns:    0 if OK - else it doesn't return at all.
304 */
305
306int
307add_portal(int argc, char **argv)
308{
309	iscsid_add_portal_req_t port;
310	iscsid_response_t *rsp;
311	iscsid_add_portal_rsp_t *res;
312
313	if (!cl_get_portal(&port, argc, argv)) {
314		arg_missing("Portal Address");
315	}
316	if (!cl_get_id('I', &port.target_id, argc, argv)) {
317		arg_missing("Target ID");
318	}
319	cl_get_symname(port.sym_name, argc, argv);
320	check_extra_args(argc, argv);
321
322	send_request(ISCSID_ADD_PORTAL, sizeof(port), &port);
323	rsp = get_response(FALSE);
324
325	if (rsp->status) {
326		status_error(rsp->status);
327	}
328	res = (iscsid_add_portal_rsp_t *)(void *)rsp->parameter;
329
330	printf("Added Portal %d to Target %d\n",
331		res->portal_id.id, res->target_id.id);
332	free_response(rsp);
333	return 0;
334}
335
336
337/*
338 * show_target:
339 *    Get information about and display a target entry (including its portals).
340 *
341 *    Parameter:
342 *       target ID
343 *       list kind
344 */
345
346STATIC void
347show_target(uint32_t id, iscsid_list_kind_t kind)
348{
349	iscsid_list_id_t req;
350	iscsid_response_t *trsp, *prsp;
351	iscsid_get_target_rsp_t *targ;
352	iscsid_get_portal_rsp_t *port;
353	unsigned i;
354
355	/* get target info */
356	req.list_kind = kind;
357	req.id.id = id;
358	req.id.name[0] = '\0';
359	send_request(ISCSID_GET_TARGET_INFO, sizeof(req), &req);
360
361	trsp = get_response(TRUE);
362	if (trsp->status) {
363		status_error(trsp->status);
364	}
365	targ = (iscsid_get_target_rsp_t *)(void *)trsp->parameter;
366
367	/* display basic target info */
368	printf("%6d", targ->target_id.id);
369	if (targ->target_id.name[0]) {
370		printf(" [%s]", targ->target_id.name);
371	}
372	printf(": %s", targ->TargetName);
373	if (targ->TargetAlias[0]) {
374		printf(" (%s)", targ->TargetAlias);
375	}
376	printf("\n");
377
378	/* now get and display info on the target's portals */
379	for (i = 0; i < targ->num_portals; i++) {
380		req.id.id = targ->portal[i];
381		send_request(ISCSID_GET_PORTAL_INFO, sizeof(req), &req);
382		prsp = get_response(FALSE);
383		if (prsp->status) {
384			status_error(prsp->status);
385		}
386		port = (iscsid_get_portal_rsp_t *)(void *)prsp->parameter;
387
388		printf("   %6d", port->portal_id.id);
389		if (port->portal_id.name[0]) {
390			printf(" [%s]", port->portal_id.name);
391		}
392		printf(": %s:%d", port->portal.address, port->portal.port);
393		if (kind != SEND_TARGETS_LIST) {
394			printf(",%d", port->portal.group_tag);
395		}
396		printf("\n");
397		free_response(prsp);
398	}
399	free_response(trsp);
400}
401
402
403/*
404 * do_list_targets:
405 *    Handle both the list_targets and list_send_targets commands.
406 *
407 *    Parameter:
408 *          argc, argv  Shifted arguments
409 *          kind        Which list
410 *
411 *    Returns:    0 if OK - else it doesn't return at all.
412 */
413
414STATIC int
415do_list_targets(int argc, char **argv, iscsid_list_kind_t kind)
416{
417	iscsid_get_list_req_t lst;
418	iscsid_response_t *rsp;
419	iscsid_get_list_rsp_t *list;
420	unsigned i;
421
422	check_extra_args(argc, argv);
423
424	/* get the list of targets */
425	lst.list_kind = kind;
426	send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
427	rsp = get_response(TRUE);
428	if (rsp->status) {
429		status_error(rsp->status);
430	}
431	list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
432
433	/* display all targets */
434	for (i = 0; i < list->num_entries; i++) {
435		show_target(list->id[i], kind);
436	}
437	free_response(rsp);
438	return 0;
439}
440
441
442/*
443 * list_targets:
444 *    Handle the list_targets command.
445 *
446 *    Parameter:  argc, argv (shifted)
447 *
448 *    Returns:    0 if OK - else it doesn't return at all.
449 */
450
451int
452list_targets(int argc, char **argv)
453{
454	return do_list_targets(argc, argv, TARGET_LIST);
455}
456
457
458/*
459 * add_send_target:
460 *    Handle the add_target command.
461 *
462 *    Parameter:  argc, argv (shifted)
463 *
464 *    Returns:    0 if OK - else it doesn't return at all.
465 */
466
467int
468add_send_target(int argc, char **argv)
469{
470	return do_add_target(argc, argv, SEND_TARGETS_LIST);
471}
472
473
474/*
475 * remove_send_target:
476 *    Handle the remove_target command.
477 *
478 *    Parameter:  argc, argv (shifted)
479 *
480 *    Returns:    0 if OK - else it doesn't return at all.
481 */
482
483int
484remove_send_target(int argc, char **argv)
485{
486	return do_remove_target(argc, argv, SEND_TARGETS_LIST);
487}
488
489
490/*
491 * list_send_targets:
492 *    Handle the list_send_targets command.
493 *
494 *    Parameter:  argc, argv (shifted)
495 *
496 *    Returns:    0 if OK - else it doesn't return at all.
497 */
498
499int
500list_send_targets(int argc, char **argv)
501{
502	return do_list_targets(argc, argv, SEND_TARGETS_LIST);
503}
504
505
506/*
507 * add_isns_server:
508 *    Handle the add_isns_server command.
509 *
510 *    Parameter:  argc, argv (shifted)
511 *
512 *    Returns:    0 if OK - else it doesn't return at all.
513 */
514
515int
516add_isns_server(int argc, char **argv)
517{
518	iscsid_add_isns_server_req_t arg;
519	iscsid_add_isns_server_rsp_t *res;
520	iscsid_response_t *rsp;
521
522	memset(&arg, 0x0, sizeof(arg));
523	if (!(cl_get_isns(&arg, argc, argv))) {
524		arg_missing("Server Address");
525	}
526	check_extra_args(argc, argv);
527
528	send_request(ISCSID_ADD_ISNS_SERVER, sizeof(arg), &arg);
529	rsp = get_response(FALSE);
530
531	if (rsp->status) {
532		status_error(rsp->status);
533	}
534	res = (iscsid_add_isns_server_rsp_t *)(void *)rsp->parameter;
535
536	printf("Added iSNS Server ID %d\n", res->server_id);
537
538	free_response(rsp);
539	return 0;
540}
541
542
543/*
544 * remove_isns_server:
545 *    Handle the add_isns_server command.
546 *
547 *    Parameter:  argc, argv (shifted)
548 *
549 *    Returns:    0 if OK - else it doesn't return at all.
550 */
551
552int
553remove_isns_server(int argc, char **argv)
554{
555	iscsid_sym_id_t req;
556	iscsid_search_list_req_t srch;
557	iscsid_response_t *rsp;
558
559	if (!cl_get_id('I', &req, argc, argv)) {
560		if (!cl_get_string('a', (char *)srch.strval, argc, argv)) {
561			arg_missing("Server Address");
562		}
563		check_extra_args(argc, argv);
564		srch.search_kind = FIND_ADDRESS;
565		srch.list_kind = ISNS_LIST;
566
567		send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
568		rsp = get_response(FALSE);
569		if (rsp->status) {
570			status_error_slist(rsp->status);
571		}
572		GET_SYM_ID(req.id, rsp->parameter);
573		free_response(rsp);
574	} else {
575		check_extra_args(argc, argv);
576	}
577	send_request(ISCSID_REMOVE_ISNS_SERVER, sizeof(req), &req);
578	rsp = get_response(TRUE);
579	if (rsp->status) {
580		status_error(rsp->status);
581	}
582	free_response(rsp);
583
584	printf("OK\n");
585	return 0;
586}
587
588
589/*
590 * find_isns_servers:
591 *    Handle the find_isns_servers command.
592 *
593 *    Parameter:  argc, argv (shifted)
594 *
595 *    Returns:    0 if OK - else it doesn't return at all.
596 */
597
598int
599/*ARGSUSED*/
600find_isns_servers(int argc, char **argv)
601{
602	printf("Not implemented\n");
603	return 5;
604}
605
606
607/*
608 * list_isns_servers:
609 *    Handle the list_isns_servers command.
610 *
611 *    Parameter:  argc, argv (shifted)
612 *
613 *    Returns:    0 if OK - else it doesn't return at all.
614 */
615
616int
617list_isns_servers(int argc, char **argv)
618{
619	iscsid_get_list_req_t lst;
620	iscsid_response_t *rsp, *prsp;
621	iscsid_get_list_rsp_t *list;
622	iscsid_get_isns_server_rsp_t *isns;
623	iscsid_sym_id_t req;
624	unsigned i;
625
626	memset(&req, 0x0, sizeof(req));
627	check_extra_args(argc, argv);
628
629	/* get the list of servers */
630	lst.list_kind = ISNS_LIST;
631	send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
632	rsp = get_response(TRUE);
633	if (rsp->status) {
634		status_error(rsp->status);
635	}
636	list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
637
638	/* display all servers */
639	for (i = 0; i < list->num_entries; i++) {
640		req.id = list->id[i];
641		send_request(ISCSID_GET_ISNS_SERVER, sizeof(req), &req);
642		prsp = get_response(FALSE);
643		if (prsp->status)
644			status_error(prsp->status);
645
646		isns = (iscsid_get_isns_server_rsp_t *)(void *)prsp->parameter;
647		printf("%6d: %s\n", list->id[i], isns->address);
648		free_response(prsp);
649	}
650	free_response(rsp);
651	return 0;
652}
653
654
655/*
656 * refresh_isns:
657 *    Handle the refresh_isns command.
658 *
659 *    Parameter:  argc, argv (shifted)
660 *
661 *    Returns:    0 if OK - else it doesn't return at all.
662 */
663
664int
665refresh_isns(int argc, char **argv)
666{
667	return do_refresh(argc, argv, ISNS_LIST);
668}
669
670
671/*
672 * add_initiator:
673 *    Handle the add_initiator command.
674 *
675 *    Parameter:  argc, argv (shifted)
676 *
677 *    Returns:    0 if OK - else it doesn't return at all.
678 */
679
680int
681add_initiator(int argc, char **argv)
682{
683	iscsid_add_initiator_req_t req;
684	iscsid_add_initiator_rsp_t *res;
685	iscsid_response_t *rsp;
686
687	memset(&req, 0x0, sizeof(req));
688	if (!cl_get_string('a', (char *)req.address, argc, argv)) {
689		arg_missing("Interface Address");
690	}
691	cl_get_symname(req.name, argc, argv);
692	check_extra_args(argc, argv);
693
694	send_request(ISCSID_ADD_INITIATOR_PORTAL, sizeof(req), &req);
695	rsp = get_response(FALSE);
696	if (rsp->status) {
697		status_error(rsp->status);
698	}
699	res = (iscsid_add_initiator_rsp_t *)(void *)rsp->parameter;
700	printf("Added Initiator Portal %d\n", res->portal_id);
701
702	free_response(rsp);
703	return 0;
704}
705
706
707/*
708 * remove_initiator:
709 *    Handle the remove_initiator command.
710 *
711 *    Parameter:  argc, argv (shifted)
712 *
713 *    Returns:    0 if OK - else it doesn't return at all.
714 */
715
716int
717remove_initiator(int argc, char **argv)
718{
719	iscsid_sym_id_t req;
720	iscsid_response_t *rsp;
721
722	memset(&req, 0x0, sizeof(req));
723	if (!cl_get_id('I', &req, argc, argv)) {
724		arg_missing("Initiator Portal ID");
725	}
726	check_extra_args(argc, argv);
727
728	send_request(ISCSID_REMOVE_INITIATOR_PORTAL, sizeof(req), &req);
729	rsp = get_response(FALSE);
730	if (rsp->status) {
731		status_error(rsp->status);
732	}
733	free_response(rsp);
734
735	printf("OK\n");
736	return 0;
737}
738
739/*
740 * list_initiators:
741 *    Handle the list_initiators command.
742 *
743 *    Parameter:  argc, argv (shifted)
744 *
745 *    Returns:    0 if OK - else it doesn't return at all.
746 */
747
748int
749list_initiators(int argc, char **argv)
750{
751	iscsid_get_list_req_t lst;
752	iscsid_response_t *rsp, *prsp;
753	iscsid_get_list_rsp_t *list;
754	iscsid_get_initiator_rsp_t *init;
755	iscsid_sym_id_t req;
756	unsigned i;
757
758	memset(&req, 0x0, sizeof(req));
759	check_extra_args(argc, argv);
760
761	/* get the list of servers */
762	lst.list_kind = INITIATOR_LIST;
763	send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
764	rsp = get_response(TRUE);
765	if (rsp->status) {
766		status_error(rsp->status);
767	}
768	list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
769
770	/* display all servers */
771	for (i = 0; i < list->num_entries; i++) {
772		req.id = list->id[i];
773		send_request(ISCSID_GET_INITIATOR_PORTAL, sizeof(req), &req);
774		prsp = get_response(FALSE);
775		if (prsp->status) {
776			status_error(prsp->status);
777		}
778		init = (iscsid_get_initiator_rsp_t *)(void *)prsp->parameter;
779		printf("%6d", init->portal_id.id);
780		if (init->portal_id.name[0]) {
781			printf("[%s]", init->portal_id.name);
782		}
783		printf(": %s\n", init->address);
784		free_response(prsp);
785	}
786	free_response(rsp);
787	return 0;
788}
789
790
791/*
792 * login_or_add:
793 *    Common routine for login and add_connection. Handles the actual command,
794 *    the only pre-initialized component is the session ID in the login request
795 *    for add_connection.
796 *
797 *    Parameters: the login request, plus argc & argv
798*/
799
800STATIC void
801login_or_add(iscsid_login_req_t * loginp, int argc, char **argv)
802{
803	iscsid_add_target_req_t *targ = NULL;
804	iscsid_add_target_rsp_t	*tgtrsp;
805	iscsid_set_target_authentication_req_t auth;
806	iscsid_get_set_target_options_t opt;
807	iscsid_search_list_req_t srch;
808	iscsid_response_t *rsp;
809	int opts, auths, tlen;
810
811	/* get the remaining parameters */
812	opts = cl_get_target_opts(&opt, argc, argv);
813	auths = cl_get_auth_opts(&auth, argc, argv);
814	cl_get_symname(loginp->sym_name, argc, argv);
815	cl_get_id ('i', &loginp->initiator_id, argc, argv);
816
817	/* do we have a portal ID? */
818	if (!cl_get_id('P', &loginp->portal_id, argc, argv)) {
819		/* No portal ID - then we must have a target name */
820		if (!(tlen = cl_get_target(&targ, argc, argv, TRUE))) {
821			if (NO_ID(&loginp->session_id)) {
822				arg_missing("Target");
823			}
824		}
825
826		check_extra_args(argc, argv);
827
828		if (targ != NULL) {
829			/* was a complete target with portal specified? */
830			if (targ->num_portals) {
831				/* then add it like in an add_target command */
832				targ->list_kind = TARGET_LIST;
833				send_request(ISCSID_ADD_TARGET, tlen, targ);
834				rsp = get_response(FALSE);
835				if (rsp->status) {
836					status_error(rsp->status);
837				}
838				tgtrsp = (iscsid_add_target_rsp_t *)(void *)(rsp->parameter);
839				(void) memcpy(&loginp->portal_id.id, &tgtrsp->target_id,
840					sizeof(loginp->portal_id.id));
841			} else {
842				/* else find the target by its TargetName */
843				srch.search_kind = FIND_TARGET_NAME;
844				srch.list_kind = TARGET_LIST;
845				strlcpy((char *)srch.strval, (char *)targ->TargetName,
846					sizeof(srch.strval));
847
848				send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
849				rsp = get_response(FALSE);
850				if (rsp->status) {
851					status_error_slist(rsp->status);
852				}
853				GET_SYM_ID(loginp->portal_id.id, rsp->parameter);
854			}
855			free_response(rsp);
856		}
857	} else
858		check_extra_args(argc, argv);
859
860	/* Options specified? Then set them */
861	if (opts) {
862		opt.target_id = loginp->portal_id;
863		opt.list_kind = TARGET_LIST;
864		send_request(ISCSID_SET_TARGET_OPTIONS, sizeof(opt), &opt);
865		rsp = get_response(FALSE);
866		if (rsp->status) {
867			status_error(rsp->status);
868		}
869		free_response(rsp);
870	}
871	/* Authentication options specified? Then set them */
872	if (auths) {
873		auth.target_id = loginp->portal_id;
874		auth.list_kind = TARGET_LIST;
875		send_request(ISCSID_SET_TARGET_AUTHENTICATION, sizeof(auth), &auth);
876		rsp = get_response(FALSE);
877		if (rsp->status) {
878			status_error(rsp->status);
879		}
880		free_response(rsp);
881	}
882}
883
884
885/*
886 * login:
887 *    Handle login command.
888 *
889 *    Parameter:  argc, argv (shifted)
890 *
891 *    Returns:    0 if OK - else it doesn't return at all.
892*/
893
894int
895login(int argc, char **argv)
896{
897	iscsid_login_req_t loginp;
898	iscsid_login_rsp_t *res;
899	iscsid_response_t *rsp;
900
901	memset(&loginp, 0x0, sizeof(loginp));
902	loginp.login_type = (cl_get_opt('m', argc, argv))
903						? ISCSI_LOGINTYPE_NOMAP : ISCSI_LOGINTYPE_MAP;
904
905	login_or_add(&loginp, argc, argv);
906
907	send_request(ISCSID_LOGIN, sizeof(loginp), &loginp);
908
909	rsp = get_response(FALSE);
910	if (rsp->status) {
911		status_error(rsp->status);
912	}
913	res = (iscsid_login_rsp_t *)(void *)rsp->parameter;
914	printf("Created Session %d, Connection %d\n",
915		res->session_id.id, res->connection_id.id);
916
917	free_response(rsp);
918	return 0;
919}
920
921
922/*
923 * logout:
924 *    Handle logout command.
925 *
926 *    Parameter:  argc, argv (shifted)
927 *
928 *    Returns:    0 if OK - else it doesn't return at all.
929*/
930
931int
932logout(int argc, char **argv)
933{
934	iscsid_sym_id_t req;
935	iscsid_response_t *rsp;
936
937	if (!cl_get_id('I', &req, argc, argv)) {
938		arg_missing("Session");
939	}
940	check_extra_args(argc, argv);
941
942	send_request(ISCSID_LOGOUT, sizeof(req), &req);
943	rsp = get_response(FALSE);
944	if (rsp->status) {
945		status_error(rsp->status);
946	}
947	free_response(rsp);
948
949	printf("OK\n");
950	return 0;
951}
952
953
954/*
955 * add_connection:
956 *    Handle add_connection command.
957 *
958 *    Parameter:  argc, argv (shifted)
959 *
960 *    Returns:    0 if OK - else it doesn't return at all.
961*/
962
963int
964add_connection(int argc, char **argv)
965{
966	iscsid_login_req_t loginp;
967	iscsid_login_rsp_t	*loginrsp;
968	iscsid_response_t *rsp;
969
970	memset(&loginp, 0x0, sizeof(loginp));
971	loginp.login_type = ISCSI_LOGINTYPE_MAP;
972	cl_get_id('I', &loginp.session_id, argc, argv);
973
974	login_or_add(&loginp, argc, argv);
975
976	send_request(ISCSID_ADD_CONNECTION, sizeof(loginp), &loginp);
977
978	rsp = get_response(FALSE);
979	if (rsp->status) {
980		status_error(rsp->status);
981	}
982	loginrsp = (iscsid_login_rsp_t *)(void *)(rsp->parameter);
983	printf("Added Connection %d\n", loginrsp->connection_id.id);
984
985	free_response(rsp);
986	return 0;
987}
988
989
990/*
991 * remove_connection:
992 *    Handle remove connection command
993 *
994 *    Parameter:  argc, argv (shifted)
995 *
996 *    Returns:    0 if OK - else it doesn't return at all.
997*/
998
999int
1000remove_connection(int argc, char **argv)
1001{
1002	iscsid_remove_connection_req_t req;
1003	iscsid_response_t *rsp;
1004
1005	if (!cl_get_id('I', &req.session_id, argc, argv)) {
1006		arg_missing("Session");
1007	}
1008	if (!cl_get_id('C', &req.connection_id, argc, argv)) {
1009		arg_missing("Connection");
1010	}
1011	check_extra_args(argc, argv);
1012
1013	send_request(ISCSID_REMOVE_CONNECTION, sizeof(req), &req);
1014	rsp = get_response(FALSE);
1015	if (rsp->status) {
1016		status_error(rsp->status);
1017	}
1018	free_response(rsp);
1019
1020	printf("OK\n");
1021	return 0;
1022}
1023
1024
1025/*
1026 * list_sessions:
1027 *    Handle list_sessions command.
1028 *
1029 *    Parameter:  argc, argv (shifted)
1030 *
1031 *    Returns:    0 if OK - else it doesn't return at all.
1032 *
1033 * ToDo: initiator portals, connection recurse
1034*/
1035
1036int
1037list_sessions(int argc, char **argv)
1038{
1039	iscsid_response_t *lrsp, *rsp;
1040	iscsid_get_session_list_rsp_t *list;
1041	iscsid_session_list_entry_t *ent;
1042	iscsid_get_connection_info_req_t creq;
1043	iscsid_get_connection_info_rsp_t *info;
1044	iscsid_sym_id_t clreq;
1045	iscsid_get_connection_list_rsp_t *clinfo;
1046	iscsid_connection_list_entry_t *clent;
1047	unsigned i;
1048	unsigned j;
1049	int lconn;
1050
1051	memset(&creq, 0x0, sizeof(creq));
1052	memset(&clreq, 0x0, sizeof(clreq));
1053	lconn = cl_get_opt('c', argc, argv);
1054
1055	check_extra_args(argc, argv);
1056
1057	send_request(ISCSID_GET_SESSION_LIST, 0, NULL);
1058	lrsp = get_response(TRUE);
1059	if (lrsp->status) {
1060		status_error(lrsp->status);
1061	}
1062	list = (iscsid_get_session_list_rsp_t *)(void *)lrsp->parameter;
1063
1064	for (i = 0, ent = list->session; i < list->num_entries; i++, ent++) {
1065		creq.session_id.id = ent->session_id.id;
1066		send_request(ISCSID_GET_CONNECTION_INFO, sizeof(creq), &creq);
1067		rsp = get_response(FALSE);
1068		if (rsp->status) {
1069			status_error(rsp->status);
1070		}
1071		info = (iscsid_get_connection_info_rsp_t *)(void *)rsp->parameter;
1072
1073		printf("Session %d", info->session_id.id);
1074		if (info->session_id.name[0]) {
1075			printf("[%s]", info->session_id.name);
1076		}
1077		printf(": Target %s", info->TargetName);
1078		if (info->target_portal_id.name[0]) {
1079			printf(" [%s]", info->target_portal_id.name);
1080		}
1081		printf("\n");
1082
1083		if (lconn) {
1084			clreq.id = info->session_id.id;
1085			send_request(ISCSID_GET_CONNECTION_LIST, sizeof(clreq), &clreq);
1086			rsp = get_response(FALSE);
1087			if (rsp->status) {
1088				status_error(rsp->status);
1089			}
1090			clinfo = (iscsid_get_connection_list_rsp_t *)(void *)rsp->parameter;
1091
1092			for (j = 0, clent = clinfo->connection;
1093				 j < clinfo->num_connections; j++, clent++) {
1094				printf(" Connection %d", clent->connection_id.id);
1095				if (clent->connection_id.name[0]) {
1096					printf("[%s]", clent->connection_id.name);
1097				}
1098				printf(" Address %s:%d,%d\n", clent->target_portal.address,
1099					clent->target_portal.port,
1100					clent->target_portal.group_tag);
1101			}
1102		}
1103	}
1104
1105	return 0;
1106}
1107
1108
1109/*
1110 * set_node_name:
1111 *    Handle the set_node_name command.
1112 *
1113 *    Parameter:  argc, argv (shifted)
1114 *
1115 *    Returns:    0 if OK - else it doesn't return at all.
1116 */
1117
1118int
1119set_node_name(int argc, char **argv)
1120{
1121	iscsid_set_node_name_req_t req;
1122	iscsid_response_t *rsp;
1123	uint64_t isid;
1124
1125	memset(&req, 0x0, sizeof(req));
1126	if (!cl_get_string('n', (char *)req.InitiatorName, argc, argv)) {
1127		arg_missing("Initiator Name");
1128	}
1129	cl_get_string('A', (char *)req.InitiatorAlias, argc, argv);
1130	isid = cl_get_longlong('i', argc, argv);
1131	hton6(req.ISID, isid);
1132
1133	check_extra_args(argc, argv);
1134
1135	send_request(ISCSID_SET_NODE_NAME, sizeof(req), &req);
1136
1137	rsp = get_response(FALSE);
1138	if (rsp->status) {
1139		status_error(rsp->status);
1140	}
1141	free_response(rsp);
1142
1143	printf("OK\n");
1144	return 0;
1145}
1146
1147/*
1148 * get_version:
1149 *    Handle the version command.
1150 *
1151 *    Parameter:  argc, argv (shifted)
1152 *
1153 *    Returns:    0 if OK - else it doesn't return at all.
1154 */
1155
1156int
1157/*ARGSUSED*/
1158get_version(int argc, char **argv)
1159{
1160	iscsid_response_t *rsp;
1161	iscsid_get_version_rsp_t *ver;
1162
1163	send_request(ISCSID_GET_VERSION, 0, NULL);
1164	rsp = get_response(FALSE);
1165	if (rsp->status) {
1166		status_error(rsp->status);
1167	}
1168	ver = (iscsid_get_version_rsp_t *)(void *)rsp->parameter;
1169	printf("%s\n%s\n%s\n", VERSION_STRING, ver->version_string,
1170		   ver->driver_version_string);
1171
1172	return 0;
1173}
1174
1175
1176#ifdef ISCSI_DEBUG
1177/*
1178 * kill_daemon:
1179 *    Handle kill_daemon command.
1180 *
1181 *    Parameter:  argc, argv (shifted)
1182 *
1183 *    Returns:    Always 0.
1184*/
1185
1186int
1187kill_daemon(int argc, char **argv)
1188{
1189	check_extra_args(argc, argv);
1190
1191	send_request(ISCSID_DAEMON_TERMINATE, 0, NULL);
1192	return 0;
1193}
1194#endif
1195