2007-07-24 15:35:02 +00:00
|
|
|
/*-
|
2010-08-09 12:36:36 +00:00
|
|
|
* Copyright (c) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
|
2007-07-24 15:35:02 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* 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 AUTHOR 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 AUTHOR 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
| $Id: iscontrol.c,v 2.2 2006/12/01 09:11:56 danny Exp danny $
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
| the user level initiator (client)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <netdb.h>
|
2012-04-18 16:47:57 +00:00
|
|
|
#include <err.h>
|
2007-07-24 15:35:02 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2012-04-18 16:47:57 +00:00
|
|
|
#include <libgen.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2007-07-24 15:35:02 +00:00
|
|
|
#include <time.h>
|
2012-04-18 16:47:57 +00:00
|
|
|
#include <unistd.h>
|
2007-07-24 15:35:02 +00:00
|
|
|
#include <camlib.h>
|
|
|
|
|
2010-08-09 12:36:36 +00:00
|
|
|
#include <dev/iscsi/initiator/iscsi.h>
|
2007-07-24 15:35:02 +00:00
|
|
|
#include "iscontrol.h"
|
|
|
|
|
2012-04-13 18:21:56 +00:00
|
|
|
static char version[] = "2.3.1"; // keep in sync with iscsi_initiator
|
|
|
|
|
2010-08-09 12:36:36 +00:00
|
|
|
#define USAGE "[-v] [-d] [-c config] [-n name] [-t target] [-p pidfile]"
|
|
|
|
#define OPTIONS "vdc:t:n:p:"
|
2007-07-24 15:35:02 +00:00
|
|
|
|
|
|
|
token_t AuthMethods[] = {
|
|
|
|
{"None", NONE},
|
|
|
|
{"KRB5", KRB5},
|
|
|
|
{"SPKM1", SPKM1},
|
|
|
|
{"SPKM2", SPKM2},
|
|
|
|
{"SRP", SRP},
|
|
|
|
{"CHAP", CHAP},
|
2010-08-09 12:36:36 +00:00
|
|
|
{0, 0}
|
2007-07-24 15:35:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
token_t DigestMethods[] = {
|
|
|
|
{"None", 0},
|
|
|
|
{"CRC32", 1},
|
|
|
|
{"CRC32C", 1},
|
2010-08-09 12:36:36 +00:00
|
|
|
{0, 0}
|
2007-07-24 15:35:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
u_char isid[6 + 6];
|
|
|
|
/*
|
|
|
|
| Default values
|
|
|
|
*/
|
|
|
|
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, // 64 * 1024,
|
|
|
|
.maxBurstLength = 128 * 1024,
|
|
|
|
.firstBurstLength = 64 * 1024, // must be less than maxBurstLength
|
|
|
|
.defaultTime2Wait = 0,
|
|
|
|
.defaultTime2Retain = 0,
|
|
|
|
.maxOutstandingR2T = 1,
|
|
|
|
.errorRecoveryLevel = 0,
|
|
|
|
|
|
|
|
.dataPDUInOrder = TRUE,
|
|
|
|
.dataSequenceInOrder = TRUE,
|
|
|
|
|
|
|
|
.initialR2T = TRUE,
|
|
|
|
.immediateData = TRUE,
|
|
|
|
};
|
|
|
|
|
2012-04-18 16:47:57 +00:00
|
|
|
static void
|
|
|
|
usage(const char *pname)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "usage: %s " USAGE "\n", pname);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2007-07-24 15:35:02 +00:00
|
|
|
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;
|
2012-04-13 18:21:56 +00:00
|
|
|
char *pname, *pidfile, *p, *q, *ta, *kw, *v;
|
2007-07-24 15:35:02 +00:00
|
|
|
isc_opt_t *op;
|
|
|
|
FILE *fd;
|
2012-04-13 18:21:56 +00:00
|
|
|
size_t n;
|
2007-07-24 15:35:02 +00:00
|
|
|
|
|
|
|
op = &opvals;
|
|
|
|
iscsidev = "/dev/"ISCSIDEV;
|
|
|
|
fd = NULL;
|
|
|
|
pname = vv[0];
|
2012-04-18 16:47:57 +00:00
|
|
|
if ((pname = basename(pname)) == NULL)
|
|
|
|
err(1, "basename");
|
2007-07-24 15:35:02 +00:00
|
|
|
|
|
|
|
kw = ta = 0;
|
|
|
|
disco = 0;
|
2010-08-09 12:36:36 +00:00
|
|
|
pidfile = NULL;
|
2012-04-13 18:21:56 +00:00
|
|
|
/*
|
|
|
|
| check for driver & controller version match
|
|
|
|
*/
|
|
|
|
n = 0;
|
2012-04-18 16:47:57 +00:00
|
|
|
#define VERSION_OID_S "net.iscsi_initiator.driver_version"
|
|
|
|
if (sysctlbyname(VERSION_OID_S, 0, &n, 0, 0) != 0) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
errx(1, "sysctlbyname(\"" VERSION_OID_S "\") "
|
|
|
|
"failed; is the iscsi driver loaded?");
|
|
|
|
err(1, "sysctlbyname(\"" VERSION_OID_S "\")");
|
2012-04-13 18:21:56 +00:00
|
|
|
}
|
2012-04-18 16:47:57 +00:00
|
|
|
v = malloc(n+1);
|
|
|
|
if (v == NULL)
|
|
|
|
err(1, "malloc");
|
|
|
|
if (sysctlbyname(VERSION_OID_S, v, &n, 0, 0) != 0)
|
|
|
|
err(1, "sysctlbyname");
|
2012-04-13 18:21:56 +00:00
|
|
|
|
2012-04-18 16:47:57 +00:00
|
|
|
if (strncmp(version, v, 3) != 0)
|
|
|
|
errx(1, "versions mismatch");
|
2007-07-24 15:35:02 +00:00
|
|
|
|
|
|
|
while((ch = getopt(cc, vv, OPTIONS)) != -1) {
|
|
|
|
switch(ch) {
|
|
|
|
case 'v':
|
|
|
|
vflag++;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
fd = fopen(optarg, "r");
|
2012-04-18 16:47:57 +00:00
|
|
|
if (fd == NULL)
|
|
|
|
err(1, "fopen(\"%s\")", optarg);
|
2007-07-24 15:35:02 +00:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
disco = 1;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
ta = optarg;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
kw = optarg;
|
|
|
|
break;
|
2010-08-09 12:36:36 +00:00
|
|
|
case 'p':
|
|
|
|
pidfile = optarg;
|
|
|
|
break;
|
2007-07-24 15:35:02 +00:00
|
|
|
default:
|
2012-04-18 16:47:57 +00:00
|
|
|
usage(pname);
|
2007-07-24 15:35:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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) {
|
2012-04-18 16:47:57 +00:00
|
|
|
warnx("no target specified!");
|
|
|
|
usage(pname);
|
2007-07-24 15:35:02 +00:00
|
|
|
}
|
2008-11-25 07:17:11 +00:00
|
|
|
q = op->targetAddress;
|
|
|
|
if(*q == '[' && (q = strchr(q, ']')) != NULL) {
|
|
|
|
*q++ = '\0';
|
|
|
|
op->targetAddress++;
|
|
|
|
} else
|
|
|
|
q = op->targetAddress;
|
|
|
|
if((p = strchr(q, ':')) != NULL) {
|
2007-07-24 15:35:02 +00:00
|
|
|
*p++ = 0;
|
|
|
|
op->port = atoi(p);
|
|
|
|
p = strchr(p, ',');
|
|
|
|
}
|
2008-11-25 07:17:11 +00:00
|
|
|
if(p || ((p = strchr(q, ',')) != NULL)) {
|
2007-07-24 15:35:02 +00:00
|
|
|
*p++ = 0;
|
|
|
|
op->targetPortalGroupTag = atoi(p);
|
|
|
|
}
|
|
|
|
if(op->initiatorName == 0) {
|
2012-04-18 16:47:57 +00:00
|
|
|
char hostname[MAXHOSTNAMELEN];
|
2007-07-24 15:35:02 +00:00
|
|
|
|
|
|
|
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); // XXX:
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(gethostname(hostname, sizeof(hostname)) == 0)
|
|
|
|
asprintf(&op->initiatorName, "%s", hostname);
|
|
|
|
else
|
|
|
|
asprintf(&op->initiatorName, "%d", (int)time(0) & 0xff); // XXX:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(disco) {
|
|
|
|
op->sessionType = "Discovery";
|
|
|
|
op->targetName = 0;
|
|
|
|
}
|
2010-08-09 12:36:36 +00:00
|
|
|
op->pidfile = pidfile;
|
2007-07-24 15:35:02 +00:00
|
|
|
fsm(op);
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|