#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/module.h>
#include <sys/linker.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <camlib.h>
#include "iscsi.h"
#include "iscontrol.h"
#define USAGE "[-dv] [-c file] [-n nickname] [-t target] [variable=value ...]"
#define OPTIONS "vdc:t:n:"
token_t AuthMethods[] = {
{"None", NONE},
{"KRB5", KRB5},
{"SPKM1", SPKM1},
{"SPKM2", SPKM2},
{"SRP", SRP},
{"CHAP", CHAP},
{0, 0}
};
token_t DigestMethods[] = {
{"None", 0},
{"CRC32", 1},
{"CRC32C", 1},
{0, 0}
};
int vflag;
char *iscsidev;
static isc_opt_t opvals = {
.port = 3260,
.sockbufsize = 128,
.iqn = "iqn.2005-01.il.ac.huji.cs:",
.sessionType = "Normal",
.targetAddress = 0,
.targetName = 0,
.initiatorName = 0,
.authMethod = "None",
.headerDigest = "None,CRC32C",
.dataDigest = "None,CRC32C",
.maxConnections = 1,
.maxRecvDataSegmentLength = 64 * 1024,
.maxXmitDataSegmentLength = 8 * 1024,
.maxBurstLength = 128 * 1024,
.firstBurstLength = 64 * 1024,
.defaultTime2Wait = 0,
.defaultTime2Retain = 0,
.maxOutstandingR2T = 1,
.errorRecoveryLevel = 0,
.dataPDUInOrder = true,
.dataSequenceInOrder = true,
.initialR2T = true,
.immediateData = true,
};
int
lookup(token_t *tbl, char *m)
{
token_t *tp;
for(tp = tbl; tp->name != NULL; tp++)
if(strcasecmp(tp->name, m) == 0)
return tp->val;
return 0;
}
int
main(int cc, char **vv)
{
int ch, disco;
char *pname, *p, *q, *ta, *kw;
isc_opt_t *op;
FILE *fd;
if (modfind(INITIATORMOD) < 0) {
if (kldload(INITIATORMOD) < 0 || modfind(INITIATORMOD) < 0) {
perror(INITIATORMOD ": Error while handling kernel module");
return 1;
}
}
op = &opvals;
iscsidev = "/dev/"ISCSIDEV;
fd = NULL;
pname = vv[0];
if((p = strrchr(pname, '/')) != NULL)
pname = p + 1;
kw = ta = NULL;
disco = 0;
while((ch = getopt(cc, vv, OPTIONS)) != -1) {
switch(ch) {
case 'v':
vflag++;
break;
case 'c':
fd = fopen(optarg, "r");
if(fd == NULL) {
perror(optarg);
exit(1);
}
break;
case 'd':
disco = 1;
break;
case 't':
ta = optarg;
break;
case 'n':
kw = optarg;
break;
default:
badu:
fprintf(stderr, "Usage: %s %s\n", pname, USAGE);
exit(1);
}
}
if(fd == NULL)
fd = fopen("/etc/iscsi.conf", "r");
if(fd != NULL) {
parseConfig(fd, kw, op);
fclose(fd);
}
cc -= optind;
vv += optind;
if(cc > 0) {
if(vflag)
printf("adding '%s'\n", *vv);
parseArgs(cc, vv, op);
}
if(ta)
op->targetAddress = ta;
if(op->targetAddress == NULL) {
fprintf(stderr, "No target!\n");
goto badu;
}
q = op->targetAddress;
if(*q == '[' && (q = strchr(q, ']')) != NULL) {
*q++ = '\0';
op->targetAddress++;
} else
q = op->targetAddress;
if((p = strchr(q, ':')) != NULL) {
*p++ = 0;
op->port = atoi(p);
p = strchr(p, ',');
}
if(p || ((p = strchr(q, ',')) != NULL)) {
*p++ = 0;
op->targetPortalGroupTag = atoi(p);
}
if(op->initiatorName == 0) {
char hostname[256];
if(op->iqn) {
if(gethostname(hostname, sizeof(hostname)) == 0)
asprintf(&op->initiatorName, "%s:%s", op->iqn, hostname);
else
asprintf(&op->initiatorName, "%s:%d", op->iqn, (int)time(0) & 0xff);
}
else {
if(gethostname(hostname, sizeof(hostname)) == 0)
asprintf(&op->initiatorName, "%s", hostname);
else
asprintf(&op->initiatorName, "%d", (int)time(0) & 0xff);
}
}
if(disco) {
op->sessionType = "Discovery";
op->targetName = 0;
}
fsm(op);
exit(0);
}