mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 10:41:26 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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(¶ms, ",")) != 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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user