1174 lines
26 KiB
C
1174 lines
26 KiB
C
/* $NetBSD: iscsic_daemonif.c,v 1.3 2015/05/30 15:57:32 joerg Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Wasabi Systems, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include "iscsic_globals.h"
|
|
|
|
/*
|
|
* do_add_target:
|
|
* Handle both the add_target and add_send_target commands.
|
|
*
|
|
* Parameter:
|
|
* argc, argv Shifted arguments
|
|
* kind Which list
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
STATIC int
|
|
do_add_target(int argc, char **argv, iscsid_list_kind_t kind)
|
|
{
|
|
iscsid_add_target_req_t *targ;
|
|
iscsid_set_target_authentication_req_t auth;
|
|
iscsid_get_set_target_options_t opt;
|
|
iscsid_response_t *rsp;
|
|
iscsid_add_target_rsp_t *res;
|
|
unsigned i;
|
|
int opts, auths, tlen;
|
|
uint32_t tid;
|
|
|
|
tlen = cl_get_target(&targ, argc, argv, kind != SEND_TARGETS_LIST);
|
|
if (tlen == 0) {
|
|
arg_missing("Target");
|
|
}
|
|
if (kind == SEND_TARGETS_LIST && !targ->num_portals) {
|
|
arg_missing("Target Address");
|
|
}
|
|
opts = cl_get_target_opts(&opt, argc, argv);
|
|
auths = cl_get_auth_opts(&auth, argc, argv);
|
|
cl_get_symname(targ->sym_name, argc, argv);
|
|
check_extra_args(argc, argv);
|
|
|
|
targ->list_kind = kind;
|
|
|
|
send_request(ISCSID_ADD_TARGET, tlen, targ);
|
|
rsp = get_response(FALSE);
|
|
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
res = (iscsid_add_target_rsp_t *)(void *)rsp->parameter;
|
|
tid = res->target_id;
|
|
|
|
if (kind == SEND_TARGETS_LIST) {
|
|
printf("Added Send Target %d\n", res->target_id);
|
|
} else {
|
|
printf("Added Target %d", res->target_id);
|
|
if (res->num_portals) {
|
|
printf(", Portal ");
|
|
for (i = 0; i < res->num_portals; i++)
|
|
printf("%d ", res->portal_id[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
free_response(rsp);
|
|
|
|
if (opts) {
|
|
opt.list_kind = kind;
|
|
opt.target_id.id = tid;
|
|
send_request(ISCSID_SET_TARGET_OPTIONS, sizeof(opt), &opt);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
}
|
|
|
|
if (auths) {
|
|
auth.list_kind = kind;
|
|
auth.target_id.id = tid;
|
|
send_request(ISCSID_SET_TARGET_AUTHENTICATION, sizeof(auth), &auth);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* do_remove_target:
|
|
* Handle both the remove_target and remove_send_target commands.
|
|
*
|
|
* Parameter:
|
|
* argc, argv Shifted arguments
|
|
* kind Which list
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
STATIC int
|
|
do_remove_target(int argc, char **argv, iscsid_list_kind_t kind)
|
|
{
|
|
iscsid_list_id_t req;
|
|
iscsid_search_list_req_t srch;
|
|
iscsid_response_t *rsp;
|
|
|
|
if (!cl_get_id('I', &req.id, argc, argv)) {
|
|
if (!cl_get_string('n', (char *)srch.strval, argc, argv)) {
|
|
arg_missing("Target ID or Name");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
|
|
srch.search_kind = FIND_TARGET_NAME;
|
|
srch.list_kind = kind;
|
|
|
|
send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error_slist(rsp->status);
|
|
}
|
|
GET_SYM_ID(req.id.id, rsp->parameter);
|
|
free_response(rsp);
|
|
} else {
|
|
check_extra_args(argc, argv);
|
|
}
|
|
req.list_kind = kind;
|
|
send_request(ISCSID_REMOVE_TARGET, sizeof(req), &req);
|
|
rsp = get_response(TRUE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* do_refresh:
|
|
* Handle the refresh_targets and refresh_isns commands.
|
|
*
|
|
* Parameter:
|
|
* argc, argv Shifted arguments
|
|
* kind Which list
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
STATIC int
|
|
do_refresh(int argc, char **argv, iscsid_list_kind_t kind)
|
|
{
|
|
iscsid_sym_id_t id;
|
|
iscsid_response_t *rsp;
|
|
iscsid_refresh_req_t req;
|
|
|
|
req.kind = kind;
|
|
|
|
if (cl_get_id('I', &id, argc, argv)) {
|
|
check_extra_args(argc, argv);
|
|
|
|
if (!id.id) {
|
|
iscsid_search_list_req_t srch;
|
|
|
|
srch.search_kind = FIND_NAME;
|
|
srch.list_kind = kind;
|
|
strlcpy((char *)srch.strval, (char *)id.name,
|
|
sizeof(srch.strval));
|
|
|
|
send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error_slist(rsp->status);
|
|
}
|
|
GET_SYM_ID(req.id[0], rsp->parameter);
|
|
free_response(rsp);
|
|
} else {
|
|
req.id[0] = id.id;
|
|
}
|
|
req.num_ids = 1;
|
|
} else {
|
|
req.num_ids = 0;
|
|
check_extra_args(argc, argv);
|
|
}
|
|
|
|
req.kind = kind;
|
|
send_request(ISCSID_REFRESH_TARGETS, sizeof(req), &req);
|
|
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
printf("OK\n");
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* add_target:
|
|
* Handle the add_target command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_target(int argc, char **argv)
|
|
{
|
|
return do_add_target(argc, argv, TARGET_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* remove_target:
|
|
* Handle the remove_target command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
remove_target(int argc, char **argv)
|
|
{
|
|
return do_remove_target(argc, argv, TARGET_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* slp_find_targets:
|
|
* Handle the slp_find_targets command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*
|
|
* ToDo: Implement.
|
|
*/
|
|
|
|
int
|
|
/*ARGSUSED*/
|
|
slp_find_targets(int argc, char **argv)
|
|
{
|
|
printf("Not implemented\n");
|
|
return 5;
|
|
}
|
|
|
|
|
|
/*
|
|
* refresh_targets:
|
|
* Handle the refresh_targets command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
refresh_targets(int argc, char **argv)
|
|
{
|
|
return do_refresh(argc, argv, SEND_TARGETS_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* add_portal:
|
|
* Handle the add_portal command.
|
|
*
|
|
* Parameter:
|
|
* argc, argv Shifted arguments
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_portal(int argc, char **argv)
|
|
{
|
|
iscsid_add_portal_req_t port;
|
|
iscsid_response_t *rsp;
|
|
iscsid_add_portal_rsp_t *res;
|
|
|
|
if (!cl_get_portal(&port, argc, argv)) {
|
|
arg_missing("Portal Address");
|
|
}
|
|
if (!cl_get_id('I', &port.target_id, argc, argv)) {
|
|
arg_missing("Target ID");
|
|
}
|
|
cl_get_symname(port.sym_name, argc, argv);
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_ADD_PORTAL, sizeof(port), &port);
|
|
rsp = get_response(FALSE);
|
|
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
res = (iscsid_add_portal_rsp_t *)(void *)rsp->parameter;
|
|
|
|
printf("Added Portal %d to Target %d\n",
|
|
res->portal_id.id, res->target_id.id);
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* show_target:
|
|
* Get information about and display a target entry (including its portals).
|
|
*
|
|
* Parameter:
|
|
* target ID
|
|
* list kind
|
|
*/
|
|
|
|
STATIC void
|
|
show_target(uint32_t id, iscsid_list_kind_t kind)
|
|
{
|
|
iscsid_list_id_t req;
|
|
iscsid_response_t *trsp, *prsp;
|
|
iscsid_get_target_rsp_t *targ;
|
|
iscsid_get_portal_rsp_t *port;
|
|
unsigned i;
|
|
|
|
/* get target info */
|
|
req.list_kind = kind;
|
|
req.id.id = id;
|
|
req.id.name[0] = '\0';
|
|
send_request(ISCSID_GET_TARGET_INFO, sizeof(req), &req);
|
|
|
|
trsp = get_response(TRUE);
|
|
if (trsp->status) {
|
|
status_error(trsp->status);
|
|
}
|
|
targ = (iscsid_get_target_rsp_t *)(void *)trsp->parameter;
|
|
|
|
/* display basic target info */
|
|
printf("%6d", targ->target_id.id);
|
|
if (targ->target_id.name[0]) {
|
|
printf(" [%s]", targ->target_id.name);
|
|
}
|
|
printf(": %s", targ->TargetName);
|
|
if (targ->TargetAlias[0]) {
|
|
printf(" (%s)", targ->TargetAlias);
|
|
}
|
|
printf("\n");
|
|
|
|
/* now get and display info on the target's portals */
|
|
for (i = 0; i < targ->num_portals; i++) {
|
|
req.id.id = targ->portal[i];
|
|
send_request(ISCSID_GET_PORTAL_INFO, sizeof(req), &req);
|
|
prsp = get_response(FALSE);
|
|
if (prsp->status) {
|
|
status_error(prsp->status);
|
|
}
|
|
port = (iscsid_get_portal_rsp_t *)(void *)prsp->parameter;
|
|
|
|
printf(" %6d", port->portal_id.id);
|
|
if (port->portal_id.name[0]) {
|
|
printf(" [%s]", port->portal_id.name);
|
|
}
|
|
printf(": %s:%d", port->portal.address, port->portal.port);
|
|
if (kind != SEND_TARGETS_LIST) {
|
|
printf(",%d", port->portal.group_tag);
|
|
}
|
|
printf("\n");
|
|
free_response(prsp);
|
|
}
|
|
free_response(trsp);
|
|
}
|
|
|
|
|
|
/*
|
|
* do_list_targets:
|
|
* Handle both the list_targets and list_send_targets commands.
|
|
*
|
|
* Parameter:
|
|
* argc, argv Shifted arguments
|
|
* kind Which list
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
STATIC int
|
|
do_list_targets(int argc, char **argv, iscsid_list_kind_t kind)
|
|
{
|
|
iscsid_get_list_req_t lst;
|
|
iscsid_response_t *rsp;
|
|
iscsid_get_list_rsp_t *list;
|
|
unsigned i;
|
|
|
|
check_extra_args(argc, argv);
|
|
|
|
/* get the list of targets */
|
|
lst.list_kind = kind;
|
|
send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
|
|
rsp = get_response(TRUE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
|
|
|
|
/* display all targets */
|
|
for (i = 0; i < list->num_entries; i++) {
|
|
show_target(list->id[i], kind);
|
|
}
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* list_targets:
|
|
* Handle the list_targets command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
list_targets(int argc, char **argv)
|
|
{
|
|
return do_list_targets(argc, argv, TARGET_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* add_send_target:
|
|
* Handle the add_target command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_send_target(int argc, char **argv)
|
|
{
|
|
return do_add_target(argc, argv, SEND_TARGETS_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* remove_send_target:
|
|
* Handle the remove_target command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
remove_send_target(int argc, char **argv)
|
|
{
|
|
return do_remove_target(argc, argv, SEND_TARGETS_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* list_send_targets:
|
|
* Handle the list_send_targets command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
list_send_targets(int argc, char **argv)
|
|
{
|
|
return do_list_targets(argc, argv, SEND_TARGETS_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* add_isns_server:
|
|
* Handle the add_isns_server command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_isns_server(int argc, char **argv)
|
|
{
|
|
iscsid_add_isns_server_req_t arg;
|
|
iscsid_add_isns_server_rsp_t *res;
|
|
iscsid_response_t *rsp;
|
|
|
|
memset(&arg, 0x0, sizeof(arg));
|
|
if (!(cl_get_isns(&arg, argc, argv))) {
|
|
arg_missing("Server Address");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_ADD_ISNS_SERVER, sizeof(arg), &arg);
|
|
rsp = get_response(FALSE);
|
|
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
res = (iscsid_add_isns_server_rsp_t *)(void *)rsp->parameter;
|
|
|
|
printf("Added iSNS Server ID %d\n", res->server_id);
|
|
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* remove_isns_server:
|
|
* Handle the add_isns_server command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
remove_isns_server(int argc, char **argv)
|
|
{
|
|
iscsid_sym_id_t req;
|
|
iscsid_search_list_req_t srch;
|
|
iscsid_response_t *rsp;
|
|
|
|
if (!cl_get_id('I', &req, argc, argv)) {
|
|
if (!cl_get_string('a', (char *)srch.strval, argc, argv)) {
|
|
arg_missing("Server Address");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
srch.search_kind = FIND_ADDRESS;
|
|
srch.list_kind = ISNS_LIST;
|
|
|
|
send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error_slist(rsp->status);
|
|
}
|
|
GET_SYM_ID(req.id, rsp->parameter);
|
|
free_response(rsp);
|
|
} else {
|
|
check_extra_args(argc, argv);
|
|
}
|
|
send_request(ISCSID_REMOVE_ISNS_SERVER, sizeof(req), &req);
|
|
rsp = get_response(TRUE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* find_isns_servers:
|
|
* Handle the find_isns_servers command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
/*ARGSUSED*/
|
|
find_isns_servers(int argc, char **argv)
|
|
{
|
|
printf("Not implemented\n");
|
|
return 5;
|
|
}
|
|
|
|
|
|
/*
|
|
* list_isns_servers:
|
|
* Handle the list_isns_servers command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
list_isns_servers(int argc, char **argv)
|
|
{
|
|
iscsid_get_list_req_t lst;
|
|
iscsid_response_t *rsp, *prsp;
|
|
iscsid_get_list_rsp_t *list;
|
|
iscsid_get_isns_server_rsp_t *isns;
|
|
iscsid_sym_id_t req;
|
|
unsigned i;
|
|
|
|
memset(&req, 0x0, sizeof(req));
|
|
check_extra_args(argc, argv);
|
|
|
|
/* get the list of servers */
|
|
lst.list_kind = ISNS_LIST;
|
|
send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
|
|
rsp = get_response(TRUE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
|
|
|
|
/* display all servers */
|
|
for (i = 0; i < list->num_entries; i++) {
|
|
req.id = list->id[i];
|
|
send_request(ISCSID_GET_ISNS_SERVER, sizeof(req), &req);
|
|
prsp = get_response(FALSE);
|
|
if (prsp->status)
|
|
status_error(prsp->status);
|
|
|
|
isns = (iscsid_get_isns_server_rsp_t *)(void *)prsp->parameter;
|
|
printf("%6d: %s\n", list->id[i], isns->address);
|
|
free_response(prsp);
|
|
}
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* refresh_isns:
|
|
* Handle the refresh_isns command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
refresh_isns(int argc, char **argv)
|
|
{
|
|
return do_refresh(argc, argv, ISNS_LIST);
|
|
}
|
|
|
|
|
|
/*
|
|
* add_initiator:
|
|
* Handle the add_initiator command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_initiator(int argc, char **argv)
|
|
{
|
|
iscsid_add_initiator_req_t req;
|
|
iscsid_add_initiator_rsp_t *res;
|
|
iscsid_response_t *rsp;
|
|
|
|
memset(&req, 0x0, sizeof(req));
|
|
if (!cl_get_string('a', (char *)req.address, argc, argv)) {
|
|
arg_missing("Interface Address");
|
|
}
|
|
cl_get_symname(req.name, argc, argv);
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_ADD_INITIATOR_PORTAL, sizeof(req), &req);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
res = (iscsid_add_initiator_rsp_t *)(void *)rsp->parameter;
|
|
printf("Added Initiator Portal %d\n", res->portal_id);
|
|
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* remove_initiator:
|
|
* Handle the remove_initiator command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
remove_initiator(int argc, char **argv)
|
|
{
|
|
iscsid_sym_id_t req;
|
|
iscsid_response_t *rsp;
|
|
|
|
memset(&req, 0x0, sizeof(req));
|
|
if (!cl_get_id('I', &req, argc, argv)) {
|
|
arg_missing("Initiator Portal ID");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_REMOVE_INITIATOR_PORTAL, sizeof(req), &req);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* list_initiators:
|
|
* Handle the list_initiators command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
list_initiators(int argc, char **argv)
|
|
{
|
|
iscsid_get_list_req_t lst;
|
|
iscsid_response_t *rsp, *prsp;
|
|
iscsid_get_list_rsp_t *list;
|
|
iscsid_get_initiator_rsp_t *init;
|
|
iscsid_sym_id_t req;
|
|
unsigned i;
|
|
|
|
memset(&req, 0x0, sizeof(req));
|
|
check_extra_args(argc, argv);
|
|
|
|
/* get the list of servers */
|
|
lst.list_kind = INITIATOR_LIST;
|
|
send_request(ISCSID_GET_LIST, sizeof(lst), &lst);
|
|
rsp = get_response(TRUE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
list = (iscsid_get_list_rsp_t *)(void *)rsp->parameter;
|
|
|
|
/* display all servers */
|
|
for (i = 0; i < list->num_entries; i++) {
|
|
req.id = list->id[i];
|
|
send_request(ISCSID_GET_INITIATOR_PORTAL, sizeof(req), &req);
|
|
prsp = get_response(FALSE);
|
|
if (prsp->status) {
|
|
status_error(prsp->status);
|
|
}
|
|
init = (iscsid_get_initiator_rsp_t *)(void *)prsp->parameter;
|
|
printf("%6d", init->portal_id.id);
|
|
if (init->portal_id.name[0]) {
|
|
printf("[%s]", init->portal_id.name);
|
|
}
|
|
printf(": %s\n", init->address);
|
|
free_response(prsp);
|
|
}
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* login_or_add:
|
|
* Common routine for login and add_connection. Handles the actual command,
|
|
* the only pre-initialized component is the session ID in the login request
|
|
* for add_connection.
|
|
*
|
|
* Parameters: the login request, plus argc & argv
|
|
*/
|
|
|
|
STATIC void
|
|
login_or_add(iscsid_login_req_t * loginp, int argc, char **argv)
|
|
{
|
|
iscsid_add_target_req_t *targ = NULL;
|
|
iscsid_add_target_rsp_t *tgtrsp;
|
|
iscsid_set_target_authentication_req_t auth;
|
|
iscsid_get_set_target_options_t opt;
|
|
iscsid_search_list_req_t srch;
|
|
iscsid_response_t *rsp;
|
|
int opts, auths, tlen;
|
|
|
|
/* get the remaining parameters */
|
|
opts = cl_get_target_opts(&opt, argc, argv);
|
|
auths = cl_get_auth_opts(&auth, argc, argv);
|
|
cl_get_symname(loginp->sym_name, argc, argv);
|
|
cl_get_id ('i', &loginp->initiator_id, argc, argv);
|
|
|
|
/* do we have a portal ID? */
|
|
if (!cl_get_id('P', &loginp->portal_id, argc, argv)) {
|
|
/* No portal ID - then we must have a target name */
|
|
if (!(tlen = cl_get_target(&targ, argc, argv, TRUE))) {
|
|
if (NO_ID(&loginp->session_id)) {
|
|
arg_missing("Target");
|
|
}
|
|
}
|
|
|
|
check_extra_args(argc, argv);
|
|
|
|
if (targ != NULL) {
|
|
/* was a complete target with portal specified? */
|
|
if (targ->num_portals) {
|
|
/* then add it like in an add_target command */
|
|
targ->list_kind = TARGET_LIST;
|
|
send_request(ISCSID_ADD_TARGET, tlen, targ);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
tgtrsp = (iscsid_add_target_rsp_t *)(void *)(rsp->parameter);
|
|
(void) memcpy(&loginp->portal_id.id, &tgtrsp->target_id,
|
|
sizeof(loginp->portal_id.id));
|
|
} else {
|
|
/* else find the target by its TargetName */
|
|
srch.search_kind = FIND_TARGET_NAME;
|
|
srch.list_kind = TARGET_LIST;
|
|
strlcpy((char *)srch.strval, (char *)targ->TargetName,
|
|
sizeof(srch.strval));
|
|
|
|
send_request(ISCSID_SEARCH_LIST, sizeof(srch), &srch);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error_slist(rsp->status);
|
|
}
|
|
GET_SYM_ID(loginp->portal_id.id, rsp->parameter);
|
|
}
|
|
free_response(rsp);
|
|
}
|
|
} else
|
|
check_extra_args(argc, argv);
|
|
|
|
/* Options specified? Then set them */
|
|
if (opts) {
|
|
opt.target_id = loginp->portal_id;
|
|
opt.list_kind = TARGET_LIST;
|
|
send_request(ISCSID_SET_TARGET_OPTIONS, sizeof(opt), &opt);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
}
|
|
/* Authentication options specified? Then set them */
|
|
if (auths) {
|
|
auth.target_id = loginp->portal_id;
|
|
auth.list_kind = TARGET_LIST;
|
|
send_request(ISCSID_SET_TARGET_AUTHENTICATION, sizeof(auth), &auth);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* login:
|
|
* Handle login command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
login(int argc, char **argv)
|
|
{
|
|
iscsid_login_req_t loginp;
|
|
iscsid_login_rsp_t *res;
|
|
iscsid_response_t *rsp;
|
|
|
|
memset(&loginp, 0x0, sizeof(loginp));
|
|
loginp.login_type = (cl_get_opt('m', argc, argv))
|
|
? ISCSI_LOGINTYPE_NOMAP : ISCSI_LOGINTYPE_MAP;
|
|
|
|
login_or_add(&loginp, argc, argv);
|
|
|
|
send_request(ISCSID_LOGIN, sizeof(loginp), &loginp);
|
|
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
res = (iscsid_login_rsp_t *)(void *)rsp->parameter;
|
|
printf("Created Session %d, Connection %d\n",
|
|
res->session_id.id, res->connection_id.id);
|
|
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* logout:
|
|
* Handle logout command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
logout(int argc, char **argv)
|
|
{
|
|
iscsid_sym_id_t req;
|
|
iscsid_response_t *rsp;
|
|
|
|
if (!cl_get_id('I', &req, argc, argv)) {
|
|
arg_missing("Session");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_LOGOUT, sizeof(req), &req);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* add_connection:
|
|
* Handle add_connection command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
add_connection(int argc, char **argv)
|
|
{
|
|
iscsid_login_req_t loginp;
|
|
iscsid_login_rsp_t *loginrsp;
|
|
iscsid_response_t *rsp;
|
|
|
|
memset(&loginp, 0x0, sizeof(loginp));
|
|
loginp.login_type = ISCSI_LOGINTYPE_MAP;
|
|
cl_get_id('I', &loginp.session_id, argc, argv);
|
|
|
|
login_or_add(&loginp, argc, argv);
|
|
|
|
send_request(ISCSID_ADD_CONNECTION, sizeof(loginp), &loginp);
|
|
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
loginrsp = (iscsid_login_rsp_t *)(void *)(rsp->parameter);
|
|
printf("Added Connection %d\n", loginrsp->connection_id.id);
|
|
|
|
free_response(rsp);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* remove_connection:
|
|
* Handle remove connection command
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
remove_connection(int argc, char **argv)
|
|
{
|
|
iscsid_remove_connection_req_t req;
|
|
iscsid_response_t *rsp;
|
|
|
|
if (!cl_get_id('I', &req.session_id, argc, argv)) {
|
|
arg_missing("Session");
|
|
}
|
|
if (!cl_get_id('C', &req.connection_id, argc, argv)) {
|
|
arg_missing("Connection");
|
|
}
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_REMOVE_CONNECTION, sizeof(req), &req);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* list_sessions:
|
|
* Handle list_sessions command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*
|
|
* ToDo: initiator portals, connection recurse
|
|
*/
|
|
|
|
int
|
|
list_sessions(int argc, char **argv)
|
|
{
|
|
iscsid_response_t *lrsp, *rsp;
|
|
iscsid_get_session_list_rsp_t *list;
|
|
iscsid_session_list_entry_t *ent;
|
|
iscsid_get_connection_info_req_t creq;
|
|
iscsid_get_connection_info_rsp_t *info;
|
|
iscsid_sym_id_t clreq;
|
|
iscsid_get_connection_list_rsp_t *clinfo;
|
|
iscsid_connection_list_entry_t *clent;
|
|
unsigned i;
|
|
unsigned j;
|
|
int lconn;
|
|
|
|
memset(&creq, 0x0, sizeof(creq));
|
|
memset(&clreq, 0x0, sizeof(clreq));
|
|
lconn = cl_get_opt('c', argc, argv);
|
|
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_GET_SESSION_LIST, 0, NULL);
|
|
lrsp = get_response(TRUE);
|
|
if (lrsp->status) {
|
|
status_error(lrsp->status);
|
|
}
|
|
list = (iscsid_get_session_list_rsp_t *)(void *)lrsp->parameter;
|
|
|
|
for (i = 0, ent = list->session; i < list->num_entries; i++, ent++) {
|
|
creq.session_id.id = ent->session_id.id;
|
|
send_request(ISCSID_GET_CONNECTION_INFO, sizeof(creq), &creq);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
info = (iscsid_get_connection_info_rsp_t *)(void *)rsp->parameter;
|
|
|
|
printf("Session %d", info->session_id.id);
|
|
if (info->session_id.name[0]) {
|
|
printf("[%s]", info->session_id.name);
|
|
}
|
|
printf(": Target %s", info->TargetName);
|
|
if (info->target_portal_id.name[0]) {
|
|
printf(" [%s]", info->target_portal_id.name);
|
|
}
|
|
printf("\n");
|
|
|
|
if (lconn) {
|
|
clreq.id = info->session_id.id;
|
|
send_request(ISCSID_GET_CONNECTION_LIST, sizeof(clreq), &clreq);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
clinfo = (iscsid_get_connection_list_rsp_t *)(void *)rsp->parameter;
|
|
|
|
for (j = 0, clent = clinfo->connection;
|
|
j < clinfo->num_connections; j++, clent++) {
|
|
printf(" Connection %d", clent->connection_id.id);
|
|
if (clent->connection_id.name[0]) {
|
|
printf("[%s]", clent->connection_id.name);
|
|
}
|
|
printf(" Address %s:%d,%d\n", clent->target_portal.address,
|
|
clent->target_portal.port,
|
|
clent->target_portal.group_tag);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* set_node_name:
|
|
* Handle the set_node_name command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
set_node_name(int argc, char **argv)
|
|
{
|
|
iscsid_set_node_name_req_t req;
|
|
iscsid_response_t *rsp;
|
|
uint64_t isid;
|
|
|
|
memset(&req, 0x0, sizeof(req));
|
|
if (!cl_get_string('n', (char *)req.InitiatorName, argc, argv)) {
|
|
arg_missing("Initiator Name");
|
|
}
|
|
cl_get_string('A', (char *)req.InitiatorAlias, argc, argv);
|
|
isid = cl_get_longlong('i', argc, argv);
|
|
hton6(req.ISID, isid);
|
|
|
|
check_extra_args(argc, argv);
|
|
|
|
send_request(ISCSID_SET_NODE_NAME, sizeof(req), &req);
|
|
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
free_response(rsp);
|
|
|
|
printf("OK\n");
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* get_version:
|
|
* Handle the version command.
|
|
*
|
|
* Parameter: argc, argv (shifted)
|
|
*
|
|
* Returns: 0 if OK - else it doesn't return at all.
|
|
*/
|
|
|
|
int
|
|
/*ARGSUSED*/
|
|
get_version(int argc, char **argv)
|
|
{
|
|
iscsid_response_t *rsp;
|
|
iscsid_get_version_rsp_t *ver;
|
|
|
|
send_request(ISCSID_GET_VERSION, 0, NULL);
|
|
rsp = get_response(FALSE);
|
|
if (rsp->status) {
|
|
status_error(rsp->status);
|
|
}
|
|
ver = (iscsid_get_version_rsp_t *)(void *)rsp->parameter;
|
|
printf("%s\n%s\n%s\n", VERSION_STRING, ver->version_string,
|
|
ver->driver_version_string);
|
|
|
|
return 0;
|
|
}
|