Home | History | Annotate | Line # | Download | only in iscsictl
      1 /*	$NetBSD: iscsic_daemonif.c,v 1.3 2015/05/30 15:57:32 joerg 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 
     44 STATIC int
     45 do_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 
    130 STATIC int
    131 do_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 
    179 STATIC int
    180 do_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 
    237 int
    238 add_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 
    253 int
    254 remove_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 
    271 int
    272 /*ARGSUSED*/
    273 slp_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 
    289 int
    290 refresh_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 
    306 int
    307 add_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 
    346 STATIC void
    347 show_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 
    414 STATIC int
    415 do_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 
    451 int
    452 list_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 
    467 int
    468 add_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 
    483 int
    484 remove_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 
    499 int
    500 list_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 
    515 int
    516 add_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 
    552 int
    553 remove_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 
    598 int
    599 /*ARGSUSED*/
    600 find_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 
    616 int
    617 list_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 
    664 int
    665 refresh_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 
    680 int
    681 add_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 
    716 int
    717 remove_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 
    748 int
    749 list_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 
    800 STATIC void
    801 login_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 
    894 int
    895 login(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 
    931 int
    932 logout(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 
    963 int
    964 add_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 
    999 int
   1000 remove_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 
   1036 int
   1037 list_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 
   1118 int
   1119 set_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 
   1156 int
   1157 /*ARGSUSED*/
   1158 get_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