Index: ObsoleteFiles.inc =================================================================== --- ObsoleteFiles.inc +++ ObsoleteFiles.inc @@ -40,6 +40,11 @@ # xargs -n1 | sort | uniq -d; # done +# 2021xxxx: retire obsolete iscsi initiator +OLD_FILES+=sbin/iscontrol +OLD_FILES+=usr/share/man/man4/iscsi_initiator.4.gz +OLD_FILES+=usr/share/man/man8/iscontrol.8.gz + # 20211022 OLD_FILES+=sbin/spppcontrol .if ${TARGET_ARCH} == "i386" Index: sbin/Makefile =================================================================== --- sbin/Makefile +++ sbin/Makefile @@ -76,7 +76,6 @@ SUBDIR.${MK_IPFILTER}+= ipf SUBDIR.${MK_IPFW}+= ipfw SUBDIR.${MK_IPFW}+= natd -SUBDIR.${MK_ISCSI}+= iscontrol SUBDIR.${MK_NVME}+= nvmecontrol SUBDIR.${MK_OPENSSL}+= decryptcore SUBDIR.${MK_PF}+= pfctl Index: sbin/iscontrol/Makefile =================================================================== --- sbin/iscontrol/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD$ - -PACKAGE=iscsilegacy -SRCS= iscontrol.c pdu.c fsm.c config.c login.c auth_subr.c misc.c -PROG= iscontrol -LIBADD= cam md -S= ${SRCTOP}/sys - -WARNS?= 3 -CFLAGS+= -I$S - -MAN= iscontrol.8 - -.include Index: sbin/iscontrol/Makefile.depend =================================================================== --- sbin/iscontrol/Makefile.depend +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - gnu/lib/csu \ - include \ - include/arpa \ - include/xlocale \ - lib/${CSU_DIR} \ - lib/libc \ - lib/libcam \ - lib/libcompiler_rt \ - lib/libmd \ - lib/libsbuf \ - - -.include - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif Index: sbin/iscontrol/auth_subr.c =================================================================== --- sbin/iscontrol/auth_subr.c +++ /dev/null @@ -1,206 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: auth_subr.c,v 2.2 2007/06/01 08:09:37 danny Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include "iscontrol.h" - -static int -chapMD5(char id, char *cp, char *chapSecret, unsigned char *digest) -{ - MD5_CTX ctx; - char *tmp; - int len; - - debug_called(3); - - MD5Init(&ctx); - - MD5Update(&ctx, &id, 1); - - if((len = str2bin(chapSecret, &tmp)) == 0) { - // print error - return -1; - } - MD5Update(&ctx, tmp, len); - free(tmp); - - if((len = str2bin(cp, &tmp)) == 0) { - // print error - return -1; - } - MD5Update(&ctx, tmp, len); - free(tmp); - - MD5Final(digest, &ctx); - - - return 0; -} - -static int -chapSHA1(char id, char *cp, char *chapSecret, unsigned char *digest) -{ - SHA1_CTX ctx; - char *tmp; - int len; - - debug_called(3); - - SHA1_Init(&ctx); - - SHA1_Update(&ctx, &id, 1); - - if((len = str2bin(chapSecret, &tmp)) == 0) { - // print error - return -1; - } - SHA1_Update(&ctx, tmp, len); - free(tmp); - - if((len = str2bin(cp, &tmp)) == 0) { - // print error - return -1; - } - SHA1_Update(&ctx, tmp, len); - free(tmp); - - SHA1_Final(digest, &ctx); - - return 0; - -} -/* - | the input text format can be anything that the rfc3270 defines - | (see section 5.1 and str2bin) - | digest length for md5 is 128bits, and for sha1 is 160bits. - | digest is an ASCII string which represents the bits in - | hexadecimal or base64 according to the challenge(cp) format - */ -char * -chapDigest(char *ap, char id, char *cp, char *chapSecret) -{ - int len; - unsigned char digest[20]; - char encoding[3]; - - debug_called(3); - - len = 0; - if(strcmp(ap, "5") == 0 && chapMD5(id, cp, chapSecret, digest) == 0) - len = 16; - else - if(strcmp(ap, "7") == 0 && chapSHA1(id, cp, chapSecret, digest) == 0) - len = 20; - - if(len) { - sprintf(encoding, "%.2s", cp); - return bin2str(encoding, digest, len); - } - - return NULL; -} - -char * -genChapChallenge(char *encoding, uint len) -{ - int fd; - unsigned char tmp[1024]; - - if(len > sizeof(tmp)) - return NULL; - - if((fd = open("/dev/random", O_RDONLY)) != -1) { - read(fd, tmp, len); - close(fd); - return bin2str(encoding, tmp, len); - } - perror("/dev/random"); - // make up something ... - return NULL; -} - -#ifdef TEST_AUTH -static void -puke(char *str, unsigned char *dg, int len) -{ - printf("%3d] %s\n 0x", len, str); - while(len-- > 0) - printf("%02x", *dg++); - printf("\n"); -} - -main(int cc, char **vv) -{ - char *p, *ap, *ip, *cp, *chapSecret, *digest; - int len; - -#if 0 - ap = "5"; - chapSecret = "0xa5aff013dd839b1edd31ee73a1df0b1b"; -// chapSecret = "abcdefghijklmnop"; - len = str2bin(chapSecret, &cp); - puke(chapSecret, cp, len); - - ip = "238"; - cp = "0xbd456029"; - - - if((digest = chapDigest(ap, ip, cp, chapSecret)) != NULL) { - len = str2bin(digest, &cp); - puke(digest, cp, len); - } -#else - printf("%d] %s\n", 24, genChallenge("0X", 24)); -#endif -} -#endif Index: sbin/iscontrol/config.c =================================================================== --- sbin/iscontrol/config.c +++ /dev/null @@ -1,382 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005-2009 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: config.c,v 2.1 2006/11/12 08:06:51 danny Exp danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "iscontrol.h" - -/* - | ints - */ -#define OPT_port 1 -#define OPT_tags 2 - -#define OPT_maxConnections 3 -#define OPT_maxRecvDataSegmentLength 4 -#define OPT_maxXmitDataSegmentLength 5 -#define OPT_maxBurstLength 6 -#define OPT_firstBurstLength 7 -#define OPT_defaultTime2Wait 8 -#define OPT_defaultTime2Retain 9 -#define OPT_maxOutstandingR2T 10 -#define OPT_errorRecoveryLevel 11 -#define OPT_targetPortalGroupTag 12 -#define OPT_headerDigest 13 -#define OPT_dataDigest 14 -/* - | Booleans - */ -#define OPT_initialR2T 16 -#define OPT_immediateData 17 -#define OPT_dataPDUInOrder 18 -#define OPT_dataSequenceInOrder 19 -/* - | strings - */ -#define OPT_sessionType 15 - -#define OPT_targetAddress 21 -#define OPT_targetAlias 22 -#define OPT_targetName 23 -#define OPT_initiatorName 24 -#define OPT_initiatorAlias 25 -#define OPT_authMethod 26 - -#define OPT_chapSecret 27 -#define OPT_chapIName 28 -#define OPT_chapDigest 29 -#define OPT_tgtChapName 30 -#define OPT_tgtChapSecret 31 -#define OPT_tgtChallengeLen 32 -/* - | private - */ -#define OPT_maxluns 33 -#define OPT_iqn 34 -#define OPT_sockbufsize 35 - -/* - | sentinel - */ -#define OPT_end 0 - -#define _OFF(v) ((int)&((isc_opt_t *)NULL)->v) -#define _E(u, s, v) {.usage=u, .scope=s, .name=#v, .tokenID=OPT_##v} - -textkey_t keyMap[] = { - _E(U_PR, S_PR, port), - _E(U_PR, S_PR, tags), - _E(U_PR, S_PR, maxluns), - _E(U_PR, S_PR, sockbufsize), - - _E(U_PR, S_PR, iqn), - _E(U_PR, S_PR, chapSecret), - _E(U_PR, S_PR, chapIName), - _E(U_PR, S_PR, chapDigest), - _E(U_PR, S_PR, tgtChapName), - _E(U_PR, S_PR, tgtChapSecret), - _E(U_PR, S_PR, tgtChallengeLen), - - _E(U_IO, S_CO, headerDigest), - _E(U_IO, S_CO, dataDigest), - - _E(U_IO, S_CO, authMethod), - - _E(U_LO, S_SW, maxConnections), - _E(U_IO, S_SW, targetName), - - _E(U_IO, S_SW, initiatorName), - _E(U_ALL,S_SW, targetAlias), - _E(U_ALL,S_SW, initiatorAlias), - _E(U_ALL,S_SW, targetAddress), - - _E(U_ALL,S_SW, targetPortalGroupTag), - - _E(U_LO, S_SW, initialR2T), - _E(U_LO, S_SW, immediateData), - - _E(U_ALL,S_CO, maxRecvDataSegmentLength), - _E(U_ALL,S_CO, maxXmitDataSegmentLength), - - _E(U_LO, S_SW, maxBurstLength), - _E(U_LO, S_SW, firstBurstLength), - _E(U_LO, S_SW, defaultTime2Wait), - _E(U_LO, S_SW, defaultTime2Retain), - - _E(U_LO, S_SW, maxOutstandingR2T), - _E(U_LO, S_SW, dataPDUInOrder), - _E(U_LO, S_SW, dataSequenceInOrder), - - _E(U_LO, S_SW, errorRecoveryLevel), - - _E(U_LO, S_SW, sessionType), - - _E(0, 0, end) -}; - -#define _OPT_INT(w) strtol((char *)w, NULL, 0) -#define _OPT_STR(w) (char *)(w) - -static __inline int -_OPT_BOOL(char *w) -{ - if(isalpha((unsigned char)*w)) - return strcasecmp(w, "TRUE") == 0; - else - return _OPT_INT(w); -} - -#define _CASE(k, v) case OPT_##k: op->k = v; break -static void -setOption(isc_opt_t *op, int which, void *rval) -{ - switch(which) { - _CASE(port, _OPT_INT(rval)); - _CASE(tags, _OPT_INT(rval)); - _CASE(maxluns, _OPT_INT(rval)); - _CASE(iqn, _OPT_STR(rval)); - _CASE(sockbufsize, _OPT_INT(rval)); - - _CASE(maxConnections, _OPT_INT(rval)); - _CASE(maxRecvDataSegmentLength, _OPT_INT(rval)); - _CASE(maxXmitDataSegmentLength, _OPT_INT(rval)); - _CASE(maxBurstLength, _OPT_INT(rval)); - _CASE(firstBurstLength, _OPT_INT(rval)); - _CASE(defaultTime2Wait, _OPT_INT(rval)); - _CASE(defaultTime2Retain, _OPT_INT(rval)); - _CASE(maxOutstandingR2T, _OPT_INT(rval)); - _CASE(errorRecoveryLevel, _OPT_INT(rval)); - _CASE(targetPortalGroupTag, _OPT_INT(rval)); - _CASE(headerDigest, _OPT_STR(rval)); - _CASE(dataDigest, _OPT_STR(rval)); - - _CASE(targetAddress, _OPT_STR(rval)); - _CASE(targetAlias, _OPT_STR(rval)); - _CASE(targetName, _OPT_STR(rval)); - _CASE(initiatorName, _OPT_STR(rval)); - _CASE(initiatorAlias, _OPT_STR(rval)); - _CASE(authMethod, _OPT_STR(rval)); - _CASE(chapSecret, _OPT_STR(rval)); - _CASE(chapIName, _OPT_STR(rval)); - _CASE(chapDigest, _OPT_STR(rval)); - - _CASE(tgtChapName, _OPT_STR(rval)); - _CASE(tgtChapSecret, _OPT_STR(rval)); - - _CASE(initialR2T, _OPT_BOOL(rval)); - _CASE(immediateData, _OPT_BOOL(rval)); - _CASE(dataPDUInOrder, _OPT_BOOL(rval)); - _CASE(dataSequenceInOrder, _OPT_BOOL(rval)); - } -} - -static char * -get_line(FILE *fd) -{ - static char *sp, line[BUFSIZ]; - char *lp, *p; - - do { - if(sp == NULL) - sp = fgets(line, sizeof line, fd); - - if((lp = sp) == NULL) - break; - if((p = strchr(lp, '\n')) != NULL) - *p = 0; - if((p = strchr(lp, '#')) != NULL) - *p = 0; - if((p = strchr(lp, ';')) != NULL) { - *p++ = 0; - sp = p; - } else - sp = NULL; - if(*lp) - return lp; - } while (feof(fd) == 0); - return NULL; -} - -static int -getConfig(FILE *fd, char *key, char **Ar, int *nargs) -{ - char *lp, *p, **ar; - int state, len, n; - - ar = Ar; - if(key) - len = strlen(key); - else - len = 0; - state = 0; - while((lp = get_line(fd)) != NULL) { - for(; isspace((unsigned char)*lp); lp++) - ; - switch(state) { - case 0: - if((p = strchr(lp, '{')) != NULL) { - while((--p > lp) && *p && isspace((unsigned char)*p)); - n = p - lp; - if(len && strncmp(lp, key, MAX(n, len)) == 0) - state = 2; - else - state = 1; - continue; - } - break; - - case 1: - if(*lp == '}') - state = 0; - continue; - - case 2: - if(*lp == '}') - goto done; - - break; - } - - - for(p = &lp[strlen(lp)-1]; isspace((unsigned char)*p); p--) - *p = 0; - if((*nargs)-- > 0) - *ar++ = strdup(lp); - } - - done: - if(*nargs > 0) - *ar = 0; - *nargs = ar - Ar; - return ar - Ar; -} - -static textkey_t * -keyLookup(char *key) -{ - textkey_t *tk; - - for(tk = keyMap; tk->name && strcmp(tk->name, "end"); tk++) { - if(strcasecmp(key, tk->name) == 0) - return tk; - } - return NULL; -} - -static void -puke(isc_opt_t *op) -{ - printf("%24s = %d\n", "port", op->port); - printf("%24s = %d\n", "tags", op->tags); - printf("%24s = %d\n", "maxluns", op->maxluns); - printf("%24s = %s\n", "iqn", op->iqn); - - printf("%24s = %d\n", "maxConnections", op->maxConnections); - printf("%24s = %d\n", "maxRecvDataSegmentLength", op->maxRecvDataSegmentLength); - printf("%24s = %d\n", "maxXmitDataSegmentLength", op->maxRecvDataSegmentLength); - printf("%24s = %d\n", "maxBurstLength", op->maxBurstLength); - printf("%24s = %d\n", "firstBurstLength", op->firstBurstLength); - printf("%24s = %d\n", "defaultTime2Wait", op->defaultTime2Wait); - printf("%24s = %d\n", "defaultTime2Retain", op->defaultTime2Retain); - printf("%24s = %d\n", "maxOutstandingR2T", op->maxOutstandingR2T); - printf("%24s = %d\n", "errorRecoveryLevel", op->errorRecoveryLevel); - printf("%24s = %d\n", "targetPortalGroupTag", op->targetPortalGroupTag); - - printf("%24s = %s\n", "headerDigest", op->headerDigest); - printf("%24s = %s\n", "dataDigest", op->dataDigest); - - printf("%24s = %d\n", "initialR2T", op->initialR2T); - printf("%24s = %d\n", "immediateData", op->immediateData); - printf("%24s = %d\n", "dataPDUInOrder", op->dataPDUInOrder); - printf("%24s = %d\n", "dataSequenceInOrder", op->dataSequenceInOrder); - - printf("%24s = %s\n", "sessionType", op->sessionType); - printf("%24s = %s\n", "targetAddress", op->targetAddress); - printf("%24s = %s\n", "targetAlias", op->targetAlias); - printf("%24s = %s\n", "targetName", op->targetName); - printf("%24s = %s\n", "initiatorName", op->initiatorName); - printf("%24s = %s\n", "initiatorAlias", op->initiatorAlias); - printf("%24s = %s\n", "authMethod", op->authMethod); - printf("%24s = %s\n", "chapSecret", op->chapSecret); - printf("%24s = %s\n", "chapIName", op->chapIName); - printf("%24s = %s\n", "tgtChapName", op->tgtChapName); - printf("%24s = %s\n", "tgtChapSecret", op->tgtChapSecret); - printf("%24s = %d\n", "tgttgtChallengeLen", op->tgtChallengeLen); -} - -void -parseArgs(int nargs, char **args, isc_opt_t *op) -{ - char **ar; - char *p, *v; - textkey_t *tk; - - for(ar = args; nargs > 0; nargs--, ar++) { - p = strchr(*ar, '='); - if(p == NULL) - continue; - *p = 0; - v = p + 1; - while(isspace((unsigned char)*--p)) - *p = 0; - while(isspace((unsigned char)*v)) - v++; - if((tk = keyLookup(*ar)) == NULL) - continue; - setOption(op, tk->tokenID, v); - } -} - -void -parseConfig(FILE *fd, char *key, isc_opt_t *op) -{ - char *Ar[256]; - int cc; - - cc = 256; - if(getConfig(fd, key, Ar, &cc)) - parseArgs(cc, Ar, op); - if(vflag) - puke(op); -} Index: sbin/iscontrol/fsm.c =================================================================== --- sbin/iscontrol/fsm.c +++ /dev/null @@ -1,759 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: fsm.c,v 2.8 2007/05/19 16:34:21 danny Exp danny $ - */ - -#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" - -typedef enum { - T1 = 1, - T2, /*T3,*/ T4, T5, /*T6,*/ T7, T8, T9, - T10, T11, T12, T13, T14, T15, T16, T18 -} trans_t; - -/* - | now supports IPV6 - | thanks to: - | Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan - | ume@mahoroba.org ume@{,jp.}FreeBSD.org - | http://www.imasy.org/~ume/ - */ -static trans_t -tcpConnect(isess_t *sess) -{ - isc_opt_t *op = sess->op; - int val, sv_errno, soc; - struct addrinfo *res, *res0, hints; - char pbuf[10]; - - debug_called(3); - if(sess->flags & (SESS_RECONNECT|SESS_REDIRECT)) { - syslog(LOG_INFO, "%s", (sess->flags & SESS_RECONNECT) - ? "Reconnect": "Redirected"); - - debug(1, "%s", (sess->flags & SESS_RECONNECT) ? "Reconnect": "Redirected"); - shutdown(sess->soc, SHUT_RDWR); - //close(sess->soc); - sess->soc = -1; - - sess->flags &= ~SESS_CONNECTED; - if(sess->flags & SESS_REDIRECT) { - sess->redirect_cnt++; - sess->flags |= SESS_RECONNECT; - } else - sleep(2); // XXX: actually should be ? -#ifdef notyet - { - time_t sec; - // make sure we are not in a loop - // XXX: this code has to be tested - sec = time(0) - sess->reconnect_time; - if(sec > (5*60)) { - // if we've been connected for more that 5 minutes - // then just reconnect - sess->reconnect_time = sec; - sess->reconnect_cnt1 = 0; - } - else { - // - sess->reconnect_cnt1++; - if((sec / sess->reconnect_cnt1) < 2) { - // if less that 2 seconds from the last reconnect - // we are most probably looping - syslog(LOG_CRIT, "too many reconnects %d", sess->reconnect_cnt1); - return 0; - } - } - } -#endif - sess->reconnect_cnt++; - } - - snprintf(pbuf, sizeof(pbuf), "%d", op->port); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - debug(1, "targetAddress=%s port=%d", op->targetAddress, op->port); - if((val = getaddrinfo(op->targetAddress, pbuf, &hints, &res0)) != 0) { - fprintf(stderr, "getaddrinfo(%s): %s\n", op->targetAddress, gai_strerror(val)); - return 0; - } - sess->flags &= ~SESS_CONNECTED; - sv_errno = 0; - soc = -1; - for(res = res0; res; res = res->ai_next) { - soc = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (soc == -1) - continue; - - // from Patrick.Guelat@imp.ch: - // iscontrol can be called without waiting for the socket entry to time out - val = 1; - if(setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, &val, (socklen_t)sizeof(val)) < 0) { - fprintf(stderr, "Cannot set socket SO_REUSEADDR %d: %s\n\n", - errno, strerror(errno)); - } - - if(connect(soc, res->ai_addr, res->ai_addrlen) == 0) - break; - sv_errno = errno; - close(soc); - soc = -1; - } - freeaddrinfo(res0); - if(soc != -1) { - sess->soc = soc; - -#if 0 - struct timeval timeout; - - val = 1; - if(setsockopt(sess->soc, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) - fprintf(stderr, "Cannot set socket KEEPALIVE option err=%d %s\n", - errno, strerror(errno)); - - if(setsockopt(sess->soc, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0) - fprintf(stderr, "Cannot set socket NO delay option err=%d %s\n", - errno, strerror(errno)); - - timeout.tv_sec = 10; - timeout.tv_usec = 0; - if((setsockopt(sess->soc, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) - || (setsockopt(sess->soc, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)) { - fprintf(stderr, "Cannot set socket timeout to %ld err=%d %s\n", - timeout.tv_sec, errno, strerror(errno)); - } -#endif -#ifdef CURIOUS - { - int len = sizeof(val); - if(getsockopt(sess->soc, SOL_SOCKET, SO_SNDBUF, &val, &len) == 0) - fprintf(stderr, "was: SO_SNDBUF=%dK\n", val/1024); - } -#endif - if(sess->op->sockbufsize) { - val = sess->op->sockbufsize * 1024; - if((setsockopt(sess->soc, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) < 0) - || (setsockopt(sess->soc, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) < 0)) { - fprintf(stderr, "Cannot set socket sndbuf & rcvbuf to %d err=%d %s\n", - val, errno, strerror(errno)); - return 0; - } - } - sess->flags |= SESS_CONNECTED; - return T1; - } - - fprintf(stderr, "errno=%d\n", sv_errno); - perror("connect"); - switch(sv_errno) { - case ECONNREFUSED: - case EHOSTUNREACH: - case ENETUNREACH: - case ETIMEDOUT: - if((sess->flags & SESS_REDIRECT) == 0) { - if(strcmp(op->targetAddress, sess->target.address) != 0) { - syslog(LOG_INFO, "reconnecting to original target address"); - free(op->targetAddress); - op->targetAddress = sess->target.address; - op->port = sess->target.port; - op->targetPortalGroupTag = sess->target.pgt; - return T1; - } - } - sleep(5); // for now ... - return T1; - default: - return 0; // terminal error - } -} - -int -setOptions(isess_t *sess, int flag) -{ - isc_opt_t oop; - char *sep; - - debug_called(3); - - bzero(&oop, sizeof(isc_opt_t)); - - if((flag & SESS_FULLFEATURE) == 0) { - oop.initiatorName = sess->op->initiatorName; - oop.targetAddress = sess->op->targetAddress; - if(sess->op->targetName != 0) - oop.targetName = sess->op->targetName; - - oop.maxRecvDataSegmentLength = sess->op->maxRecvDataSegmentLength; - oop.maxXmitDataSegmentLength = sess->op->maxXmitDataSegmentLength; // XXX: - oop.maxBurstLength = sess->op->maxBurstLength; - oop.maxluns = sess->op->maxluns; - } - else { - /* - | turn on digestion only after login - */ - if(sess->op->headerDigest != NULL) { - sep = strchr(sess->op->headerDigest, ','); - if(sep == NULL) - oop.headerDigest = sess->op->headerDigest; - debug(1, "oop.headerDigest=%s", oop.headerDigest); - } - if(sess->op->dataDigest != NULL) { - sep = strchr(sess->op->dataDigest, ','); - if(sep == NULL) - oop.dataDigest = sess->op->dataDigest; - debug(1, "oop.dataDigest=%s", oop.dataDigest); - } - } - - if(ioctl(sess->fd, ISCSISETOPT, &oop)) { - perror("ISCSISETOPT"); - return -1; - } - return 0; -} - -static trans_t -startSession(isess_t *sess) -{ - - int n, fd, nfd; - char *dev; - - debug_called(3); - - if((sess->flags & SESS_CONNECTED) == 0) { - return T2; - } - if(sess->fd == -1) { - fd = open(iscsidev, O_RDWR); - if(fd < 0) { - perror(iscsidev); - return 0; - } - { - // XXX: this has to go - size_t n; - n = sizeof(sess->isid); - if(sysctlbyname("net.iscsi_initiator.isid", (void *)sess->isid, (size_t *)&n, 0, 0) != 0) - perror("sysctlbyname"); - } - if(ioctl(fd, ISCSISETSES, &n)) { - perror("ISCSISETSES"); - return 0; - } - asprintf(&dev, "%s%d", iscsidev, n); - nfd = open(dev, O_RDWR); - if(nfd < 0) { - perror(dev); - free(dev); - return 0; - } - free(dev); - close(fd); - sess->fd = nfd; - - if(setOptions(sess, 0) != 0) - return -1; - } - - if(ioctl(sess->fd, ISCSISETSOC, &sess->soc)) { - perror("ISCSISETSOC"); - return 0; - } - - return T4; -} - -isess_t *currsess; - -static void -trap(int sig) -{ - syslog(LOG_NOTICE, "trapped signal %d", sig); - fprintf(stderr, "trapped signal %d\n", sig); - - switch(sig) { - case SIGHUP: - currsess->flags |= SESS_DISCONNECT; - break; - - case SIGUSR1: - currsess->flags |= SESS_RECONNECT; - break; - - case SIGINT: - case SIGTERM: - default: - return; // ignore - } -} - -static int -doCAM(isess_t *sess) -{ - char pathstr[1024]; - union ccb *ccb; - int i, n; - - if(ioctl(sess->fd, ISCSIGETCAM, &sess->cam) != 0) { - syslog(LOG_WARNING, "ISCSIGETCAM failed: %d", errno); - return 0; - } - debug(1, "nluns=%d", sess->cam.target_nluns); - /* - | for now will do this for each lun ... - */ - for(n = i = 0; i < sess->cam.target_nluns; i++) { - debug(2, "CAM path_id=%d target_id=%d", - sess->cam.path_id, sess->cam.target_id); - - sess->camdev = cam_open_btl(sess->cam.path_id, sess->cam.target_id, - i, O_RDWR, NULL); - if(sess->camdev == NULL) { - //syslog(LOG_WARNING, "%s", cam_errbuf); - debug(3, "%s", cam_errbuf); - continue; - } - - cam_path_string(sess->camdev, pathstr, sizeof(pathstr)); - debug(2, "pathstr=%s", pathstr); - - ccb = cam_getccb(sess->camdev); - CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->crs); - ccb->ccb_h.func_code = XPT_REL_SIMQ; - ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS; - ccb->crs.openings = sess->op->tags; - if(cam_send_ccb(sess->camdev, ccb) < 0) - debug(2, "%s", cam_errbuf); - else - if((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - syslog(LOG_WARNING, "XPT_REL_SIMQ CCB failed"); - // cam_error_print(sess->camdev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); - } - else { - n++; - syslog(LOG_INFO, "%s tagged openings now %d\n", pathstr, ccb->crs.openings); - } - cam_freeccb(ccb); - cam_close_device(sess->camdev); - } - return n; -} - -static trans_t -supervise(isess_t *sess) -{ - int sig, val; - - debug_called(3); - - if(strcmp(sess->op->sessionType, "Discovery") == 0) { - sess->flags |= SESS_DISCONNECT; - return T9; - } - - if(vflag) - printf("ready to go scsi\n"); - - if(setOptions(sess, SESS_FULLFEATURE) != 0) - return 0; // failure - - if((sess->flags & SESS_FULLFEATURE) == 0) { - if(daemon(0, 1) != 0) { - perror("daemon"); - exit(1); - } - if(sess->op->pidfile != NULL) { - FILE *pidf; - - pidf = fopen(sess->op->pidfile, "w"); - if(pidf != NULL) { - fprintf(pidf, "%d\n", getpid()); - fclose(pidf); - } - } - openlog("iscontrol", LOG_CONS|LOG_PERROR|LOG_PID|LOG_NDELAY, LOG_KERN); - syslog(LOG_INFO, "running"); - - currsess = sess; - if(ioctl(sess->fd, ISCSISTART)) { - perror("ISCSISTART"); - return -1; - } - if(doCAM(sess) == 0) { - syslog(LOG_WARNING, "no device found"); - ioctl(sess->fd, ISCSISTOP); - return T15; - } - - } - else { - if(ioctl(sess->fd, ISCSIRESTART)) { - perror("ISCSIRESTART"); - return -1; - } - } - - signal(SIGINT, trap); - signal(SIGHUP, trap); - signal(SIGTERM, trap); - - sig = SIGUSR1; - signal(sig, trap); - if(ioctl(sess->fd, ISCSISIGNAL, &sig)) { - perror("ISCSISIGNAL"); - return -1; - } - sess->flags |= SESS_FULLFEATURE; - - sess->flags &= ~(SESS_REDIRECT | SESS_RECONNECT); - if(vflag) - printf("iscontrol: supervise starting main loop\n"); - /* - | the main loop - actually do nothing - | all the work is done inside the kernel - */ - while((sess->flags & (SESS_REDIRECT|SESS_RECONNECT|SESS_DISCONNECT)) == 0) { - // do something? - // like sending a nop_out? - sleep(60); - } - printf("iscontrol: supervise going down\n"); - syslog(LOG_INFO, "sess flags=%x", sess->flags); - - sig = 0; - if(ioctl(sess->fd, ISCSISIGNAL, &sig)) { - perror("ISCSISIGNAL"); - } - - if(sess->flags & SESS_DISCONNECT) { - sess->flags &= ~SESS_FULLFEATURE; - return T9; - } - else { - val = 0; - if(ioctl(sess->fd, ISCSISTOP, &val)) { - perror("ISCSISTOP"); - } - sess->flags |= SESS_INITIALLOGIN1; - } - return T8; -} - -static int -handledDiscoveryResp(isess_t *sess, pdu_t *pp) -{ - u_char *ptr; - int len, n; - - debug_called(3); - - len = pp->ds_len; - ptr = pp->ds_addr; - while(len > 0) { - if(*ptr != 0) - printf("%s\n", ptr); - n = strlen((char *)ptr) + 1; - len -= n; - ptr += n; - } - return 0; -} - -static int -doDiscovery(isess_t *sess) -{ - pdu_t spp; - text_req_t *tp = (text_req_t *)&spp.ipdu.bhs; - - debug_called(3); - - bzero(&spp, sizeof(pdu_t)); - tp->cmd = ISCSI_TEXT_CMD /*| 0x40 */; // because of a bug in openiscsi-target - tp->F = 1; - tp->ttt = 0xffffffff; - addText(&spp, "SendTargets=All"); - return sendPDU(sess, &spp, handledDiscoveryResp); -} - -static trans_t -doLogin(isess_t *sess) -{ - isc_opt_t *op = sess->op; - int status, count; - - debug_called(3); - - if(op->chapSecret == NULL && op->tgtChapSecret == NULL) - /* - | don't need any security negotiation - | or in other words: we don't have any secrets to exchange - */ - sess->csg = LON_PHASE; - else - sess->csg = SN_PHASE; - - if(sess->tsih) { - sess->tsih = 0; // XXX: no 'reconnect' yet - sess->flags &= ~SESS_NEGODONE; // XXX: KLUDGE - } - count = 10; // should be more than enough - do { - debug(3, "count=%d csg=%d", count, sess->csg); - status = loginPhase(sess); - if(count-- == 0) - // just in case we get into a loop - status = -1; - } while(status == 0 && (sess->csg != FF_PHASE)); - - sess->flags &= ~SESS_INITIALLOGIN; - debug(3, "status=%d", status); - - switch(status) { - case 0: // all is ok ... - sess->flags |= SESS_LOGGEDIN; - if(strcmp(sess->op->sessionType, "Discovery") == 0) - doDiscovery(sess); - return T5; - - case 1: // redirect - temporary/permanent - /* - | start from scratch? - */ - sess->flags &= ~SESS_NEGODONE; - sess->flags |= (SESS_REDIRECT | SESS_INITIALLOGIN1); - syslog(LOG_DEBUG, "target sent REDIRECT"); - return T7; - - case 2: // initiator terminal error - return 0; - case 3: // target terminal error -- could retry ... - sleep(5); - return T7; // lets try - default: - return 0; - } -} - -static int -handleLogoutResp(isess_t *sess, pdu_t *pp) -{ - if(sess->flags & SESS_DISCONNECT) { - int val = 0; - if(ioctl(sess->fd, ISCSISTOP, &val)) { - perror("ISCSISTOP"); - } - return 0; - } - return T13; -} - -static trans_t -startLogout(isess_t *sess) -{ - pdu_t spp; - logout_req_t *p = (logout_req_t *)&spp.ipdu.bhs; - - bzero(&spp, sizeof(pdu_t)); - p->cmd = ISCSI_LOGOUT_CMD| 0x40; - p->reason = BIT(7) | 0; - p->CID = htons(1); - - return sendPDU(sess, &spp, handleLogoutResp); -} - -static trans_t -inLogout(isess_t *sess) -{ - if(sess->flags & SESS_RECONNECT) - return T18; - return 0; -} - -typedef enum { - S1, S2, /*S3,*/ S4, S5, S6, S7, S8 -} state_t; - -/** - S1: FREE - S2: XPT_WAIT - S4: IN_LOGIN - S5: LOGGED_IN - S6: IN_LOGOUT - S7: LOGOUT_REQUESTED - S8: CLEANUP_WAIT - - -------<-------------+ - +--------->/ S1 \<----+ | - T13| +->\ /<-+ \ | - | / ---+--- \ \ | - | / | T2 \ | | - | T8 | |T1 | | | - | | | / |T7 | - | | | / | | - | | | / | | - | | V / / | - | | ------- / / | - | | / S2 \ / | - | | \ / / | - | | ---+--- / | - | | |T4 / | - | | V / | T18 - | | ------- / | - | | / S4 \ | - | | \ / | - | | ---+--- | T15 - | | |T5 +--------+---------+ - | | | /T16+-----+------+ | - | | | / -+-----+--+ | | - | | | / / S7 \ |T12| | - | | | / +->\ /<-+ V V - | | | / / -+----- ------- - | | | / /T11 |T10 / S8 \ - | | V / / V +----+ \ / - | | ---+-+- ----+-- | ------- - | | / S5 \T9 / S6 \<+ ^ - | +-----\ /--->\ / T14 | - | ------- --+----+------+T17 - +---------------------------+ -*/ - -int -fsm(isc_opt_t *op) -{ - state_t state; - isess_t *sess; - - if((sess = calloc(1, sizeof(isess_t))) == NULL) { - // boy, is this a bad start ... - fprintf(stderr, "no memory!\n"); - return -1; - } - - state = S1; - sess->op = op; - sess->fd = -1; - sess->soc = -1; - sess->target.address = strdup(op->targetAddress); - sess->target.port = op->port; - sess->target.pgt = op->targetPortalGroupTag; - - sess->flags = SESS_INITIALLOGIN | SESS_INITIALLOGIN1; - - do { - switch(state) { - - case S1: - switch(tcpConnect(sess)) { - case T1: state = S2; break; - default: state = S8; break; - } - break; - - case S2: - switch(startSession(sess)) { - case T2: state = S1; break; - case T4: state = S4; break; - default: state = S8; break; - } - break; - - case S4: - switch(doLogin(sess)) { - case T7: state = S1; break; - case T5: state = S5; break; - default: state = S8; break; - } - break; - - case S5: - switch(supervise(sess)) { - case T8: state = S1; break; - case T9: state = S6; break; - case T11: state = S7; break; - case T15: state = S8; break; - default: state = S8; break; - } - break; - - case S6: - switch(startLogout(sess)) { - case T13: state = S1; break; - case T14: state = S6; break; - case T16: state = S8; break; - default: state = S8; break; - } - break; - - case S7: - switch(inLogout(sess)) { - case T18: state = S1; break; - case T10: state = S6; break; - case T12: state = S7; break; - case T16: state = S8; break; - default: state = S8; break; - } - break; - - case S8: - // maybe do some clean up? - syslog(LOG_INFO, "terminated"); - return 0; - } - } while(1); -} Index: sbin/iscontrol/iscontrol.h =================================================================== --- sbin/iscontrol/iscontrol.h +++ /dev/null @@ -1,167 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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. - * - * $FreeBSD$ - */ -/* - | $Id: iscontrol.h,v 2.3 2007/04/27 08:36:49 danny Exp danny $ - */ -#ifdef DEBUG -int vflag; - -# define debug(level, fmt, args...) do {if (level <= vflag) printf("%s: " fmt "\n", __func__ , ##args);} while(0) -# define debug_called(level) do {if (level <= vflag) printf("%s: called\n", __func__);} while(0) -#else -# define debug(level, fmt, args...) -# define debug_called(level) -#endif // DEBUG -#define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args) - -#define BIT(n) (1 <<(n)) - -#define MAXREDIRECTS 2 - -typedef int auth_t(void *sess); - -typedef struct { - char *address; - int port; - int pgt; -} target_t; - -typedef struct isess { - int flags; -#define SESS_CONNECTED BIT(0) -#define SESS_DISCONNECT BIT(1) -#define SESS_LOGGEDIN BIT(2) -#define SESS_RECONNECT BIT(3) -#define SESS_REDIRECT BIT(4) - -#define SESS_NEGODONE BIT(10) // XXX: kludge - -#define SESS_FULLFEATURE BIT(29) -#define SESS_INITIALLOGIN1 BIT(30) -#define SESS_INITIALLOGIN BIT(31) - - - isc_opt_t *op; // operational values - target_t target; // the Original target address - int fd; // the session fd - int soc; // the socket - iscsi_cam_t cam; - struct cam_device *camdev; - - time_t open_time; - int redirect_cnt; - time_t redirect_time; - int reconnect_cnt; - int reconnect_cnt1; - time_t reconnect_time; - char isid[6+1]; - int csg; // current stage - int nsg; // next stage - // Phases/Stages -#define SN_PHASE 0 // Security Negotiation -#define LON_PHASE 1 // Login Operational Negotiation -#define FF_PHASE 3 // FuLL-Feature - uint tsih; - sn_t sn; -} isess_t; - -typedef struct token { - char *name; - int val; -} token_t; - -typedef enum { - NONE = 0, - KRB5, - SPKM1, - SPKM2, - SRP, - CHAP -} authm_t; - -extern token_t AuthMethods[]; -extern token_t DigestMethods[]; - -typedef enum { - SET, - GET -} oper_t; - -typedef enum { - U_PR, // private - U_IO, // Initialize Only -- during login - U_LO, // Leading Only -- when TSIH is zero - U_FFPO, // Full Feature Phase Only - U_ALL // in any phase -} usage_t; - -typedef enum { - S_PR, - S_CO, // Connect only - S_SW // Session Wide -} scope_t; - -typedef void keyfun_t(isess_t *, oper_t); - -typedef struct { - usage_t usage; - scope_t scope; - char *name; - int tokenID; -} textkey_t; - -typedef int handler_t(isess_t *sess, pdu_t *pp); - -int authenticateLogin(isess_t *sess); -int fsm(isc_opt_t *op); -int sendPDU(isess_t *sess, pdu_t *pp, handler_t *hdlr); -int addText(pdu_t *pp, char *fmt, ...); -void freePDU(pdu_t *pp); -int xmitpdu(isess_t *sess, pdu_t *pp); -int recvpdu(isess_t *sess, pdu_t *pp); - -int lookup(token_t *tbl, char *m); - -extern int vflag; -extern char *iscsidev; - -void parseArgs(int nargs, char **args, isc_opt_t *op); -void parseConfig(FILE *fd, char *key, isc_opt_t *op); - -char *chapDigest(char *ap, char id, char *cp, char *chapSecret); -char *genChapChallenge(char *encoding, uint len); - -int str2bin(char *str, char **rsp); -char *bin2str(char *fmt, unsigned char *md, int blen); - -int negotiateOPV(isess_t *sess); -int setOptions(isess_t *sess, int flag); - -int loginPhase(isess_t *sess); Index: sbin/iscontrol/iscontrol.8 =================================================================== --- sbin/iscontrol/iscontrol.8 +++ /dev/null @@ -1,141 +0,0 @@ -.\" Copyright (c) 2007-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. -.\" -.\" $FreeBSD$ -.\" -.Dd September 9, 2016 -.Dt ISCONTROL 8 -.Os -.Sh NAME -.Nm iscontrol -.Nd login/negotiator/control for an iSCSI initiator session -.Sh SYNOPSIS -.Nm -.Op Fl dv -.Oo -.Fl c Ar file -.Op Fl n Ar nickname -.Oc -.Op Fl p Ar pidfile -.Op Fl t Ar target -.Op Ar variable Ns = Ns Ar value -.Sh DESCRIPTION -.Bf -symbolic -This command, along with its kernel counterpart -.Xr iscsi_initiator 4 , -is obsolete. -Users are advised to use -.Xr iscsictl 8 -instead. -.Ef -.Pp -Internet SCSI (iSCSI) is a network protocol standard, that allows the -use of the SCSI protocol over TCP/IP networks, -the -.Nm -program is the userland side of an iSCSI session, see -.Xr iscsi_initiator 4 . -It has 2 modes of operation, if -d (discovery session) is specified, -it will print out the -.Em target names -returned by the target and exit. -In the second mode, it will, after a successful login/negotiation, run -in daemon mode, monitoring the connection, and will try to reconnect -in case of a network/target failure. -It will terminate/logout the session -when a SIGHUP signal is received. -The flags are as follows: -.Bl -tag -width variable=value -.It Fl c Ar file -a file containing configuration -.Em key-options , -see -.Xr iscsi.conf 5 . -.It Fl d -do a -.Em discovery session -and exit. -.It Fl n Ar nickname -if -.Sy -c file -is specified, then search for the block named -.Em nickname -in that file, see -.Xr iscsi.conf 5 . -.It Fl p Ar pidfile -will write the process ID of the session to the specified -.Em pidfile -.It Fl t Ar target -the target's IP address or name. -.It Fl v -verbose mode. -.It Ar variable Ns = Ns Ar value -see -.Xr iscsi.conf 5 -for the complete list of variables/options and their -possible values. -.El -.Sh EXAMPLES -.Dl iscontrol -dt myiscsitarget -.Pp -will start a -.Em discovery session -with the target and -print to stdout the list of available targetnames/targetadresses. -Note: this listing does not necessarily mean availability, since -depending on the target configuration, a discovery session might -not need login/access permission, but a -.Em full session -certainly does. -.sp -.Dl iscontrol -c /etc/iscsi.conf -n myiscsi -.Pp -will read options from -.Pa /etc/iscsi.conf , -use the targetaddress -found in the block nicknamed myiscsi, login and negotiate -whatever options are specified, and start an iscsi-session. -.Sh SEE ALSO -.Xr da 4 , -.Xr iscsi_initiator 4 , -.Xr sa 4 , -.Xr iscsi.conf 5 , -.Xr camcontrol 8 , -.Xr iscsictl 8 -.Sh STANDARDS -RFC 3720 -.Sh HISTORY -The -.Nm -utility appeared in -.Fx 7.0 . -.Sh BUGS -.Nm -should probably load the iscsi_initiator module if needed. -.br -Not all functions/specifications have been implemented yet, noticeably -missing are the Task Management Functions. -The error recovery, though not -.Em fully compliant -does a brave effort to recover from network disconnects. Index: sbin/iscontrol/iscontrol.c =================================================================== --- sbin/iscontrol/iscontrol.c +++ /dev/null @@ -1,264 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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} -}; - -int vflag; -char *iscsidev; - -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); -} Index: sbin/iscontrol/login.c =================================================================== --- sbin/iscontrol/login.c +++ /dev/null @@ -1,442 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: login.c,v 1.4 2007/04/27 07:40:40 danny Exp danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "iscontrol.h" - -static char *status_class1[] = { - "Initiator error", - "Authentication failure", - "Authorization failure", - "Not found", - "Target removed", - "Unsupported version", - "Too many connections", - "Missing parameter", - "Can't include in session", - "Session type not supported", - "Session does not exist", - "Invalid during login", -}; -#define CLASS1_ERRS ((sizeof status_class1) / sizeof(char *)) - -static char *status_class3[] = { - "Target error", - "Service unavailable", - "Out of resources" -}; -#define CLASS3_ERRS ((sizeof status_class3) / sizeof(char *)) - -static char * -selectFrom(char *str, token_t *list) -{ - char *sep, *sp; - token_t *lp; - int n; - - sp = str; - do { - sep = strchr(sp, ','); - if(sep != NULL) - n = sep - sp; - else - n = strlen(sp); - - for(lp = list; lp->name != NULL; lp++) { - if(strncasecmp(lp->name, sp, n) == 0) - return strdup(lp->name); - } - sp = sep + 1; - } while(sep != NULL); - - return NULL; -} - -static char * -getkeyval(char *key, pdu_t *pp) -{ - char *ptr; - int klen, len, n; - - debug_called(3); - - len = pp->ds_len; - ptr = (char *)pp->ds_addr; - klen = strlen(key); - while(len > klen) { - if(strncmp(key, ptr, klen) == 0) - return ptr+klen; - n = strlen(ptr) + 1; - len -= n; - ptr += n; - } - return 0; -} - -static int -handleTgtResp(isess_t *sess, pdu_t *pp) -{ - isc_opt_t *op = sess->op; - char *np, *rp, *d1, *d2; - int res, l1, l2; - - res = -1; - if(((np = getkeyval("CHAP_N=", pp)) == NULL) || - ((rp = getkeyval("CHAP_R=", pp)) == NULL)) - goto out; - if(strcmp(np, op->tgtChapName? op->tgtChapName: op->initiatorName) != 0) { - fprintf(stderr, "%s does not match\n", np); - goto out; - } - l1 = str2bin(op->tgtChapDigest, &d1); - l2 = str2bin(rp, &d2); - - debug(3, "l1=%d '%s' l2=%d '%s'", l1, op->tgtChapDigest, l2, rp); - if(l1 == l2 && memcmp(d1, d2, l1) == 0) - res = 0; - if(l1) - free(d1); - if(l2) - free(d2); - out: - free(op->tgtChapDigest); - op->tgtChapDigest = NULL; - - debug(3, "res=%d", res); - - return res; -} - -static void -processParams(isess_t *sess, pdu_t *pp) -{ - isc_opt_t *op = sess->op; - int len, klen, n; - char *eq, *ptr; - - debug_called(3); - - len = pp->ds_len; - ptr = (char *)pp->ds_addr; - while(len > 0) { - if(vflag > 1) - printf("got: len=%d %s\n", len, ptr); - klen = 0; - if((eq = strchr(ptr, '=')) != NULL) - klen = eq - ptr; - if(klen > 0) { - if(strncmp(ptr, "TargetAddress", klen) == 0) { - char *p, *q, *ta = NULL; - - // TargetAddress=domainname[:port][,portal-group-tag] - // XXX: if(op->targetAddress) free(op->targetAddress); - q = op->targetAddress = strdup(eq+1); - if(*q == '[') { - // bracketed IPv6 - if((q = strchr(q, ']')) != NULL) { - *q++ = '\0'; - ta = op->targetAddress; - op->targetAddress = strdup(ta+1); - } else - q = op->targetAddress; - } - if((p = strchr(q, ',')) != NULL) { - *p++ = 0; - op->targetPortalGroupTag = atoi(p); - } - if((p = strchr(q, ':')) != NULL) { - *p++ = 0; - op->port = atoi(p); - } - if(ta) - free(ta); - } else if(strncmp(ptr, "MaxRecvDataSegmentLength", klen) == 0) { - // danny's RFC - op->maxXmitDataSegmentLength = strtol(eq+1, (char **)NULL, 0); - } else if(strncmp(ptr, "TargetPortalGroupTag", klen) == 0) { - op->targetPortalGroupTag = strtol(eq+1, (char **)NULL, 0); - } else if(strncmp(ptr, "HeaderDigest", klen) == 0) { - op->headerDigest = selectFrom(eq+1, DigestMethods); - } else if(strncmp(ptr, "DataDigest", klen) == 0) { - op->dataDigest = selectFrom(eq+1, DigestMethods); - } else if(strncmp(ptr, "MaxOutstandingR2T", klen) == 0) - op->maxOutstandingR2T = strtol(eq+1, (char **)NULL, 0); -#if 0 - else - for(kp = keyMap; kp->name; kp++) { - if(strncmp(ptr, kp->name, kp->len) == 0 && ptr[kp->len] == '=') - mp->func(sess, ptr+kp->len+1, GET); - } -#endif - } - n = strlen(ptr) + 1; - len -= n; - ptr += n; - } - -} - -static int -handleLoginResp(isess_t *sess, pdu_t *pp) -{ - login_rsp_t *lp = (login_rsp_t *)pp; - uint st_class, status = ntohs(lp->status); - - debug_called(3); - debug(4, "Tbit=%d csg=%d nsg=%d status=%x", lp->T, lp->CSG, lp->NSG, status); - - st_class = status >> 8; - if(status) { - uint st_detail = status & 0xff; - - switch(st_class) { - case 1: // Redirect - switch(st_detail) { - // the ITN (iSCSI target Name) requests a: - case 1: // temporary address change - case 2: // permanent address change - status = 0; - } - break; - - case 2: // Initiator Error - if(st_detail < CLASS1_ERRS) - printf("0x%04x: %s\n", status, status_class1[st_detail]); - break; - - case 3: - if(st_detail < CLASS3_ERRS) - printf("0x%04x: %s\n", status, status_class3[st_detail]); - break; - } - } - - if(status == 0) { - processParams(sess, pp); - setOptions(sess, 0); // XXX: just in case ... - - if(lp->T) { - isc_opt_t *op = sess->op; - - if(sess->csg == SN_PHASE && (op->tgtChapDigest != NULL)) - if(handleTgtResp(sess, pp) != 0) - return 1; // XXX: Authentication failure ... - sess->csg = lp->NSG; - if(sess->csg == FF_PHASE) { - // XXX: will need this when implementing reconnect. - sess->tsih = lp->tsih; - debug(2, "TSIH=%x", sess->tsih); - } - } - } - - return st_class; -} - -static int -handleChap(isess_t *sess, pdu_t *pp) -{ - pdu_t spp; - login_req_t *lp; - isc_opt_t *op = sess->op; - char *ap, *ip, *cp, *digest; // MD5 is 128bits, SHA1 160bits - - debug_called(3); - - bzero(&spp, sizeof(pdu_t)); - lp = (login_req_t *)&spp.ipdu.bhs; - lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate - memcpy(lp->isid, sess->isid, 6); - lp->tsih = sess->tsih; // MUST be zero the first time! - lp->CID = htons(1); - lp->CSG = SN_PHASE; // Security Negotiation - lp->NSG = LON_PHASE; - lp->T = 1; - - if(((ap = getkeyval("CHAP_A=", pp)) == NULL) || - ((ip = getkeyval("CHAP_I=", pp)) == NULL) || - ((cp = getkeyval("CHAP_C=", pp)) == NULL)) - return -1; - - if((digest = chapDigest(ap, (char)strtol(ip, (char **)NULL, 0), cp, op->chapSecret)) == NULL) - return -1; - - addText(&spp, "CHAP_N=%s", op->chapIName? op->chapIName: op->initiatorName); - addText(&spp, "CHAP_R=%s", digest); - free(digest); - - if(op->tgtChapSecret != NULL) { - op->tgtChapID = (random() >> 24) % 255; // should be random enough ... - addText(&spp, "CHAP_I=%d", op->tgtChapID); - cp = genChapChallenge(cp, op->tgtChallengeLen? op->tgtChallengeLen: 8); - addText(&spp, "CHAP_C=%s", cp); - op->tgtChapDigest = chapDigest(ap, op->tgtChapID, cp, op->tgtChapSecret); - } - - return sendPDU(sess, &spp, handleLoginResp); -} - -static int -authenticate(isess_t *sess) -{ - pdu_t spp; - login_req_t *lp; - isc_opt_t *op = sess->op; - - bzero(&spp, sizeof(pdu_t)); - lp = (login_req_t *)&spp.ipdu.bhs; - lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate - memcpy(lp->isid, sess->isid, 6); - lp->tsih = sess->tsih; // MUST be zero the first time! - lp->CID = htons(1); - lp->CSG = SN_PHASE; // Security Negotiation - lp->NSG = SN_PHASE; - lp->T = 0; - - switch((authm_t)lookup(AuthMethods, op->authMethod)) { - case NONE: - return 0; - - case KRB5: - case SPKM1: - case SPKM2: - case SRP: - return 2; - - case CHAP: - if(op->chapDigest == 0) - addText(&spp, "CHAP_A=5"); - else - if(strcmp(op->chapDigest, "MD5") == 0) - addText(&spp, "CHAP_A=5"); - else - if(strcmp(op->chapDigest, "SHA1") == 0) - addText(&spp, "CHAP_A=7"); - else - addText(&spp, "CHAP_A=5,7"); - return sendPDU(sess, &spp, handleChap); - } - return 1; -} - -int -loginPhase(isess_t *sess) -{ - pdu_t spp, *sp = &spp; - isc_opt_t *op = sess->op; - login_req_t *lp; - int status = 1; - - debug_called(3); - - bzero(sp, sizeof(pdu_t)); - lp = (login_req_t *)&spp.ipdu.bhs; - lp->cmd = ISCSI_LOGIN_CMD | 0x40; // login request + Inmediate - memcpy(lp->isid, sess->isid, 6); - lp->tsih = sess->tsih; // MUST be zero the first time! - lp->CID = htons(1); // sess->cid? - - if((lp->CSG = sess->csg) == LON_PHASE) - lp->NSG = FF_PHASE; // lets try and go full feature ... - else - lp->NSG = LON_PHASE; - lp->T = 1; // transit to next login stage - - if(sess->flags & SESS_INITIALLOGIN1) { - sess->flags &= ~SESS_INITIALLOGIN1; - - addText(sp, "SessionType=%s", op->sessionType); - addText(sp, "InitiatorName=%s", op->initiatorName); - if(strcmp(op->sessionType, "Discovery") != 0) { - addText(sp, "TargetName=%s", op->targetName); - } - } - switch(sess->csg) { - case SN_PHASE: // Security Negotiation - addText(sp, "AuthMethod=%s", op->authMethod); - break; - - case LON_PHASE: // Login Operational Negotiation - if((sess->flags & SESS_NEGODONE) == 0) { - sess->flags |= SESS_NEGODONE; - addText(sp, "MaxBurstLength=%d", op->maxBurstLength); - addText(sp, "HeaderDigest=%s", op->headerDigest); - addText(sp, "DataDigest=%s", op->dataDigest); - addText(sp, "MaxRecvDataSegmentLength=%d", op->maxRecvDataSegmentLength); - addText(sp, "ErrorRecoveryLevel=%d", op->errorRecoveryLevel); - addText(sp, "DefaultTime2Wait=%d", op->defaultTime2Wait); - addText(sp, "DefaultTime2Retain=%d", op->defaultTime2Retain); - addText(sp, "DataPDUInOrder=%s", op->dataPDUInOrder? "Yes": "No"); - addText(sp, "DataSequenceInOrder=%s", op->dataSequenceInOrder? "Yes": "No"); - addText(sp, "MaxOutstandingR2T=%d", op->maxOutstandingR2T); - - if(strcmp(op->sessionType, "Discovery") != 0) { - addText(sp, "MaxConnections=%d", op->maxConnections); - addText(sp, "FirstBurstLength=%d", op->firstBurstLength); - addText(sp, "InitialR2T=%s", op->initialR2T? "Yes": "No"); - addText(sp, "ImmediateData=%s", op->immediateData? "Yes": "No"); - } - } - - break; - } - - status = sendPDU(sess, &spp, handleLoginResp); - - switch(status) { - case 0: // all is ok ... - if(sess->csg == SN_PHASE) - /* - | if we are still here, then we need - | to exchange some secrets ... - */ - status = authenticate(sess); - } - - return status; -} Index: sbin/iscontrol/misc.c =================================================================== --- sbin/iscontrol/misc.c +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: misc.c,v 2.1 2006/11/12 08:06:51 danny Exp $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include "iscontrol.h" - -static inline char -c2b(unsigned char c) -{ - switch(c) { - case '0' ... '9': - return c - '0'; - case 'a' ... 'f': - return c - 'a' + 10; - case 'A' ... 'F': - return c - 'A' + 10; - } - return 0; -} - -static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - -static __inline unsigned char -c64tobin(unsigned char c64) -{ - int i; - for(i = 0; i < 64; i++) - if(base64[i] == c64) - break; - return i; -} -/* - | according to rfc3720, the binary string - | cannot be larger than 1024 - but i can't find it :-) XXX - | not enforced yet. - */ -int -str2bin(char *str, char **rsp) -{ - char *src, *dst, *tmp; - int i, len = 0; - - src = str; - tmp = NULL; - if(strncasecmp("0x", src, 2) == 0) { - src += 2; - len = strlen(src); - - if((tmp = malloc((len+1)/2)) == NULL) { - // XXX: print some error? - return 0; - } - dst = tmp; - if(len & 1) - *dst++ = c2b(*src++); - while(*src) { - *dst = c2b(*src++) << 4; - *dst++ |= c2b(*src++); - } - len = dst - tmp; - } else - if(strncasecmp("0b", src , 2) == 0) { - // base64 - unsigned char b6; - - src += 2; - len = strlen(src) / 4 * 3; - if((tmp = malloc(len)) == NULL) { - // XXX: print some error? - return 0; - } - dst = tmp; - i = 0; - while(*src && ((b6 = c64tobin(*src++)) != 64)) { - switch(i % 4) { - case 0: - *dst = b6 << 2; - break; - case 1: - *dst++ |= b6 >> 4; - *dst = b6 << 4; - break; - case 2: - *dst++ |= b6 >> 2; - *dst = b6 << 6; - break; - case 3: - *dst++ |= b6; - break; - } - i++; - } - len = dst - tmp; - } - else { - /* - | assume it to be an ascii string, so just copy it - */ - len = strlen(str); - if((tmp = malloc(len)) == NULL) - return 0; - dst = tmp; - src = str; - while(*src) - *dst++ = *src++; - } - - *rsp = tmp; - return len; -} - -char * -bin2str(char *encoding, unsigned char *md, int blen) -{ - int len; - char *dst, *ds; - unsigned char *cp; - - if(strncasecmp(encoding, "0x", 2) == 0) { - char ofmt[5]; - - len = blen * 2; - dst = malloc(len + 3); - strcpy(dst, encoding); - ds = dst + 2; - cp = md; - sprintf(ofmt, "%%02%c", encoding[1]); - while(blen-- > 0) { - sprintf(ds, ofmt, *cp++); - ds += 2; - } - *ds = 0; - return dst; - } - if(strncasecmp(encoding, "0b", 2) == 0) { - int i, b6; - - len = (blen + 2) * 4 / 3; - dst = malloc(len + 3); - strcpy(dst, encoding); - ds = dst + 2; - cp = md; - b6 = 0; // to keep compiler happy. - for(i = 0; i < blen; i++) { - switch(i % 3) { - case 0: - *ds++ = base64[*cp >> 2]; - b6 = (*cp & 0x3) << 4; - break; - case 1: - b6 += (*cp >> 4); - *ds++ = base64[b6]; - b6 = (*cp & 0xf) << 2; - break; - case 2: - b6 += (*cp >> 6); - *ds++ = base64[b6]; - *ds++ = base64[*cp & 0x3f]; - } - cp++; - } - switch(blen % 3) { - case 0: - break; - case 1: - *ds++ = base64[b6]; - *ds++ = '='; - *ds++ = '='; - break; - case 2: - *ds++ = base64[b6]; - *ds++ = '='; - break; - } - - *ds = 0; - return dst; - } - - return NULL; -} Index: sbin/iscontrol/pdu.c =================================================================== --- sbin/iscontrol/pdu.c +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: pdu.c,v 2.2 2006/12/01 09:11:56 danny Exp danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "iscontrol.h" - -static void pukeText(char *it, pdu_t *pp); - -int -xmitpdu(isess_t *sess, pdu_t *pp) -{ - if(ioctl(sess->fd, ISCSISEND, pp)) { - perror("xmitpdu"); - return -1; - } - if(vflag) - pukeText("I-", pp); - - return 0; -} - -int -recvpdu(isess_t *sess, pdu_t *pp) -{ - if(ioctl(sess->fd, ISCSIRECV, pp)) { - perror("recvpdu"); - return -1; - } - // XXX: return error if truncated via - // the FUDGE factor. - if(vflag) - pukeText("T-", pp); - - return 0; -} - -int -sendPDU(isess_t *sess, pdu_t *pp, handler_t *hdlr) -{ - if(xmitpdu(sess, pp)) - return 0; - if(hdlr) { - int res; - - pp->ahs_size = 8 * 1024; - if((pp->ahs_addr = malloc(pp->ahs_size)) == NULL) { - fprintf(stderr, "out of mem!"); - return -1; - } - pp->ds_size = 0; - if((res = recvpdu(sess, pp)) != 0) { - fprintf(stderr, "recvpdu failed\n"); - return res; - } - res = hdlr(sess, pp); - freePDU(pp); - return res; - } - return 1; -} - - -#define FUDGE (512 * 8) -/* - | We use the same memory for the response - | so make enough room ... - | XXX: must find a better way. - */ -int -addText(pdu_t *pp, char *fmt, ...) -{ - u_int len; - char *str; - va_list ap; - - va_start(ap, fmt); - len = vasprintf(&str, fmt, ap) + 1; - if((pp->ds_len + len) > 0xffffff) { - printf("ds overflow\n"); - free(str); - return 0; - } - - if((pp->ds_len + len) > pp->ds_size) { - u_char *np; - - np = realloc(pp->ds_addr, pp->ds_size + len + FUDGE); - if(np == NULL) { - free(str); - //XXX: out of memory! - return -1; - } - pp->ds_addr = np; - pp->ds_size += len + FUDGE; - } - memcpy(pp->ds_addr + pp->ds_len, str, len); - pp->ds_len += len; - free(str); - return len; -} - -void -freePDU(pdu_t *pp) -{ - if(pp->ahs_size) - free(pp->ahs_addr); - if(pp->ds_size) - free(pp->ds_addr); - bzero(&pp->ipdu, sizeof(union ipdu_u)); - pp->ahs_addr = NULL; - pp->ds_addr = NULL; - pp->ahs_size = 0; - pp->ds_size = pp->ds_len = 0; -} - -static void -pukeText(char *it, pdu_t *pp) -{ - char *ptr; - int cmd; - size_t len, n; - - len = pp->ds_len; - ptr = (char *)pp->ds_addr; - cmd = pp->ipdu.bhs.opcode; - - printf("%s: cmd=0x%x len=%d\n", it, cmd, (int)len); - while(len > 0) { - printf("\t%s\n", ptr); - n = strlen(ptr) + 1; - len -= n; - ptr += n; - } -} Index: share/man/man4/Makefile =================================================================== --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -937,7 +937,6 @@ .if ${MK_ISCSI} != "no" MAN+= cfiscsi.4 MAN+= iscsi.4 -MAN+= iscsi_initiator.4 MAN+= iser.4 .endif Index: share/man/man4/iscsi_initiator.4 =================================================================== --- share/man/man4/iscsi_initiator.4 +++ /dev/null @@ -1,118 +0,0 @@ -.\" Copyright (c) 2007-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. -.\" -.\" $FreeBSD$ -.\" -.Dd October 9, 2014 -.Dt ISCSI_INITIATOR 4 -.Os -.Sh NAME -.Nm iscsi_initiator -.Nd kernel driver for the iSCSI protocol -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device iscsi_initiator" -.Ed -.Pp -Alternatively, to load the driver as a -module at boot time, place the following line in -.Xr loader.conf 5 : -.Bd -literal -offset indent -iscsi_initiator_load="YES" -.Ed -.Sh DESCRIPTION -.Bf -symbolic -This driver, along with its userspace counterpart -.Xr iscontrol 8 , -is obsolete. -Users are advised to use -.Xr iscsi 4 -instead. -.Ef -.Pp -The -.Nm -implements the kernel side of the Internet SCSI (iSCSI) network -protocol standard, the userland companion is -.Xr iscontrol 8 , -and permits access to remote -.Em virtual -SCSI devices via -.Xr cam 4 . -.Sh SYSCTL VARIABLES -.Bl -tag -width ".Va net.iscsi.n.targeaddress" -.It Va debug.iscsi_initiator -set the debug-level, 0 means no debugging, 9 for maximum. -.It Va net.iscsi.isid -the initiator part of the Session Identifier. -.It Va "kern.cam.cam_srch_hi=1" -allow search above LUN 7 for SCSI3 and greater devices. -.It "the following are informative only:" -.It Va net.iscsi.driver_version -the current version of the driver. -.It Va net.iscsi.sessions -the number of current active sessions. -.It Va net.iscsi.n.targetname -is the targe name of session -.Em n . -.It Va net.iscsi.n.targeaddress -is the IP address of the target of session -.Em n . -.It Va net.iscsi.n.stats -are some statistics for session -.Em n -.It Va net.iscsi.n.pid -is the -.Em "process id" -of the userland side of session -.Em n , -see -.Xr iscontrol 8 . -.El -.Sh FILES -The -.Nm -driver creates the following: -.Pp -.Bl -tag -width ".Pa /dev/iscsi%dxx" -compact -.It Pa /dev/iscsi -used to create new sessions. -.It Pa /dev/iscsi%d -for each new session. -.El -.Sh SEE ALSO -.Xr cam 4 , -.Xr camcontrol 8 , -.Xr iscontrol 8 -.Sh STANDARDS -iSCSI RFC 3720 -.\" .Sh HISTORY -.Sh AUTHORS -This software was written by -.An Daniel Braniss Aq Mt danny@cs.huji.ac.il -.Sh BUGS -The lun discovery method is old-fashioned. Index: sys/conf/NOTES =================================================================== --- sys/conf/NOTES +++ sys/conf/NOTES @@ -1523,7 +1523,6 @@ device ahc device ahd device esp -device iscsi_initiator device isp envvar hint.isp.0.disable="1" envvar hint.isp.0.role="3" Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -1929,12 +1929,6 @@ dev/iscsi/icl_soft.c optional iscsi dev/iscsi/icl_soft_proxy.c optional iscsi dev/iscsi/iscsi.c optional iscsi scbus -dev/iscsi_initiator/iscsi.c optional iscsi_initiator scbus -dev/iscsi_initiator/iscsi_subr.c optional iscsi_initiator scbus -dev/iscsi_initiator/isc_cam.c optional iscsi_initiator scbus -dev/iscsi_initiator/isc_soc.c optional iscsi_initiator scbus -dev/iscsi_initiator/isc_sm.c optional iscsi_initiator scbus -dev/iscsi_initiator/isc_subr.c optional iscsi_initiator scbus dev/ismt/ismt.c optional ismt dev/isl/isl.c optional isl iicbus dev/isp/isp.c optional isp Index: sys/dev/iscsi_initiator/isc_cam.c =================================================================== --- sys/dev/iscsi_initiator/isc_cam.c +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: isc_cam.c 998 2009-12-20 10:32:45Z danny $ - */ -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -static void -_inq(struct cam_sim *sim, union ccb *ccb) -{ - struct ccb_pathinq *cpi = &ccb->cpi; - isc_session_t *sp = cam_sim_softc(sim); - - debug_called(8); - debug(3, "sid=%d target=%d lun=%jx", sp->sid, ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun); - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_32; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = 0; //ISCSI_MAX_TARGETS - 1; - cpi->initiator_id = ISCSI_MAX_TARGETS; - cpi->max_lun = sp->opt.maxluns - 1; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; // 40000; // XXX: - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN); - strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->ccb_h.status = CAM_REQ_CMP; -#if defined(KNOB_VALID_ADDRESS) - cpi->transport = XPORT_ISCSI; - cpi->transport_version = 0; -#endif -} - -static __inline int -_scsi_encap(struct cam_sim *sim, union ccb *ccb) -{ - int ret; - isc_session_t *sp = cam_sim_softc(sim); - - mtx_unlock(&sp->cam_mtx); - ret = scsi_encap(sim, ccb); - mtx_lock(&sp->cam_mtx); - - return ret; -} - -void -ic_lost_target(isc_session_t *sp, int target) -{ - debug_called(8); - sdebug(2, "lost target=%d", target); - - if(sp->cam_path != NULL) { - mtx_lock(&sp->cam_mtx); - xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); - xpt_free_path(sp->cam_path); - mtx_unlock(&sp->cam_mtx); - sp->cam_path = 0; // XXX - } -} - -static void -scan_callback(struct cam_periph *periph, union ccb *ccb) -{ - isc_session_t *sp = (isc_session_t *)ccb->ccb_h.spriv_ptr0; - - debug_called(8); - - xpt_free_ccb(ccb); - - if(sp->flags & ISC_SCANWAIT) { - sp->flags &= ~ISC_SCANWAIT; - wakeup(sp); - } -} - -static int -ic_scan(isc_session_t *sp) -{ - union ccb *ccb; - - debug_called(8); - sdebug(2, "scanning sid=%d", sp->sid); - - sp->flags &= ~ISC_CAMDEVS; - sp->flags |= ISC_SCANWAIT; - - ccb = xpt_alloc_ccb(); - ccb->ccb_h.path = sp->cam_path; - ccb->ccb_h.cbfcnp = scan_callback; - ccb->ccb_h.spriv_ptr0 = sp; - - xpt_rescan(ccb); - - while(sp->flags & ISC_SCANWAIT) - tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should - // be configurable - sdebug(2, "# of luns=%d", sp->target_nluns); - - if(sp->target_nluns > 0) { - sp->flags |= ISC_CAMDEVS; - return 0; - } - - return ENODEV; -} - -static void -ic_action(struct cam_sim *sim, union ccb *ccb) -{ - isc_session_t *sp = cam_sim_softc(sim); - struct ccb_hdr *ccb_h = &ccb->ccb_h; - - debug_called(8); - - ccb_h->spriv_ptr0 = sp; - sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%jx retry_count=%d timeout=%d", - ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status, - ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun, - ccb->ccb_h.retry_count, ccb_h->timeout); - if(sp == NULL) { - xdebug("sp == NULL! cannot happen"); - return; - } - switch(ccb_h->func_code) { - case XPT_PATH_INQ: - _inq(sim, ccb); - break; - - case XPT_RESET_BUS: // (can just be a stub that does nothing and completes) - { - struct ccb_pathinq *cpi = &ccb->cpi; - - debug(3, "XPT_RESET_BUS"); - cpi->ccb_h.status = CAM_REQ_CMP; - break; - } - - case XPT_SCSI_IO: - { - struct ccb_scsiio* csio = &ccb->csio; - - debug(4, "XPT_SCSI_IO cmd=0x%x", csio->cdb_io.cdb_bytes[0]); - if(sp == NULL) { - ccb_h->status = CAM_REQ_INVALID; //CAM_NO_NEXUS; - debug(4, "xpt_done.status=%d", ccb_h->status); - break; - } - if(ccb_h->target_lun == CAM_LUN_WILDCARD) { - debug(3, "target=%d: bad lun (-1)", ccb_h->target_id); - ccb_h->status = CAM_LUN_INVALID; - break; - } - if(_scsi_encap(sim, ccb) != 0) - return; - break; - } - - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - - ccg = &ccb->ccg; - debug(4, "sid=%d target=%d lun=%jx XPT_CALC_GEOMETRY vsize=%jd bsize=%d", - sp->sid, ccb->ccb_h.target_id, (uintmax_t)ccb->ccb_h.target_lun, - ccg->volume_size, ccg->block_size); - if(ccg->block_size == 0 || - (ccg->volume_size < ccg->block_size)) { - // print error message ... - /* XXX: what error is appropriate? */ - break; - } - else { - int lun, *off, boff; - - lun = ccb->ccb_h.target_lun; - if(lun > ISCSI_MAX_LUNS) { - // XXX: - xdebug("lun %d > ISCSI_MAX_LUNS!\n", lun); - lun %= ISCSI_MAX_LUNS; - } - off = &sp->target_lun[lun / (sizeof(int)*8)]; - boff = BIT(lun % (sizeof(int)*8)); - debug(4, "sp->target_nluns=%d *off=%x boff=%x", - sp->target_nluns, *off, boff); - - if((*off & boff) == 0) { - sp->target_nluns++; - *off |= boff; - } - cam_calc_geometry(ccg, /*extended*/1); - } - break; - } - - case XPT_GET_TRAN_SETTINGS: - default: - ccb_h->status = CAM_REQ_INVALID; - break; - } - xpt_done(ccb); - return; -} - -static void -ic_poll(struct cam_sim *sim) -{ - debug_called(4); - -} - -int -ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp) -{ - debug_called(8); - - if(sp && sp->cam_sim) { - cp->path_id = cam_sim_path(sp->cam_sim); - cp->target_id = 0; - cp->target_nluns = ISCSI_MAX_LUNS; // XXX: -1? - return 0; - } - return ENXIO; -} - -void -ic_destroy(isc_session_t *sp ) -{ - debug_called(8); - - if(sp->cam_path != NULL) { - sdebug(2, "name=%s unit=%d", - cam_sim_name(sp->cam_sim), cam_sim_unit(sp->cam_sim)); -#if 0 - xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); -#else - xpt_async(XPT_RESET_BUS, sp->cam_path, NULL); -#endif - xpt_free_path(sp->cam_path); - xpt_bus_deregister(cam_sim_path(sp->cam_sim)); - cam_sim_free(sp->cam_sim, TRUE /*free_devq*/); - - sdebug(2, "done"); - } -} - -int -ic_init(isc_session_t *sp) -{ - struct cam_sim *sim; - struct cam_devq *devq; - - debug_called(8); - - if((devq = cam_simq_alloc(256)) == NULL) - return ENOMEM; - - mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF); - sim = cam_sim_alloc(ic_action, - ic_poll, - "iscsi", - sp, - sp->sid, // unit - &sp->cam_mtx, - 1, // max_dev_transactions - 0, // max_tagged_dev_transactions - devq); - if(sim == NULL) { - cam_simq_free(devq); - mtx_destroy(&sp->cam_mtx); - return ENXIO; - } - - if(xpt_bus_register(sim, - NULL, - 0/*bus_number*/) != CAM_SUCCESS) { - cam_sim_free(sim, /*free_devq*/TRUE); - mtx_destroy(&sp->cam_mtx); - return ENXIO; - } - sp->cam_sim = sim; - if(xpt_create_path(&sp->cam_path, NULL, cam_sim_path(sp->cam_sim), - CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister(cam_sim_path(sp->cam_sim)); - cam_sim_free(sim, /*free_devq*/TRUE); - mtx_destroy(&sp->cam_mtx); - return ENXIO; - } - - sdebug(1, "cam subsystem initialized"); - - ic_scan(sp); - - return 0; -} Index: sys/dev/iscsi_initiator/isc_sm.c =================================================================== --- sys/dev/iscsi_initiator/isc_sm.c +++ /dev/null @@ -1,750 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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. - * - */ -/* - | iSCSI - Session Manager - | $Id: isc_sm.c 743 2009-08-08 10:54:53Z danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -static void -_async(isc_session_t *sp, pduq_t *pq) -{ - debug_called(8); - - iscsi_async(sp, pq); - - pdu_free(sp->isc, pq); -} - -static void -_reject(isc_session_t *sp, pduq_t *pq) -{ - pduq_t *opq; - pdu_t *pdu; - reject_t *reject; - int itt; - - debug_called(8); - pdu = mtod(pq->mp, pdu_t *); - itt = pdu->ipdu.bhs.itt; - reject = &pq->pdu.ipdu.reject; - sdebug(2, "itt=%x reason=0x%x", ntohl(itt), reject->reason); - opq = i_search_hld(sp, itt, 0); - if(opq != NULL) - iscsi_reject(sp, opq, pq); - else { - switch(pq->pdu.ipdu.bhs.opcode) { - case ISCSI_LOGOUT_CMD: // XXX: wasabi does this - can't figure out why - sdebug(2, "ISCSI_LOGOUT_CMD ..."); - break; - default: - xdebug("%d] we lost something itt=%x", - sp->sid, ntohl(pq->pdu.ipdu.bhs.itt)); - } - } - pdu_free(sp->isc, pq); -} - -static void -_r2t(isc_session_t *sp, pduq_t *pq) -{ - pduq_t *opq; - - debug_called(8); - opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1); - if(opq != NULL) { - iscsi_r2t(sp, opq, pq); - } - else { - r2t_t *r2t = &pq->pdu.ipdu.r2t; - - xdebug("%d] we lost something itt=%x r2tSN=%d bo=%x ddtl=%x", - sp->sid, ntohl(pq->pdu.ipdu.bhs.itt), - ntohl(r2t->r2tSN), ntohl(r2t->bo), ntohl(r2t->ddtl)); - } - pdu_free(sp->isc, pq); -} - -static void -_scsi_rsp(isc_session_t *sp, pduq_t *pq) -{ - pduq_t *opq; - - debug_called(8); - opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 0); - debug(5, "itt=%x pq=%p opq=%p", ntohl(pq->pdu.ipdu.bhs.itt), pq, opq); - if(opq != NULL) { - iscsi_done(sp, opq, pq); - i_acked_hld(sp, &pq->pdu); - } - else - xdebug("%d] we lost something itt=%x", - sp->sid, ntohl(pq->pdu.ipdu.bhs.itt)); - pdu_free(sp->isc, pq); -} - -static void -_read_data(isc_session_t *sp, pduq_t *pq) -{ - pduq_t *opq; - - debug_called(8); - opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1); - if(opq != NULL) { - if(scsi_decap(sp, opq, pq) != 1) { - i_remove_hld(sp, opq); // done - pdu_free(sp->isc, opq); - } - } - else - xdebug("%d] we lost something itt=%x", - sp->sid, ntohl(pq->pdu.ipdu.bhs.itt)); - pdu_free(sp->isc, pq); -} -/* - | this is a kludge, - | the jury is not back with a veredict, user or kernel - */ -static void -_nop_out(isc_session_t *sp) -{ - pduq_t *pq; - nop_out_t *nop_out; - - debug_called(8); - - sdebug(4, "cws=%d", sp->cws); - if(sp->cws == 0) { - /* - | only send a nop if window is closed. - */ - if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) - // I guess we ran out of resources - return; - nop_out = &pq->pdu.ipdu.nop_out; - nop_out->opcode = ISCSI_NOP_OUT; - nop_out->itt = htonl(sp->sn.itt); - nop_out->ttt = -1; - nop_out->I = 1; - nop_out->F = 1; - if(isc_qout(sp, pq) != 0) { - sdebug(1, "failed"); - pdu_free(sp->isc, pq); - } - } -} - -static void -_nop_in(isc_session_t *sp, pduq_t *pq) -{ - pdu_t *pp = &pq->pdu; - nop_in_t *nop_in = &pp->ipdu.nop_in; - bhs_t *bhs = &pp->ipdu.bhs; - - debug_called(8); - - sdebug(5, "itt=%x ttt=%x", htonl(nop_in->itt), htonl(nop_in->ttt)); - if(nop_in->itt == -1) { - if(pp->ds_len != 0) { - /* - | according to RFC 3720 this should be zero - | what to do if not? - */ - xdebug("%d] dslen not zero", sp->sid); - } - if(nop_in->ttt != -1) { - nop_out_t *nop_out; - /* - | target wants a nop_out - */ - bhs->opcode = ISCSI_NOP_OUT; - bhs->I = 1; - bhs->F = 1; - /* - | we are reusing the pdu, so bhs->ttt == nop_in->ttt; - | and need to zero out 'Reserved' - | small cludge here. - */ - nop_out = &pp->ipdu.nop_out; - nop_out->sn.maxcmd = 0; - memset(nop_out->mbz, 0, sizeof(nop_out->mbz)); - (void)isc_qout(sp, pq); //XXX: should check return? - return; - } - //else { - // just making noise? - // see 10.9.1: target does not want and answer. - //} - - } else - if(nop_in->ttt == -1) { - /* - | it is an answer to a nop_in from us - */ - if(nop_in->itt != -1) { -#ifdef ISC_WAIT4PING - // XXX: MUTEX please - if(sp->flags & ISC_WAIT4PING) { - i_nqueue_rsp(sp, pq); - wakeup(&sp->rsp); - return; - } -#endif - } - } - /* - | drop it - */ - pdu_free(sp->isc, pq); - return; -} - -int -i_prepPDU(isc_session_t *sp, pduq_t *pq) -{ - size_t len, n; - pdu_t *pp = &pq->pdu; - bhs_t *bhp = &pp->ipdu.bhs; - - len = sizeof(bhs_t); - if(pp->ahs_len) { - len += pp->ahs_len; - bhp->AHSLength = pp->ahs_len / 4; - } - if(ISOK2DIG(sp->hdrDigest, pp)) - len += 4; - if(pp->ds_len) { - n = pp->ds_len; - len += n; -#if BYTE_ORDER == LITTLE_ENDIAN - bhp->DSLength = ((n & 0x00ff0000) >> 16) - | (n & 0x0000ff00) - | ((n & 0x000000ff) << 16); -#else - bhp->DSLength = n; -#endif - if(len & 03) { - n = 4 - (len & 03); - len += n; - } - if(ISOK2DIG(sp->dataDigest, pp)) - len += 4; - } - - pq->len = len; - len -= sizeof(bhs_t); - if(sp->opt.maxBurstLength && (len > sp->opt.maxBurstLength)) { - xdebug("%d] pdu len=%zd > %d", - sp->sid, len, sp->opt.maxBurstLength); - // XXX: when this happens it used to hang ... - return E2BIG; - } - return 0; -} - -int -isc_qout(isc_session_t *sp, pduq_t *pq) -{ - int error = 0; - - debug_called(8); - - if(pq->len == 0 && (error = i_prepPDU(sp, pq))) - return error; - - if(pq->pdu.ipdu.bhs.I) - i_nqueue_isnd(sp, pq); - else - if(pq->pdu.ipdu.data_out.opcode == ISCSI_WRITE_DATA) - i_nqueue_wsnd(sp, pq); - else - i_nqueue_csnd(sp, pq); - - sdebug(5, "enqued: pq=%p", pq); - - mtx_lock(&sp->io_mtx); - sp->flags |= ISC_OQNOTEMPTY; - if(sp->flags & ISC_OWAITING) - wakeup(&sp->flags); - mtx_unlock(&sp->io_mtx); - - return error; -} -/* - | called when a fullPhase is restarted - */ -void -ism_restart(isc_session_t *sp) -{ - int lastcmd; - - sdebug(2, "restart ..."); - lastcmd = iscsi_requeue(sp); -#if 0 - if(lastcmd != sp->sn.cmd) { - sdebug(1, "resetting CmdSN to=%d (from %d)", lastcmd, sp->sn.cmd); - sp->sn.cmd = lastcmd; - } -#endif - mtx_lock(&sp->io_mtx); - if(sp->flags & ISC_OWAITING) { - wakeup(&sp->flags); - } - mtx_unlock(&sp->io_mtx); - - sdebug(2, "restarted sn.cmd=0x%x lastcmd=0x%x", sp->sn.cmd, lastcmd); -} - -void -ism_recv(isc_session_t *sp, pduq_t *pq) -{ - bhs_t *bhs; - int statSN; - - debug_called(8); - - bhs = &pq->pdu.ipdu.bhs; - statSN = ntohl(bhs->OpcodeSpecificFields[1]); - -#ifdef notyet - if(sp->sn.expCmd != sn->cmd) { - sdebug(1, "we lost something ... exp=0x%x cmd=0x%x", - sn->expCmd, sn->cmd); - } -#endif - sdebug(5, "opcode=0x%x itt=0x%x stat#0x%x maxcmd=0x%0x", - bhs->opcode, ntohl(bhs->itt), statSN, sp->sn.maxCmd); - - switch(bhs->opcode) { - case ISCSI_READ_DATA: { - data_in_t *cmd = &pq->pdu.ipdu.data_in; - - if(cmd->S == 0) - break; - } - - default: - if(statSN > (sp->sn.stat + 1)) { - sdebug(1, "we lost some rec=0x%x exp=0x%x", - statSN, sp->sn.stat); - // XXX: must do some error recovery here. - } - sp->sn.stat = statSN; - } - - switch(bhs->opcode) { - case ISCSI_LOGIN_RSP: - case ISCSI_TEXT_RSP: - case ISCSI_LOGOUT_RSP: - i_nqueue_rsp(sp, pq); - wakeup(&sp->rsp); - sdebug(3, "wakeup rsp"); - break; - - case ISCSI_NOP_IN: _nop_in(sp, pq); break; - case ISCSI_SCSI_RSP: _scsi_rsp(sp, pq); break; - case ISCSI_READ_DATA: _read_data(sp, pq); break; - case ISCSI_R2T: _r2t(sp, pq); break; - case ISCSI_REJECT: _reject(sp, pq); break; - case ISCSI_ASYNC: _async(sp, pq); break; - - case ISCSI_TASK_RSP: - default: - sdebug(1, "opcode=0x%x itt=0x%x not implemented yet", - bhs->opcode, ntohl(bhs->itt)); - break; - } -} - -/* - | go through the out queues looking for work - | if either nothing to do, or window is closed - | return. - */ -static int -proc_out(isc_session_t *sp) -{ - sn_t *sn = &sp->sn; - pduq_t *pq; - int error, which; - - debug_called(8); - error = 0; - - while(sp->flags & ISC_LINK_UP) { - pdu_t *pp; - bhs_t *bhs; - /* - | check if there is outstanding work in: - | 1- the Immediate queue - | 2- the R2T queue - | 3- the cmd queue, only if the command window allows it. - */ - which = BIT(0) | BIT(1); - if(SNA_GT(sn->cmd, sn->maxCmd) == 0) // if(sn->maxCmd - sn->smc + 1) > 0 - which |= BIT(2); - - sdebug(4, "which=%d sn->maxCmd=%d sn->cmd=%d", which, sn->maxCmd, sn->cmd); - - if((pq = i_dqueue_snd(sp, which)) == NULL) - break; - sdebug(4, "pq=%p", pq); - - pp = &pq->pdu; - bhs = &pp->ipdu.bhs; - switch(bhs->opcode) { - case ISCSI_SCSI_CMD: - sn->itt++; - bhs->itt = htonl(sn->itt); - - case ISCSI_LOGIN_CMD: - case ISCSI_TEXT_CMD: - case ISCSI_LOGOUT_CMD: - case ISCSI_SNACK: - case ISCSI_NOP_OUT: - case ISCSI_TASK_CMD: - bhs->CmdSN = htonl(sn->cmd); - if(bhs->I == 0) - sn->cmd++; - - case ISCSI_WRITE_DATA: - bhs->ExpStSN = htonl(sn->stat + 1); - break; - - default: - // XXX: can this happen? - xdebug("bad opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)", - bhs->opcode, - sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt); - // XXX: and now? - } - - sdebug(4, "opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)", - bhs->opcode, - sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt); - - if(bhs->opcode != ISCSI_NOP_OUT) - /* - | enqued till ack is received - | note: sosend(...) does not mean the packet left - | the host so that freeing resources has to wait - */ - i_nqueue_hld(sp, pq); - - error = isc_sendPDU(sp, pq); - if(bhs->opcode == ISCSI_NOP_OUT) - pdu_free(sp->isc, pq); - if(error) { - xdebug("error=%d opcode=0x%x ccb=%p itt=%x", - error, bhs->opcode, pq->ccb, ntohl(bhs->itt)); - i_remove_hld(sp, pq); - switch(error) { - case EPIPE: - sp->flags &= ~ISC_LINK_UP; - - case EAGAIN: - xdebug("requed"); - i_rqueue_pdu(sp, pq); - break; - - default: - if(pq->ccb) { - xdebug("back to cam"); - pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error? - xpt_done(pq->ccb); - pdu_free(sp->isc, pq); - } - else - xdebug("we lost it!"); - } - } - } - return error; -} - -/* - | survives link breakdowns. - */ -static void -ism_out(void *vp) -{ - isc_session_t *sp = (isc_session_t *)vp; - int error; - - debug_called(8); - - sp->flags |= ISC_SM_RUNNING; - sdebug(3, "started sp->flags=%x", sp->flags); - do { - if((sp->flags & ISC_HOLD) == 0) { - error = proc_out(sp); - if(error) { - sdebug(3, "error=%d", error); - } - } - mtx_lock(&sp->io_mtx); - if((sp->flags & ISC_LINK_UP) == 0) { - sdebug(3, "ISC_LINK_UP==0, sp->flags=%x ", sp->flags); - if(sp->soc != NULL) - sdebug(3, "so_state=%x", sp->soc->so_state); - wakeup(&sp->soc); - } - - if(!(sp->flags & ISC_OQNOTEMPTY)) { - sp->flags |= ISC_OWAITING; - if(msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK) { - if(sp->flags & ISC_CON_RUNNING) - _nop_out(sp); - } - sp->flags &= ~ISC_OWAITING; - } - sp->flags &= ~ISC_OQNOTEMPTY; - mtx_unlock(&sp->io_mtx); - } while(sp->flags & ISC_SM_RUN); - - sp->flags &= ~ISC_SM_RUNNING; - sdebug(3, "dropped ISC_SM_RUNNING"); - - wakeup(&sp->soc); - wakeup(sp); // XXX: do we need this one? - - destroy_dev(sp->dev); - - debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid); - - kproc_exit(0); -} - -#if 0 -static int -isc_dump_options(SYSCTL_HANDLER_ARGS) -{ - int error; - isc_session_t *sp; - struct sbuf sb; - - sbuf_new_for_sysctl(&sb, NULL, 128, req); - - sp = (isc_session_t *)arg1; - sbuf_printf(&sb, "targetname='%s'", sp->opt.targetName); - sbuf_printf(&sb, " targetaddress='%s'", sp->opt.targetAddress); - error = sbuf_finish(&sb); - sbuf_delete(&sb); - return error; -} -#endif - -static int -isc_dump_stats(SYSCTL_HANDLER_ARGS) -{ - isc_session_t *sp; - struct isc_softc *sc; - int error; - struct sbuf sb; - - sp = (isc_session_t *)arg1; - sc = sp->isc; - - sbuf_new_for_sysctl(&sb, NULL, 128, req); - - sbuf_printf(&sb, "recv=%d sent=%d", sp->stats.nrecv, sp->stats.nsent); - sbuf_printf(&sb, " flags=0x%08x pdus-alloc=%d pdus-max=%d", - sp->flags, sc->npdu_alloc, sc->npdu_max); - sbuf_printf(&sb, " cws=%d cmd=%x exp=%x max=%x stat=%x itt=%x", - sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt); - error = sbuf_finish(&sb); - sbuf_delete(&sb); - return error; -} - -static void -isc_add_sysctls(isc_session_t *sp) -{ - debug_called(8); - sdebug(6, "sid=%d %s", sp->sid, devtoname(sp->dev)); - - sysctl_ctx_init(&sp->clist); - sp->oid = SYSCTL_ADD_NODE(&sp->clist, - SYSCTL_CHILDREN(sp->isc->oid), - OID_AUTO, - devtoname(sp->dev) + 5, // iscsi0 - CTLFLAG_RD | CTLFLAG_MPSAFE, - 0, - "initiator"); - SYSCTL_ADD_PROC(&sp->clist, - SYSCTL_CHILDREN(sp->oid), - OID_AUTO, - "targetname", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - (void *)&sp->opt.targetName, 0, - sysctl_handle_string, "A", "target name"); - - SYSCTL_ADD_PROC(&sp->clist, - SYSCTL_CHILDREN(sp->oid), - OID_AUTO, - "targeaddress", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - (void *)&sp->opt.targetAddress, 0, - sysctl_handle_string, "A", "target address"); - - SYSCTL_ADD_PROC(&sp->clist, - SYSCTL_CHILDREN(sp->oid), - OID_AUTO, - "stats", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - (void *)sp, 0, - isc_dump_stats, "A", "statistics"); - - SYSCTL_ADD_INT(&sp->clist, - SYSCTL_CHILDREN(sp->oid), - OID_AUTO, - "douio", - CTLFLAG_RW, - &sp->douio, 0, "enable uio on read"); -} - -void -ism_stop(isc_session_t *sp) -{ - struct isc_softc *sc = sp->isc; - int n; - - debug_called(8); - sdebug(2, "terminating"); - /* - | first stop the receiver - */ - isc_stop_receiver(sp); - /* - | now stop the xmitter - */ - n = 5; - sp->flags &= ~ISC_SM_RUN; - while(n-- && (sp->flags & ISC_SM_RUNNING)) { - sdebug(2, "n=%d", n); - wakeup(&sp->flags); - tsleep(sp, PRIBIO, "-", 5*hz); - } - sdebug(2, "final n=%d", n); - sp->flags &= ~ISC_FFPHASE; - - iscsi_cleanup(sp); - - (void)i_pdu_flush(sp); - - ic_destroy(sp); - - sx_xlock(&sc->unit_sx); - free_unr(sc->unit, sp->sid); - sx_xunlock(&sc->unit_sx); - - mtx_lock(&sc->isc_mtx); - TAILQ_REMOVE(&sc->isc_sess, sp, sp_link); - sc->nsess--; - mtx_unlock(&sc->isc_mtx); - - mtx_destroy(&sp->rsp_mtx); - mtx_destroy(&sp->rsv_mtx); - mtx_destroy(&sp->hld_mtx); - mtx_destroy(&sp->snd_mtx); - mtx_destroy(&sp->io_mtx); - - i_freeopt(&sp->opt); - - if(sysctl_ctx_free(&sp->clist)) - xdebug("sysctl_ctx_free failed"); - - free(sp, M_ISCSI); -} - -int -ism_start(isc_session_t *sp) -{ - debug_called(8); - /* - | now is a good time to do some initialization - */ - TAILQ_INIT(&sp->rsp); - TAILQ_INIT(&sp->rsv); - TAILQ_INIT(&sp->csnd); - TAILQ_INIT(&sp->isnd); - TAILQ_INIT(&sp->wsnd); - TAILQ_INIT(&sp->hld); - - mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_DEF); - mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_DEF); - mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_DEF); - mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_DEF); - mtx_init(&sp->io_mtx, "iscsi-io", NULL, MTX_DEF); - - isc_add_sysctls(sp); - - sp->flags |= ISC_SM_RUN; - - debug(4, "starting ism_proc: sp->sid=%d", sp->sid); - - return kproc_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid); -} Index: sys/dev/iscsi_initiator/isc_soc.c =================================================================== --- sys/dev/iscsi_initiator/isc_soc.c +++ /dev/null @@ -1,680 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: isc_soc.c 998 2009-12-20 10:32:45Z danny $ - */ -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#ifndef NO_USE_MBUF -#define USE_MBUF -#endif - -#ifdef USE_MBUF -static int ou_refcnt = 0; -/* - | function for freeing external storage for mbuf - */ -static void -ext_free(struct mbuf *m) -{ - pduq_t *pq = m->m_ext.ext_arg1; - - if(pq->buf != NULL) { - debug(3, "ou_refcnt=%d a=%p b=%p", - ou_refcnt, m->m_ext.ext_buf, pq->buf); - free(pq->buf, M_ISCSIBUF); - pq->buf = NULL; - } -} - -int -isc_sendPDU(isc_session_t *sp, pduq_t *pq) -{ - struct mbuf *mh, **mp; - pdu_t *pp = &pq->pdu; - int len, error; - - debug_called(8); - /* - | mbuf for the iSCSI header - */ - MGETHDR(mh, M_WAITOK, MT_DATA); - mh->m_pkthdr.rcvif = NULL; - mh->m_next = NULL; - mh->m_len = sizeof(union ipdu_u); - - if(ISOK2DIG(sp->hdrDigest, pp)) { - pp->hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0); - mh->m_len += sizeof(pp->hdr_dig); - if(pp->ahs_len) { - debug(2, "ahs_len=%d", pp->ahs_len); - pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig); - } - debug(3, "pp->hdr_dig=%04x", htonl(pp->hdr_dig)); - } - if(pp->ahs_len) { - /* - | Add any AHS to the iSCSI hdr mbuf - */ - if((mh->m_len + pp->ahs_len) < MHLEN) { - M_ALIGN(mh, mh->m_len + pp->ahs_len); - bcopy(&pp->ipdu, mh->m_data, mh->m_len); - bcopy(pp->ahs_addr, mh->m_data + mh->m_len, pp->ahs_len); - mh->m_len += pp->ahs_len; - } - else - panic("len AHS=%d too big, not impleneted yet", pp->ahs_len); - } - else { - M_ALIGN(mh, mh->m_len); - bcopy(&pp->ipdu, mh->m_data, mh->m_len); - } - mh->m_pkthdr.len = mh->m_len; - mp = &mh->m_next; - if(pp->ds_len && pq->pdu.ds_addr) { - struct mbuf *md; - int off = 0; - - len = pp->ds_len; - while(len > 0) { - int l; - - MGET(md, M_WAITOK, MT_DATA); - md->m_ext.ext_cnt = &ou_refcnt; - l = min(MCLBYTES, len); - debug(4, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l); - m_extadd(md, pp->ds_addr + off, l, ext_free, pq, NULL, 0, - EXT_EXTREF); - md->m_len = l; - md->m_next = NULL; - mh->m_pkthdr.len += l; - *mp = md; - mp = &md->m_next; - len -= l; - off += l; - } - if(((pp->ds_len & 03) != 0) || ISOK2DIG(sp->dataDigest, pp)) { - MGET(md, M_WAITOK, MT_DATA); - if(pp->ds_len & 03) - len = 4 - (pp->ds_len & 03); - else - len = 0; - md->m_len = len; - if(ISOK2DIG(sp->dataDigest, pp)) - md->m_len += sizeof(pp->ds_dig); - M_ALIGN(md, md->m_len); - if(ISOK2DIG(sp->dataDigest, pp)) { - pp->ds_dig = sp->dataDigest(pp->ds_addr, pp->ds_len, 0); - if(len) { - bzero(md->m_data, len); // RFC says SHOULD be 0 - pp->ds_dig = sp->dataDigest(md->m_data, len, pp->ds_dig); - } - bcopy(&pp->ds_dig, md->m_data+len, sizeof(pp->ds_dig)); - } - md->m_next = NULL; - mh->m_pkthdr.len += md->m_len; - *mp = md; - } - } - if((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, sp->td)) != 0) { - sdebug(2, "error=%d", error); - return error; - } - sp->stats.nsent++; - getbintime(&sp->stats.t_sent); - return 0; -} -#else /* NO_USE_MBUF */ -int -isc_sendPDU(isc_session_t *sp, pduq_t *pq) -{ - struct uio *uio = &pq->uio; - struct iovec *iv; - pdu_t *pp = &pq->pdu; - int len, error; - - debug_called(8); - - bzero(uio, sizeof(struct uio)); - uio->uio_rw = UIO_WRITE; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_td = sp->td; - uio->uio_iov = iv = pq->iov; - - iv->iov_base = &pp->ipdu; - iv->iov_len = sizeof(union ipdu_u); - uio->uio_resid = iv->iov_len; - iv++; - if(ISOK2DIG(sp->hdrDigest, pp)) - pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0); - if(pp->ahs_len) { - iv->iov_base = pp->ahs_addr; - iv->iov_len = pp->ahs_len; - uio->uio_resid += iv->iov_len; - iv++; - if(ISOK2DIG(sp->hdrDigest, pp)) - pp->hdr_dig = sp->hdrDigest(&pp->ahs_addr, pp->ahs_len, pp->hdr_dig); - } - if(ISOK2DIG(sp->hdrDigest, pp)) { - debug(3, "hdr_dig=%04x", htonl(pp->hdr_dig)); - iv->iov_base = &pp->hdr_dig; - iv->iov_len = sizeof(int); - uio->uio_resid += iv->iov_len ; - iv++; - } - if(pq->pdu.ds_addr && pp->ds_len) { - iv->iov_base = pp->ds_addr; - iv->iov_len = pp->ds_len; - while(iv->iov_len & 03) // the specs say it must be int aligned - iv->iov_len++; - uio->uio_resid += iv->iov_len ; - iv++; - if(ISOK2DIG(sp->dataDigest, pp)) { - pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0); - iv->iov_base = &pp->ds_dig; - iv->iov_len = sizeof(pp->ds_dig); - uio->uio_resid += iv->iov_len ; - iv++; - } - } - uio->uio_iovcnt = iv - pq->iov; - sdebug(4, "pq->len=%d uio->uio_resid=%d uio->uio_iovcnt=%d", pq->len, - uio->uio_resid, - uio->uio_iovcnt); - - sdebug(4, "opcode=%x iovcnt=%d uio_resid=%d itt=%x", - pp->ipdu.bhs.opcode, uio->uio_iovcnt, uio->uio_resid, - ntohl(pp->ipdu.bhs.itt)); - sdebug(5, "sp=%p sp->soc=%p uio=%p sp->td=%p", - sp, sp->soc, uio, sp->td); - do { - len = uio->uio_resid; - error = sosend(sp->soc, NULL, uio, 0, 0, 0, sp->td); - if(uio->uio_resid == 0 || error || len == uio->uio_resid) { - if(uio->uio_resid) { - sdebug(2, "uio->uio_resid=%d uio->uio_iovcnt=%d error=%d len=%d", - uio->uio_resid, uio->uio_iovcnt, error, len); - if(error == 0) - error = EAGAIN; // 35 - } - break; - } - /* - | XXX: untested code - */ - sdebug(1, "uio->uio_resid=%d uio->uio_iovcnt=%d", - uio->uio_resid, uio->uio_iovcnt); - iv = uio->uio_iov; - len -= uio->uio_resid; - while(uio->uio_iovcnt > 0) { - if(iv->iov_len > len) { - caddr_t bp = (caddr_t)iv->iov_base; - - iv->iov_len -= len; - iv->iov_base = (void *)&bp[len]; - break; - } - len -= iv->iov_len; - uio->uio_iovcnt--; - uio->uio_iov++; - iv++; - } - } while(uio->uio_resid); - - if(error == 0) { - sp->stats.nsent++; - getbintime(&sp->stats.t_sent); - } - - return error; -} -#endif /* USE_MBUF */ - -/* - | wait till a PDU header is received - | from the socket. - */ -/* - The format of the BHS is: - - Byte/ 0 | 1 | 2 | 3 | - / | | | | - |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7| - +---------------+---------------+---------------+---------------+ - 0|.|I| Opcode |F| Opcode-specific fields | - +---------------+---------------+---------------+---------------+ - 4|TotalAHSLength | DataSegmentLength | - +---------------+---------------+---------------+---------------+ - 8| LUN or Opcode-specific fields | - + + - 12| | - +---------------+---------------+---------------+---------------+ - 16| Initiator Task Tag | - +---------------+---------------+---------------+---------------+ - 20/ Opcode-specific fields / - +/ / - +---------------+---------------+---------------+---------------+ - 48 - */ -static __inline int -so_getbhs(isc_session_t *sp) -{ - bhs_t *bhs = &sp->bhs; - struct uio *uio = &sp->uio; - struct iovec *iov = &sp->iov; - int error, flags; - - debug_called(8); - - iov->iov_base = bhs; - iov->iov_len = sizeof(bhs_t); - - uio->uio_iov = iov; - uio->uio_iovcnt = 1; - uio->uio_rw = UIO_READ; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_td = curthread; // why ... - uio->uio_resid = sizeof(bhs_t); - - flags = MSG_WAITALL; - error = soreceive(sp->soc, NULL, uio, 0, 0, &flags); - - if(error) - debug(2, - "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd", - error, - sp->soc->so_error, uio->uio_resid, iov->iov_len); - if(!error && (uio->uio_resid > 0)) { - error = EPIPE; // was EAGAIN - debug(2, - "error=%d so_error=%d uio->uio_resid=%zd iov.iov_len=%zd so_state=%x", - error, - sp->soc->so_error, uio->uio_resid, iov->iov_len, sp->soc->so_state); - } - return error; -} - -/* - | so_recv gets called when - | an iSCSI header has been received. - | Note: the designers had no intentions - | in making programmer's life easy. - */ -static int -so_recv(isc_session_t *sp, pduq_t *pq) -{ - sn_t *sn = &sp->sn; - struct uio *uio = &pq->uio; - pdu_t *pp = &pq->pdu; - bhs_t *bhs = &pp->ipdu.bhs; - struct iovec *iov = pq->iov; - int error; - u_int len; - u_int max, exp; - int flags = MSG_WAITALL; - - debug_called(8); - /* - | now calculate how much data should be in the buffer - */ - uio->uio_iov = iov; - uio->uio_iovcnt = 0; - len = 0; - if(bhs->AHSLength) { - debug(2, "bhs->AHSLength=%d", bhs->AHSLength); - pp->ahs_len = bhs->AHSLength * 4; - len += pp->ahs_len; - pp->ahs_addr = malloc(pp->ahs_len, M_TEMP, M_WAITOK); // XXX: could get stuck here - iov->iov_base = pp->ahs_addr; - iov->iov_len = pp->ahs_len; - uio->uio_iovcnt++; - iov++; - } - if(ISOK2DIG(sp->hdrDigest, pp)) { - len += sizeof(pp->hdr_dig); - iov->iov_base = &pp->hdr_dig; - iov->iov_len = sizeof(pp->hdr_dig); - uio->uio_iovcnt++; - } - if(len) { - uio->uio_rw = UIO_READ; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_resid = len; - uio->uio_td = sp->td; // why ... - error = soreceive(sp->soc, NULL, uio, NULL, NULL, &flags); - //if(error == EAGAIN) - // XXX: this needs work! it hangs iscontrol - if(error || uio->uio_resid) { - debug(2, - "len=%d error=%d uio->uio_resid=%zd", - len, error, uio->uio_resid); - goto out; - } - if(ISOK2DIG(sp->hdrDigest, pp)) { - bhs_t *bhs; - u_int digest; - - bhs = (bhs_t *)&pp->ipdu; - digest = sp->hdrDigest(bhs, sizeof(bhs_t), 0); - if(pp->ahs_len) - digest = sp->hdrDigest(pp->ahs_addr, pp->ahs_len, digest); - if(pp->hdr_dig != digest) { - debug(2, "bad header digest: received=%x calculated=%x", pp->hdr_dig, digest); - // XXX: now what? - error = EIO; - goto out; - } - } - if(pp->ahs_len) { - debug(2, "ahs len=%x type=%x spec=%x", - pp->ahs_addr->len, pp->ahs_addr->type, pp->ahs_addr->spec); - // XXX: till I figure out what to do with this - free(pp->ahs_addr, M_TEMP); - } - pq->len += len; // XXX: who needs this? - bzero(uio, sizeof(struct uio)); - len = 0; - } - - if(bhs->DSLength) { - len = bhs->DSLength; -#if BYTE_ORDER == LITTLE_ENDIAN - len = ((len & 0x00ff0000) >> 16) - | (len & 0x0000ff00) - | ((len & 0x000000ff) << 16); -#endif - pp->ds_len = len; - if((sp->opt.maxRecvDataSegmentLength > 0) && (len > sp->opt.maxRecvDataSegmentLength)) { - xdebug("impossible PDU length(%d) opt.maxRecvDataSegmentLength=%d", - len, sp->opt.maxRecvDataSegmentLength); - log(LOG_ERR, - "so_recv: impossible PDU length(%d) from iSCSI %s/%s\n", - len, sp->opt.targetAddress, sp->opt.targetName); - /* - | XXX: this will really screwup the stream. - | should clear up the buffer till a valid header - | is found, or just close connection ... - | should read the RFC. - */ - error = E2BIG; - goto out; - } - while(len & 03) - len++; - if(ISOK2DIG(sp->dataDigest, pp)) - len += 4; - uio->uio_resid = len; - uio->uio_td = sp->td; // why ... - pq->len += len; // XXX: do we need this? - error = soreceive(sp->soc, NULL, uio, &pq->mp, NULL, &flags); - //if(error == EAGAIN) - // XXX: this needs work! it hangs iscontrol - if(error || uio->uio_resid) - goto out; - if(ISOK2DIG(sp->dataDigest, pp)) { - struct mbuf *m; - u_int digest, ds_len, cnt; - - // get the received digest - m_copydata(pq->mp, - len - sizeof(pp->ds_dig), - sizeof(pp->ds_dig), - (caddr_t)&pp->ds_dig); - // calculate all mbufs - digest = 0; - ds_len = len - sizeof(pp->ds_dig); - for(m = pq->mp; m != NULL; m = m->m_next) { - cnt = MIN(ds_len, m->m_len); - digest = sp->dataDigest(mtod(m, char *), cnt, digest); - ds_len -= cnt; - if(ds_len == 0) - break; - } - if(digest != pp->ds_dig) { - sdebug(1, "bad data digest: received=%x calculated=%x", pp->ds_dig, digest); - error = EIO; // XXX: find a better error - goto out; - } - KASSERT(ds_len == 0, ("ds_len not zero")); - } - } - sdebug(6, "len=%d] opcode=0x%x ahs_len=0x%x ds_len=0x%x", - pq->len, bhs->opcode, pp->ahs_len, pp->ds_len); - - max = ntohl(bhs->MaxCmdSN); - exp = ntohl(bhs->ExpStSN); - if(max < exp - 1 && - max > exp - _MAXINCR) { - sdebug(2, "bad cmd window size"); - error = EIO; // XXX: for now; - goto out; // error - } - if(SNA_GT(max, sn->maxCmd)) - sn->maxCmd = max; - if(SNA_GT(exp, sn->expCmd)) - sn->expCmd = exp; - /* - | remove from the holding queue packets - | that have been acked and don't need - | further processing. - */ - i_acked_hld(sp, NULL); - - sp->cws = sn->maxCmd - sn->expCmd + 1; - - return 0; - - out: - // XXX: need some work here - if(pp->ahs_len) { - // XXX: till I figure out what to do with this - free(pp->ahs_addr, M_TEMP); - } - xdebug("have a problem, error=%d", error); - pdu_free(sp->isc, pq); - if(!error && uio->uio_resid > 0) - error = EPIPE; - return error; -} - -/* - | wait for something to arrive. - | and if the pdu is without errors, process it. - */ -static int -so_input(isc_session_t *sp) -{ - pduq_t *pq; - int error; - - debug_called(8); - /* - | first read in the iSCSI header - */ - error = so_getbhs(sp); - if(error == 0) { - /* - | now read the rest. - */ - pq = pdu_alloc(sp->isc, M_NOWAIT); - if(pq == NULL) { // XXX: might cause a deadlock ... - debug(2, "out of pdus, wait"); - pq = pdu_alloc(sp->isc, M_WAITOK); // OK to WAIT - } - pq->pdu.ipdu.bhs = sp->bhs; - pq->len = sizeof(bhs_t); // so far only the header was read - error = so_recv(sp, pq); - if(error != 0) { - error += 0x800; // XXX: just to see the error. - // terminal error - // XXX: close connection and exit - } - else { - sp->stats.nrecv++; - getbintime(&sp->stats.t_recv); - ism_recv(sp, pq); - } - } - return error; -} - -/* - | one per active (connected) session. - | this thread is responsible for reading - | in packets from the target. - */ -static void -isc_in(void *vp) -{ - isc_session_t *sp = (isc_session_t *)vp; - struct socket *so = sp->soc; - int error; - - debug_called(8); - - sp->flags |= ISC_CON_RUNNING; - error = 0; - while((sp->flags & (ISC_CON_RUN | ISC_LINK_UP)) == (ISC_CON_RUN | ISC_LINK_UP)) { - // XXX: hunting ... - if(sp->soc == NULL || !(so->so_state & SS_ISCONNECTED)) { - debug(2, "sp->soc=%p", sp->soc); - break; - } - error = so_input(sp); - if(error == 0) { - mtx_lock(&sp->io_mtx); - if(sp->flags & ISC_OWAITING) { - wakeup(&sp->flags); - } - mtx_unlock(&sp->io_mtx); - } else if(error == EPIPE) { - break; - } - else if(error == EAGAIN) { - if(so->so_state & SS_ISCONNECTED) - // there seems to be a problem in 6.0 ... - tsleep(sp, PRIBIO, "isc_soc", 2*hz); - } - } - sdebug(2, "terminated, flags=%x so_count=%d so_state=%x error=%d proc=%p", - sp->flags, so->so_count, so->so_state, error, sp->proc); - if((sp->proc != NULL) && sp->signal) { - PROC_LOCK(sp->proc); - kern_psignal(sp->proc, sp->signal); - PROC_UNLOCK(sp->proc); - sp->flags |= ISC_SIGNALED; - sdebug(2, "pid=%d signaled(%d)", sp->proc->p_pid, sp->signal); - } - else { - // we have to do something ourselves - // like closing this session ... - } - /* - | we've been terminated - */ - // do we need this mutex ...? - mtx_lock(&sp->io_mtx); - sp->flags &= ~(ISC_CON_RUNNING | ISC_LINK_UP); - wakeup(&sp->soc); - mtx_unlock(&sp->io_mtx); - - sdebug(2, "dropped ISC_CON_RUNNING"); - kproc_exit(0); -} - -void -isc_stop_receiver(isc_session_t *sp) -{ - int n; - - debug_called(8); - sdebug(3, "sp=%p sp->soc=%p", sp, sp? sp->soc: 0); - mtx_lock(&sp->io_mtx); - sp->flags &= ~ISC_LINK_UP; - msleep(&sp->soc, &sp->io_mtx, PRIBIO|PDROP, "isc_stpc", 5*hz); - - soshutdown(sp->soc, SHUT_RD); - - mtx_lock(&sp->io_mtx); - sdebug(3, "soshutdown"); - sp->flags &= ~ISC_CON_RUN; - n = 2; - while(n-- && (sp->flags & ISC_CON_RUNNING)) { - sdebug(3, "waiting n=%d... flags=%x", n, sp->flags); - msleep(&sp->soc, &sp->io_mtx, PRIBIO, "isc_stpc", 5*hz); - } - mtx_unlock(&sp->io_mtx); - - if(sp->fp != NULL) - fdrop(sp->fp, sp->td); - sp->soc = NULL; - sp->fp = NULL; - - sdebug(3, "done"); -} - -void -isc_start_receiver(isc_session_t *sp) -{ - debug_called(8); - - sp->flags |= ISC_CON_RUN | ISC_LINK_UP; - kproc_create(isc_in, sp, &sp->soc_proc, 0, 0, "isc_in %d", sp->sid); -} Index: sys/dev/iscsi_initiator/isc_subr.c =================================================================== --- sys/dev/iscsi_initiator/isc_subr.c +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005-2011 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. - * - */ -/* - | iSCSI - | $Id: isc_subr.c 560 2009-05-07 07:37:49Z danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static MALLOC_DEFINE(M_ISC, "iSC", "iSCSI driver options"); - -static char * -i_strdupin(char *s, size_t maxlen) -{ - size_t len; - char *p, *q; - - p = malloc(maxlen, M_ISC, M_WAITOK); - if(copyinstr(s, p, maxlen, &len)) { - free(p, M_ISC); - return NULL; - } - q = malloc(len, M_ISC, M_WAITOK); - bcopy(p, q, len); - free(p, M_ISC); - - return q; -} - -static uint32_t -i_crc32c(const void *buf, size_t size, uint32_t crc) -{ - crc = crc ^ 0xffffffff; - crc = calculate_crc32c(crc, buf, size); - crc = crc ^ 0xffffffff; - return crc; -} - -/* - | XXX: not finished coding - */ -int -i_setopt(isc_session_t *sp, isc_opt_t *opt) -{ - char buf[16]; - int error; - - if(opt->maxRecvDataSegmentLength > 0) { - sp->opt.maxRecvDataSegmentLength = opt->maxRecvDataSegmentLength; - sdebug(2, "maxRecvDataSegmentLength=%d", sp->opt.maxRecvDataSegmentLength); - } - if(opt->maxXmitDataSegmentLength > 0) { - // danny's RFC - sp->opt.maxXmitDataSegmentLength = opt->maxXmitDataSegmentLength; - sdebug(2, "opt.maXmitDataSegmentLength=%d", sp->opt.maxXmitDataSegmentLength); - } - if(opt->maxBurstLength != 0) { - sp->opt.maxBurstLength = opt->maxBurstLength; - sdebug(2, "opt.maxBurstLength=%d", sp->opt.maxBurstLength); - } - - if(opt->targetAddress != NULL) { - if(sp->opt.targetAddress != NULL) - free(sp->opt.targetAddress, M_ISC); - sp->opt.targetAddress = i_strdupin(opt->targetAddress, 128); - sdebug(2, "opt.targetAddress='%s'", sp->opt.targetAddress); - } - if(opt->targetName != NULL) { - if(sp->opt.targetName != NULL) - free(sp->opt.targetName, M_ISC); - sp->opt.targetName = i_strdupin(opt->targetName, 128); - sdebug(2, "opt.targetName='%s'", sp->opt.targetName); - } - if(opt->initiatorName != NULL) { - if(sp->opt.initiatorName != NULL) - free(sp->opt.initiatorName, M_ISC); - sp->opt.initiatorName = i_strdupin(opt->initiatorName, 128); - sdebug(2, "opt.initiatorName='%s'", sp->opt.initiatorName); - } - - if(opt->maxluns > 0) { - if(opt->maxluns > ISCSI_MAX_LUNS) - sp->opt.maxluns = ISCSI_MAX_LUNS; // silently chop it down ... - sp->opt.maxluns = opt->maxluns; - sdebug(2, "opt.maxluns=%d", sp->opt.maxluns); - } - - if(opt->headerDigest != NULL) { - error = copyinstr(opt->headerDigest, buf, sizeof(buf), NULL); - if (error != 0) - return (error); - sdebug(2, "opt.headerDigest='%s'", buf); - if(strcmp(buf, "CRC32C") == 0) { - sp->hdrDigest = (digest_t *)i_crc32c; - sdebug(2, "opt.headerDigest set"); - } - } - if(opt->dataDigest != NULL) { - error = copyinstr(opt->dataDigest, buf, sizeof(buf), NULL); - if (error != 0) - return (error); - sdebug(2, "opt.dataDigest='%s'", opt->dataDigest); - if(strcmp(buf, "CRC32C") == 0) { - sp->dataDigest = (digest_t *)i_crc32c; - sdebug(2, "opt.dataDigest set"); - } - } - - return 0; -} - -void -i_freeopt(isc_opt_t *opt) -{ - debug_called(8); - - if(opt->targetAddress != NULL) { - free(opt->targetAddress, M_ISC); - opt->targetAddress = NULL; - } - if(opt->targetName != NULL) { - free(opt->targetName, M_ISC); - opt->targetName = NULL; - } - if(opt->initiatorName != NULL) { - free(opt->initiatorName, M_ISC); - opt->initiatorName = NULL; - } -} Index: sys/dev/iscsi_initiator/iscsi.h =================================================================== --- sys/dev/iscsi_initiator/iscsi.h +++ /dev/null @@ -1,502 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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. - * - * $FreeBSD$ - */ -/* - | $Id: iscsi.h 743 2009-08-08 10:54:53Z danny $ - */ -#define TRUE 1 -#define FALSE 0 -#ifndef _KERNEL -typedef int boolean_t; -#endif - -#include - -#define ISCSIDEV "iscsi" -#define ISCSI_MAX_TARGETS 64 -/* - | iSCSI commands - */ - -/* - | Initiator Opcodes: - */ -#define ISCSI_NOP_OUT 0x00 -#define ISCSI_SCSI_CMD 0x01 -#define ISCSI_TASK_CMD 0x02 -#define ISCSI_LOGIN_CMD 0x03 -#define ISCSI_TEXT_CMD 0x04 -#define ISCSI_WRITE_DATA 0x05 -#define ISCSI_LOGOUT_CMD 0x06 -#define ISCSI_SNACK 0x10 -/* - | Target Opcodes: - */ -#define ISCSI_NOP_IN 0x20 -#define ISCSI_SCSI_RSP 0x21 -#define ISCSI_TASK_RSP 0x22 -#define ISCSI_LOGIN_RSP 0x23 -#define ISCSI_TEXT_RSP 0x24 -#define ISCSI_READ_DATA 0x25 -#define ISCSI_LOGOUT_RSP 0x26 -#define ISCSI_R2T 0x31 -#define ISCSI_ASYNC 0x32 -#define ISCSI_REJECT 0x3f -/* - | PDU stuff - */ -/* - | BHS Basic Header Segment - */ -typedef struct bhs { - // the order is network byte order! - u_char opcode:6; - u_char I:1; - u_char _:1; - u_char __:7; - u_char F:1; // Final bit - u_char ___[2]; - - u_int AHSLength:8; // in 4byte words - u_int DSLength:24; // in bytes - - u_int LUN[2]; // or Opcode-specific fields - u_int itt; - u_int OpcodeSpecificFields[7]; -#define CmdSN OpcodeSpecificFields[1] -#define ExpStSN OpcodeSpecificFields[2] -#define MaxCmdSN OpcodeSpecificFields[3] -} bhs_t; - -typedef struct ahs { - u_int len:16; - u_int type:8; - u_int spec:8; - char data[0]; -} ahs_t; - -typedef struct { - // Sequence Numbers - // (computers were invented to count, right?) - int cmd; - int expcmd; - int maxcmd; -} req_sn_t; - -typedef struct { - // Sequence Numbers - // (computers were invented to count, right?) - int stat; - int expcmd; - int maxcmd; -} rsp_sn_t; - -typedef struct scsi_req { - u_char opcode:6; // 0x01 - u_char I:1; - u_char _:1; - - u_char attr:3; - u_char _0:2; - u_char W:1; - u_char R:1; - u_char F:1; -#define iSCSI_TASK_UNTAGGED 0 -#define iSCSI_TASK_SIMPLE 1 -#define iSCSI_TASK_ORDER 2 -#define iSCSI_TASK_HOFQ 3 -#define iSCSI_TASK_ACA 4 - char _1[2]; - int len; - int lun[2]; - int itt; - int edtlen; // expectect data transfere length - int cmdSN; - int extStatSN; - int cdb[4]; -} scsi_req_t; - -typedef struct scsi_rsp { - char opcode; // 0x21 - u_char flag; - u_char response; - u_char status; - - int len; - int _[2]; - int itt; - int stag; - rsp_sn_t sn; - int expdatasn; - int bdrcnt; // bidirectional residual count - int rcnt; // residual count -} scsi_rsp_t; - -typedef struct nop_out { - // the order is network byte order! - u_char opcode:6; - u_char I:1; - u_char _:1; - u_char __:7; - u_char F:1; // Final bit - u_char ___[2]; - - u_int len; - u_int lun[2]; - u_int itt; - u_int ttt; - req_sn_t sn; - u_int mbz[3]; -} nop_out_t; - -typedef struct nop_in { - // the order is network byte order! - u_char opcode:6; - u_char I:1; - u_char _:1; - u_char __:7; - u_char F:1; // Final bit - u_char ___[2]; - - u_int len; - u_int lun[2]; - u_int itt; - u_int ttt; - rsp_sn_t sn; - u_int ____[2]; - -} nop_in_t; - -typedef struct r2t { - u_char opcode:6; - u_char I:1; - u_char _:1; - u_char __:7; - u_char F:1; // Final bit - u_char ___[2]; - - u_int len; - u_int lun[2]; - u_int itt; - u_int ttt; - rsp_sn_t sn; - u_int r2tSN; - u_int bo; - u_int ddtl; -} r2t_t; - -typedef struct data_out { - u_char opcode:6; - u_char I:1; - u_char _:1; - u_char __:7; - u_char F:1; // Final bit - u_char ___[2]; - - u_int len; - u_int lun[2]; - u_int itt; - u_int ttt; - rsp_sn_t sn; - u_int dsn; // data seq. number - u_int bo; - u_int ____; -} data_out_t; - -typedef struct data_in { - u_char opcode:6; - u_char I:1; - u_char _:1; - - u_char S:1; - u_char U:1; - u_char O:1; - u_char __:3; - u_char A:1; - u_char F:1; // Final bit - u_char ___[1]; - u_char status; - - u_int len; - u_int lun[2]; - u_int itt; - u_int ttt; - rsp_sn_t sn; - u_int dataSN; - u_int bo; - u_int ____; -} data_in_t; - -typedef struct reject { - u_char opcode:6; - u_char _:2; - u_char F:1; - u_char __:7; - u_char reason; - u_char ___; - - u_int len; - u_int ____[2]; - u_int tt[2]; // must be -1 - rsp_sn_t sn; - u_int dataSN; // or R2TSN or reserved - u_int _____[2]; -} reject_t; - -typedef struct async { - u_char opcode:6; - u_char _:2; - u_char F:1; - u_char __:7; - u_char ___[2]; - - u_int len; - u_int lun[2]; - u_int itt; // must be -1 - u_int ____; - rsp_sn_t sn; - - u_char asyncEvent; - u_char asyncVCode; - u_char param1[2]; - u_char param2[2]; - u_char param3[2]; - - u_int _____; - -} async_t; - -typedef struct login_req { - char cmd; // 0x03 - - u_char NSG:2; - u_char CSG:2; - u_char _:2; - u_char C:1; - u_char T:1; - - char v_max; - char v_min; - - int len; // remapped via standard bhs - char isid[6]; - short tsih; - int itt; // Initiator Task Tag; - - int CID:16; - int rsv:16; - - int cmdSN; - int expStatSN; - int unused[4]; -} login_req_t; - -typedef struct login_rsp { - char cmd; // 0x23 - u_char NSG:2; - u_char CSG:2; - u_char _1:2; - u_char C:1; - u_char T:1; - - char v_max; - char v_act; - - int len; // remapped via standard bhs - char isid[6]; - short tsih; - int itt; // Initiator Task Tag; - int _2; - rsp_sn_t sn; - int status:16; - int _3:16; - int _4[2]; -} login_rsp_t; - -typedef struct text_req { - char cmd; // 0x04 - - u_char _1:6; - u_char C:1; // Continuation - u_char F:1; // Final - char _2[2]; - - int len; - int itt; // Initiator Task Tag - int LUN[2]; - int ttt; // Target Transfer Tag - int cmdSN; - int expStatSN; - int unused[4]; -} text_req_t; - -typedef struct logout_req { - char cmd; // 0x06 - u_char reason; // 0 - close session - // 1 - close connection - // 2 - remove the connection for recovery - char _2[2]; - - int len; - int _r[2]; - int itt; // Initiator Task Tag; - - u_int CID:16; - u_int rsv:16; - - int cmdSN; - int expStatSN; - int unused[4]; -} logout_req_t; - -typedef struct logout_rsp { - char cmd; // 0x26 - char cbits; - char _1[2]; - int len; - int _2[2]; - int itt; - int _3; - rsp_sn_t sn; - short time2wait; - short time2retain; - int _4; -} logout_rsp_t; - -union ipdu_u { - bhs_t bhs; - scsi_req_t scsi_req; - scsi_rsp_t scsi_rsp; - nop_out_t nop_out; - nop_in_t nop_in; - r2t_t r2t; - data_out_t data_out; - data_in_t data_in; - reject_t reject; - async_t async; -}; - -/* - | Sequence Numbers - */ -typedef struct { - u_int itt; - u_int cmd; - u_int expCmd; - u_int maxCmd; - u_int stat; - u_int expStat; - u_int data; -} sn_t; - -/* - | in-core version of a Protocol Data Unit - */ -typedef struct { - union ipdu_u ipdu; - u_int hdr_dig; // header digest - - ahs_t *ahs_addr; - u_int ahs_len; - u_int ahs_size; // the allocated size - - u_char *ds_addr; - u_int ds_len; - u_int ds_size; // the allocated size - u_int ds_dig; // data digest -} pdu_t; - -typedef struct opvals { - int port; - int tags; - int maxluns; - int sockbufsize; - - int maxConnections; - int maxRecvDataSegmentLength; - int maxXmitDataSegmentLength; // pseudo ... - int maxBurstLength; - int firstBurstLength; - int defaultTime2Wait; - int defaultTime2Retain; - int maxOutstandingR2T; - int errorRecoveryLevel; - int targetPortalGroupTag; - - boolean_t initialR2T; - boolean_t immediateData; - boolean_t dataPDUInOrder; - boolean_t dataSequenceInOrder; - char *headerDigest; - char *dataDigest; - char *sessionType; - char *sendTargets; - char *targetAddress; - char *targetAlias; - char *targetName; - char *initiatorName; - char *initiatorAlias; - char *authMethod; - char *chapSecret; - char *chapIName; - char *chapDigest; - char *tgtChapName; - char *tgtChapSecret; - int tgtChallengeLen; - u_char tgtChapID; - char *tgtChapDigest; - char *iqn; - char *pidfile; -} isc_opt_t; - -/* - | ioctl - */ -#define ISCSISETSES _IOR('i', 1, int) -#define ISCSISETSOC _IOW('i', 2, int) -#define ISCSISETOPT _IOW('i', 5, isc_opt_t) -#define ISCSIGETOPT _IOR('i', 6, isc_opt_t) - -#define ISCSISEND _IOW('i', 10, pdu_t) -#define ISCSIRECV _IOWR('i', 11, pdu_t) - -#define ISCSIPING _IO('i', 20) -#define ISCSISIGNAL _IOW('i', 21, int *) - -#define ISCSISTART _IO('i', 30) -#define ISCSIRESTART _IO('i', 31) -#define ISCSISTOP _IO('i', 32) - -typedef struct iscsi_cam { - path_id_t path_id; - target_id_t target_id; - int target_nluns; -} iscsi_cam_t; - -#define ISCSIGETCAM _IOR('i', 33, iscsi_cam_t) Index: sys/dev/iscsi_initiator/iscsi.c =================================================================== --- sys/dev/iscsi_initiator/iscsi.c +++ /dev/null @@ -1,880 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005-2011 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: iscsi.c 752 2009-08-20 11:23:28Z danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#ifdef DO_EVENTHANDLER -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -static char *iscsi_driver_version = "2.3.1"; - -static struct isc_softc *isc; - -MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI driver"); -MALLOC_DEFINE(M_ISCSIBUF, "iSCbuf", "iSCSI buffers"); -static MALLOC_DEFINE(M_TMP, "iSCtmp", "iSCSI tmp"); - -#ifdef ISCSI_INITIATOR_DEBUG -int iscsi_debug = ISCSI_INITIATOR_DEBUG; -SYSCTL_INT(_debug, OID_AUTO, iscsi_initiator, CTLFLAG_RW, &iscsi_debug, 0, - "iSCSI driver debug flag"); - -struct mtx iscsi_dbg_mtx; -#endif - -static int max_sessions = MAX_SESSIONS; -SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_sessions, CTLFLAG_RDTUN, - &max_sessions, 0, "Max sessions allowed"); -static int max_pdus = MAX_PDUS; -SYSCTL_INT(_net, OID_AUTO, iscsi_initiator_max_pdus, CTLFLAG_RDTUN, - &max_pdus, 0, "Max PDU pool"); - -static char isid[6+1] = { - 0x80, - 'D', - 'I', - 'B', - '0', - '0', - 0 -}; - -static int i_create_session(struct cdev *dev, int *ndev); - -static int i_ping(struct cdev *dev); -static int i_send(struct cdev *dev, caddr_t arg, struct thread *td); -static int i_recv(struct cdev *dev, caddr_t arg, struct thread *td); -static int i_setsoc(isc_session_t *sp, int fd, struct thread *td); -static int i_fullfeature(struct cdev *dev, int flag); - -static d_open_t iscsi_open; -static d_close_t iscsi_close; -static d_ioctl_t iscsi_ioctl; -#ifdef ISCSI_INITIATOR_DEBUG -static d_read_t iscsi_read; -#endif - -static struct cdevsw iscsi_cdevsw = { - .d_version = D_VERSION, - .d_open = iscsi_open, - .d_close = iscsi_close, - .d_ioctl = iscsi_ioctl, -#ifdef ISCSI_INITIATOR_DEBUG - .d_read = iscsi_read, -#endif - .d_name = "iSCSI", -}; - -static int -iscsi_open(struct cdev *dev, int flags, int otype, struct thread *td) -{ - debug_called(8); - - debug(7, "dev=%d", dev2unit(dev)); - - if(dev2unit(dev) > max_sessions) { - // should not happen - return ENODEV; - } - return 0; -} - -static int -iscsi_close(struct cdev *dev, int flag, int otyp, struct thread *td) -{ - isc_session_t *sp; - - debug_called(8); - - debug(3, "session=%d flag=%x", dev2unit(dev), flag); - - if(dev2unit(dev) == max_sessions) { - return 0; - } - sp = dev->si_drv2; - if(sp != NULL) { - sdebug(3, "sp->flags=%x", sp->flags ); - /* - | if still in full phase, this probably means - | that something went really bad. - | it could be a result from 'shutdown', in which case - | we will ignore it (so buffers can be flushed). - | the problem is that there is no way of differentiating - | between a shutdown procedure and 'iscontrol' dying. - */ - if(sp->flags & ISC_FFPHASE) - // delay in case this is a shutdown. - tsleep(sp, PRIBIO, "isc-cls", 60*hz); - ism_stop(sp); - } - debug(2, "done"); - return 0; -} - -static int -iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, struct thread *td) -{ - struct isc_softc *sc; - isc_session_t *sp; - isc_opt_t *opt; - int error; - - debug_called(8); - - error = 0; - if(dev2unit(dev) == max_sessions) { - /* - | non Session commands - */ - sc = dev->si_drv1; - if(sc == NULL) - return ENXIO; - - switch(cmd) { - case ISCSISETSES: - error = i_create_session(dev, (int *)arg); - if(error == 0) - break; - - default: - error = ENXIO; - } - return error; - } - /* - | session commands - */ - sp = dev->si_drv2; - if(sp == NULL) - return ENXIO; - - sdebug(6, "dev=%d cmd=%d", dev2unit(dev), (int)(cmd & 0xff)); - - switch(cmd) { - case ISCSISETSOC: - error = i_setsoc(sp, *(u_int *)arg, td); - break; - - case ISCSISETOPT: - opt = (isc_opt_t *)arg; - error = i_setopt(sp, opt); - break; - - case ISCSISEND: - error = i_send(dev, arg, td); - break; - - case ISCSIRECV: - error = i_recv(dev, arg, td); - break; - - case ISCSIPING: - error = i_ping(dev); - break; - - case ISCSISTART: - error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 1); - if(error == 0) { - sp->proc = td->td_proc; - SYSCTL_ADD_INT(&sp->clist, SYSCTL_CHILDREN(sp->oid), - OID_AUTO, "pid", CTLFLAG_RD, - &sp->proc->p_pid, sizeof(pid_t), "control process id"); - } - break; - - case ISCSIRESTART: - error = sp->soc == NULL? ENOTCONN: i_fullfeature(dev, 2); - break; - - case ISCSISTOP: - error = i_fullfeature(dev, 0); - break; - - case ISCSISIGNAL: { - int sig = *(int *)arg; - - if(sig < 0 || sig > _SIG_MAXSIG) - error = EINVAL; - else - sp->signal = sig; - break; - } - - case ISCSIGETCAM: { - iscsi_cam_t *cp = (iscsi_cam_t *)arg; - - error = ic_getCamVals(sp, cp); - break; - } - - default: - error = ENOIOCTL; - } - - return error; -} - -static int -iscsi_read(struct cdev *dev, struct uio *uio, int ioflag) -{ -#ifdef ISCSI_INITIATOR_DEBUG - struct isc_softc *sc; - isc_session_t *sp; - pduq_t *pq; - char buf[1024]; - - sc = dev->si_drv1; - sp = dev->si_drv2; - if(dev2unit(dev) == max_sessions) { - sprintf(buf, "/----- Session ------/\n"); - uiomove(buf, strlen(buf), uio); - int i = 0; - - TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) { - if(uio->uio_resid == 0) - return 0; - sprintf(buf, "%03d] '%s' '%s'\n", i++, sp->opt.targetAddress, sp->opt.targetName); - uiomove(buf, strlen(buf), uio); - } - sprintf(buf, "free npdu_alloc=%d, npdu_max=%d\n", sc->npdu_alloc, sc->npdu_max); - uiomove(buf, strlen(buf), uio); - } - else { - int i = 0; - struct socket *so = sp->soc; -#define pukeit(i, pq) do {\ - sprintf(buf, "%03d] %06x %02x %06x %06x %jd\n",\ - i, ntohl(pq->pdu.ipdu.bhs.CmdSN),\ - pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\ - ntohl(pq->pdu.ipdu.bhs.ExpStSN),\ - (intmax_t)pq->ts.sec);\ - } while(0) - - sprintf(buf, "%d/%d /---- hld -----/\n", sp->stats.nhld, sp->stats.max_hld); - uiomove(buf, strlen(buf), uio); - TAILQ_FOREACH(pq, &sp->hld, pq_link) { - if(uio->uio_resid == 0) - return 0; - pukeit(i, pq); i++; - uiomove(buf, strlen(buf), uio); - } - sprintf(buf, "%d/%d /---- rsp -----/\n", sp->stats.nrsp, sp->stats.max_rsp); - uiomove(buf, strlen(buf), uio); - i = 0; - TAILQ_FOREACH(pq, &sp->rsp, pq_link) { - if(uio->uio_resid == 0) - return 0; - pukeit(i, pq); i++; - uiomove(buf, strlen(buf), uio); - } - sprintf(buf, "%d/%d /---- csnd -----/\n", sp->stats.ncsnd, sp->stats.max_csnd); - i = 0; - uiomove(buf, strlen(buf), uio); - TAILQ_FOREACH(pq, &sp->csnd, pq_link) { - if(uio->uio_resid == 0) - return 0; - pukeit(i, pq); i++; - uiomove(buf, strlen(buf), uio); - } - sprintf(buf, "%d/%d /---- wsnd -----/\n", sp->stats.nwsnd, sp->stats.max_wsnd); - i = 0; - uiomove(buf, strlen(buf), uio); - TAILQ_FOREACH(pq, &sp->wsnd, pq_link) { - if(uio->uio_resid == 0) - return 0; - pukeit(i, pq); i++; - uiomove(buf, strlen(buf), uio); - } - sprintf(buf, "%d/%d /---- isnd -----/\n", sp->stats.nisnd, sp->stats.max_isnd); - i = 0; - uiomove(buf, strlen(buf), uio); - TAILQ_FOREACH(pq, &sp->isnd, pq_link) { - if(uio->uio_resid == 0) - return 0; - pukeit(i, pq); i++; - uiomove(buf, strlen(buf), uio); - } - - sprintf(buf, "/---- Stats ---/\n"); - uiomove(buf, strlen(buf), uio); - - sprintf(buf, "recv=%d sent=%d\n", sp->stats.nrecv, sp->stats.nsent); - uiomove(buf, strlen(buf), uio); - - sprintf(buf, "flags=%x pdus: alloc=%d max=%d\n", - sp->flags, sc->npdu_alloc, sc->npdu_max); - uiomove(buf, strlen(buf), uio); - - sprintf(buf, "cws=%d last cmd=%x exp=%x max=%x stat=%x itt=%x\n", - sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt); - uiomove(buf, strlen(buf), uio); - - sprintf(buf, "/---- socket -----/\nso_count=%d so_state=%x\n", so->so_count, so->so_state); - uiomove(buf, strlen(buf), uio); - } -#endif - return 0; -} - -static int -i_ping(struct cdev *dev) -{ - return 0; -} -/* - | low level I/O - */ -static int -i_setsoc(isc_session_t *sp, int fd, struct thread *td) -{ - cap_rights_t rights; - int error = 0; - - if(sp->soc != NULL) - isc_stop_receiver(sp); - - error = getsock_cap(td, fd, cap_rights_init_one(&rights, CAP_SOCK_CLIENT), - &sp->fp, NULL, NULL); - if(error) - return error; - - sp->soc = sp->fp->f_data; - sp->td = td; - isc_start_receiver(sp); - - return error; -} - -static int -i_send(struct cdev *dev, caddr_t arg, struct thread *td) -{ - isc_session_t *sp = dev->si_drv2; - caddr_t bp; - pduq_t *pq; - pdu_t *pp; - int n, error; - - debug_called(8); - - if(sp->soc == NULL) - return ENOTCONN; - - if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) - return EAGAIN; - pp = &pq->pdu; - pq->pdu = *(pdu_t *)arg; - if((error = i_prepPDU(sp, pq)) != 0) - goto out; - - bp = NULL; - if((pq->len - sizeof(union ipdu_u)) > 0) { - pq->buf = bp = malloc(pq->len - sizeof(union ipdu_u), M_ISCSIBUF, M_NOWAIT); - if(pq->buf == NULL) { - error = EAGAIN; - goto out; - } - } - else - pq->buf = NULL; // just in case? - - sdebug(2, "len=%d ahs_len=%d ds_len=%d buf=%zu@%p", - pq->len, pp->ahs_len, pp->ds_len, pq->len - sizeof(union ipdu_u), bp); - - if(pp->ahs_len) { - // XXX: never tested, looks suspicious - n = pp->ahs_len; - error = copyin(pp->ahs_addr, bp, n); - if(error != 0) { - sdebug(3, "copyin ahs: error=%d", error); - goto out; - } - pp->ahs_addr = (ahs_t *)bp; - bp += n; - } - if(pp->ds_len) { - n = pp->ds_len; - error = copyin(pp->ds_addr, bp, n); - if(error != 0) { - sdebug(3, "copyin ds: error=%d", error); - goto out; - } - pp->ds_addr = bp; - bp += n; - while(n & 03) { - n++; - *bp++ = 0; - } - } - - error = isc_qout(sp, pq); - if(error == 0) - wakeup(&sp->flags); // XXX: to 'push' proc_out ... -out: - if(error) - pdu_free(sp->isc, pq); - - return error; -} - -static int -i_recv(struct cdev *dev, caddr_t arg, struct thread *td) -{ - isc_session_t *sp = dev->si_drv2; - pduq_t *pq; - pdu_t *pp, *up; - caddr_t bp; - int error, mustfree, cnt; - size_t need, have, n; - - debug_called(8); - - if(sp == NULL) - return EIO; - - if(sp->soc == NULL) - return ENOTCONN; - cnt = 6; // XXX: maybe the user can request a time out? - mtx_lock(&sp->rsp_mtx); - while((pq = TAILQ_FIRST(&sp->rsp)) == NULL) { - msleep(&sp->rsp, &sp->rsp_mtx, PRIBIO, "isc_rsp", hz*10); - if(cnt-- == 0) break; // XXX: for now, needs work - } - if(pq != NULL) { - sp->stats.nrsp--; - TAILQ_REMOVE(&sp->rsp, pq, pq_link); - } - mtx_unlock(&sp->rsp_mtx); - - sdebug(6, "cnt=%d", cnt); - - if(pq == NULL) { - error = ENOTCONN; - sdebug(3, "error=%d sp->flags=%x ", error, sp->flags); - return error; - } - up = (pdu_t *)arg; - pp = &pq->pdu; - up->ipdu = pp->ipdu; - n = 0; - up->ds_len = 0; - up->ahs_len = 0; - error = 0; - - if(pq->mp) { - u_int len; - - // Grr... - len = 0; - if(pp->ahs_len) { - len += pp->ahs_len; - } - if(pp->ds_len) { - len += pp->ds_len; - } - - mustfree = 0; - if(len > pq->mp->m_len) { - mustfree++; - bp = malloc(len, M_TMP, M_WAITOK); - sdebug(4, "need mbufcopy: %d", len); - i_mbufcopy(pq->mp, bp, len); - } - else - bp = mtod(pq->mp, caddr_t); - - if(pp->ahs_len) { - need = pp->ahs_len; - n = MIN(up->ahs_size, need); - error = copyout(bp, (caddr_t)up->ahs_addr, n); - up->ahs_len = n; - bp += need; - } - if(!error && pp->ds_len) { - need = pp->ds_len; - if((have = up->ds_size) == 0) { - have = up->ahs_size - n; - up->ds_addr = (caddr_t)up->ahs_addr + n; - } - n = MIN(have, need); - error = copyout(bp, (caddr_t)up->ds_addr, n); - up->ds_len = n; - } - - if(mustfree) - free(bp, M_TMP); - } - - sdebug(6, "len=%d ahs_len=%d ds_len=%d", pq->len, pp->ahs_len, pp->ds_len); - - pdu_free(sp->isc, pq); - - return error; -} - -static int -i_fullfeature(struct cdev *dev, int flag) -{ - isc_session_t *sp = dev->si_drv2; - int error; - - sdebug(2, "flag=%d", flag); - - error = 0; - switch(flag) { - case 0: // stop - sp->flags &= ~ISC_FFPHASE; - break; - case 1: // start - sp->flags |= ISC_FFPHASE; - error = ic_init(sp); - break; - case 2: // restart - sp->flags |= ISC_FFPHASE; - ism_restart(sp); - break; - } - return error; -} - -static int -i_create_session(struct cdev *dev, int *ndev) -{ - struct isc_softc *sc = dev->si_drv1; - isc_session_t *sp; - int error, n; - - debug_called(8); - - sp = malloc(sizeof(isc_session_t), M_ISCSI, M_WAITOK | M_ZERO); - if(sp == NULL) - return ENOMEM; - - sx_xlock(&sc->unit_sx); - if((n = alloc_unr(sc->unit)) < 0) { - sx_unlock(&sc->unit_sx); - free(sp, M_ISCSI); - xdebug("too many sessions!"); - return EPERM; - } - sx_unlock(&sc->unit_sx); - - mtx_lock(&sc->isc_mtx); - TAILQ_INSERT_TAIL(&sc->isc_sess, sp, sp_link); - isc->nsess++; - mtx_unlock(&sc->isc_mtx); - - sp->dev = make_dev(&iscsi_cdevsw, n, UID_ROOT, GID_WHEEL, 0600, "iscsi%d", n); - *ndev = sp->sid = n; - sp->isc = sc; - sp->dev->si_drv1 = sc; - sp->dev->si_drv2 = sp; - - sp->opt.maxRecvDataSegmentLength = 8192; - sp->opt.maxXmitDataSegmentLength = 8192; - sp->opt.maxBurstLength = 65536; // 64k - sp->opt.maxluns = ISCSI_MAX_LUNS; - - error = ism_start(sp); - - return error; -} - -#ifdef notused -static void -iscsi_counters(isc_session_t *sp) -{ - int h, r, s; - pduq_t *pq; - -#define _puke(i, pq) do {\ - debug(2, "%03d] %06x %02x %x %ld %jd %x\n",\ - i, ntohl( pq->pdu.ipdu.bhs.CmdSN), \ - pq->pdu.ipdu.bhs.opcode, ntohl(pq->pdu.ipdu.bhs.itt),\ - (long)pq->ts.sec, pq->ts.frac, pq->flags);\ - } while(0) - - h = r = s = 0; - TAILQ_FOREACH(pq, &sp->hld, pq_link) { - _puke(h, pq); - h++; - } - TAILQ_FOREACH(pq, &sp->rsp, pq_link) r++; - TAILQ_FOREACH(pq, &sp->csnd, pq_link) s++; - TAILQ_FOREACH(pq, &sp->wsnd, pq_link) s++; - TAILQ_FOREACH(pq, &sp->isnd, pq_link) s++; - debug(2, "hld=%d rsp=%d snd=%d", h, r, s); -} -#endif - -static void -iscsi_shutdown(void *v) -{ - struct isc_softc *sc = v; - isc_session_t *sp; - int n; - - debug_called(8); - if(sc == NULL) { - xdebug("sc is NULL!"); - return; - } -#ifdef DO_EVENTHANDLER - if(sc->eh == NULL) - debug(2, "sc->eh is NULL"); - else { - EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->eh); - debug(2, "done n=%d", sc->nsess); - } -#endif - n = 0; - TAILQ_FOREACH(sp, &sc->isc_sess, sp_link) { - debug(2, "%2d] sp->flags=0x%08x", n, sp->flags); - n++; - } - debug(2, "done"); -} - -static void -free_pdus(struct isc_softc *sc) -{ - debug_called(8); - - if(sc->pdu_zone != NULL) { - uma_zdestroy(sc->pdu_zone); - sc->pdu_zone = NULL; - } -} - -static int -iscsi_start(void) -{ - debug_called(8); - - isc = malloc(sizeof(struct isc_softc), M_ISCSI, M_ZERO|M_WAITOK); - mtx_init(&isc->isc_mtx, "iscsi-isc", NULL, MTX_DEF); - - TAILQ_INIT(&isc->isc_sess); - /* - | now init the free pdu list - */ - isc->pdu_zone = uma_zcreate("pdu", sizeof(pduq_t), - NULL, NULL, NULL, NULL, - 0, 0); - uma_zone_set_max(isc->pdu_zone, max_pdus); - isc->unit = new_unrhdr(0, max_sessions-1, NULL); - sx_init(&isc->unit_sx, "iscsi sx"); - -#ifdef DO_EVENTHANDLER - if((isc->eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, iscsi_shutdown, - sc, SHUTDOWN_PRI_DEFAULT-1)) == NULL) - xdebug("shutdown event registration failed\n"); -#endif - /* - | sysctl stuff - */ - sysctl_ctx_init(&isc->clist); - isc->oid = SYSCTL_ADD_NODE(&isc->clist, - SYSCTL_STATIC_CHILDREN(_net), - OID_AUTO, - "iscsi_initiator", - CTLFLAG_RD | CTLFLAG_MPSAFE, - 0, - "iSCSI Subsystem"); - - SYSCTL_ADD_STRING(&isc->clist, - SYSCTL_CHILDREN(isc->oid), - OID_AUTO, - "driver_version", - CTLFLAG_RD, - iscsi_driver_version, - 0, - "iscsi driver version"); - - SYSCTL_ADD_STRING(&isc->clist, - SYSCTL_CHILDREN(isc->oid), - OID_AUTO, - "isid", - CTLFLAG_RW, - isid, - 6+1, - "initiator part of the Session Identifier"); - - SYSCTL_ADD_INT(&isc->clist, - SYSCTL_CHILDREN(isc->oid), - OID_AUTO, - "sessions", - CTLFLAG_RD, - &isc->nsess, - sizeof(isc->nsess), - "number of active session"); - -#ifdef ISCSI_INITIATOR_DEBUG - mtx_init(&iscsi_dbg_mtx, "iscsi_dbg", NULL, MTX_DEF); -#endif - - isc->dev = make_dev_credf(MAKEDEV_CHECKNAME, &iscsi_cdevsw, max_sessions, - NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi"); - if (isc->dev == NULL) { - xdebug("iscsi_initiator: make_dev_credf failed"); - return (EEXIST); - } - isc->dev->si_drv1 = isc; - - printf("iscsi: version %s\n", iscsi_driver_version); - return (0); -} - -/* - | Notes: - | unload SHOULD fail if there is activity - | activity: there is/are active session/s - */ -static void -iscsi_stop(void) -{ - isc_session_t *sp, *sp_tmp; - - debug_called(8); - - /* - | go through all the sessions - | Note: close should have done this ... - */ - TAILQ_FOREACH_SAFE(sp, &isc->isc_sess, sp_link, sp_tmp) { - //XXX: check for activity ... - ism_stop(sp); - } - mtx_destroy(&isc->isc_mtx); - sx_destroy(&isc->unit_sx); - - free_pdus(isc); - - if(isc->dev) - destroy_dev(isc->dev); - - if(sysctl_ctx_free(&isc->clist)) - xdebug("sysctl_ctx_free failed"); - - iscsi_shutdown(isc); // XXX: check EVENTHANDLER_ ... - -#ifdef ISCSI_INITIATOR_DEBUG - mtx_destroy(&iscsi_dbg_mtx); -#endif - - free(isc, M_ISCSI); -} - -static int -iscsi_modevent(module_t mod, int what, void *arg) -{ - int error = 0; - - debug_called(8); - - switch(what) { - case MOD_LOAD: - error = iscsi_start(); - break; - - case MOD_QUIESCE: - if(isc->nsess) { - xdebug("iscsi module busy(nsess=%d), cannot unload", isc->nsess); - log(LOG_ERR, "iscsi module busy, cannot unload"); - } - return isc->nsess; - - case MOD_SHUTDOWN: - break; - - case MOD_UNLOAD: - iscsi_stop(); - break; - - default: - break; - } - return (error); -} - -moduledata_t iscsi_mod = { - "iscsi_initiator", - (modeventhand_t) iscsi_modevent, - 0 -}; - -#ifdef ISCSI_ROOT -static void -iscsi_rootconf(void) -{ -#if 0 - nfs_setup_diskless(); - if (nfs_diskless_valid) - rootdevnames[0] = "nfs:"; -#endif - printf("** iscsi_rootconf **\n"); -} - -SYSINIT(cpu_rootconf1, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, iscsi_rootconf, NULL) -#endif - -DECLARE_MODULE(iscsi_initiator, iscsi_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); -MODULE_DEPEND(iscsi_initiator, cam, 1, 1, 1); Index: sys/dev/iscsi_initiator/iscsi_subr.c =================================================================== --- sys/dev/iscsi_initiator/iscsi_subr.c +++ /dev/null @@ -1,603 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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: iscsi_subr.c 743 2009-08-08 10:54:53Z danny $ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_iscsi_initiator.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - | Interface to the SCSI layer - */ -void -iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq) -{ - union ccb *ccb = opq->ccb; - struct ccb_scsiio *csio = &ccb->csio; - pdu_t *opp = &opq->pdu; - bhs_t *bhp = &opp->ipdu.bhs; - r2t_t *r2t = &pq->pdu.ipdu.r2t; - pduq_t *wpq; - int error; - - debug_called(8); - sdebug(4, "itt=%x r2tSN=%d bo=%x ddtl=%x W=%d", ntohl(r2t->itt), - ntohl(r2t->r2tSN), ntohl(r2t->bo), ntohl(r2t->ddtl), opp->ipdu.scsi_req.W); - - switch(bhp->opcode) { - case ISCSI_SCSI_CMD: - if(opp->ipdu.scsi_req.W) { - data_out_t *cmd; - u_int ddtl = ntohl(r2t->ddtl); - u_int edtl = ntohl(opp->ipdu.scsi_req.edtlen); - u_int bleft, bs, dsn, bo; - caddr_t bp = csio->data_ptr; - - bo = ntohl(r2t->bo); - bp += MIN(bo, edtl - ddtl); - bleft = ddtl; - - if(sp->opt.maxXmitDataSegmentLength > 0) // danny's RFC - bs = MIN(sp->opt.maxXmitDataSegmentLength, ddtl); - else - bs = ddtl; - dsn = 0; - sdebug(4, "edtl=%x ddtl=%x bo=%x dsn=%x bs=%x maxX=%x", - edtl, ddtl, bo, dsn, bs, sp->opt.maxXmitDataSegmentLength); - while(bleft > 0) { - wpq = pdu_alloc(sp->isc, M_NOWAIT); // testing ... - if(wpq == NULL) { - sdebug(3, "itt=%x r2tSN=%d bo=%x ddtl=%x W=%d", ntohl(r2t->itt), - ntohl(r2t->r2tSN), ntohl(r2t->bo), ntohl(r2t->ddtl), opp->ipdu.scsi_req.W); - sdebug(1, "npdu_max=%d npdu_alloc=%d", sp->isc->npdu_max, sp->isc->npdu_alloc); - - while((wpq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) { - sdebug(2, "waiting..."); - pause("isc_r2t", 5*hz); - } - } - cmd = &wpq->pdu.ipdu.data_out; - cmd->opcode = ISCSI_WRITE_DATA; - cmd->lun[0] = r2t->lun[0]; - cmd->lun[1] = r2t->lun[1]; - cmd->ttt = r2t->ttt; - cmd->itt = r2t->itt; - - cmd->dsn = htonl(dsn); - cmd->bo = htonl(bo); - - cmd->F = (bs < bleft)? 0: 1; // is this the last one? - bs = MIN(bs, bleft); - - wpq->pdu.ds_len = bs; - wpq->pdu.ds_addr = bp; - - error = isc_qout(sp, wpq); - sdebug(6, "bs=%x bo=%x bp=%p dsn=%x error=%d", bs, bo, bp, dsn, error); - if(error) - break; - bo += bs; - bp += bs; - bleft -= bs; - dsn++; - } - } - break; - - default: - // XXX: should not happen ... - xdebug("huh? opcode=0x%x", bhp->opcode); - } -} - -static int -getSenseData(u_int status, union ccb *ccb, pduq_t *pq) -{ - pdu_t *pp = &pq->pdu; - struct ccb_scsiio *scsi = (struct ccb_scsiio *)ccb; - struct scsi_sense_data *sense = &scsi->sense_data; - struct mbuf *m = pq->mp; - scsi_rsp_t *cmd = &pp->ipdu.scsi_rsp; - caddr_t bp; - int sense_len, mustfree = 0; - int error_code, sense_key, asc, ascq; - - bp = mtod(pq->mp, caddr_t); - if((sense_len = scsi_2btoul(bp)) == 0) - return 0; - debug(4, "sense_len=%d", sense_len); - /* - | according to the specs, the sense data cannot - | be larger than 252 ... - */ - if(sense_len > m->m_len) { - bp = malloc(sense_len, M_ISCSI, M_WAITOK); - debug(3, "calling i_mbufcopy(len=%d)", sense_len); - i_mbufcopy(pq->mp, bp, sense_len); - mustfree++; - } - scsi->scsi_status = status; - - bcopy(bp+2, sense, min(sense_len, scsi->sense_len)); - scsi->sense_resid = 0; - if(cmd->flag & (BIT(1)|BIT(2))) - scsi->sense_resid = ntohl(pp->ipdu.scsi_rsp.rcnt); - scsi_extract_sense_len(sense, scsi->sense_len - scsi->sense_resid, - &error_code, &sense_key, &asc, &ascq, /*show_errors*/ 1); - - debug(3, "sense_len=%d rcnt=%d sense_resid=%d dsl=%d error_code=%x flags=%x", - sense_len, - ntohl(pp->ipdu.scsi_rsp.rcnt), scsi->sense_resid, - pp->ds_len, error_code, sense_key); - - if(mustfree) - free(bp, M_ISCSI); - - return 1; -} - -/* - | Some information is from SAM draft. - */ -static void -_scsi_done(isc_session_t *sp, u_int response, u_int status, union ccb *ccb, pduq_t *pq) -{ - struct ccb_hdr *ccb_h = &ccb->ccb_h; - - debug_called(8); - - if(status || response) { - sdebug(3, "response=%x status=%x ccb=%p pq=%p", response, status, ccb, pq); - if(pq != NULL) - sdebug(3, "mp=%p buf=%p len=%d", pq->mp, pq->buf, pq->len); - } - ccb_h->status = 0; - switch(response) { - case 0: // Command Completed at Target - switch(status) { - case 0: // Good, all is ok - ccb_h->status = CAM_REQ_CMP; - break; - - case 0x02: // Check Condition - if((pq != NULL) && (pq->mp != NULL) && getSenseData(status, ccb, pq)) - ccb_h->status |= CAM_AUTOSNS_VALID; - - case 0x14: // Intermediate-Condition Met - case 0x10: // Intermediate - case 0x04: // Condition Met - ccb_h->status |= CAM_SCSI_STATUS_ERROR; - break; - - case 0x08: - ccb_h->status = CAM_BUSY; - break; - - case 0x18: // Reservation Conflict - case 0x28: // Task Set Full - ccb_h->status = CAM_REQUEUE_REQ; - break; - default: - //case 0x22: // Command Terminated - //case 0x30: // ACA Active - //case 0x40: // Task Aborted - ccb_h->status = CAM_REQ_CMP_ERR; //CAM_REQ_ABORTED; - } - break; - - default: - if((response >= 0x80) && (response <= 0xFF)) { - // Vendor specific ... - } - case 1: // target failure - ccb_h->status = CAM_REQ_CMP_ERR; //CAM_REQ_ABORTED; - break; - } - sdebug(5, "ccb_h->status=%x", ccb_h->status); - - xpt_done(ccb); -} - -/* - | returns the lowest cmdseq that was not acked - */ -int -iscsi_requeue(isc_session_t *sp) -{ - pduq_t *pq; - u_int i, n, last; - - debug_called(8); - i = last = 0; - sp->flags |= ISC_HOLD; - while((pq = i_dqueue_hld(sp)) != NULL) { - i++; - if(pq->ccb != NULL) { - _scsi_done(sp, 0, 0x28, pq->ccb, NULL); - n = ntohl(pq->pdu.ipdu.bhs.CmdSN); - if(last==0 || (last > n)) - last = n; - sdebug(2, "last=%x n=%x", last, n); - } - pdu_free(sp->isc, pq); - } - sp->flags &= ~ISC_HOLD; - return i? last: sp->sn.cmd; -} - -int -i_pdu_flush(isc_session_t *sp) -{ - int n = 0; - pduq_t *pq; - - debug_called(8); - while((pq = i_dqueue_rsp(sp)) != NULL) { - pdu_free(sp->isc, pq); - n++; - } - while((pq = i_dqueue_rsv(sp)) != NULL) { - pdu_free(sp->isc, pq); - n++; - } - while((pq = i_dqueue_snd(sp, -1)) != NULL) { - pdu_free(sp->isc, pq); - n++; - } - while((pq = i_dqueue_hld(sp)) != NULL) { - pdu_free(sp->isc, pq); - n++; - } - while((pq = i_dqueue_wsnd(sp)) != NULL) { - pdu_free(sp->isc, pq); - n++; - } - if(n != 0) - xdebug("%d pdus recovered, should have been ZERO!", n); - return n; -} -/* - | called from ism_destroy. - */ -void -iscsi_cleanup(isc_session_t *sp) -{ - pduq_t *pq, *pqtmp; - - debug_called(8); - - TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, pqtmp) { - sdebug(3, "hld pq=%p", pq); - if(pq->ccb) - _scsi_done(sp, 1, 0x40, pq->ccb, NULL); - TAILQ_REMOVE(&sp->hld, pq, pq_link); - if(pq->buf) { - free(pq->buf, M_ISCSIBUF); - pq->buf = NULL; - } - pdu_free(sp->isc, pq); - } - while((pq = i_dqueue_snd(sp, BIT(0)|BIT(1)|BIT(2))) != NULL) { - sdebug(3, "pq=%p", pq); - if(pq->ccb) - _scsi_done(sp, 1, 0x40, pq->ccb, NULL); - if(pq->buf) { - free(pq->buf, M_ISCSIBUF); - pq->buf = NULL; - } - pdu_free(sp->isc, pq); - } - - wakeup(&sp->rsp); -} - -void -iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq) -{ - pdu_t *pp = &pq->pdu; - scsi_rsp_t *cmd = &pp->ipdu.scsi_rsp; - - debug_called(8); - - _scsi_done(sp, cmd->response, cmd->status, opq->ccb, pq); - - pdu_free(sp->isc, opq); -} - -// see RFC 3720, 10.9.1 page 146 -/* - | NOTE: - | the call to isc_stop_receiver is a kludge, - | instead, it should be handled by the userland controller, - | but that means that there should be a better way, other than - | sending a signal. Somehow, this packet should be supplied to - | the userland via read. - */ -void -iscsi_async(isc_session_t *sp, pduq_t *pq) -{ - pdu_t *pp = &pq->pdu; - async_t *cmd = &pp->ipdu.async; - - debug_called(8); - - sdebug(3, "asyncevent=0x%x asyncVCode=0x%0x", cmd->asyncEvent, cmd->asyncVCode); - switch(cmd->asyncEvent) { - case 0: // check status ... - break; - - case 1: // target request logout - isc_stop_receiver(sp); // XXX: temporary solution - break; - - case 2: // target indicates it wants to drop connection - isc_stop_receiver(sp); // XXX: temporary solution - break; - - case 3: // target indicates it will drop all connections. - isc_stop_receiver(sp); // XXX: temporary solution - break; - - case 4: // target request parameter negotiation - break; - - default: - break; - } -} - -void -iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq) -{ - union ccb *ccb = opq->ccb; - //reject_t *reject = &pq->pdu.ipdu.reject; - - debug_called(8); - //XXX: check RFC 10.17.1 (page 176) - ccb->ccb_h.status = CAM_REQ_ABORTED; - xpt_done(ccb); - - pdu_free(sp->isc, opq); -} - -/* - | deal with lun - */ -static int -dwl(isc_session_t *sp, int lun, u_char *lp) -{ - debug_called(8); - sdebug(4, "lun=%d", lun); - /* - | mapping LUN to iSCSI LUN - | check the SAM-2 specs - | hint: maxLUNS is a small number, cam's LUN is 32bits - | iSCSI is 64bits, scsi is ? - */ - // XXX: check if this will pass the endian test - if(lun < 256) { - lp[0] = 0; - lp[1] = lun; - } else - if(lun < 16384) { - lp[0] = (1 << 5) | ((lun >> 8) & 0x3f); - lp[1] = lun & 0xff; - } - else { - xdebug("lun %d: is unsupported!", lun); - return -1; - } - - return 0; -} - -/* - | encapsulate the scsi command and - */ -int -scsi_encap(struct cam_sim *sim, union ccb *ccb) -{ - isc_session_t *sp = cam_sim_softc(sim); - struct ccb_scsiio *csio = &ccb->csio; - struct ccb_hdr *ccb_h = &ccb->ccb_h; - pduq_t *pq; - scsi_req_t *cmd; - - debug_called(8); - - debug(4, "ccb->sp=%p", ccb_h->spriv_ptr0); - sp = ccb_h->spriv_ptr0; - - if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) { - debug(2, "ccb->sp=%p", ccb_h->spriv_ptr0); - sdebug(1, "pdu_alloc failed sc->npdu_max=%d npdu_alloc=%d", - sp->isc->npdu_max, sp->isc->npdu_alloc); - while((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) { - sdebug(2, "waiting..."); - pause("isc_encap", 5*hz); - } - } - cmd = &pq->pdu.ipdu.scsi_req; - cmd->opcode = ISCSI_SCSI_CMD; - cmd->F = 1; -#if 0 -// this breaks at least Isilon's iscsi target. - /* - | map tag option, default is UNTAGGED - */ - switch(csio->tag_action) { - case MSG_SIMPLE_Q_TAG: cmd->attr = iSCSI_TASK_SIMPLE; break; - case MSG_HEAD_OF_Q_TAG: cmd->attr = iSCSI_TASK_HOFQ; break; - case MSG_ORDERED_Q_TAG: cmd->attr = iSCSI_TASK_ORDER; break; - case MSG_ACA_TASK: cmd->attr = iSCSI_TASK_ACA; break; - } -#else - cmd->attr = iSCSI_TASK_SIMPLE; -#endif - - dwl(sp, ccb_h->target_lun, (u_char *)&cmd->lun); - - if((ccb_h->flags & CAM_CDB_POINTER) != 0) { - if((ccb_h->flags & CAM_CDB_PHYS) == 0) { - if(csio->cdb_len > 16) { - sdebug(3, "oversize cdb %d > 16", csio->cdb_len); - goto invalid; - } - } - else { - sdebug(3, "not phys"); - goto invalid; - } - } - - if(csio->cdb_len > sizeof(cmd->cdb)) - xdebug("guevalt! %d > %ld", csio->cdb_len, (long)sizeof(cmd->cdb)); - - memcpy(cmd->cdb, - ccb_h->flags & CAM_CDB_POINTER? csio->cdb_io.cdb_ptr: csio->cdb_io.cdb_bytes, - csio->cdb_len); - - cmd->W = (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT; - cmd->R = (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN; - cmd->edtlen = htonl(csio->dxfer_len); - - pq->ccb = ccb; - /* - | place it in the out queue - */ - if(isc_qout(sp, pq) == 0) - return 1; - invalid: - ccb->ccb_h.status = CAM_REQ_INVALID; - pdu_free(sp->isc, pq); - - return 0; -} - -int -scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq) -{ - union ccb *ccb = opq->ccb; - struct ccb_scsiio *csio = &ccb->csio; - pdu_t *opp = &opq->pdu; - bhs_t *bhp = &opp->ipdu.bhs; - - debug_called(8); - sdebug(6, "pq=%p opq=%p bhp->opcode=0x%x len=%d", - pq, opq, bhp->opcode, pq->pdu.ds_len); - if(ccb == NULL) { - sdebug(1, "itt=0x%x pq=%p opq=%p bhp->opcode=0x%x len=%d", - ntohl(pq->pdu.ipdu.bhs.itt), - pq, opq, bhp->opcode, pq->pdu.ds_len); - xdebug("%d] ccb == NULL!", sp->sid); - return 0; - } - if(pq->pdu.ds_len != 0) { - switch(bhp->opcode) { - case ISCSI_SCSI_CMD: { - scsi_req_t *cmd = &opp->ipdu.scsi_req; - sdebug(5, "itt=0x%x opcode=%x R=%d", - ntohl(pq->pdu.ipdu.bhs.itt), - pq->pdu.ipdu.bhs.opcode, cmd->R); - - switch(pq->pdu.ipdu.bhs.opcode) { - case ISCSI_READ_DATA: // SCSI Data in - { - caddr_t bp = NULL; // = mtod(pq->mp, caddr_t); - data_in_t *rcmd = &pq->pdu.ipdu.data_in; - - if(cmd->R) { - sdebug(5, "copy to=%p from=%p l1=%d l2=%d mp@%p", - csio->data_ptr, bp? mtod(pq->mp, caddr_t): 0, - ntohl(cmd->edtlen), pq->pdu.ds_len, pq->mp); - if(ntohl(cmd->edtlen) >= pq->pdu.ds_len) { - int offset, len = pq->pdu.ds_len; - - if(pq->mp != NULL) { - caddr_t dp; - - offset = ntohl(rcmd->bo); - dp = csio->data_ptr + offset; - i_mbufcopy(pq->mp, dp, len); - } - } - else { - xdebug("edtlen=%d < ds_len=%d", - ntohl(cmd->edtlen), pq->pdu.ds_len); - } - } - if(rcmd->S) { - /* - | contains also the SCSI Status - */ - _scsi_done(sp, 0, rcmd->status, opq->ccb, NULL); - return 0; - } else - return 1; - } - break; - } - } - default: - sdebug(3, "opcode=%02x", bhp->opcode); - break; - } - } - /* - | XXX: error ... - */ - return 1; -} Index: sys/dev/iscsi_initiator/iscsivar.h =================================================================== --- sys/dev/iscsi_initiator/iscsivar.h +++ /dev/null @@ -1,571 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005-2011 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. - * - * $FreeBSD$ - */ - -/* - | $Id: iscsivar.h 743 2009-08-08 10:54:53Z danny $ - */ -#include -#include - -#define ISCSI_MAX_LUNS 128 // don't touch this -#if ISCSI_MAX_LUNS > 8 -/* - | for this to work - | sysctl kern.cam.cam_srch_hi=1 - */ -#endif - -#ifndef ISCSI_INITIATOR_DEBUG -#define ISCSI_INITIATOR_DEBUG 1 -#endif - -#ifdef ISCSI_INITIATOR_DEBUG -extern int iscsi_debug; -#define debug(level, fmt, args...) do {if(level <= iscsi_debug)\ - printf("%s: " fmt "\n", __func__ , ##args);} while(0) -#define sdebug(level, fmt, args...) do {if(level <= iscsi_debug)\ - printf("%d] %s: " fmt "\n", sp->sid, __func__ , ##args);} while(0) -#define debug_called(level) do {if(level <= iscsi_debug)\ - printf("%s: called\n", __func__);} while(0) -#else -#define debug(level, fmt, args...) -#define debug_called(level) -#define sdebug(level, fmt, args...) -#endif /* ISCSI_INITIATOR_DEBUG */ - -#define xdebug(fmt, args...) printf(">>> %s: " fmt "\n", __func__ , ##args) - -#define MAX_SESSIONS ISCSI_MAX_TARGETS -#define MAX_PDUS (MAX_SESSIONS*256) // XXX: at the moment this is arbitrary - -typedef uint32_t digest_t(const void *, int len, uint32_t ocrc); - -MALLOC_DECLARE(M_ISCSI); -MALLOC_DECLARE(M_ISCSIBUF); - -#define ISOK2DIG(dig, pp) ((dig != NULL) && ((pp->ipdu.bhs.opcode & 0x1f) != ISCSI_LOGIN_CMD)) - -#ifndef BIT -#define BIT(n) (1 <<(n)) -#endif - -#define ISC_SM_RUN BIT(0) -#define ISC_SM_RUNNING BIT(1) - -#define ISC_LINK_UP BIT(2) -#define ISC_CON_RUN BIT(3) -#define ISC_CON_RUNNING BIT(4) -#define ISC_KILL BIT(5) -#define ISC_OQNOTEMPTY BIT(6) -#define ISC_OWAITING BIT(7) -#define ISC_FFPHASE BIT(8) - -#define ISC_CAMDEVS BIT(9) -#define ISC_SCANWAIT BIT(10) - -#define ISC_MEMWAIT BIT(11) -#define ISC_SIGNALED BIT(12) - -#define ISC_HOLD BIT(15) -#define ISC_HOLDED BIT(16) - -#define ISC_SHUTDOWN BIT(31) - -/* - | some stats - */ -struct i_stats { - int npdu; // number of pdus malloc'ed. - int nrecv; // unprocessed received pdus - int nsent; // sent pdus - - int nrsp, max_rsp; - int nrsv, max_rsv; - int ncsnd, max_csnd; - int nisnd, max_isnd; - int nwsnd, max_wsnd; - int nhld, max_hld; - - struct bintime t_sent; - struct bintime t_recv; -}; - -/* - | one per 'session' - */ - -typedef TAILQ_HEAD(, pduq) queue_t; - -typedef struct isc_session { - TAILQ_ENTRY(isc_session) sp_link; - int flags; - struct cdev *dev; - struct socket *soc; - struct file *fp; - struct thread *td; - - struct proc *proc; // the userland process - int signal; - struct proc *soc_proc; - struct proc *stp; // the sm thread - - struct isc_softc *isc; - - digest_t *hdrDigest; // the digest alg. if any - digest_t *dataDigest; // the digest alg. if any - - int sid; // Session ID - sn_t sn; // sequence number stuff; - int cws; // current window size - - int target_nluns; // this and target_lun are - // hopefully temporal till I - // figure out a better way. - int target_lun[ISCSI_MAX_LUNS/(sizeof(int)*8) + 1]; - - struct mtx rsp_mtx; - struct mtx rsv_mtx; - struct mtx snd_mtx; - struct mtx hld_mtx; - struct mtx io_mtx; - queue_t rsp; - queue_t rsv; - queue_t csnd; - queue_t isnd; - queue_t wsnd; - queue_t hld; - - isc_opt_t opt; // negotiable values - - struct i_stats stats; - bhs_t bhs; - struct uio uio; - struct iovec iov; - /* - | cam stuff - */ - struct cam_sim *cam_sim; - struct cam_path *cam_path; - struct mtx cam_mtx; - /* - | sysctl stuff - */ - struct sysctl_ctx_list clist; - struct sysctl_oid *oid; - int douio; //XXX: turn on/off uio on read -} isc_session_t; - -typedef struct pduq { - TAILQ_ENTRY(pduq) pq_link; - - caddr_t buf; - u_int len; // the total length of the pdu - pdu_t pdu; - union ccb *ccb; - - struct uio uio; - struct iovec iov[5]; // XXX: careful ... - struct mbuf *mp; - struct bintime ts; - queue_t *pduq; -} pduq_t; -/* - */ -struct isc_softc { - struct mtx isc_mtx; - TAILQ_HEAD(,isc_session) isc_sess; - int nsess; - struct cdev *dev; - char isid[6]; // Initiator Session ID (48 bits) - struct unrhdr *unit; - struct sx unit_sx; - - uma_zone_t pdu_zone; // pool of free pdu's - TAILQ_HEAD(,pduq) freepdu; - -#ifdef ISCSI_INITIATOR_DEBUG - int npdu_alloc, npdu_max; // for instrumentation -#endif -#ifdef DO_EVENTHANDLER - eventhandler_tag eh; -#endif - /* - | sysctl stuff - */ - struct sysctl_ctx_list clist; - struct sysctl_oid *oid; -}; - -#ifdef ISCSI_INITIATOR_DEBUG -extern struct mtx iscsi_dbg_mtx; -#endif - -void isc_start_receiver(isc_session_t *sp); -void isc_stop_receiver(isc_session_t *sp); - -int isc_sendPDU(isc_session_t *sp, pduq_t *pq); -int isc_qout(isc_session_t *sp, pduq_t *pq); -int i_prepPDU(isc_session_t *sp, pduq_t *pq); - -int ism_fullfeature(struct cdev *dev, int flag); - -int i_pdu_flush(isc_session_t *sc); -int i_setopt(isc_session_t *sp, isc_opt_t *opt); -void i_freeopt(isc_opt_t *opt); - -int ic_init(isc_session_t *sp); -void ic_destroy(isc_session_t *sp); -void ic_lost_target(isc_session_t *sp, int target); -int ic_getCamVals(isc_session_t *sp, iscsi_cam_t *cp); - -void ism_recv(isc_session_t *sp, pduq_t *pq); -int ism_start(isc_session_t *sp); -void ism_restart(isc_session_t *sp); -void ism_stop(isc_session_t *sp); - -int scsi_encap(struct cam_sim *sim, union ccb *ccb); -int scsi_decap(isc_session_t *sp, pduq_t *opq, pduq_t *pq); -void iscsi_r2t(isc_session_t *sp, pduq_t *opq, pduq_t *pq); -void iscsi_done(isc_session_t *sp, pduq_t *opq, pduq_t *pq); -void iscsi_reject(isc_session_t *sp, pduq_t *opq, pduq_t *pq); -void iscsi_async(isc_session_t *sp, pduq_t *pq); -void iscsi_cleanup(isc_session_t *sp); -int iscsi_requeue(isc_session_t *sp); - -// Serial Number Arithmetic -#define _MAXINCR 0x7FFFFFFF // 2 ^ 31 - 1 -#define SNA_GT(i1, i2) ((i1 != i2) && (\ - (i1 < i2 && i2 - i1 > _MAXINCR) ||\ - (i1 > i2 && i1 - i2 < _MAXINCR))?1: 0) - -/* - | inlines - */ -static __inline pduq_t * -pdu_alloc(struct isc_softc *isc, int wait) -{ - pduq_t *pq; - - pq = (pduq_t *)uma_zalloc(isc->pdu_zone, wait /* M_WAITOK or M_NOWAIT*/); - if(pq == NULL) { - debug(7, "out of mem"); - return NULL; - } -#ifdef ISCSI_INITIATOR_DEBUG - mtx_lock(&iscsi_dbg_mtx); - isc->npdu_alloc++; - if(isc->npdu_alloc > isc->npdu_max) - isc->npdu_max = isc->npdu_alloc; - mtx_unlock(&iscsi_dbg_mtx); -#endif - memset(pq, 0, sizeof(pduq_t)); - - return pq; -} - -static __inline void -pdu_free(struct isc_softc *isc, pduq_t *pq) -{ - if(pq->mp) - m_freem(pq->mp); -#ifdef NO_USE_MBUF - if(pq->buf != NULL) - free(pq->buf, M_ISCSIBUF); -#endif - uma_zfree(isc->pdu_zone, pq); -#ifdef ISCSI_INITIATOR_DEBUG - mtx_lock(&iscsi_dbg_mtx); - isc->npdu_alloc--; - mtx_unlock(&iscsi_dbg_mtx); -#endif -} - -static __inline void -i_nqueue_rsp(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->rsp_mtx); - if(++sp->stats.nrsp > sp->stats.max_rsp) - sp->stats.max_rsp = sp->stats.nrsp; - TAILQ_INSERT_TAIL(&sp->rsp, pq, pq_link); - mtx_unlock(&sp->rsp_mtx); -} - -static __inline pduq_t * -i_dqueue_rsp(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->rsp_mtx); - if((pq = TAILQ_FIRST(&sp->rsp)) != NULL) { - sp->stats.nrsp--; - TAILQ_REMOVE(&sp->rsp, pq, pq_link); - } - mtx_unlock(&sp->rsp_mtx); - - return pq; -} - -static __inline void -i_nqueue_rsv(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->rsv_mtx); - if(++sp->stats.nrsv > sp->stats.max_rsv) - sp->stats.max_rsv = sp->stats.nrsv; - TAILQ_INSERT_TAIL(&sp->rsv, pq, pq_link); - mtx_unlock(&sp->rsv_mtx); -} - -static __inline pduq_t * -i_dqueue_rsv(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->rsv_mtx); - if((pq = TAILQ_FIRST(&sp->rsv)) != NULL) { - sp->stats.nrsv--; - TAILQ_REMOVE(&sp->rsv, pq, pq_link); - } - mtx_unlock(&sp->rsv_mtx); - - return pq; -} - -static __inline void -i_nqueue_csnd(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->snd_mtx); - if(++sp->stats.ncsnd > sp->stats.max_csnd) - sp->stats.max_csnd = sp->stats.ncsnd; - TAILQ_INSERT_TAIL(&sp->csnd, pq, pq_link); - mtx_unlock(&sp->snd_mtx); -} - -static __inline pduq_t * -i_dqueue_csnd(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->snd_mtx); - if((pq = TAILQ_FIRST(&sp->csnd)) != NULL) { - sp->stats.ncsnd--; - TAILQ_REMOVE(&sp->csnd, pq, pq_link); - } - mtx_unlock(&sp->snd_mtx); - - return pq; -} - -static __inline void -i_nqueue_isnd(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->snd_mtx); - if(++sp->stats.nisnd > sp->stats.max_isnd) - sp->stats.max_isnd = sp->stats.nisnd; - TAILQ_INSERT_TAIL(&sp->isnd, pq, pq_link); - mtx_unlock(&sp->snd_mtx); -} - -static __inline pduq_t * -i_dqueue_isnd(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->snd_mtx); - if((pq = TAILQ_FIRST(&sp->isnd)) != NULL) { - sp->stats.nisnd--; - TAILQ_REMOVE(&sp->isnd, pq, pq_link); - } - mtx_unlock(&sp->snd_mtx); - - return pq; -} - -static __inline void -i_nqueue_wsnd(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->snd_mtx); - if(++sp->stats.nwsnd > sp->stats.max_wsnd) - sp->stats.max_wsnd = sp->stats.nwsnd; - TAILQ_INSERT_TAIL(&sp->wsnd, pq, pq_link); - mtx_unlock(&sp->snd_mtx); -} - -static __inline pduq_t * -i_dqueue_wsnd(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->snd_mtx); - if((pq = TAILQ_FIRST(&sp->wsnd)) != NULL) { - sp->stats.nwsnd--; - TAILQ_REMOVE(&sp->wsnd, pq, pq_link); - } - mtx_unlock(&sp->snd_mtx); - - return pq; -} - -static __inline pduq_t * -i_dqueue_snd(isc_session_t *sp, int which) -{ - pduq_t *pq; - - pq = NULL; - mtx_lock(&sp->snd_mtx); - if((which & BIT(0)) && (pq = TAILQ_FIRST(&sp->isnd)) != NULL) { - sp->stats.nisnd--; - TAILQ_REMOVE(&sp->isnd, pq, pq_link); - pq->pduq = &sp->isnd; // remember where you came from - } else - if((which & BIT(1)) && (pq = TAILQ_FIRST(&sp->wsnd)) != NULL) { - sp->stats.nwsnd--; - TAILQ_REMOVE(&sp->wsnd, pq, pq_link); - pq->pduq = &sp->wsnd; // remember where you came from - } else - if((which & BIT(2)) && (pq = TAILQ_FIRST(&sp->csnd)) != NULL) { - sp->stats.ncsnd--; - TAILQ_REMOVE(&sp->csnd, pq, pq_link); - pq->pduq = &sp->csnd; // remember where you came from - } - mtx_unlock(&sp->snd_mtx); - - return pq; -} - -static __inline void -i_rqueue_pdu(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->snd_mtx); - KASSERT(pq->pduq != NULL, ("pq->pduq is NULL")); - TAILQ_INSERT_TAIL(pq->pduq, pq, pq_link); - mtx_unlock(&sp->snd_mtx); -} - -/* - | Waiting for ACK (or something :-) - */ -static __inline void -i_nqueue_hld(isc_session_t *sp, pduq_t *pq) -{ - getbintime(&pq->ts); - mtx_lock(&sp->hld_mtx); - if(++sp->stats.nhld > sp->stats.max_hld) - sp->stats.max_hld = sp->stats.nhld; - TAILQ_INSERT_TAIL(&sp->hld, pq, pq_link); - mtx_unlock(&sp->hld_mtx); - return; -} - -static __inline void -i_remove_hld(isc_session_t *sp, pduq_t *pq) -{ - mtx_lock(&sp->hld_mtx); - sp->stats.nhld--; - TAILQ_REMOVE(&sp->hld, pq, pq_link); - mtx_unlock(&sp->hld_mtx); -} - -static __inline pduq_t * -i_dqueue_hld(isc_session_t *sp) -{ - pduq_t *pq; - - mtx_lock(&sp->hld_mtx); - if((pq = TAILQ_FIRST(&sp->hld)) != NULL) { - sp->stats.nhld--; - TAILQ_REMOVE(&sp->hld, pq, pq_link); - } - mtx_unlock(&sp->hld_mtx); - - return pq; -} - -static __inline pduq_t * -i_search_hld(isc_session_t *sp, int itt, int keep) -{ - pduq_t *pq, *tmp; - - pq = NULL; - - mtx_lock(&sp->hld_mtx); - TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) { - if(pq->pdu.ipdu.bhs.itt == itt) { - if(!keep) { - sp->stats.nhld--; - TAILQ_REMOVE(&sp->hld, pq, pq_link); - } - break; - } - } - mtx_unlock(&sp->hld_mtx); - - return pq; -} - -static __inline void -i_acked_hld(isc_session_t *sp, pdu_t *op) -{ - pduq_t *pq, *tmp; - u_int exp = sp->sn.expCmd; - - pq = NULL; - mtx_lock(&sp->hld_mtx); - TAILQ_FOREACH_SAFE(pq, &sp->hld, pq_link, tmp) { - if((op && op->ipdu.bhs.itt == pq->pdu.ipdu.bhs.itt) - || (pq->ccb == NULL - && (pq->pdu.ipdu.bhs.opcode != ISCSI_WRITE_DATA) - && SNA_GT(exp, ntohl(pq->pdu.ipdu.bhs.ExpStSN)))) { - sp->stats.nhld--; - TAILQ_REMOVE(&sp->hld, pq, pq_link); - pdu_free(sp->isc, pq); - } - } - mtx_unlock(&sp->hld_mtx); -} - -static __inline void -i_mbufcopy(struct mbuf *mp, caddr_t dp, int len) -{ - struct mbuf *m; - caddr_t bp; - - for(m = mp; m != NULL; m = m->m_next) { - bp = mtod(m, caddr_t); - /* - | the pdu is word (4 octed) aligned - | so len <= packet - */ - memcpy(dp, bp, MIN(len, m->m_len)); - dp += m->m_len; - len -= m->m_len; - if(len <= 0) - break; - } -} Index: sys/modules/Makefile =================================================================== --- sys/modules/Makefile +++ sys/modules/Makefile @@ -487,7 +487,6 @@ .if ${MK_ISCSI} != "no" || defined(ALL_MODULES) SUBDIR+= cfiscsi SUBDIR+= iscsi -SUBDIR+= iscsi_initiator .endif .if !empty(OPT_FDT) Index: sys/modules/iscsi_initiator/Makefile =================================================================== --- sys/modules/iscsi_initiator/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/iscsi_initiator -KMOD=iscsi_initiator - -SRCS= iscsi.h iscsivar.h -SRCS+= iscsi.c isc_cam.c isc_soc.c isc_sm.c isc_subr.c iscsi_subr.c -SRCS+= opt_cam.h opt_iscsi_initiator.h -SRCS+= bus_if.h device_if.h - -# Debugging -# CFLAGS+= -DISCSI_INITIATOR_DEBUG=9 - -.include Index: targets/pseudo/userland/Makefile.depend =================================================================== --- targets/pseudo/userland/Makefile.depend +++ targets/pseudo/userland/Makefile.depend @@ -88,7 +88,6 @@ sbin/ipf/ippool \ sbin/ipf/libipf \ sbin/ipfw \ - sbin/iscontrol \ sbin/kldconfig \ sbin/kldload \ sbin/kldstat \ Index: tools/build/mk/OptionalObsoleteFiles.inc =================================================================== --- tools/build/mk/OptionalObsoleteFiles.inc +++ tools/build/mk/OptionalObsoleteFiles.inc @@ -2717,13 +2717,10 @@ OLD_FILES+=etc/rc.d/iscsid OLD_FILES+=rescue/iscsictl OLD_FILES+=rescue/iscsid -OLD_FILES+=sbin/iscontrol OLD_FILES+=usr/bin/iscsictl OLD_FILES+=usr/sbin/iscsid OLD_FILES+=usr/share/man/man4/iscsi.4.gz -OLD_FILES+=usr/share/man/man4/iscsi_initiator.4.gz OLD_FILES+=usr/share/man/man5/iscsi.conf.5.gz -OLD_FILES+=usr/share/man/man8/iscontrol.8.gz OLD_FILES+=usr/share/man/man8/iscsictl.8.gz OLD_FILES+=usr/share/man/man8/iscsid.8.gz .endif Index: usr.bin/iscsictl/iscsi.conf.5 =================================================================== --- usr.bin/iscsictl/iscsi.conf.5 +++ usr.bin/iscsictl/iscsi.conf.5 @@ -35,9 +35,7 @@ .Nm configuration file is used by the .Xr iscsictl 8 -and -.Xr iscontrol 8 -utilities. +utility. The general syntax is: .Bf Li .Bd -literal @@ -189,7 +187,6 @@ } .Ed .Sh SEE ALSO -.Xr iscontrol 8 , .Xr iscsictl 8 .\"Sh HISTORY .\"Sh AUTHORS Index: usr.bin/iscsictl/iscsictl.8 =================================================================== --- usr.bin/iscsictl/iscsictl.8 +++ usr.bin/iscsictl/iscsictl.8 @@ -169,21 +169,6 @@ the .Xr iscsid 8 daemon must be running. -.Pp -Also note that -.Fx -currently supports two different initiators: the old one, -.Xr iscsi_initiator 4 , -with its control utility -.Xr iscontrol 8 , -and the new one, -.Xr iscsi 4 , -with -.Nm -and -.Xr iscsid 8 . -The only thing the two have in common is the configuration file, -.Xr iscsi.conf 5 . .Sh FILES .Bl -tag -width ".Pa /etc/iscsi.conf" -compact .It Pa /etc/iscsi.conf