/*- * Copyright (c) 2005-2010 Daniel Braniss * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "iscontrol.h" static char version[] = "2.3.1"; // keep in sync with iscsi_initiator #define USAGE "[-v] [-d] [-c config] [-n name] [-t target] [-p pidfile]" #define OPTIONS "vdc:t:n:p:" 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} }; 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, }; static void usage(const char *pname) { fprintf(stderr, "usage: %s " USAGE "\n", pname); exit(1); } 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, *pidfile, *p, *q, *ta, *kw, *v; isc_opt_t *op; FILE *fd; size_t n; op = &opvals; iscsidev = "/dev/"ISCSIDEV; fd = NULL; pname = vv[0]; if ((pname = basename(pname)) == NULL) err(1, "basename"); kw = ta = 0; disco = 0; pidfile = NULL; /* | check for driver & controller version match */ n = 0; #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 "\")"); } v = malloc(n+1); if (v == NULL) err(1, "malloc"); if (sysctlbyname(VERSION_OID_S, v, &n, 0, 0) != 0) err(1, "sysctlbyname"); if (strncmp(version, v, 3) != 0) errx(1, "versions mismatch"); while((ch = getopt(cc, vv, OPTIONS)) != -1) { switch(ch) { case 'v': vflag++; break; case 'c': fd = fopen(optarg, "r"); if (fd == NULL) err(1, "fopen(\"%s\")", optarg); break; case 'd': disco = 1; break; case 't': ta = optarg; break; case 'n': kw = optarg; break; case 'p': pidfile = optarg; break; default: usage(pname); } } 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) { warnx("no target specified!"); usage(pname); } 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[MAXHOSTNAMELEN]; 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; } op->pidfile = pidfile; fsm(op); exit(0); }