+ add support for IPv6 in the target (CIDR scoping has still to be

implemented for IPv6, but works fine for IPv4)

+ now poll any connections opened in the target.  select is used if
poll is not available

+ remove ramdisk type of backing store, since it was never used, and
is of no use for our needs

+ bump version to 20060727
This commit is contained in:
agc 2006-08-03 20:21:59 +00:00
parent a6fd778155
commit 66644e0749
17 changed files with 389 additions and 245 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: conffile.h,v 1.2 2006/03/20 20:25:42 agc Exp $ */
/* $NetBSD: conffile.h,v 1.3 2006/08/03 20:21:59 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -34,6 +34,9 @@
#include <sys/param.h>
#include <stdio.h>
#include <time.h>
#include "defs.h"
DEFINE_ARRAY(strv_t, char *);

View File

@ -34,6 +34,12 @@
/* Define to 1 if you have the `fsync_range' function. */
#define HAVE_FSYNC_RANGE 1
/* Define to 1 if you have the `getaddrinfo' function. */
#define HAVE_GETADDRINFO 1
/* Define to 1 if you have the `getnameinfo' function. */
#define HAVE_GETNAMEINFO 1
/* Define to 1 if you have the `htobe64' function. */
/* #undef HAVE_HTOBE64 */
@ -70,6 +76,12 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#define HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1
/* Define to 1 if you have the <poll.h> header file. */
#define HAVE_POLL_H 1
/* Define to 1 if you have the <pthread.h> header file. */
#define HAVE_PTHREAD_H 1
@ -124,6 +136,9 @@
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
@ -179,13 +194,13 @@
#define PACKAGE_NAME "netbsd-iscsi"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "netbsd-iscsi 20060529"
#define PACKAGE_STRING "netbsd-iscsi 20060727"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "netbsd-iscsi"
/* Define to the version of this package. */
#define PACKAGE_VERSION "20060529"
#define PACKAGE_VERSION "20060727"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

View File

@ -33,6 +33,12 @@
/* Define to 1 if you have the `fsync_range' function. */
#undef HAVE_FSYNC_RANGE
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getnameinfo' function. */
#undef HAVE_GETNAMEINFO
/* Define to 1 if you have the `htobe64' function. */
#undef HAVE_HTOBE64
@ -69,6 +75,12 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */
#undef HAVE_NETINET_TCP_H
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the <poll.h> header file. */
#undef HAVE_POLL_H
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
@ -123,6 +135,9 @@
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H

View File

@ -116,11 +116,17 @@ typedef struct iscsi_target_t {
DEFINE_ARRAY(strv_t, char *);
enum {
ISCSI_IPv4 = AF_INET,
ISCSI_IPv6 = AF_INET6,
ISCSI_UNSPEC = PF_UNSPEC
};
/**********
* Public *
**********/
int initiator_init(const char *, const char *, int, int, int);
int initiator_init(const char *, int, const char *, int, int, int);
int initiator_info(char *, int, int);
int initiator_command(initiator_cmd_t *);
int initiator_enqueue(initiator_cmd_t *);

View File

@ -51,9 +51,13 @@
enum {
MAX_TGT_NAME_SIZE = 512,
MAX_INITIATOR_ADDRESS_SIZE = 256,
MAX_CONFIG_FILE_NAME = 512,
ISCSI_IPv4 = 4,
ISCSI_IPv6 = 6
ISCSI_IPv4 = AF_INET,
ISCSI_IPv6 = AF_INET6,
ISCSI_UNSPEC = PF_UNSPEC,
MAXSOCK = 8
};
/* global variables, moved from target.c */
@ -61,15 +65,20 @@ typedef struct globals_t {
char targetname[MAX_TGT_NAME_SIZE]; /* name of target */
uint16_t port; /* target port */
iscsi_socket_t sock; /* socket on which it's listening */
int sockc; /* # of live sockets on which it's listening */
iscsi_socket_t sockv[MAXSOCK]; /* sockets on which it's listening */
int famv[MAXSOCK]; /* address families */
int state; /* current state of target */
int listener_pid; /* PID on which it's listening */
volatile int listener_listening; /* whether a listener is listening */
char targetaddress[MAX_TGT_NAME_SIZE]; /* iSCSI TargetAddress set after iscsi_sock_accept() */
targv_t *tv; /* array of target devices */
int address_family; /* IP address family */
int address_family; /* global default IP address family */
int max_sessions; /* maximum number of sessions */
char config_file[MAX_CONFIG_FILE_NAME]; /* config file name */
} globals_t;
/* session parameters */
typedef struct target_session_t {
int id;
int d;
@ -91,7 +100,7 @@ typedef struct target_session_t {
iscsi_sess_param_t sess_params;
char initiator[MAX_INITIATOR_ADDRESS_SIZE];
int address_family;
} target_session_t;
} target_session_t;
typedef struct target_cmd_t {
iscsi_scsi_cmd_args_t *scsi_cmd;

View File

@ -70,7 +70,6 @@
#include <syslog.h>
#endif
/*
*
*/
@ -293,6 +292,9 @@ typedef int iscsi_socket_t;
#define ISCSI_SOCK_MSG_BYTE_ALIGN 4
int iscsi_sock_create(iscsi_socket_t * );
int iscsi_socks_establish(iscsi_socket_t *, int *, int *, int);
int iscsi_waitfor_connection(iscsi_socket_t *, int, const char *cf, iscsi_socket_t *);
const char *iscsi_address_family(int);
int iscsi_sock_setsockopt(iscsi_socket_t * , int , int , void *, unsigned );
int iscsi_sock_getsockopt(iscsi_socket_t * , int , int , void *, unsigned *);
int iscsi_sock_bind(iscsi_socket_t , int );

14
dist/iscsi/src/TODO vendored
View File

@ -1,7 +1,15 @@
To do
=====
cmdline fs or fsmmap
add kevent
add HUP support to read sig and targets file
CRC/digests
finish reservations
VPD 80 handling
RAID 1 rebuilding, breaking etc
bind to cmdline port properly now too
proper allow_netmask support for IPv6
add ability to add a target in, take one out (if !busy)
proper IPv6 support in harness
Done
====
@ -35,3 +43,7 @@ add uuid
Solaris initiator compatibility
fix 64-byte swapping macros
add reservations - RESERVE_6 and RELEASE_6 done
pass addr family in sess structure
add poll configure glue
use poll if we have it
proper IPv6 support in target

View File

@ -1,4 +1,4 @@
/* $NetBSD: conffile.c,v 1.3 2006/05/13 22:50:24 christos Exp $ */
/* $NetBSD: conffile.c,v 1.4 2006/08/03 20:21:59 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -29,6 +29,7 @@
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>

View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for netbsd-iscsi 20060529.
# Generated by GNU Autoconf 2.59 for netbsd-iscsi 20060727.
#
# Report bugs to <Alistair Crooks <agc@NetBSD.org>>.
#
@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='netbsd-iscsi'
PACKAGE_TARNAME='netbsd-iscsi'
PACKAGE_VERSION='20060529'
PACKAGE_STRING='netbsd-iscsi 20060529'
PACKAGE_VERSION='20060727'
PACKAGE_STRING='netbsd-iscsi 20060727'
PACKAGE_BUGREPORT='Alistair Crooks <agc@NetBSD.org>'
ac_unique_file="iscsi.c"
@ -780,7 +780,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures netbsd-iscsi 20060529 to adapt to many kinds of systems.
\`configure' configures netbsd-iscsi 20060727 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -837,7 +837,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of netbsd-iscsi 20060529:";;
short | recursive ) echo "Configuration of netbsd-iscsi 20060727:";;
esac
cat <<\_ACEOF
@ -949,7 +949,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
netbsd-iscsi configure 20060529
netbsd-iscsi configure 20060727
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@ -963,7 +963,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by netbsd-iscsi $as_me 20060529, which was
It was created by netbsd-iscsi $as_me 20060727, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@ -3069,7 +3069,8 @@ done
for ac_header in arpa/inet.h netinet/in.h netinet/tcp.h netdb.h
for ac_header in arpa/inet.h netinet/in.h netinet/tcp.h netdb.h poll.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@ -3224,7 +3225,8 @@ done
for ac_header in asm/byteorder.h sys/bswap.h sys/byteorder.h libkern/OSByteOrder.h byteswap.h machine/endian.h
for ac_header in asm/byteorder.h sys/bswap.h sys/byteorder.h sys/select.h libkern/OSByteOrder.h byteswap.h machine/endian.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@ -4159,7 +4161,10 @@ fi
for ac_func in __bswap64 asprintf asnprintf bswap64 daemon htobe64 fsync_range snprintf strlcpy strtoll syslog uuid_create uuid_to_string vasprintf vasnprintf vsnprintf
for ac_func in __bswap64 asprintf asnprintf bswap64 daemon fsync_range getaddrinfo getnameinfo htobe64 poll snprintf strlcpy strtoll syslog uuid_create uuid_to_string vasprintf vasnprintf vsnprintf
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
@ -4624,7 +4629,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
This file was extended by netbsd-iscsi $as_me 20060529, which was
This file was extended by netbsd-iscsi $as_me 20060727, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -4684,7 +4689,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
netbsd-iscsi config.status 20060529
netbsd-iscsi config.status 20060727
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT([netbsd-iscsi],[20060529],[Alistair Crooks <agc@NetBSD.org>])
AC_INIT([netbsd-iscsi],[20060727],[Alistair Crooks <agc@NetBSD.org>])
AC_CONFIG_SRCDIR([iscsi.c])
AC_CONFIG_HEADER(../include/config.h)
@ -12,8 +12,8 @@ AC_PROG_RANLIB
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/types.h sys/param.h sys/stat.h sys/time.h sys/mman.h sys/uio.h sys/socket.h sys/time.h sys/vfs.h)
AC_CHECK_HEADERS(arpa/inet.h netinet/in.h netinet/tcp.h netdb.h)
AC_CHECK_HEADERS(asm/byteorder.h sys/bswap.h sys/byteorder.h libkern/OSByteOrder.h byteswap.h machine/endian.h)
AC_CHECK_HEADERS(arpa/inet.h netinet/in.h netinet/tcp.h netdb.h poll.h)
AC_CHECK_HEADERS(asm/byteorder.h sys/bswap.h sys/byteorder.h sys/select.h libkern/OSByteOrder.h byteswap.h machine/endian.h)
AC_CHECK_HEADERS(ctype.h errno.h fcntl.h pthread.h pwd.h signal.h stdlib.h syslog.h unistd.h string.h stdarg.h utime.h uuid.h)
dnl Checks for typedefs, structures, and compiler characteristics.
@ -34,7 +34,7 @@ AC_CHECK_LIB(socket, connect)
AC_CHECK_LIB(resolv, inet_aton)
dnl Check for functionality
AC_CHECK_FUNCS(__bswap64 asprintf asnprintf bswap64 daemon htobe64 fsync_range snprintf strlcpy strtoll syslog uuid_create uuid_to_string vasprintf vasnprintf vsnprintf)
AC_CHECK_FUNCS(__bswap64 asprintf asnprintf bswap64 daemon fsync_range getaddrinfo getnameinfo htobe64 poll snprintf strlcpy strtoll syslog uuid_create uuid_to_string vasprintf vasnprintf vsnprintf)
dnl that's it for now...
AC_OUTPUT(Makefile)

88
dist/iscsi/src/disk.c vendored
View File

@ -1,4 +1,4 @@
/* $NetBSD: disk.c,v 1.19 2006/05/31 19:53:13 agc Exp $ */
/* $NetBSD: disk.c,v 1.20 2006/08/03 20:21:59 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -126,14 +126,6 @@
#include "defs.h"
#include "storage.h"
/*
* Begin disk configuration. If we're operating in filesystem mode, then the
* file /tmp/<targetname>_<iscsi port>_iscsi_disk_lun_x is created for each
* lun x. You can create symbolic links in /tmp to point to devices in /dev.
* For example, "ln -s /dev/sda /tmp/mytarget_3260_iscsi_disk_lun_0." If
* we're operating in ramdisk mode, then each lun is its own ramdisk.
*/
#define CONFIG_DISK_NUM_LUNS_DFLT 1
#define CONFIG_DISK_BLOCK_LEN_DFLT 512
#define CONFIG_DISK_NUM_BLOCKS_DFLT 204800
@ -146,25 +138,28 @@
* Globals
*/
enum {
ISCSI_RAMDISK = 0x01,
MAX_RESERVATIONS = 32,
ISCSI_FS_MMAP = 0x02,
ISCSI_FS = 0x03
};
#define MB(x) ((x) * 1024 * 1024)
/* this struct describes an iscsi disk */
typedef struct iscsi_disk_t {
int type;
uint8_t *ramdisk[CONFIG_DISK_MAX_LUNS];
char filename[MAXPATHLEN];
uint8_t buffer[CONFIG_DISK_MAX_LUNS][MB(1)];
uint64_t blockc;
uint64_t blocklen;
uint64_t luns;
uint64_t size;
uuid_t uuid;
char *uuid_string;
targv_t *tv;
int type; /* type of disk - fs/mmap and fs */
char filename[MAXPATHLEN]; /* filename for the disk itself */
uint8_t buffer[CONFIG_DISK_MAX_LUNS][MB(1)]; /* buffer for fs and fs/mmap options */
uint64_t blockc; /* # of blocks */
uint64_t blocklen; /* block size */
uint64_t luns; /* # of luns */
uint64_t size; /* size of complete disk */
uuid_t uuid; /* disk's uuid */
char *uuid_string; /* uuid string */
targv_t *tv; /* the component devices and extents */
uint32_t resc; /* # of reservation keys */
uint64_t reskeys[MAX_RESERVATIONS]; /* the reservation keys */
} iscsi_disk_t;
DEFINE_ARRAY(disks_t, iscsi_disk_t);
@ -185,8 +180,8 @@ disk/extent code
* Private Interface
*/
static int disk_read(target_session_t * , iscsi_scsi_cmd_args_t * , uint32_t , uint16_t , uint8_t );
static int disk_write(target_session_t * , iscsi_scsi_cmd_args_t * , uint8_t , uint32_t , uint32_t );
static int disk_read(target_session_t * , iscsi_scsi_cmd_args_t * , uint32_t , uint16_t , uint8_t);
static int disk_write(target_session_t * , iscsi_scsi_cmd_args_t * , uint8_t , uint32_t , uint32_t);
/* return the de index and offset within the device for RAID0 */
static int
@ -334,7 +329,7 @@ extent_fsync_range(disc_extent_t *xp, int how, off_t from, off_t len)
#endif
}
/* (recursively) lseek on the device's devices */
/* (recursively) fsync_range on the device's devices */
static int
device_fsync_range(disc_device_t *dp, int how, off_t from, off_t len)
{
@ -902,30 +897,19 @@ device_init(globals_t *gp, targv_t *tvp, disc_target_t *tp)
disks.v[disks.c].luns,
(disks.v[disks.c].luns == 1) ? "" : "s",
disks.v[disks.c].blockc, disks.v[disks.c].blocklen,
(disks.v[disks.c].type == ISCSI_FS) ? "iscsi fs" :
(disks.v[disks.c].type == ISCSI_FS_MMAP) ? "iscsi fs mmap" : "iscsi ramdisk");
(disks.v[disks.c].type == ISCSI_FS) ? "iscsi fs" : "iscsi fs mmap");
for (i = 0; i < disks.v[disks.c].luns; i++) {
printf("DISK: LUN %d: ", i);
if (disks.v[disks.c].type == ISCSI_RAMDISK) {
if ((disks.v[disks.c].ramdisk[i] = iscsi_malloc((unsigned)disks.v[disks.c].size)) == NULL) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_malloc() failed\n");
return -1;
}
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "allocated %" PRIu64 " bytes at %p\n", disks.v[disks.c].size, disks.v[disks.c].ramdisk[i]);
printf("%" PRIu64 " MB ramdisk\n", disks.v[disks.c].size / MB(1));
} else {
(void) strlcpy(disks.v[disks.c].filename, disc_get_filename(&tp->de), sizeof(disks.v[disks.c].filename));
if (de_open(&tp->de, O_CREAT | O_RDWR, 0666) == -1) {
iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\"\n", disks.v[disks.c].filename);
return -1;
}
if (!allocate_space(tp)) {
iscsi_trace_error(__FILE__, __LINE__, "error allocating space for \"%s\"", tp->target);
return -1;
}
printf("%" PRIu64 " MB disk storage for \"%s\"\n", (de_getsize(&tp->de) / MB(1)), tp->target);
(void) strlcpy(disks.v[disks.c].filename, disc_get_filename(&tp->de), sizeof(disks.v[disks.c].filename));
if (de_open(&tp->de, O_CREAT | O_RDWR, 0666) == -1) {
iscsi_trace_error(__FILE__, __LINE__, "error opening \"%s\"\n", disks.v[disks.c].filename);
return -1;
}
if (!allocate_space(tp)) {
iscsi_trace_error(__FILE__, __LINE__, "error allocating space for \"%s\"", tp->target);
return -1;
}
printf("%" PRIu64 " MB disk storage for \"%s\"\n", (de_getsize(&tp->de) / MB(1)), tp->target);
}
return disks.c++;
}
@ -1234,14 +1218,6 @@ device_command(target_session_t * sess, target_cmd_t * cmd)
int
device_shutdown(target_session_t *sess)
{
int i;
if (disks.v[sess->d].type == ISCSI_RAMDISK) {
for (i = 0; i < disks.v[sess->d].luns; i++) {
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "freeing ramdisk[%d] (%p)\n", i, disks.v[sess->d].ramdisk[i]);
iscsi_free(disks.v[sess->d].ramdisk[i]);
}
}
return 1;
}
@ -1263,9 +1239,6 @@ disk_write(target_session_t *sess, iscsi_scsi_cmd_args_t *args, uint8_t lun, uin
/* Assign ptr for write data */
switch(disks.v[sess->d].type) {
case ISCSI_RAMDISK:
ptr = disks.v[sess->d].ramdisk[lun] + (int) byte_offset;
break;
case ISCSI_FS:
RETURN_GREATER("num_bytes (FIX ME)", (unsigned) num_bytes, MB(1), NO_CLEANUP, -1);
ptr = disks.v[sess->d].buffer[lun];
@ -1348,9 +1321,6 @@ disk_read(target_session_t * sess, iscsi_scsi_cmd_args_t * args, uint32_t lba, u
return -1;
}
switch (disks.v[sess->d].type) {
case ISCSI_RAMDISK:
ptr = disks.v[sess->d].ramdisk[lun] + (int)byte_offset;
break;
case ISCSI_FS:
RETURN_GREATER("num_bytes (FIX ME)", (unsigned) num_bytes, MB(1), NO_CLEANUP, -1);
ptr = disks.v[sess->d].buffer[lun];

View File

@ -681,7 +681,7 @@ full_feature_phase(initiator_session_t * sess)
}
int
initiator_init(const char *hostname, const char *user, int auth_type, int mutual_auth, int digest_type)
initiator_init(const char *hostname, int address_family, const char *user, int auth_type, int mutual_auth, int digest_type)
{
int i;
initiator_session_t *sess = NULL;
@ -1269,30 +1269,17 @@ tx_worker_proc_i(void *arg)
ISCSI_LOCK(&me->work_mutex, return -1);
/*
* The Rx thread will receive a response for the
* command and execute the
*/
/*
* callback. We need to make sure the callback
* function is not executed
*/
/*
* before the Tx thread has completed sending the
* command. This is what
*/
/*
* tx_done is used for. The last step is to set
* tx_done and signal the
*/
/*
* Rx thread, which may be block on the condition.
* NOP_OUT (without ping)
*/
/*
* will have no response for the Rx thread to process
* - so we execute
*/
/* the callback directly. */
* The Rx thread will receive a response for
* the command and execute the callback. We
* need to make sure the callback function is
* not executed before the Tx thread has
* completed sending the command. This is
* what tx_done is used for. The last step is
* to set tx_done and signal the Rx thread,
* which may be block on the condition.
* NOP_OUT (without ping) will have no
* response for the Rx thread to process - so
* we execute the callback directly. */
if ((cmd->type == ISCSI_NOP_OUT) && (((iscsi_nop_out_args_t *) (cmd->ptr))->tag == 0xffffffff)) {
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "executing callback() function directly for NOP_OUT (no NOP_IN)\n");
@ -1674,20 +1661,12 @@ login_phase_i(initiator_session_t * sess, char *text, int text_len)
do {
/*
* Build login command. Note that the <length> and <text>
* fields may get
*/
/*
* updated by login_response_i. Such is the case when we
* receive offers
*/
/*
* from the target. The new <length> and <text> fields will
* represent
*/
/*
* the response that we need to send to the target on the
* next login.
* Build login command. Note that the <length> and
* <text> fields may get updated by login_response_i.
* Such is the case when we receive offers from the
* target. The new <length> and <text> fields will
* represent the response that we need to send to the
* target on the next login.
*/
login_cmd->cont = 0;
@ -2124,14 +2103,10 @@ nop_out_i(initiator_cmd_t * cmd)
if (nop_out->tag != 0xffffffff) {
/*
* Insert cmd into the hash table, keyed by nop_out->tag.
* Upon receipt of the
*/
/*
* NOP_IN_T, the Rx thread will retreive the cmd ptr using
* the tag from the
*/
/* NOP_IN_T PDU. */
* Insert cmd into the hash table, keyed by
* nop_out->tag. Upon receipt of the NOP_IN_T, the Rx
* thread will retreive the cmd ptr using the tag from
* the NOP_IN_T PDU. */
if (hash_insert(&g_tag_hash, cmd, nop_out->tag) != 0) {
iscsi_trace_error(__FILE__, __LINE__, "hash_insert() failed\n");
@ -2148,18 +2123,12 @@ nop_out_i(initiator_cmd_t * cmd)
return -1;
}
/*
* We need to make a copy of nop_out->length and save in the variable
* length. Otherwise,
*/
/*
* we may get a seg fault - as if this is a NOP_OUT without ping, the
* Tx thread will
*/
/*
* issue the callback function immediately after we return - thereby
* unallocating the
*/
/* NOP_OUT and initiator command structures. */
* We need to make a copy of nop_out->length and save in the
* variable length. Otherwise, we may get a seg fault - as if
* this is a NOP_OUT without ping, the Tx thread will issue
* the callback function immediately after we return - thereby
* de-allocating the NOP_OUT and initiator command structures.
* */
if ((rc = iscsi_sock_send_header_and_data(sess->sock, header, ISCSI_HEADER_LEN, nop_out->data,
length, 0)) != ISCSI_HEADER_LEN + length) {
@ -2250,10 +2219,9 @@ scsi_command_i(initiator_cmd_t * cmd)
goto error;
}
/*
* If we're sending any immediate data, we need to make a new iovec
* that
*/
/* contains only the immediata data (a subset of the original iovec). */
* If we're sending any immediate data, we need to make a new
* iovec that contains only the immediata data (a subset of
* the original iovec). */
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sending command PDU with %u bytes immediate data\n", scsi_cmd->length);
if (scsi_cmd->length && sess->sess_params.immediate_data) {
if ((sg_copy = iscsi_malloc_atomic(sg_len * sizeof(struct iovec))) == NULL) {
@ -2304,12 +2272,9 @@ scsi_command_i(initiator_cmd_t * cmd)
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "command PDU sent with %u bytes immediate data (%u bytes AHS)\n", scsi_cmd->length, scsi_cmd->ahs_len);
/*
* Send data PDUS if 1) we're not in R2T mode and 2) we haven't sent
* everything as immediate
*/
/*
* data and 3) we have not reached the first burst when sending
* immediate data
* Send data PDUS if 1) we're not in R2T mode and 2) we
* haven't sent everything as immediate data and 3) we have
* not reached the first burst when sending immediate data
*/
if (scsi_cmd->output
&& (!sess->sess_params.initial_r2t)
@ -2658,12 +2623,9 @@ scsi_r2t_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *header)
int sg_len, sg_len_copy, sg_len_which;
int fragment_flag;
/* Make sure an initiator_cmd_t was specified, that it has a callback */
/*
* function specified and that it also has a iscsi_scsi_cmd_args_t
* associated
*/
/* with it. */
/* Make sure an initiator_cmd_t was specified, that it has a
* callback function specified and that it also has a
* iscsi_scsi_cmd_args_t associated with it. */
if (cmd) {
if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) {
@ -2799,12 +2761,9 @@ scsi_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *head
iscsi_scsi_cmd_args_t *scsi_cmd;
iscsi_scsi_rsp_t scsi_rsp;
/* Make sure an initiator_cmd_t was specified, that it has a callback */
/*
* function specified and that it also has a iscsi_scsi_cmd_args_t
* associated
*/
/* with it. */
/* Make sure an initiator_cmd_t was specified, that it has a
* callback function specified and that it also has a
* iscsi_scsi_cmd_args_t associated with it. */
if (cmd) {
if ((scsi_cmd = (iscsi_scsi_cmd_args_t *) cmd->ptr) == NULL) {
@ -2820,10 +2779,8 @@ scsi_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *head
}
/*
* Read SCSI response and check return args. Those marked "FIX ME"
* are not
*/
/* yet implemented. */
* Read SCSI response and check return args. Those marked
* "FIX ME" are not yet implemented. */
if (iscsi_scsi_rsp_decap(header, &scsi_rsp) != 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_scsi_rsp_decap() failed\n");
@ -2848,9 +2805,7 @@ scsi_response_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *head
}
/*
* Make sure all data was successfully transferred if command
* completed successfully,
*/
/* otherwise read sense data. */
* completed successfully, otherwise read sense data. */
if (scsi_rsp.status == 0) {
if (scsi_cmd->output) {
@ -2917,12 +2872,9 @@ scsi_read_data_i(initiator_session_t * sess, initiator_cmd_t * cmd, uint8_t *hea
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "processing read data\n");
/* Make sure an initiator_cmd_t was specified, that it has a callback */
/*
* function specified and that it also has a iscsi_scsi_cmd_args_t
* associated
*/
/* with it. */
/* Make sure an initiator_cmd_t was specified, that it has a
* callback function specified and that it also has a
* iscsi_scsi_cmd_args_t associated with it. */
if (cmd) {
if (cmd->type != ISCSI_SCSI_CMD) {

View File

@ -72,6 +72,7 @@ main(int argc, char **argv)
char hostname[1024];
char *host;
char *user;
int address_family;
int tgtlo = 0;
int tgthi = CONFIG_INITIATOR_NUM_TARGETS;
int target = -1;
@ -89,10 +90,17 @@ main(int argc, char **argv)
(void) gethostname(host = hostname, sizeof(hostname));
digest_type = DigestNone;
auth_type = AuthNone;
address_family = ISCSI_UNSPEC;
mutual_auth = 0;
while ((i = getopt(argc, argv, "a:d:h:l:n:t:u:V")) != -1) {
while ((i = getopt(argc, argv, "46a:d:h:l:n:t:u:V")) != -1) {
switch(i) {
case '4':
address_family = ISCSI_IPv4;
break;
case '6':
address_family = ISCSI_IPv6;
break;
case 'a':
if (strcasecmp(optarg, "chap") == 0) {
auth_type = AuthCHAP;
@ -152,7 +160,7 @@ main(int argc, char **argv)
tgthi = target + 1;
}
if (argc == 1) {
(void) fprintf(stderr, "usage: %s [-V] [-a auth-type] [-d digest-type] [-h hostname] [-l lun] [-n iterations] [-t target] [-u user]\n", *argv);
(void) fprintf(stderr, "usage: %s [-4] [-6] [-V] [-a auth-type] [-d digest-type] [-h hostname] [-l lun] [-n iterations] [-t target] [-u user]\n", *argv);
exit(EXIT_FAILURE);
}
for (j = 0; j < iterations; j++) {
@ -165,7 +173,7 @@ main(int argc, char **argv)
sigaction(SIGPIPE, &act, NULL);
/* Initialize Initiator */
if (initiator_init(host, user, auth_type, mutual_auth, digest_type) == -1) {
if (initiator_init(host, address_family, user, auth_type, mutual_auth, digest_type) == -1) {
iscsi_trace_error(__FILE__, __LINE__, "initiator_init() failed\n");
return -1;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: iscsi-target.c,v 1.10 2006/05/27 21:21:04 agc Exp $ */
/* $NetBSD: iscsi-target.c,v 1.11 2006/08/03 20:21:59 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -64,7 +64,6 @@ static globals_t g;
int
main(int argc, char **argv)
{
const char *cf;
targv_t tv;
devv_t dv;
extv_t ev;
@ -81,10 +80,10 @@ main(int argc, char **argv)
(void) strlcpy(TargetName, DEFAULT_TARGET_NAME, sizeof(TargetName));
detach_me_harder = 1;
g.port = ISCSI_PORT;
g.address_family = ISCSI_IPv4;
g.address_family = ISCSI_UNSPEC;
g.max_sessions = DEFAULT_TARGET_MAX_SESSIONS;
cf = _PATH_ISCSI_TARGETS;
(void) strlcpy(g.config_file, _PATH_ISCSI_TARGETS, sizeof(g.config_file));
while ((i = getopt(argc, argv, "46b:Df:p:s:t:Vv:")) != -1) {
switch (i) {
@ -101,7 +100,7 @@ main(int argc, char **argv)
detach_me_harder = 0;
break;
case 'f':
cf = optarg;
(void) strlcpy(g.config_file, optarg, sizeof(g.config_file));
break;
case 'p':
g.port = (uint16_t) atoi(optarg);
@ -132,8 +131,8 @@ main(int argc, char **argv)
}
}
if (!read_conf_file(cf, &tv, &dv, &ev)) {
(void) fprintf(stderr, "Error: can't open `%s'\n", cf);
if (!read_conf_file(g.config_file, &tv, &dv, &ev)) {
(void) fprintf(stderr, "Error: can't open `%s'\n", g.config_file);
return EXIT_FAILURE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: storage.c,v 1.4 2006/03/20 20:45:07 agc Exp $ */
/* $NetBSD: storage.c,v 1.5 2006/08/03 20:21:59 agc Exp $ */
/*
* Copyright © 2006 Alistair Crooks. All rights reserved.
@ -404,4 +404,3 @@ write_pid_file(const char *f)
fclose(fp);
}
}

View File

@ -68,6 +68,10 @@
#include <errno.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@ -646,7 +650,7 @@ text_command_t(target_session_t * sess, uint8_t *header)
PARAM_TEXT_ADD(sess->params, "SendTargets", "Reject", text_out, &len_out, 2048, 0, TC_ERROR);
} else {
for (i = 0 ; i < sess->globals->tv->c ; i++) {
if (sess->address_family == ISCSI_IPv6 ||
if (sess->address_family == ISCSI_IPv6 ||
(sess->address_family == ISCSI_IPv4 && allow_netmask(sess->globals->tv->v[i].mask, sess->initiator))) {
(void) snprintf(buf, sizeof(buf), "%s:%s", sess->globals->targetname, sess->globals->tv->v[i].target);
PARAM_TEXT_ADD(sess->params, "TargetName", buf, text_out, &len_out, 2048, 0, TC_ERROR);
@ -1494,11 +1498,10 @@ target_init(globals_t *gp, targv_t *tv, char *TargetName)
gp->listener_pid = -1;
gp->state = TARGET_INITIALIZED;
printf("TARGET: TargetName is %s, listening on %s port %d\n",
gp->targetname,
(gp->address_family == ISCSI_IPv4) ? "IPv4" :
(gp->address_family == ISCSI_IPv6) ? "IPv6" : "unknown",
gp->port);
printf("TARGET: TargetName is %s\n", gp->targetname);
for (i = 0 ; i < gp->sockc ; i++) {
printf("\tsocket %d listening on port %hd\n", gp->sockv[i], gp->port);
}
return 0;
}
@ -1566,41 +1569,29 @@ target_shutdown(globals_t *gp)
int
target_listen(globals_t *gp)
{
struct sockaddr_in6 remoteAddrStorage6;
struct sockaddr_in6 localAddrStorage6;
struct sockaddr_in remoteAddrStorage;
struct sockaddr_in localAddrStorage;
target_session_t *sess;
iscsi_socket_t newconn;
socklen_t remoteAddrLen;
socklen_t localAddrLen;
char remote[1024];
char local[1024];
int one = 1;
int i;
ISCSI_THREAD_START("listen_thread");
gp->listener_pid = ISCSI_GETPID;
gp->listener_listening++;
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "listener thread started\n");
/* Create/Bind/Listen */
if (!iscsi_sock_create(&gp->sock)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_create() failed\n");
goto done;
}
if (!iscsi_sock_setsockopt(&gp->sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n");
goto done;
}
if (!iscsi_sock_setsockopt(&gp->sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n");
return -1;
}
if (!iscsi_sock_bind(gp->sock, gp->port)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_bind() failed\n");
goto done;
}
if (!iscsi_sock_listen(gp->sock)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_listen() failed\n");
if (!iscsi_socks_establish(gp->sockv, gp->famv, &gp->sockc, gp->address_family)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_establish() failed\n");
goto done;
}
gp->sock = gp->sockv[0];
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "create, bind, listen OK\n");
/* Loop for connections: FIX ME with queue */
@ -1616,52 +1607,75 @@ target_listen(globals_t *gp)
sess->globals = gp;
sess->address_family = gp->address_family;
/* Accept connection, spawn session thread, and */
/* clean up old threads */
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "waiting for IPv4 connection on port %hd\n", gp->port);
if (!iscsi_sock_accept(gp->sock, &sess->sock)) {
i = iscsi_waitfor_connection(gp->sockv, gp->sockc, gp->config_file, &newconn);
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "waiting for %s connection on port %hd\n",
iscsi_address_family(gp->famv[i]),
gp->port);
if (!iscsi_sock_accept(newconn, &sess->sock)) {
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "iscsi_sock_accept() failed\n");
goto done;
}
localAddrLen = sizeof(localAddrStorage);
(void) memset(&localAddrStorage, 0x0, sizeof(localAddrStorage));
if (!iscsi_sock_getsockname(sess->sock, (struct sockaddr *) (void *) &localAddrStorage, &localAddrLen)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_getsockname() failed\n");
goto done;
}
switch (gp->famv[i]) {
case AF_INET:
sess->address_family = ISCSI_IPv4;
(void) memset(&localAddrStorage, 0x0, localAddrLen = sizeof(localAddrStorage));
if (getsockname(sess->sock, (struct sockaddr *) (void *) &localAddrStorage, &localAddrLen) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_getsockname() failed\n");
goto done;
}
remoteAddrLen = sizeof(remoteAddrStorage);
(void) memset(&remoteAddrStorage, 0x0, sizeof(remoteAddrStorage));
if (!iscsi_sock_getpeername(sess->sock, (struct sockaddr *) (void *) &remoteAddrStorage, &remoteAddrLen)) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_getpeername() failed\n");
goto done;
}
(void) memset(&remoteAddrStorage, 0x0, remoteAddrLen = sizeof(remoteAddrStorage));
if (getpeername(sess->sock, (struct sockaddr *) (void *) &remoteAddrStorage, &remoteAddrLen) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_getpeername() failed\n");
goto done;
}
switch (sess->address_family = (remoteAddrStorage.sin_family = PF_INET6) ? ISCSI_IPv6 : ISCSI_IPv4) {
case ISCSI_IPv4:
#ifdef HAVE_GETNAMEINFO
if (getnameinfo((struct sockaddr *)(void *)&localAddrStorage,
sizeof(localAddrStorage), local, sizeof(local), NULL, 0, NI_NUMERICHOST) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "getnameinfo local failed\n");
}
if (getnameinfo((struct sockaddr *)(void *)&remoteAddrStorage,
sizeof(remoteAddrStorage), remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "getnameinfo remote failed\n");
}
(void) strlcpy(sess->initiator, remote, sizeof(sess->initiator));
#else
(void) strlcpy(local, inet_ntoa(localAddrStorage.sin_addr), sizeof(local));
(void) strlcpy(sess->initiator, inet_ntoa(remoteAddrStorage.sin_addr), sizeof(sess->initiator));
#endif
(void) snprintf(gp->targetaddress, sizeof(gp->targetaddress), "%s:%u,1", local, gp->port);
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "IPv4 connection accepted on port %d (local IP %s, remote IP %s)\n",
gp->port, local, sess->initiator);
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "TargetAddress = \"%s\"\n", gp->targetaddress);
if (iscsi_thread_create(&sess->worker.thread, (void *) worker_proc_t, sess) != 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_thread_create() failed\n");
break;
case AF_INET6:
sess->address_family = ISCSI_IPv6;
(void) memset(&localAddrStorage6, 0x0, localAddrLen = sizeof(localAddrStorage6));
if (getsockname(sess->sock, (struct sockaddr *) (void *) &localAddrStorage6, &localAddrLen) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "getsockname() failed\n");
goto done;
}
break;
case ISCSI_IPv6:
if (inet_ntop(localAddrStorage.sin_family, (void *)&localAddrStorage.sin_addr, local, sizeof(local)) == NULL) {
iscsi_trace_error(__FILE__, __LINE__, "inet_ntop local failed\n");
(void) memset(&remoteAddrStorage6, 0x0, remoteAddrLen = sizeof(remoteAddrStorage6));
if (getpeername(sess->sock, (struct sockaddr *) (void *) &remoteAddrStorage6, &remoteAddrLen) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_getpeername() failed\n");
goto done;
}
if (inet_ntop(remoteAddrStorage.sin_family, (void *)&remoteAddrStorage.sin_addr, remote, sizeof(remote)) == NULL) {
iscsi_trace_error(__FILE__, __LINE__, "inet_ntop remotefailed\n");
if (getnameinfo((struct sockaddr *)(void *)&localAddrStorage6, sizeof(localAddrStorage6), local, sizeof(local), NULL, 0, NI_NUMERICHOST) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "getnameinfo local failed\n");
}
if (getnameinfo((struct sockaddr *)(void *)&remoteAddrStorage6, sizeof(remoteAddrStorage6), remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) < 0) {
iscsi_trace_error(__FILE__, __LINE__, "getnameinfo remote failed\n");
}
(void) strlcpy(sess->initiator, remote, sizeof(sess->initiator));
(void) snprintf(gp->targetaddress, sizeof(gp->targetaddress), "%s:%u,1", local, gp->port);
@ -1670,6 +1684,7 @@ target_listen(globals_t *gp)
iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "TargetAddress = \"%s\"\n", gp->targetaddress);
break;
}
if (iscsi_thread_create(&sess->worker.thread, (void *) worker_proc_t, sess) != 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_thread_create() failed\n");
goto done;

133
dist/iscsi/src/util.c vendored
View File

@ -33,6 +33,7 @@
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
@ -74,6 +75,14 @@
#include <stdarg.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@ -543,6 +552,130 @@ iscsi_sock_listen(iscsi_socket_t sock)
return 1;
}
#ifndef MAXSOCK
#define MAXSOCK 16
#endif
int
iscsi_socks_establish(iscsi_socket_t *sockv, int *famv, int *sockc, int family)
{
struct addrinfo hints;
struct addrinfo *res;
struct addrinfo *res0;
const char *cause = NULL;
int one = 1;
int error;
(void) memset(&hints, 0x0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((error = getaddrinfo(NULL, "iscsi", &hints, &res0)) != 0) {
iscsi_trace_error(__FILE__, __LINE__, "getaddrinfo: %s", gai_strerror(error));
return 0;
}
*sockc = 0;
for (res = res0; res && *sockc < MAXSOCK; res = res->ai_next) {
if ((sockv[*sockc] = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) {
cause = "socket";
continue;
}
famv[*sockc] = res->ai_family;
if (!iscsi_sock_setsockopt(&sockv[*sockc], SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n");
continue;
}
if (!iscsi_sock_setsockopt(&sockv[*sockc], SOL_TCP, TCP_NODELAY, &one, sizeof(one))) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_setsockopt() failed\n");
continue;
}
if (bind(sockv[*sockc], res->ai_addr, res->ai_addrlen) < 0) {
cause = "bind";
close(sockv[*sockc]);
continue;
}
(void) listen(sockv[*sockc], 32);
*sockc += 1;
}
if (*sockc == 0) {
iscsi_trace_error(__FILE__, __LINE__, "iscsi_sock_establish: no sockets found: %s", cause);
freeaddrinfo(res0);
return 0;
}
freeaddrinfo(res0);
return 1;
}
/* return the address family for the socket */
const char *
iscsi_address_family(int fam)
{
return (fam == AF_INET) ? "IPv4" : (fam == AF_INET6) ? "IPv6" : "[unknown type]";
}
/* wait for a connection to come in on a socket */
int
iscsi_waitfor_connection(iscsi_socket_t *sockv, int sockc, const char *cf, iscsi_socket_t *sock)
{
#ifdef HAVE_POLL
struct pollfd socks[MAXSOCK];
int i;
for (;;) {
for (i = 0 ; i < sockc ; i++) {
socks[i].fd = sockv[i];
socks[i].events = POLLIN;
socks[i].revents = 0;
}
switch(poll(socks, sockc, INFTIM)) {
case -1:
/* interrupted system call */
continue;
case 0:
/* timeout */
continue;
default:
for (i = 0 ; i < sockc ; i++) {
if (socks[i].revents & POLLIN) {
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "connection %d selected\n", sockv[i]);
*sock = sockv[i];
return i;
}
}
}
}
#else
fd_set infds;
int i;
for (;;) {
FD_ZERO(&infds);
for (i = 0 ; i < sockc ; i++) {
FD_SET(sockv[i], &infds);
}
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "waiting for connection\n");
switch (select(32, &infds, NULL, NULL, NULL)) {
case -1:
/* interrupted system call */
continue;
case 0:
/* timeout */
continue;
default:
for (i = 0 ; i < sockc ; i++) {
if (FD_ISSET(sockv[i], &infds)) {
iscsi_trace(TRACE_NET_DEBUG, __FILE__, __LINE__, "connection %d selected\n", sockv[i]);
*sock = sockv[i];
return i;
}
}
}
}
#endif
}
int
iscsi_sock_accept(iscsi_socket_t sock, iscsi_socket_t * newsock)
{