Merge with IET r160-168: add iscsi-scst-adm support to display list of CHAP accounts and their data

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@646 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2009-01-29 12:12:42 +00:00
parent 2f392619fb
commit 04041fa3f1
6 changed files with 291 additions and 60 deletions

View File

@@ -153,7 +153,7 @@ display status of target 1 (see /proc/scsi_tgt/iscsi to get the matching target
create dynamically a new target, numbered 2. \s-1CAUTION\s0 : the target will disappear if you restart iscsi-scstd, you'll have to edit /etc/iscsi-scstd.conf to make it permanent!
.SH "ERROR MESSAGES"
.IX Header "ERROR MESSAGES"
iscsi-scst-adm misses error messages. Look carefully the \s-1STDERR\s0 output : in case of error
iscsi-scst-adm misses error messages. Look carefully at the \s-1STDERR\s0 output : in case of error
it will send a 3 number error code, ending with \-1, for instance :
.PP
iscsi-scstd_request 203 3 \-1
@@ -203,6 +203,17 @@ add a new account with [pass] for specific target.
If you don't specify a target (omit \-\-tid option),
you add a new account for discovery sessions.
.PP
\&\fB\-\-op show \-\-tid=[id] \-\-user\fR
.PP
show a list of CHAP accounts.
If \-\-tid is omitted or [id] is \*(L"0\*(R" (zero), discovery accounts are displayed.
.PP
\&\fB\-\-op show \-\-tid=[id] \-\-user \-\-params=[user]=[name]\fR
.PP
show CHAP account information for the account specified by [name].
[user] can be [IncomingUser] or [OutgoingUser].
If \-\-tid is omitted or [id] is \*(L"0\*(R" (zero), [name] is supposed to be a discovery account name.
.PP
\&\fB\-\-op delete \-\-tid=[id] \-\-user \-\-params=[user]=[name]\fR
.PP
delete specific account having [name] of specific

View File

@@ -26,6 +26,7 @@ struct config_operations {
int (*account_add) (u32, int, char *, char *);
int (*account_del) (u32, int, char *);
int (*account_query) (u32, int, char *, char *);
int (*account_list) (u32, int, u32 *, u32 *, char *, size_t);
int (*initiator_access) (u32, int);
};

View File

@@ -37,6 +37,8 @@
#define SET_CONNECTION (1 << 2)
#define SET_USER (1 << 4)
typedef int (user_handle_fn_t)(struct iscsi_adm_req *req, char *user, char *pass);
enum iscsi_adm_op {
OP_NEW,
OP_DELETE,
@@ -79,6 +81,14 @@ iSCSI-SCST Target Administration Utility.\n\
show iSCSI parameters in effect for session [sid]. If\n\
[sid] is \"0\" (zero), the configured parameters\n\
will be displayed.\n\
--op show --tid=[id] --user\n\
show list of Discovery (--tid omitted / id=0 (zero))\n\
or target CHAP accounts.\n\
--op show --tid=[id] --user --params=[user]=[name]\n\
show CHAP account information. [user] can be\n\
\"IncomingUser\" or \"OutgoingUser\". If --tid is\n\
omitted / id=0 (zero), [user] is treated as Discovery\n\
user.\n\
--op delete --tid=[id] --sid=[sid] --cid=[cid]\n\
delete specific connection with [cid] in a session\n\
with [sid] that the target with [id] has.\n\
@@ -145,7 +155,8 @@ static int iscsid_request_send(int fd, struct iscsi_adm_req *req)
return err;
}
static int iscsid_response_recv(int fd, struct iscsi_adm_req *req)
static int iscsid_response_recv(int fd, struct iscsi_adm_req *req, void *rsp_data,
size_t rsp_data_sz)
{
int err, ret;
struct iovec iov[2];
@@ -167,6 +178,15 @@ static int iscsid_response_recv(int fd, struct iscsi_adm_req *req)
} else
err = rsp.err;
if (!err && rsp_data_sz && rsp_data) {
ret = read(fd, rsp_data, rsp_data_sz);
if (ret != rsp_data_sz) {
err = (ret < 0) ? -errno : -EIO;
fprintf(stderr, "%s %d %d %d\n", __FUNCTION__,
__LINE__, ret, err);
}
}
return err;
}
@@ -189,7 +209,8 @@ static int iscsid_connect(void)
return fd;
}
static int iscsid_request(struct iscsi_adm_req *req)
static int iscsid_request(struct iscsi_adm_req *req, void *rsp_data,
size_t rsp_data_sz)
{
int fd = -1, err = -EIO;
@@ -201,7 +222,7 @@ static int iscsid_request(struct iscsi_adm_req *req)
if ((err = iscsid_request_send(fd, req)) < 0)
goto out;
err = iscsid_response_recv(fd, req);
err = iscsid_response_recv(fd, req, rsp_data, rsp_data_sz);
out:
if (fd > 0)
@@ -324,7 +345,7 @@ static int trgt_handle(int op, u32 set, u32 tid, char *params)
break;
}
err = iscsid_request(&req);
err = iscsid_request(&req, NULL, 0);
if (!err && req.rcmnd == C_TRGT_SHOW)
show_iscsi_param(key_target, req.u.trgt.target_param);
@@ -355,7 +376,7 @@ static int sess_handle(int op, u32 set, u32 tid, u64 sid, char *params)
break;
case OP_SHOW:
req.rcmnd = C_SESS_SHOW;
err = iscsid_request(&req);
err = iscsid_request(&req, NULL, 0);
if (!err)
show_iscsi_param(key_session, req.u.trgt.session_param);
break;
@@ -365,30 +386,10 @@ out:
return err;
}
static int user_handle(int op, u32 set, u32 tid, char *params)
static int parse_user_params(char *params, u32 *auth_dir, char **user,
char **pass)
{
int err = -EINVAL;
char *p, *q, *user = NULL, *pass = NULL;
struct iscsi_adm_req req;
if (set & ~(SET_TARGET | SET_USER))
goto out;
memset(&req, 0, sizeof(req));
req.tid = tid;
switch (op) {
case OP_NEW:
req.rcmnd = C_ACCT_NEW;
break;
case OP_DELETE:
req.rcmnd = C_ACCT_DEL;
break;
case OP_UPDATE:
case OP_SHOW:
fprintf(stderr, "Unsupported.\n");
goto out;
}
char *p, *q;
while ((p = strsep(&params, ",")) != NULL) {
if (!*p)
@@ -401,37 +402,189 @@ static int user_handle(int op, u32 set, u32 tid, char *params)
q++;
if (!strcasecmp(p, "IncomingUser")) {
if (user)
fprintf(stderr, "Already specified user %s\n", q);
user = q;
req.u.acnt.auth_dir = AUTH_DIR_INCOMING;
if (*user)
fprintf(stderr,
"Already specified IncomingUser %s\n",
q);
*user = q;
*auth_dir = AUTH_DIR_INCOMING;
} else if (!strcasecmp(p, "OutgoingUser")) {
if (user)
fprintf(stderr, "Already specified user %s\n", q);
user = q;
req.u.acnt.auth_dir = AUTH_DIR_OUTGOING;
if (*user)
fprintf(stderr,
"Already specified OutgoingUser %s\n",
q);
*user = q;
*auth_dir = AUTH_DIR_OUTGOING;
} else if (!strcasecmp(p, "Password")) {
if (pass)
fprintf(stderr, "Already specified pass %s\n", q);
pass = q;
if (*pass)
fprintf(stderr,
"Already specified Password %s\n", q);
*pass = q;
} else {
fprintf(stderr, "Unknown parameter %p\n", q);
goto out;
return -EINVAL;
}
}
return 0;
}
if ((op == OP_NEW && ((user && !pass) || (!user && pass) || (!user && !pass))) ||
(op == OP_DELETE && ((!user && pass) || (!user && !pass)))) {
fprintf(stderr,
"You need to specify a user and its password %s %s\n", pass, user);
static void show_account(int auth_dir, char *user, char *pass)
{
char buf[(ISCSI_NAME_LEN + 1) * 2] = {0};
snprintf(buf, ISCSI_NAME_LEN, "%s", user);
if (pass)
snprintf(buf + strlen(buf), ISCSI_NAME_LEN, " %s", pass);
printf("%sUser %s\n", (auth_dir == AUTH_DIR_INCOMING) ?
"Incoming" : "Outgoing", buf);
}
static int user_handle_show_user(struct iscsi_adm_req *req, char *user)
{
int err;
req->rcmnd = C_ACCT_SHOW;
strncpy(req->u.acnt.u.user.name, user,
sizeof(req->u.acnt.u.user.name) - 1);
err = iscsid_request(req, NULL, 0);
if (!err)
show_account(req->u.acnt.auth_dir, req->u.acnt.u.user.name,
req->u.acnt.u.user.pass);
return err;
}
static int user_handle_show_list(struct iscsi_adm_req *req)
{
int i, err, retry;
size_t buf_sz = 0;
char *buf;
req->u.acnt.auth_dir = AUTH_DIR_INCOMING;
req->rcmnd = C_ACCT_LIST;
do {
retry = 0;
buf_sz = buf_sz ? buf_sz : ISCSI_NAME_LEN;
buf = calloc(buf_sz, sizeof(char *));
if (!buf) {
fprintf(stderr, "Memory allocation failed\n");
return -ENOMEM;
}
req->u.acnt.u.list.alloc_len = buf_sz;
err = iscsid_request(req, buf, buf_sz);
if (err) {
free(buf);
break;
}
if (req->u.acnt.u.list.overflow) {
buf_sz = ISCSI_NAME_LEN * (req->u.acnt.u.list.count +
req->u.acnt.u.list.overflow);
retry = 1;
free(buf);
continue;
}
for (i = 0; i < req->u.acnt.u.list.count; i++)
show_account(req->u.acnt.auth_dir,
&buf[i * ISCSI_NAME_LEN], NULL);
if (req->u.acnt.auth_dir == AUTH_DIR_INCOMING) {
req->u.acnt.auth_dir = AUTH_DIR_OUTGOING;
buf_sz = 0;
retry = 1;
}
free(buf);
} while (retry);
return err;
}
static int user_handle_show(struct iscsi_adm_req *req, char *user, char *pass)
{
if (pass)
fprintf(stderr, "Ignoring specified password\n");
if (user)
return user_handle_show_user(req, user);
else
return user_handle_show_list(req);
}
static int user_handle_new(struct iscsi_adm_req *req, char *user, char *pass)
{
if (!user || !pass) {
fprintf(stderr, "Username and password must be specified\n");
return -EINVAL;
}
req->rcmnd = C_ACCT_NEW;
strncpy(req->u.acnt.u.user.name, user,
sizeof(req->u.acnt.u.user.name) - 1);
strncpy(req->u.acnt.u.user.pass, pass,
sizeof(req->u.acnt.u.user.pass) - 1);
return iscsid_request(req, NULL, 0);
}
static int user_handle_del(struct iscsi_adm_req *req, char *user, char *pass)
{
if (!user) {
fprintf(stderr, "Username must be specified\n");
return -EINVAL;
}
if (pass)
fprintf(stderr, "Ignoring specified password\n");
req->rcmnd = C_ACCT_DEL;
strncpy(req->u.acnt.u.user.name, user,
sizeof(req->u.acnt.u.user.name) - 1);
return iscsid_request(req, NULL, 0);
}
static int user_handle(int op, u32 set, u32 tid, char *params)
{
int err = -EINVAL;
char *user = NULL, *pass = NULL;
struct iscsi_adm_req req;
static user_handle_fn_t *user_handle_fn[] = {
user_handle_new,
user_handle_del,
NULL,
user_handle_show,
}, *fn;
if (set & ~(SET_TARGET | SET_USER))
goto out;
memset(&req, 0, sizeof(req));
req.tid = tid;
err = parse_user_params(params, &req.u.acnt.auth_dir, &user, &pass);
if (err)
goto out;
if ((op >= sizeof(user_handle_fn)/sizeof(user_handle_fn[0])) ||
((fn = user_handle_fn[op]) == NULL)) {
fprintf(stderr, "Unsupported\n");
goto out;
}
strncpy(req.u.acnt.user, user, sizeof(req.u.acnt.user) - 1);
if (pass)
strncpy(req.u.acnt.pass, pass, sizeof(req.u.acnt.pass) - 1);
err = fn(&req, user, pass);
err = iscsid_request(&req);
out:
return err;
}
@@ -464,7 +617,7 @@ static int conn_handle(int op, u32 set, u32 tid, u64 sid, u32 cid, char *params)
break;
}
err = iscsid_request(&req);
err = iscsid_request(&req, NULL, 0);
out:
return err;
}
@@ -488,7 +641,7 @@ static int sys_handle(int op, u32 set, char *params)
break;
}
err = iscsid_request(&req);
err = iscsid_request(&req, NULL, 0);
return err;
}

View File

@@ -31,8 +31,17 @@ struct msg_trgt {
struct msg_acnt {
u32 auth_dir;
char user[ISCSI_NAME_LEN];
char pass[ISCSI_NAME_LEN];
union {
struct {
char name[ISCSI_NAME_LEN];
char pass[ISCSI_NAME_LEN];
} user;
struct {
u32 alloc_len;
u32 count;
u32 overflow;
} list;
} u;
};
enum iscsi_adm_cmnd {
@@ -60,6 +69,8 @@ enum iscsi_adm_cmnd {
C_SYS_DEL,
C_SYS_UPDATE,
C_SYS_SHOW,
C_ACCT_LIST,
};
struct iscsi_adm_req {

View File

@@ -15,6 +15,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
@@ -47,7 +48,8 @@ int iscsi_adm_request_listen(void)
return fd;
}
static void iscsi_adm_request_exec(struct iscsi_adm_req *req, struct iscsi_adm_rsp *rsp)
static void iscsi_adm_request_exec(struct iscsi_adm_req *req, struct iscsi_adm_rsp *rsp,
void **rsp_data, size_t *rsp_data_sz)
{
int err = 0;
@@ -102,14 +104,35 @@ static void iscsi_adm_request_exec(struct iscsi_adm_req *req, struct iscsi_adm_r
break;
case C_ACCT_NEW:
err = cops->account_add(req->tid, req->u.acnt.auth_dir, req->u.acnt.user,
req->u.acnt.pass);
err = cops->account_add(req->tid, req->u.acnt.auth_dir,
req->u.acnt.u.user.name,
req->u.acnt.u.user.pass);
break;
case C_ACCT_DEL:
err = cops->account_del(req->tid, req->u.acnt.auth_dir, req->u.acnt.user);
err = cops->account_del(req->tid, req->u.acnt.auth_dir,
req->u.acnt.u.user.name);
break;
case C_ACCT_LIST:
*rsp_data = malloc(req->u.acnt.u.list.alloc_len);
if (!*rsp_data) {
err = -ENOMEM;
break;
}
*rsp_data_sz = req->u.acnt.u.list.alloc_len;
memset(*rsp_data, 0x0, *rsp_data_sz);
err = cops->account_list(req->tid, req->u.acnt.auth_dir,
&req->u.acnt.u.list.count,
&req->u.acnt.u.list.overflow,
*rsp_data, *rsp_data_sz);
break;
case C_ACCT_UPDATE:
break;
case C_ACCT_SHOW:
err = cops->account_query(req->tid, req->u.acnt.auth_dir,
req->u.acnt.u.user.name,
req->u.acnt.u.user.pass);
break;
case C_SYS_NEW:
break;
@@ -135,7 +158,9 @@ int iscsi_adm_request_handle(int accept_fd)
socklen_t len;
struct iscsi_adm_req req;
struct iscsi_adm_rsp rsp;
struct iovec iov[2];
struct iovec iov[3];
void *rsp_data = NULL;
size_t rsp_data_sz;
memset(&rsp, 0, sizeof(rsp));
len = sizeof(addr);
@@ -165,17 +190,22 @@ int iscsi_adm_request_handle(int accept_fd)
goto out;
}
iscsi_adm_request_exec(&req, &rsp);
iscsi_adm_request_exec(&req, &rsp, &rsp_data, &rsp_data_sz);
send:
iov[0].iov_base = &req;
iov[0].iov_len = sizeof(req);
iov[1].iov_base = &rsp;
iov[1].iov_len = sizeof(rsp);
iov[2].iov_base = rsp.err ? NULL : rsp_data;
iov[2].iov_len = iov[2].iov_base ? rsp_data_sz : 0;
err = writev(fd, iov, 2);
err = writev(fd, iov, 2 + !!iov[2].iov_len);
out:
if (fd > 0)
close(fd);
if (rsp_data)
free(rsp_data);
return err;
}

View File

@@ -170,6 +170,30 @@ static int plain_account_query(u32 tid, int dir, char *name, char *pass)
return 0;
}
static int plain_account_list(u32 tid, int dir, u32 *cnt, u32 *overflow,
char *buf, size_t buf_sz)
{
struct __qelem *list = account_list_get(tid, dir);
struct user *user;
*cnt = *overflow = 0;
if (!list)
return -ENOENT;
list_for_each_entry(user, list, ulist) {
if (buf_sz >= ISCSI_NAME_LEN) {
strncpy(buf, user->name, ISCSI_NAME_LEN);
buf_sz -= ISCSI_NAME_LEN;
buf += ISCSI_NAME_LEN;
*cnt += 1;
} else
*overflow += 1;
}
return 0;
}
static void account_destroy(struct user *user)
{
if (!user)
@@ -631,5 +655,6 @@ struct config_operations plain_ops = {
.account_add = plain_account_add,
.account_del = plain_account_del,
.account_query = plain_account_query,
.account_list = plain_account_list,
.initiator_access = plain_initiator_access,
};