version 1.1.1.1, 2012/02/21 16:42:02
|
version 1.1.1.3, 2013/07/21 23:49:22
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (C) 2008-2010 Daisuke Aoyama <aoyama@peach.ne.jp>. | * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
Line 40
|
Line 40
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
|
#include <syslog.h> |
#include <sys/types.h> |
#include <sys/types.h> |
|
|
#include "istgt.h" |
#include "istgt.h" |
Line 49
|
Line 50
|
#include "istgt_misc.h" |
#include "istgt_misc.h" |
#include "istgt_md5.h" |
#include "istgt_md5.h" |
|
|
|
#if !defined(__GNUC__) |
|
#undef __attribute__ |
|
#define __attribute__(x) |
|
#endif |
|
|
//#define TRACE_UCTL |
//#define TRACE_UCTL |
|
|
#define DEFAULT_UCTL_CONFIG BUILD_ETC_ISTGT "/istgtcontrol.conf" |
#define DEFAULT_UCTL_CONFIG BUILD_ETC_ISTGT "/istgtcontrol.conf" |
Line 118 typedef struct istgt_uctl_t {
|
Line 124 typedef struct istgt_uctl_t {
|
typedef UCTL *UCTL_Ptr; |
typedef UCTL *UCTL_Ptr; |
|
|
|
|
|
static void fatal(const char *format, ...) __attribute__((__noreturn__, __format__(__printf__, 1, 2))); |
|
|
static void |
static void |
fatal(const char *format, ...) |
fatal(const char *format, ...) |
{ |
{ |
Line 148 uctl_readline(UCTL_Ptr uctl)
|
Line 156 uctl_readline(UCTL_Ptr uctl)
|
ssize_t total; |
ssize_t total; |
|
|
total = istgt_readline_socket(uctl->sock, uctl->recvbuf, uctl->recvbufsize, |
total = istgt_readline_socket(uctl->sock, uctl->recvbuf, uctl->recvbufsize, |
uctl->recvtmp, uctl->recvtmpsize, | uctl->recvtmp, uctl->recvtmpsize, |
&uctl->recvtmpidx, &uctl->recvtmpcnt, | &uctl->recvtmpidx, &uctl->recvtmpcnt, |
uctl->timeout); | uctl->timeout); |
if (total < 0) { |
if (total < 0) { |
return UCTL_CMD_DISCON; |
return UCTL_CMD_DISCON; |
} |
} |
Line 177 uctl_writeline(UCTL_Ptr uctl)
|
Line 185 uctl_writeline(UCTL_Ptr uctl)
|
return UCTL_CMD_OK; |
return UCTL_CMD_OK; |
} |
} |
|
|
|
static int uctl_snprintf(UCTL_Ptr uctl, const char *format, ...) __attribute__((__format__(__printf__, 2, 3))); |
|
|
static int |
static int |
uctl_snprintf(UCTL_Ptr uctl, const char *format, ...) |
uctl_snprintf(UCTL_Ptr uctl, const char *format, ...) |
{ |
{ |
Line 204 get_banner(UCTL_Ptr uctl)
|
Line 214 get_banner(UCTL_Ptr uctl)
|
} |
} |
|
|
static int |
static int |
is_err_req_auth(UCTL_Ptr uctl, char *s) | is_err_req_auth(UCTL_Ptr uctl __attribute__((__unused__)), char *s) |
{ |
{ |
const char *req_auth_string = "auth required"; |
const char *req_auth_string = "auth required"; |
|
|
Line 217 is_err_req_auth(UCTL_Ptr uctl, char *s)
|
Line 227 is_err_req_auth(UCTL_Ptr uctl, char *s)
|
} |
} |
|
|
static int |
static int |
is_err_chap_seq(UCTL_Ptr uctl, char *s) | is_err_chap_seq(UCTL_Ptr uctl __attribute__((__unused__)), char *s) |
{ |
{ |
const char *chap_seq_string = "CHAP sequence error"; |
const char *chap_seq_string = "CHAP sequence error"; |
|
|
Line 348 exec_unload(UCTL_Ptr uctl)
|
Line 358 exec_unload(UCTL_Ptr uctl)
|
return UCTL_CMD_ERR; |
return UCTL_CMD_ERR; |
} |
} |
uctl_snprintf(uctl, "UNLOAD \"%s\" %d\n", |
uctl_snprintf(uctl, "UNLOAD \"%s\" %d\n", |
uctl->iqn, uctl->lun); | uctl->iqn, uctl->lun); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 384 exec_load(UCTL_Ptr uctl)
|
Line 394 exec_load(UCTL_Ptr uctl)
|
return UCTL_CMD_ERR; |
return UCTL_CMD_ERR; |
} |
} |
uctl_snprintf(uctl, "LOAD \"%s\" %d\n", |
uctl_snprintf(uctl, "LOAD \"%s\" %d\n", |
uctl->iqn, uctl->lun); | uctl->iqn, uctl->lun); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 468 exec_change(UCTL_Ptr uctl)
|
Line 478 exec_change(UCTL_Ptr uctl)
|
return UCTL_CMD_ERR; |
return UCTL_CMD_ERR; |
} |
} |
uctl_snprintf(uctl, "CHANGE \"%s\" %d \"%s\" " |
uctl_snprintf(uctl, "CHANGE \"%s\" %d \"%s\" " |
"\"%s\" \"%s\" \"%s\"\n", | "\"%s\" \"%s\" \"%s\"\n", |
uctl->iqn, uctl->lun, uctl->mtype, | uctl->iqn, uctl->lun, uctl->mtype, |
uctl->mflags, uctl->mfile, uctl->msize); | uctl->mflags, uctl->mfile, uctl->msize); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 506 exec_reset(UCTL_Ptr uctl)
|
Line 516 exec_reset(UCTL_Ptr uctl)
|
return UCTL_CMD_ERR; |
return UCTL_CMD_ERR; |
} |
} |
uctl_snprintf(uctl, "RESET \"%s\" %d\n", |
uctl_snprintf(uctl, "RESET \"%s\" %d\n", |
uctl->iqn, uctl->lun); | uctl->iqn, uctl->lun); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 619 do_auth(UCTL_Ptr uctl)
|
Line 629 do_auth(UCTL_Ptr uctl)
|
|
|
#ifdef TRACE_UCTL |
#ifdef TRACE_UCTL |
printf("do_auth: user=%s, secret=%s, muser=%s, msecret=%s\n", |
printf("do_auth: user=%s, secret=%s, muser=%s, msecret=%s\n", |
uctl->auth.user, | uctl->auth.user, |
uctl->auth.secret, | uctl->auth.secret, |
uctl->auth.muser, | uctl->auth.muser, |
uctl->auth.msecret); | uctl->auth.msecret); |
#endif /* TRACE_UCTL */ |
#endif /* TRACE_UCTL */ |
|
|
/* send algorithm CHAP_A */ |
/* send algorithm CHAP_A */ |
uctl_snprintf(uctl, "AUTH CHAP_A %d\n", |
uctl_snprintf(uctl, "AUTH CHAP_A %d\n", |
algorithm); | algorithm); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 662 do_auth(UCTL_Ptr uctl)
|
Line 672 do_auth(UCTL_Ptr uctl)
|
uctl->auth.chap_id[0] = (uint8_t) strtol(chap_i, NULL, 10); |
uctl->auth.chap_id[0] = (uint8_t) strtol(chap_i, NULL, 10); |
/* Challenge Value */ |
/* Challenge Value */ |
rc = istgt_hex2bin(uctl->auth.chap_challenge, |
rc = istgt_hex2bin(uctl->auth.chap_challenge, |
UCTL_CHAP_CHALLENGE_LEN, | UCTL_CHAP_CHALLENGE_LEN, |
chap_c); | chap_c); |
if (rc < 0) { |
if (rc < 0) { |
fprintf(stderr, "challenge format error\n"); |
fprintf(stderr, "challenge format error\n"); |
return UCTL_CMD_ERR; |
return UCTL_CMD_ERR; |
Line 680 do_auth(UCTL_Ptr uctl)
|
Line 690 do_auth(UCTL_Ptr uctl)
|
istgt_md5update(&md5ctx, uctl->auth.chap_id, 1); |
istgt_md5update(&md5ctx, uctl->auth.chap_id, 1); |
/* followed by secret */ |
/* followed by secret */ |
istgt_md5update(&md5ctx, uctl->auth.secret, |
istgt_md5update(&md5ctx, uctl->auth.secret, |
strlen(uctl->auth.secret)); | strlen(uctl->auth.secret)); |
/* followed by Challenge Value */ |
/* followed by Challenge Value */ |
istgt_md5update(&md5ctx, uctl->auth.chap_challenge, |
istgt_md5update(&md5ctx, uctl->auth.chap_challenge, |
uctl->auth.chap_challenge_len); | uctl->auth.chap_challenge_len); |
/* uctlmd5 is Response Value */ |
/* uctlmd5 is Response Value */ |
istgt_md5final(uctlmd5, &md5ctx); |
istgt_md5final(uctlmd5, &md5ctx); |
|
|
Line 691 do_auth(UCTL_Ptr uctl)
|
Line 701 do_auth(UCTL_Ptr uctl)
|
worksize = uctl->worksize; |
worksize = uctl->worksize; |
|
|
istgt_bin2hex(workp, worksize, |
istgt_bin2hex(workp, worksize, |
uctlmd5, ISTGT_MD5DIGEST_LEN); | uctlmd5, ISTGT_MD5DIGEST_LEN); |
hexmd5 = workp; |
hexmd5 = workp; |
worksize -= strlen(hexmd5) + 1; |
worksize -= strlen(hexmd5) + 1; |
workp += strlen(hexmd5) + 1; |
workp += strlen(hexmd5) + 1; |
Line 704 do_auth(UCTL_Ptr uctl)
|
Line 714 do_auth(UCTL_Ptr uctl)
|
/* (binary length MUST not exceed 1024 bytes) */ |
/* (binary length MUST not exceed 1024 bytes) */ |
uctl->auth.chap_mchallenge_len = UCTL_CHAP_CHALLENGE_LEN; |
uctl->auth.chap_mchallenge_len = UCTL_CHAP_CHALLENGE_LEN; |
istgt_gen_random(uctl->auth.chap_mchallenge, |
istgt_gen_random(uctl->auth.chap_mchallenge, |
uctl->auth.chap_mchallenge_len); | uctl->auth.chap_mchallenge_len); |
|
|
istgt_bin2hex(workp, worksize, |
istgt_bin2hex(workp, worksize, |
uctl->auth.chap_mchallenge, | uctl->auth.chap_mchallenge, |
uctl->auth.chap_mchallenge_len); | uctl->auth.chap_mchallenge_len); |
hexchallenge = workp; |
hexchallenge = workp; |
worksize -= strlen(hexchallenge) + 1; |
worksize -= strlen(hexchallenge) + 1; |
workp += strlen(hexchallenge) + 1; |
workp += strlen(hexchallenge) + 1; |
|
|
/* send CHAP_NR with CHAP_IC */ |
/* send CHAP_NR with CHAP_IC */ |
uctl_snprintf(uctl, "AUTH CHAP_NR %s %s %d %s\n", |
uctl_snprintf(uctl, "AUTH CHAP_NR %s %s %d %s\n", |
uctl->auth.user, hexmd5, | uctl->auth.user, hexmd5, |
(int) uctl->auth.chap_mid[0], hexchallenge); | (int) uctl->auth.chap_mid[0], hexchallenge); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 763 do_auth(UCTL_Ptr uctl)
|
Line 773 do_auth(UCTL_Ptr uctl)
|
istgt_md5update(&md5ctx, uctl->auth.chap_mid, 1); |
istgt_md5update(&md5ctx, uctl->auth.chap_mid, 1); |
/* followed by secret */ |
/* followed by secret */ |
istgt_md5update(&md5ctx, uctl->auth.msecret, |
istgt_md5update(&md5ctx, uctl->auth.msecret, |
strlen(uctl->auth.msecret)); | strlen(uctl->auth.msecret)); |
/* followed by Challenge Value */ |
/* followed by Challenge Value */ |
istgt_md5update(&md5ctx, uctl->auth.chap_mchallenge, |
istgt_md5update(&md5ctx, uctl->auth.chap_mchallenge, |
uctl->auth.chap_mchallenge_len); | uctl->auth.chap_mchallenge_len); |
/* uctlmd5 is expecting Response Value */ |
/* uctlmd5 is expecting Response Value */ |
istgt_md5final(uctlmd5, &md5ctx); |
istgt_md5final(uctlmd5, &md5ctx); |
|
|
Line 792 do_auth(UCTL_Ptr uctl)
|
Line 802 do_auth(UCTL_Ptr uctl)
|
/* not mutual */ |
/* not mutual */ |
/* send CHAP_NR */ |
/* send CHAP_NR */ |
uctl_snprintf(uctl, "AUTH CHAP_NR %s %s\n", |
uctl_snprintf(uctl, "AUTH CHAP_NR %s %s\n", |
uctl->auth.user, hexmd5); | uctl->auth.user, hexmd5); |
rc = uctl_writeline(uctl); |
rc = uctl_writeline(uctl); |
if (rc != UCTL_CMD_OK) { |
if (rc != UCTL_CMD_OK) { |
return rc; |
return rc; |
Line 984 uctl_init(UCTL_Ptr uctl)
|
Line 994 uctl_init(UCTL_Ptr uctl)
|
uctl->req_auth_auto = 1; |
uctl->req_auth_auto = 1; |
uctl->req_auth = 0; |
uctl->req_auth = 0; |
uctl->req_auth_mutual = 0; |
uctl->req_auth_mutual = 0; |
|
} else if (strcasecmp(val, "None") == 0) { |
|
uctl->req_auth = 0; |
|
uctl->req_auth_mutual = 0; |
} else { |
} else { |
fprintf(stderr, "unknown auth\n"); |
fprintf(stderr, "unknown auth\n"); |
return -1; |
return -1; |
Line 999 uctl_init(UCTL_Ptr uctl)
|
Line 1012 uctl_init(UCTL_Ptr uctl)
|
printf("AuthMethod Auto\n"); |
printf("AuthMethod Auto\n"); |
} else { |
} else { |
printf("AuthMethod %s %s\n", |
printf("AuthMethod %s %s\n", |
uctl->req_auth ? "CHAP" : "", | uctl->req_auth ? "CHAP" : "", |
uctl->req_auth_mutual ? "Mutual" : ""); | uctl->req_auth_mutual ? "Mutual" : ""); |
} |
} |
#endif /* TRACE_UCTL */ |
#endif /* TRACE_UCTL */ |
|
|
Line 1019 uctl_init(UCTL_Ptr uctl)
|
Line 1032 uctl_init(UCTL_Ptr uctl)
|
uctl->auth.msecret = xstrdup(msecret); |
uctl->auth.msecret = xstrdup(msecret); |
#ifdef TRACE_UCTL |
#ifdef TRACE_UCTL |
printf("user=%s, secret=%s, muser=%s, msecret=%s\n", |
printf("user=%s, secret=%s, muser=%s, msecret=%s\n", |
user, secret, muser, msecret); | user, secret, muser, msecret); |
#endif /* TRACE_UCTL */ |
#endif /* TRACE_UCTL */ |
|
|
return 0; |
return 0; |
Line 1094 main(int argc, char *argv[])
|
Line 1107 main(int argc, char *argv[])
|
|
|
#ifdef HAVE_SETPROCTITLE |
#ifdef HAVE_SETPROCTITLE |
setproctitle("version %s (%s)", |
setproctitle("version %s (%s)", |
ISTGT_VERSION, ISTGT_EXTRA_VERSION); | ISTGT_VERSION, ISTGT_EXTRA_VERSION); |
#endif |
#endif |
|
|
memset(&xuctl, 0, sizeof xuctl); |
memset(&xuctl, 0, sizeof xuctl); |
Line 1120 main(int argc, char *argv[])
|
Line 1133 main(int argc, char *argv[])
|
break; |
break; |
case 'l': |
case 'l': |
l = strtol(optarg, NULL, 10); |
l = strtol(optarg, NULL, 10); |
if (l < 0 || l > 0x3fffU) { | if (l < 0 || l > 0x3fff) { |
fatal("invalid lun %s\n", optarg); |
fatal("invalid lun %s\n", optarg); |
} |
} |
lun = (int) l; |
lun = (int) l; |
Line 1141 main(int argc, char *argv[])
|
Line 1154 main(int argc, char *argv[])
|
if (strcasecmp(optarg, "CHAP") == 0) { |
if (strcasecmp(optarg, "CHAP") == 0) { |
req_auth = 1; |
req_auth = 1; |
} else if (strcasecmp(optarg, "Mutual") == 0 |
} else if (strcasecmp(optarg, "Mutual") == 0 |
|| strcasecmp(optarg, "Mutual CHAP") == 0 | || strcasecmp(optarg, "Mutual CHAP") == 0 |
|| strcasecmp(optarg, "CHAP Mutual") == 0) { | || strcasecmp(optarg, "CHAP Mutual") == 0) { |
req_auth = 2; |
req_auth = 2; |
} else if (strcasecmp(optarg, "Auto") == 0) { |
} else if (strcasecmp(optarg, "Auto") == 0) { |
req_auth = 0; |
req_auth = 0; |
Line 1173 main(int argc, char *argv[])
|
Line 1186 main(int argc, char *argv[])
|
break; |
break; |
case 'V': |
case 'V': |
printf("istgtcontrol version %s (%s)\n", |
printf("istgtcontrol version %s (%s)\n", |
ISTGT_VERSION, ISTGT_EXTRA_VERSION); | ISTGT_VERSION, ISTGT_EXTRA_VERSION); |
exit(EXIT_SUCCESS); |
exit(EXIT_SUCCESS); |
case 'H': |
case 'H': |
default: |
default: |
Line 1199 main(int argc, char *argv[])
|
Line 1212 main(int argc, char *argv[])
|
uctl->config = config; |
uctl->config = config; |
//istgt_print_config(config); |
//istgt_print_config(config); |
|
|
|
istgtcontrol_open_log(); |
|
|
/* take specified command */ |
/* take specified command */ |
if (argc < 1) { |
if (argc < 1) { |
error_usage_return: |
error_usage_return: |
Line 1247 main(int argc, char *argv[])
|
Line 1262 main(int argc, char *argv[])
|
} |
} |
|
|
/* build parameters */ |
/* build parameters */ |
uctl_init(uctl); | rc = uctl_init(uctl); |
| if (rc < 0) { |
| fprintf(stderr, "uctl_init() failed\n"); |
| istgt_free_config(config); |
| exit(EXIT_FAILURE); |
| } |
uctl->recvtmpcnt = 0; |
uctl->recvtmpcnt = 0; |
uctl->recvtmpidx = 0; |
uctl->recvtmpidx = 0; |
uctl->recvtmpsize = sizeof uctl->recvtmp; |
uctl->recvtmpsize = sizeof uctl->recvtmp; |
Line 1293 main(int argc, char *argv[])
|
Line 1313 main(int argc, char *argv[])
|
} |
} |
#ifdef TRACE_UCTL |
#ifdef TRACE_UCTL |
printf("auto=%d, auth=%d, mutual=%d\n", |
printf("auto=%d, auth=%d, mutual=%d\n", |
uctl->req_auth_auto, uctl->req_auth, uctl->req_auth_mutual); | uctl->req_auth_auto, uctl->req_auth, uctl->req_auth_mutual); |
#endif /* TRACE_UCTL */ |
#endif /* TRACE_UCTL */ |
|
|
if (host != NULL) { |
if (host != NULL) { |
Line 1331 main(int argc, char *argv[])
|
Line 1351 main(int argc, char *argv[])
|
if (verbose) { |
if (verbose) { |
printf("iqn=%s, lun=%d\n", NULLP(uctl->iqn), uctl->lun); |
printf("iqn=%s, lun=%d\n", NULLP(uctl->iqn), uctl->lun); |
printf("media file=%s, flags=%s, size=%s\n", |
printf("media file=%s, flags=%s, size=%s\n", |
NULLP(uctl->mfile), NULLP(uctl->mflags), NULLP(uctl->msize)); | NULLP(uctl->mfile), NULLP(uctl->mflags), NULLP(uctl->msize)); |
} |
} |
|
|
/* set signals */ |
/* set signals */ |
Line 1434 main(int argc, char *argv[])
|
Line 1454 main(int argc, char *argv[])
|
xfree(banner); |
xfree(banner); |
xfree(cmd); |
xfree(cmd); |
istgt_free_config(config); |
istgt_free_config(config); |
|
istgtcontrol_close_log(); |
|
|
/* return value as execution result */ |
/* return value as execution result */ |
if (exec_result != UCTL_CMD_OK) { |
if (exec_result != UCTL_CMD_OK) { |