Blob Blame History Raw
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/Changelog open-iscsi-2.0-872-rc4-bnx2i.work/Changelog
--- open-iscsi-2.0-872-rc4-bnx2i/Changelog	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/Changelog	2011-02-03 20:14:23.000000000 -0600
@@ -1,132 +1,114 @@
-open-iscsi-2.0-871 - open-iscsi-2.0.870
+open-iscsi-2.0-872 - open-iscsi-2.0.871
 
-Boaz Harrosh (1):
-      open-iscsi: Makefile: separate out user: and kernel: make targets
+Avi Kaplan (2):
+      Remove unused field iscsi_conn from struct iscsi_sw_tcp_conn
+      Change restore_callbacks argument iscsi_sw_tcp_conn to iscsi_conn
 
 Erez Zilber (1):
-      Add Module.markers to .gitignore
+      Fix 2.6.14-23_compat.patch to support all RHEL 5.X versions
 
-Karen Xie (2):
-      userspace - add new transport cxgb3i
-      userspace - setting interface ip address
-
-Mike Christie (84):
-      iscsid: fix relogin retry handling
-      iscsid idbm: print out header and tail to seperate records
-      ibft: add support to use iscsi_ibft module and log into all portals found in firmware
-      fwparam: rm unused filepath argument
-      iscsid idbm: move record strings to header
-      iscsiadm: discovery mode supports the --show
-      iscsiadm: have fw discovery handle --op arguments
-      iscsiadm: fix output ordering
-      iscsi modules: fix compilation
-      iscsid/iscsiadm: fix strto* usage
-      iscsid: fix logout response and time2wait handling
-      iscsiadm: remove default bnx2i iface
-      iscsid/iscsiadm: support multiple inititor names per host.
-      iscsiadm: print session and session info running through ifaces in iface mode
-      iscsid: update transport handle
-      idbm: have idbm_rec_update_param update the value string of the matching rec_info
-      iscsi mod: sync up kernel modules with 2.6.29
-      iscsi mod: 2.6.27 compat
-      iscsi mod: 2.6.26 compat
-      iscsi mod: 2.6.24-25 compat
-      iscsi mod: 2.6.20-23 compat
-      iscsi mod: 2.6.14-19 compat
-      iscsi mod: fix up 2.6.14-19 compat patch
-      iscsi mod iscsi_tcp: compat fix for pI4/pI6
-      build: add a make user
-      iscsi tools: fix chap
-      PATCH: iscsi tools: do not use exit()
-      PATCH: fix iBFT firmware reading with newer kernels
-      2.6.29-rc libiscsi: Fix scsi command timeout oops in iscsi_eh_timed_out
-      iscsi mod: 2.6.14-19 compat
-      iscsi tools: convert from strncat to strlcat
-      iscsi tools: convert from strncpy to strlcpy
-      iscsi tool make: add notification that iscsi start was made
-      iscsid: Fix up connection failed messages
-      docs: fix up iscsiadm man page iface info
-      iscsi tools: update version in preparation for new release
-      iscsid: flush sysfs cache.
-      iscsid: mv event loop code to new file
-      docs: update readme with libiscsi_tcp info
-
-
-
-
--------------------------------------------------------------------
-open-iscsi-2.0-870 - open-iscsi-2.0.869
-
-Doron Shoham (1):
-      log.c: add error messages when allocation shared memory
-
-Erez Zilber (2):
-      Minor fixes in iscsi_discovery documentation
-      rm unused variable in fw_entry.c
-
-Hannes Reinecke (1):
-      Add SLES10 SP2 compat
-
-Hans de Goede (1):
-      PATCH: add error checking to iscsi discovery db lock creation
-
-Mike Christie (58):
-      change mgmt_ipc to logout by sid
-      iscsi class/if kernel: add ifacename attr
-      add ifacename support tools
-      rm db param
-      rm num_transports from sysfs header.
-      Add bind by initiatorname
-      break up iface code and add default iser, tcp/default and bnx2i ifaces
-      Use startup definition in util.c.
-      set header digests to off by default
-      fix compile warning for missing iface.h
-      User 64 bit params mask.
-      Do not allow iface setting to be changed in node mode.
-      Fix bad merge. User iscsi param masks instead of params.
-      Support mutlple ifaces with the same binding (lack of binding).
-      Release transport entry when the transport is unloaded
-      Fix ep_disconnect handling of invalid ep
-      libiscsi: Fix nop timeout handling
-      libiscsi: fix recv tmo
-      Revert Release-transport-entry-when-the-transport-is-unload.patch
-      pass ep to session creation
-      Fix iser create bound session compat
-      fix compilation on Fedora 9
-      Fix sysfs handling of block:sdX and scsi bus changes
-      Only autobind to ifaces with transport = tcp
-      Increase login retry for iscsistart.
-      Sync kernel modules to scsi-misc for 2.6.27.
-      Update 2.6.14 - 2.6.19 compat patch
-      Update 2.6.20 - 2.6.24 patch
-      Update 2.6.24 - 2.6.25 patch
-      iscsid: don't print enosys errors.
-      libiscsi: support older tools that did not set can_queue/cmds_max
-      Fix transport_name compat support.
-      Fix idbm iscsid segfault when accsing ifaces
-      Fix discovery and autobinding
-      fix ipv6 login redirect support.
-      Fix login redirect failure handling.
-      remove sysfs_file
-      fix dynamic tpgt support.
-      Bump version for new release.
-      Add compat patch for RHEL 5.2
-      iscsid: adjust requested settings for user
-      Sync kernel modules with 2.6.27
-      Add 2.6.26 compat support
-      Add Makefile support for 2.6.26 compat patch
-      Add .gitignore files
-      Revert broken SLES 10 compat patch.
-      iscsi conf: increase default login max
-      iscsi conf: partially revert increase default login max change
-      modify initial login retry max
-      libiscsi: fix data corruption when target has to resend data-in packets
-      iscsi class: fix endpoint id handling
-      handle ISCSI_ERR_INVALID_HOST
-      iscsi_tcp: return a descriptive error value during connection errors
-      libiscsi: fix locking in iscsi_eh_device_reset
-      update 2.6.14-19_compat.patch
-      update 2.6.20-21_compat.patch
-      update 2.6.24_compat.patch
-      Fix initiator.c compile warning
+Hannes Reinecke (2):
+      Allow update of discovery records.
+      Update 2.6.27_compat.patch for SLES 11
+
+Mike Christie (91):
+      Don't kill iscsid if logout from all nodes fail
+      iscsid: fix ISCSI_ERR_INVALID_HOST err handling
+      iscsid: add flag to indicate if driver needs iscsid to set ip
+      iscsid: add be2iscsi template
+      iscsid be2iscsi: add more driver limits
+      iscsid: start iscsid automatically when needed
+      iscsid: fix segfault during session sync up
+      iscsiadm: fix discovery record use
+      iscsi mod: sync to linux-2.6-iscsi tree's 2.6.33 feature window patches
+      iscsid: handle new replacement_timeout values
+      iscsi tools: support tgt reset timeout
+      iscsi-iname: fix misleading help description
+      iscsid: fix iferror log message
+      iscsi mod: Update 2.6.14-23_compat.patch patch
+      iscsiadm: fix login/logout message
+      do not use a semarg in shared-mem for semop calls
+      Fix wrong logs in log.c
+      update 2.6.26 compat patch
+      iscsi tools: Allow empty username for CHAP
+      iscsi ibft/boot: fix net dev loopup
+      iscsistart option to bring up NICs using configuration in iBFT.
+      ibft boot: mv setup nics to fw_entry.c so iscsiadm can use it
+      iscsistart ibft: fix fwparam network cmd
+      iscsid be2iscsi: don't set set_host_ip
+      iscsi tools: merge functions to get net iface name from mac address
+      ibft boot: do not setup nic if offload can be used
+      iscsistart ibft boot: setup iscsi offload during boot
+      ibft boot: remove be2iscsi
+      iscsi tools: idbm/fw function cleanup
+      iscsi tool: trivial fixes
+      ibft boot: add offload ibft support to iscsiadm
+      iscsiadm: only do auto iface setup when iface mode is run
+      ibft boot: add iscsiadm offload ibft rec support
+      doc: add iscsistart man page
+      doc: add iscsi-iname man page
+      ibft boot: fix dev to iface matching
+      offload boot: turn off
+      iscsi tools: nic setup cleanup
+      iscsi tools: fix compile errors
+      iscsi kern: fix 2.6.27 compat patch
+      iscsiadm: add nonpersistent mode to discovery mode
+      iscsi tool: mv idbm_node_setup_defaults to idbm.c
+      iscsi tools: cleanup get_global_string_param use
+      iscsi tools: make config file parser a little smarter.
+      iscsiadm: mv session management functions to new file
+      st discovery: fix reopen max handling
+      iscsid: have iscsid watch for new portals using sendtargets
+      iscsi tools: mv iscsid request helpers to its own file
+      iscsi tools: add str prefix to strings.c functions
+      iscsi tools: use open-isns services
+      iscsi tools: add MaxXmitDataSegmentLength param
+      iscsi tools: do not exit on mem alloc failures during discovery
+      Fix makefile cleanup
+      iscsid: add isns discovery daemon and SCN support
+      iscsid: support discovery daemon auto logout
+      isns: fix compilation
+      iscsi tools: fix null sysfs string handling
+      iscsi tools: fix compilation on s390
+      Update version number to 872
+      iscsi tools: fix MaxXmitDataSegmentLength=0 handling
+      be2iscsi iscsi tool: fix MaxXmitDataSegmentLength handling
+      iscsi tools: be2iscsi: fix initial_r2t_en handling
+      iscsi tools: prep for userspace libiscsi
+      iscsi tools: add log_info helper
+      iscsi tools: fix port handling for iscsiadm commands
+      iscsi tools: fix port handling for iscsiadm commands take 2
+      iscsid: fix discoveryd shutdown
+      iscsi scripts: use iscsiadm -k to shutdown daemon
+      iscsiadm: fix discovery record management
+      iscsid: fix sendtargets discovery daemon CHAP handling
+      iscsiadm: mv disc code to new function
+      iscsiadm: fix disc port handling
+      iscsiadm: add new discovery mode
+      iscsiadm: add isns db support
+      iscsiadm: cleanup default port handling
+      iscsid: use isns discovery rec for isns discoveryd setttings
+      iscsiadm: fix iface mode ENODEV handling
+      iscsiadm: mark discovery mode as depreciated
+      sync to upstream
+      2.6.33 - 34 kernel compat patch
+      2.6.28 - 32 kernel compat patch
+      2.6.27 kernel compat patch
+      2.6.26 kernel compat patch
+      2.6.24 - 25 kernel compat patch
+      2.6.14 - 23 kernel compat patch
+      iscsiadm: fix discovery2 db op return value
+      iscsiadm: print isns recs in discovery mode
+      iscsi boot: add support for iscsi boot sysfs module
+      iscsiadm: rename discovery2 mode as discoverydb
+      iscsiadm: fix boot code compile error
+      iscsiadm: fix iface update/delete return value fix
+
+Ritesh Raj Sarraf (3):
+      fix some spelling errors reported by lintian
+      minor manpage updates
+      Fix CVE-2009-1297
+
+Wulf C. Krueger (1):
+      Use DESTDIR when generating an InitiatorName.
 
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/doc/iscsiadm.8 open-iscsi-2.0-872-rc4-bnx2i.work/doc/iscsiadm.8
--- open-iscsi-2.0-872-rc4-bnx2i/doc/iscsiadm.8	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/doc/iscsiadm.8	2011-02-03 20:14:23.000000000 -0600
@@ -49,7 +49,13 @@ print debugging information. Valid value
 display help text and exit
 
 .TP
-\fB\-I\fR, \fB\-\-interface\fI[iface]\fR
+\fB\-H\fR, \fB\-\-host=\fI[hostno]\fR
+The host agrument specifies the SCSI host to use for the operation. The
+hostno value is the host number assigned to the host by the kernel's
+scsi layer.
+
+.TP
+\fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
 The interface argument specifies the iSCSI interface to use for the operation.
 iSCSI interfaces (iface) are defined in /etc/iscsi/ifaces. For hardware
 iSCSI (qla4xxx) the iface config must have the hardware address
@@ -294,6 +300,152 @@ or
 SendTargets (st)
 discovery type. An SLP implementation is under development.
 
+.SH EXIT STATUS
+ 
+On success 0 is returned. On error one of the return codes below will
+be returned.
+
+Commands that operation on multiple objects (sessions, records, etc),
+iscsiadm/iscsistart will return the first error that is encountered.
+iscsiadm/iscsistart will attempt to execute the operation on the objects it
+can. If no objects are found ISCSI_ERR_NO_OBJS_FOUND is returned.
+
+
+.TP
+.B
+0
+ISCSI_SUCCESS - command executed successfully.
+
+.TP
+.B
+1
+ISCSI_ERR - generic error code.
+
+.TP     
+.B
+2
+ISCSI_ERR_SESS_NOT_FOUND - session could not be found.
+
+.TP
+.B
+3
+ISCSI_ERR_NOMEM - could not allocate resource for operation.
+.TP
+.B
+4
+ISCSI_ERR_TRANS - connect problem caused operation to fail.
+
+.TP
+.B
+5
+ISCSI_ERR_LOGIN - generic iSCSI login failure.
+
+.TP
+.B
+6
+ISCSI_ERR_IDBM - error accessing/managing iSCSI DB.
+
+.TP
+.B
+7
+ISCSI_ERR_INVAL - invalid argument.
+
+.TP
+.B
+8
+ISCSI_ERR_TRANS_TIMEOUT - connection timer exired while trying to connect.
+
+.TP
+.B
+9
+ISCSI_ERR_INTERNAL - generic internal iscsid/kernel failure.
+
+.TP
+.B
+10
+ISCSI_ERR_LOGOUT - iSCSI logout failed.
+
+.TP
+.B
+11
+ISCSI_ERR_PDU_TIMEOUT - iSCSI PDU timedout.
+
+.TP
+.B
+12
+ISCSI_ERR_TRANS_NOT_FOUND - iSCSI transport module not loaded in kernel or iscsid.
+
+.TP
+.B
+13
+ISCSI_ERR_ACCESS - did not have proper OS permissions to access iscsid or execute iscsiadm command.
+
+.TP
+.B
+14
+ISCSI_ERR_TRANS_CAPS - transport module did not support operation.
+
+.TP
+.B
+15
+ISCSI_ERR_SESS_EXISTS - session is logged in.
+
+.TP
+.B
+16
+ISCSI_ERR_INVALID_MGMT_REQ - invalid IPC MGMT request.
+
+.TP
+.B
+17
+ISCSI_ERR_ISNS_UNAVAILABLE - iSNS service is not supported.
+
+.TP
+.B
+18
+ISCSI_ERR_ISCSID_COMM_ERR - a read/write to iscsid failed.
+
+.TP
+.B
+19
+ISCSI_ERR_FATAL_LOGIN - fatal iSCSI login error.
+
+.TP
+.B
+20
+ISCSI_ERR_ISCSID_NOTCONN - could ont connect to iscsid.
+
+.TP
+.B
+21
+ISCSI_ERR_NO_OBJS_FOUND - no records/targets/sessions/portals found to execute operation on.
+
+.TP
+.B
+22
+ISCSI_ERR_SYSFS_LOOKUP - could not lookup object in sysfs.
+
+.TP
+.B
+23
+ISCSI_ERR_HOST_NOT_FOUND - could not lookup host.
+
+.TP
+.B
+24
+ISCSI_ERR_LOGIN_AUTH_FAILED - login failed due to authorization failure.
+
+.TP
+.B
+25
+ISCSI_ERR_ISNS_QUERY - iSNS query failure.
+
+.TP
+.B
+26
+ISCSI_ERR_ISNS_REG_FAILED - iSNS registration/deregistration failed.
+
+
 .SH EXAMPLES
 
 .nf
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/etc/initd/initd.suse open-iscsi-2.0-872-rc4-bnx2i.work/etc/initd/initd.suse
--- open-iscsi-2.0-872-rc4-bnx2i/etc/initd/initd.suse	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/etc/initd/initd.suse	2011-02-03 20:14:23.000000000 -0600
@@ -30,7 +30,7 @@ iscsi_login_all_nodes()
 {
 	echo -n "Setting up iSCSI targets: "
 	$ISCSIADM -m node --loginall=automatic 2> /dev/null
-	if [ $? == 19 ] ; then
+	if [ $? == 21 ] ; then
 	    rc_failed 6
 	fi
 	rc_status -v
@@ -41,7 +41,7 @@ iscsi_logout_all_nodes()
 	echo -n "Closing all iSCSI connections: "
 	# Logout from all sessions marked automatic
 	if ! $ISCSIADM -m node --logoutall=automatic 2> /dev/null; then
-		if [ $? == 19 ] ; then
+		if [ $? == 21 ] ; then
 		    RETVAL=6
 		else
 		    RETVAL=1
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_err.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_err.h
--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_err.h	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_err.h	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,69 @@
+/*
+ * Return codes used by iSCSI tools.
+ */
+#ifndef _ISCSI_ERR_
+#define _ISCSI_ERR_
+
+enum {
+	ISCSI_SUCCESS			= 0,
+	/* Generic error */
+	ISCSI_ERR			= 1,
+	/* session could not be found */
+	ISCSI_ERR_SESS_NOT_FOUND	= 2,
+	/* Could not allocate resource for operation */
+	ISCSI_ERR_NOMEM			= 3,
+	/* Transport error caused operation to fail */
+	ISCSI_ERR_TRANS			= 4,
+	/* Generic login failure */
+	ISCSI_ERR_LOGIN			= 5,
+	/* Error accessing/managing iSCSI DB */
+	ISCSI_ERR_IDBM			= 6,
+	/* Invalid argument */
+	ISCSI_ERR_INVAL			= 7,
+	/* Connection timer exired while trying to connect */
+	ISCSI_ERR_TRANS_TIMEOUT		= 8,
+	/* Generic internal iscsid failure */
+	ISCSI_ERR_INTERNAL		= 9,
+	/* Logout failed */
+	ISCSI_ERR_LOGOUT		= 10,
+	/* iSCSI PDU timedout */
+	ISCSI_ERR_PDU_TIMEOUT		= 11,
+	/* iSCSI transport module not loaded in kernel or iscsid */
+	ISCSI_ERR_TRANS_NOT_FOUND	= 12,
+	/* Permission denied */
+	ISCSI_ERR_ACCESS		= 13,
+	/* Transport module did not support operation */
+	ISCSI_ERR_TRANS_CAPS		= 14,
+	/* Session is logged in */
+	ISCSI_ERR_SESS_EXISTS		= 15,
+	/* Invalid IPC MGMT request */
+	ISCSI_ERR_INVALID_MGMT_REQ	= 16,
+	/* iSNS service is not supported */
+	ISCSI_ERR_ISNS_UNAVAILABLE	= 17,
+	/* A read/write to iscsid failed */
+	ISCSI_ERR_ISCSID_COMM_ERR	= 18,
+	/* Fatal login error */
+	ISCSI_ERR_FATAL_LOGIN		= 19,
+	/* Could ont connect to iscsid */
+	ISCSI_ERR_ISCSID_NOTCONN	= 20,
+	/* No records/targets/sessions/portals found to execute operation on */
+	ISCSI_ERR_NO_OBJS_FOUND		= 21,
+	/* Could not lookup object in sysfs */
+	ISCSI_ERR_SYSFS_LOOKUP		= 22,
+	/* Could not lookup host */
+	ISCSI_ERR_HOST_NOT_FOUND	= 23,
+	/* Login failed due to authorization failure */
+	ISCSI_ERR_LOGIN_AUTH_FAILED	= 24,
+	/* iSNS query failure */
+	ISCSI_ERR_ISNS_QUERY		= 25,
+	/* iSNS registration/deregistration failed */
+	ISCSI_ERR_ISNS_REG_FAILED	= 26,
+
+	/* Always last. Indicates end of error code space */
+	ISCSI_MAX_ERR_VAL,
+} iscsi_err;
+
+extern void iscsi_err_print_msg(int err);
+extern char *iscsi_err_to_str(int err);
+
+#endif
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h
--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h	2011-02-03 20:14:23.000000000 -0600
@@ -65,6 +65,8 @@ enum iscsi_uevent_e {
 
 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
 
+	ISCSI_UEVENT_MAX		= ISCSI_UEVENT_PATH_UPDATE,
+
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
 	ISCSI_KEVENT_CONN_ERROR		= KEVENT_BASE + 2,
@@ -75,6 +77,8 @@ enum iscsi_uevent_e {
 
 	ISCSI_KEVENT_PATH_REQ		= KEVENT_BASE + 7,
 	ISCSI_KEVENT_IF_DOWN		= KEVENT_BASE + 8,
+
+	ISCSI_KEVENT_MAX		= ISCSI_KEVENT_IF_DOWN,
 };
 
 enum iscsi_tgt_dscvr {
@@ -386,7 +390,7 @@ enum iscsi_host_param {
 #define CAP_HDRDGST		0x10
 #define CAP_DATADGST		0x20
 #define CAP_MULTI_CONN		0x40
-#define CAP_TEXT_NEGO		0x80
+#define CAP_TEXT_NEGO		0x80	/* support for text requests */
 #define CAP_MARKERS		0x100
 #define CAP_FW_DB		0x200
 #define CAP_SENDTARGETS_OFFLOAD	0x400	/* offload discovery process */
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/actor.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/actor.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/actor.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/actor.c	2011-02-03 20:14:23.000000000 -0600
@@ -113,14 +113,13 @@ actor_schedule_private(actor_t *thread, 
 		 * state to scheduled, else add current time to ttschedule and
 		 * insert in the queue at the correct point */
 		if (delay_time == 0) {
-			if (poll_in_progress) {
+			/* For head addition, it must go onto the head of the
+			   actor_list regardless if poll is in progress or not
+			 */
+			if (poll_in_progress && !head) {
 				thread->state = ACTOR_POLL_WAITING;
-				if (head)
-					list_add(&thread->list,
-						 &poll_list);
-				else
-					list_add_tail(&thread->list,
-						      &poll_list);
+				list_add_tail(&thread->list,
+					      &poll_list);
 			} else {
 				thread->state = ACTOR_SCHEDULED;
 				if (head)
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/config.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/config.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/config.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/config.h	2011-02-03 20:14:23.000000000 -0600
@@ -141,7 +141,8 @@ struct iscsi_sendtargets_config {
 	int discoveryd_poll_inval;
 	struct iscsi_auth_config auth;
 	struct iscsi_connection_timeout_config conn_timeo;
-	struct iscsi_conn_operational_config iscsi;
+	struct iscsi_conn_operational_config conn_conf;
+	struct iscsi_session_operational_config session_conf;
 };
 
 struct iscsi_isns_config {
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/cxgb3i.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgb3i.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/cxgb3i.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgb3i.c	1969-12-31 18:00:00.000000000 -0600
@@ -1,24 +0,0 @@
-/*
- * cxgb3i helpers
- *
- * Copyright (C) 2006 Mike Christie
- * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- */
-#include "initiator.h"
-
-void cxgb3i_create_conn(struct iscsi_conn *conn)
-{
-	/* card can handle up to 15360 bytes */
-	if (conn->max_recv_dlength > 8192)
-		conn->max_recv_dlength = 8192;
-}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/cxgb3i.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgb3i.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/cxgb3i.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgb3i.h	1969-12-31 18:00:00.000000000 -0600
@@ -1,8 +0,0 @@
-#ifndef CXGB3I_TRANSPORT
-#define CXGB3I_TRANSPORT
-
-struct iscsi_conn;
-
-extern void cxgb3i_create_conn(struct iscsi_conn *conn);
-
-#endif
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/cxgbi.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgbi.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/cxgbi.c	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgbi.c	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,24 @@
+/*
+ * cxgb3i/cxgb4i helpers
+ *
+ * Copyright (C) 2006 Mike Christie
+ * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+#include "initiator.h"
+
+void cxgbi_create_conn(struct iscsi_conn *conn)
+{
+	/* card can handle up to 15360 bytes */
+	if (conn->max_recv_dlength > 8192)
+		conn->max_recv_dlength = 8192;
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/cxgbi.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgbi.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/cxgbi.h	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/cxgbi.h	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,8 @@
+#ifndef CXGBI_TRANSPORT
+#define CXGBI_TRANSPORT
+
+struct iscsi_conn;
+
+extern void cxgbi_create_conn(struct iscsi_conn *conn);
+
+#endif
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/discovery.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/discovery.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/discovery.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/discovery.c	2011-02-03 20:14:32.000000000 -0600
@@ -43,6 +43,12 @@
 #include "fw_context.h"
 #include "iscsid_req.h"
 #include "iscsi_util.h"
+#include "transport.h"
+#include "iscsi_sysfs.h"
+#include "iscsi_ipc.h"
+#include "iface.h"
+#include "iscsi_timer.h"
+#include "iscsi_err.h"
 /* libisns includes */
 #include "isns.h"
 #include "paths.h"
@@ -54,10 +60,9 @@
 
 #define DISCOVERY_NEED_RECONNECT 0xdead0001
 
-static int rediscover = 0;
-
 static char initiator_name[TARGET_NAME_MAXLEN + 1];
 static char initiator_alias[TARGET_NAME_MAXLEN + 1];
+static struct iscsi_ev_context ipc_ev_context;
 
 static int request_initiator_name(void)
 {
@@ -107,14 +112,14 @@ int discovery_isns_set_servername(char *
 
 	if (port > USHRT_MAX) {
 		log_error("Invalid port %d\n", port);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	/* 5 for port and 1 for colon and 1 for null */
 	len = strlen(address) + 7;
 	server = calloc(1, len);
 	if (!server)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	snprintf(server, len, "%s:%d", address, port);
 	isns_assign_string(&isns_config.ic_server_name, server);
@@ -136,11 +141,11 @@ int discovery_isns_query(struct discover
 	isns_config.ic_security = 0;
 	source = isns_source_create_iscsi(iname);
 	if (!source)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	clnt = isns_create_client(NULL, iname); 
 	if (!clnt) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_src;
 	}
 
@@ -158,7 +163,7 @@ int discovery_isns_query(struct discover
 
 	qry = isns_create_query2(clnt, &key_attrs, source);
 	if (!qry) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_clnt;
 	}
 
@@ -177,11 +182,11 @@ int discovery_isns_query(struct discover
 		break;
 	case ISNS_SOURCE_UNKNOWN:
 		/* server requires that we are registered but we are not */
-		rc = ENOENT;
+		rc = ISCSI_ERR_ISNS_REG_FAILED;
 		goto free_query;
 	default:
 		log_error("iSNS discovery failed: %s", isns_strerror(status));
-		rc = EIO;
+		rc = ISCSI_ERR_ISNS_QUERY;
 		goto free_query;
 	}
 
@@ -189,7 +194,7 @@ int discovery_isns_query(struct discover
 	if (status) {
 		log_error("Unable to extract object list from query "
 			  "response: %s\n", isns_strerror(status));
-		rc = EIO;
+		rc = ISCSI_ERR;
 		goto free_query;
 	}
 
@@ -239,7 +244,7 @@ int discovery_isns_query(struct discover
 
 		rec = calloc(1, sizeof(*rec));
 		if (!rec) {
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto destroy_list;
 		}
 
@@ -291,11 +296,11 @@ static int discovery_isns_reg_node(const
 
 	source = isns_source_create_iscsi(iname);
 	if (!source)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	clnt = isns_create_client(NULL, iname); 
 	if (!clnt) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_src;
 	}
 
@@ -303,7 +308,7 @@ static int discovery_isns_reg_node(const
 				 ISNS_DEVICE_DEREGISTER,
 				 source, NULL);
 	if (!reg) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_clnt;
 	}
 
@@ -318,7 +323,7 @@ static int discovery_isns_reg_node(const
 		log_error("Could not %s %s with iSNS server: %s.",
 			  reg ? "register" : "deregister", iname,
 			  isns_strerror(status));
-		rc = EIO;
+		rc = ISCSI_ERR_ISNS_REG_FAILED;
 	} else
 		log_debug(1, "%s %s with iSNS server successful.",
 			  op_reg ? "register" : "deregister", iname);
@@ -342,7 +347,7 @@ int discovery_isns(void *data, struct if
 		if (request_initiator_name() || initiator_name[0] == '\0') {
 			log_error("Cannot perform discovery. Initiatorname "
 				  "required.");
-			return EINVAL;
+			return ISCSI_ERR_INVAL;
 		}
 		iname = initiator_name;
 	}
@@ -352,7 +357,7 @@ int discovery_isns(void *data, struct if
 		return rc;
 retry:
 	rc = discovery_isns_query(drec, iname, NULL, rec_list);
-	if (!registered && rc == ENOENT) {
+	if (!registered && rc == ISCSI_ERR_ISNS_REG_FAILED) {
 		rc = discovery_isns_reg_node(iname, 1);
 		if (!rc) {
 			registered = 1;
@@ -396,7 +401,7 @@ int discovery_fw(void *data, struct ifac
 		if (!rec) {
 			log_error("Could not convert firmware info to "
 				  "node record.\n");
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto free_targets;
 		}
 		rec->disc_type = drec->type;
@@ -428,10 +433,10 @@ int discovery_offload_sendtargets(int ho
 
 	/* resolve the DiscoveryAddress to an IP address */
 	sprintf(default_port, "%d", drec->port);
-	if (resolve_address(drec->address, default_port, &ss)) {
-		log_error("Cannot resolve host name %s.", drec->address);
-		return EIO;
-	}       
+	rc = resolve_address(drec->address, default_port, &ss);
+	if (rc)
+		return rc;
+
 	req.u.st.ss = ss;
 
 	/*
@@ -447,8 +452,8 @@ int discovery_offload_sendtargets(int ho
 	if (rc) {
 		log_error("Could not offload sendtargets to %s.\n",
 			  drec->address);
-		iscsid_handle_error(rc);
-		return EIO;
+		iscsi_err_print_msg(rc);
+		return rc;
 	}
 
 	return 0;
@@ -490,15 +495,12 @@ request_targets(iscsi_session_t *session
 
 	if (!iscsi_add_text(hdr, data, sizeof (data), "SendTargets", "All")) {
 		log_error("failed to add SendTargets text key");
-		exit(1);
+		return 0;
 	}
 
 	text.ttt = ISCSI_RESERVED_TAG;
 	text.flags = ISCSI_FLAG_CMD_FINAL;
 
-	if (++session->itt == ISCSI_RESERVED_TAG)
-		session->itt = 1;
-
 	if (!iscsi_io_send_pdu(&session->conn[0], hdr, ISCSI_DIGEST_NONE, data,
 		    ISCSI_DIGEST_NONE, session->conn[0].active_timeout)) {
 		log_error("failed to send SendTargets PDU");
@@ -527,9 +529,6 @@ iterate_targets(iscsi_session_t *session
 	text.ttt = ttt;
 	text.flags = ISCSI_FLAG_CMD_FINAL;
 
-	if (++session->itt == ISCSI_RESERVED_TAG)
-		session->itt = 1;
-
 	if (!iscsi_io_send_pdu(&session->conn[0], pdu, ISCSI_DIGEST_NONE, data,
 		    ISCSI_DIGEST_NONE, session->conn[0].active_timeout)) {
 		log_error("failed to send empty text PDU");
@@ -543,19 +542,13 @@ static int add_portal(struct list_head *
 		      char *targetname, char *address, char *port, char *tag)
 {
 	struct sockaddr_storage ss;
-	char host[NI_MAXHOST];
 	struct node_rec *rec;
 
-	/* resolve the address, in case it was a DNS name */
 	if (resolve_address(address, port, &ss)) {
 		log_error("cannot resolve %s", address);
 		return 0;
 	}
 
-	/* convert the resolved name to text */
-	getnameinfo((struct sockaddr *) &ss, sizeof(ss),
-		    host, sizeof(host), NULL, 0, NI_NUMERICHOST);
-
 	rec = calloc(1, sizeof(*rec));
 	if (!rec)
 		return 0;
@@ -582,7 +575,7 @@ static int add_portal(struct list_head *
 
 static int
 add_target_record(char *name, char *end, discovery_rec_t *drec,
-		  struct list_head *rec_list, char *default_port)
+		  struct list_head *rec_list)
 {
 	char *text = NULL;
 	char *nul = name;
@@ -625,11 +618,16 @@ add_target_record(char *name, char *end,
 			log_error("no default address known for target %s",
 				  name);
 			return 0;
-		} else if (!add_portal(rec_list, drec, name, drec->address,
-				       default_port, NULL)) {
-			log_error("failed to add default portal, ignoring "
-				  "target %s", name);
-			return 0;
+		} else {
+			char default_port[NI_MAXSERV];
+
+			sprintf(default_port, "%d", drec->port);
+			if (!add_portal(rec_list, drec, name, drec->address,
+				        default_port, NULL)) {
+				log_error("failed to add default portal, "
+					  "ignoring target %s", name);
+				return 0;
+			}
 		}
 		/* finished adding the default */
 		return 1;
@@ -681,8 +679,7 @@ add_target_record(char *name, char *end,
 static int
 process_sendtargets_response(struct str_buffer *sendtargets,
 			     int final, discovery_rec_t *drec,
-			     struct list_head *rec_list,
-			     char *default_port)
+			     struct list_head *rec_list)
 {
 	char *start = str_buffer_data(sendtargets);
 	char *text = start;
@@ -733,8 +730,7 @@ process_sendtargets_response(struct str_
 				 * "TargetName=" prefix.
 				 */
 				if (!add_target_record(record + 11, text,
-							drec, rec_list,
-							default_port)) {
+							drec, rec_list)) {
 					log_error(
 					       "failed to add target record");
 					str_truncate_buffer(sendtargets, 0);
@@ -762,7 +758,7 @@ process_sendtargets_response(struct str_
 				 "line %s",
 				 record, record);
 			if (add_target_record (record + 11, text,
-					       drec, rec_list, default_port)) {
+					       drec, rec_list)) {
 				num_targets++;
 				record = NULL;
 				str_truncate_buffer(sendtargets, 0);
@@ -792,110 +788,47 @@ process_sendtargets_response(struct str_
 	return 1;
 }
 
-static void
-clear_timer(struct timeval *timer)
-{
-	memset(timer, 0, sizeof (*timer));
-}
-
-/* set timer to now + seconds */
-static void
-set_timer(struct timeval *timer, int seconds)
+static void iscsi_free_session(struct iscsi_session *session)
 {
-	if (timer) {
-		memset(timer, 0, sizeof (*timer));
-		gettimeofday(timer, NULL);
-
-		timer->tv_sec += seconds;
-	}
-}
-
-static int
-timer_expired(struct timeval *timer)
-{
-	struct timeval now;
-
-	/* no timer, can't have expired */
-	if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0)))
-		return 0;
-
-	memset(&now, 0, sizeof (now));
-	gettimeofday(&now, NULL);
-
-	if (now.tv_sec > timer->tv_sec)
-		return 1;
-	if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec))
-		return 1;
-	return 0;
-}
-
-static int
-msecs_until(struct timeval *timer)
-{
-	struct timeval now;
-	int msecs;
-	long partial;
-
-	/* no timer, can't have expired, infinite time til it expires */
-	if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0)))
-		return -1;
-
-	memset(&now, 0, sizeof (now));
-	gettimeofday(&now, NULL);
-
-	/* already expired? */
-	if (now.tv_sec > timer->tv_sec)
-		return 0;
-	if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec))
-		return 0;
-
-	/* not expired yet, do the math */
-	partial = timer->tv_usec - now.tv_usec;
-	if (partial < 0) {
-		partial += 1000 * 1000;
-		msecs = (partial + 500) / 1000;
-		msecs += (timer->tv_sec - now.tv_sec - 1) * 1000;
-	} else {
-		msecs = (partial + 500) / 1000;
-		msecs += (timer->tv_sec - now.tv_sec) * 1000;
-	}
-
-	return msecs;
+	list_del_init(&session->list);
+	free(session);
 }
 
 static iscsi_session_t *
-init_new_session(struct iscsi_sendtargets_config *config,
-		 struct iface_rec *iface)
+iscsi_alloc_session(struct iscsi_sendtargets_config *config,
+		    struct iface_rec *iface, int *rc)
 {
 	iscsi_session_t *session;
 
+	*rc = 0;
+
 	session = calloc(1, sizeof (*session));
-	if (session == NULL)
-		goto done;
+	if (session == NULL) {
+		*rc = ISCSI_ERR_NOMEM;
+		return NULL;
+	}
+
+	session->t = iscsi_sysfs_get_transport_by_name(iface->transport_name);
+	if (!session->t) {
+		log_error("iSCSI driver %s is not loaded. Load the module "
+			  "then retry the command.\n", iface->transport_name);
+		*rc = ISCSI_ERR_TRANS_NOT_FOUND;
+		goto fail;
+	}
 
+	INIT_LIST_HEAD(&session->list);
 	/* initialize the session's leading connection */
+	session->conn[0].id = 0;
 	session->conn[0].socket_fd = -1;
+	session->conn[0].session = session;
 	session->conn[0].login_timeout = config->conn_timeo.login_timeout;
 	session->conn[0].auth_timeout = config->conn_timeo.auth_timeout;
 	session->conn[0].active_timeout = config->conn_timeo.active_timeout;
-	session->conn[0].hdrdgst_en = ISCSI_DIGEST_NONE;
-	session->conn[0].datadgst_en = ISCSI_DIGEST_NONE;
-
-	session->conn[0].max_recv_dlength =
-					config->iscsi.MaxRecvDataSegmentLength;
-	if (session->conn[0].max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
-	    session->conn[0].max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
-		log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be "
-			  "within %u and %u. Setting to %u.",
-			  ISCSI_MIN_MAX_RECV_SEG_LEN,
-			  ISCSI_MAX_MAX_RECV_SEG_LEN,
-			  DEF_INI_DISC_MAX_RECV_SEG_LEN);
-		session->conn[0].max_recv_dlength =
-						DEF_INI_DISC_MAX_RECV_SEG_LEN;
-	}
-	session->conn[0].max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
-
+	session->conn[0].noop_out_timeout = 0;
+	session->conn[0].noop_out_interval = 0;
 	session->reopen_cnt = config->reopen_max + 1;
+	iscsi_copy_operational_params(&session->conn[0], &config->session_conf,
+				      &config->conn_conf);
 
 	/* OUI and uniqifying number */
 	session->isid[0] = DRIVER_ISID_0;
@@ -914,102 +847,29 @@ init_new_session(struct iscsi_sendtarget
 		if (initiator_name[0] == '\0') {
 			log_error("Cannot perform discovery. Initiatorname "
 				  "required.");
-			free(session);
-			return NULL;
+			*rc = ISCSI_ERR_INVAL;
+			goto fail;
 		}
 	}
 
+	iface_copy(&session->nrec.iface, iface);
 	session->initiator_name = initiator_name;
 	session->initiator_alias = initiator_alias;
 	session->portal_group_tag = PORTAL_GROUP_TAG_UNKNOWN;
 	session->type = ISCSI_SESSION_TYPE_DISCOVERY;
-done:
-	return session;
-}
-
-
-static int
-setup_authentication(iscsi_session_t *session,
-		     discovery_rec_t *drec,
-		     struct iscsi_sendtargets_config *config)
-{
-	int rc;
+	session->id = -1;
 
-	rc = 1;
-
-	/* if we have any incoming credentials, we insist on authenticating
-	 * the target or not logging in at all
-	 */
-	if (config->auth.username_in[0]
-	    || config->auth.password_in_length) {
-		session->bidirectional_auth = 1;
-
-		/* sanity check the config */
-		if (config->auth.password_length == 0) {
-			log_error(
-			       "discovery process to %s:%d has incoming "
-			       "authentication credentials but has no outgoing "
-			       "credentials configured",
-			       drec->address, drec->port);
-			log_error(
-			       "discovery process to %s:%d exiting, bad "
-			       "configuration",
-			       drec->address, drec->port);
-			rc = 0;
-			goto done;
-		}
-	} else {
-		/* no or 1-way authentication */
-		session->bidirectional_auth = 0;
-	}
+	/* setup authentication variables for the session*/
+	*rc = iscsi_setup_authentication(session, &config->auth);
+	if (*rc)
+		goto fail;
 
-	/* copy in whatever credentials we have */
-	strlcpy(session->username, config->auth.username,
-		sizeof (session->username));
-	session->username[sizeof (session->username) - 1] = '\0';
-	if ((session->password_length = config->auth.password_length))
-		memcpy(session->password, config->auth.password,
-		       session->password_length);
-
-	strlcpy(session->username_in, config->auth.username_in,
-		sizeof (session->username_in));
-	session->username_in[sizeof (session->username_in) - 1] = '\0';
-	if ((session->password_in_length =
-	     config->auth.password_in_length))
-		memcpy(session->password_in, config->auth.password_in,
-		       session->password_in_length);
-
-	if (session->password_length || session->password_in_length) {
-		/* setup the auth buffers */
-		session->auth_buffers[0].address = &session->auth_client_block;
-		session->auth_buffers[0].length =
-		    sizeof (session->auth_client_block);
-		session->auth_buffers[1].address =
-		    &session->auth_recv_string_block;
-		session->auth_buffers[1].length =
-		    sizeof (session->auth_recv_string_block);
-
-		session->auth_buffers[2].address =
-		    &session->auth_send_string_block;
-		session->auth_buffers[2].length =
-		    sizeof (session->auth_send_string_block);
-
-		session->auth_buffers[3].address =
-		    &session->auth_recv_binary_block;
-		session->auth_buffers[3].length =
-		    sizeof (session->auth_recv_binary_block);
-
-		session->auth_buffers[4].address =
-		    &session->auth_send_binary_block;
-		session->auth_buffers[4].length =
-		    sizeof (session->auth_send_binary_block);
+	list_add_tail(&session->list, &session->t->sessions);
+	return session;
 
-		session->num_auth_buffers = 5;
-	} else {
-		session->num_auth_buffers = 0;
-	}
- done:
-	return(rc);
+fail:
+	free(session);
+	return NULL;
 }
 
 static int
@@ -1018,7 +878,6 @@ process_recvd_pdu(struct iscsi_hdr *pdu,
 		  struct list_head *rec_list,
 		  iscsi_session_t *session,
 		  struct str_buffer *sendtargets,
-		  char *default_port,
 		  int *active,
 		  int *valid_text,
 		  char *data)
@@ -1063,8 +922,7 @@ process_recvd_pdu(struct iscsi_hdr *pdu,
 			process_sendtargets_response(sendtargets,
 						     final,
 						     drec,
-						     rec_list,
-						     default_port);
+						     rec_list);
 
 			if (final) {
 				/* SendTargets exchange is now complete
@@ -1096,11 +954,9 @@ process_recvd_pdu(struct iscsi_hdr *pdu,
 }
 
 /*
- * Make a best effort to logout the session, then disconnect the
- * socket.
+ * Make a best effort to logout the session.
  */
-static void
-iscsi_logout_and_disconnect(iscsi_session_t * session)
+static void iscsi_logout(iscsi_session_t * session)
 {
 	struct iscsi_logout logout_req;
 	struct iscsi_logout_rsp logout_resp;
@@ -1128,7 +984,7 @@ iscsi_logout_and_disconnect(iscsi_sessio
 	if (!rc) {
 		log_error(
 		       "iscsid: iscsi_logout - failed to send logout PDU.");
-		goto done;
+		return;
 	}
 
 	/*
@@ -1138,117 +994,278 @@ iscsi_logout_and_disconnect(iscsi_sessio
 	rc = iscsi_io_recv_pdu(&session->conn[0],
 		(struct iscsi_hdr *)&logout_resp, ISCSI_DIGEST_NONE, NULL,
 		0, ISCSI_DIGEST_NONE, 1);
-	if (!rc) {
+	if (rc < 0) {
 		log_error("iscsid: logout - failed to receive logout resp");
-		goto done;
+		return;
 	}
 	if (logout_resp.response != ISCSI_LOGOUT_SUCCESS) {
 		log_error("iscsid: logout failed - response = 0x%x",
 		       logout_resp.response);
 	}
+}
 
+static void iscsi_destroy_session(struct iscsi_session *session)
+{
+	struct iscsi_transport *t = session->t;
+	struct iscsi_conn *conn = &session->conn[0];
+	int rc;
+
+	if (session->id == -1)
+		return;
+
+	if (!(t->caps & CAP_TEXT_NEGO)) {
+		iscsi_io_disconnect(&session->conn[0]);
+		goto done;
+	}
+
+	log_debug(2, "%s ep disconnect", __FUNCTION__);
+	t->template->ep_disconnect(conn);
+
+	log_debug(2, "stop conn");
+	rc = ipc->stop_conn(session->t->handle, session->id,
+			   conn->id, STOP_CONN_TERM);
+	if (rc) {
+		log_error("Could not stop conn %d:%d cleanly (err %d)\n",
+			  session->id, conn->id, rc);
+		goto done;
+        }
+
+	log_debug(2, "%s destroy conn", __FUNCTION__);
+        rc = ipc->destroy_conn(session->t->handle, session->id, conn->id);
+	if (rc) {
+		log_error("Could not safely destroy conn %d:%d (err %d)",
+			  session->id, conn->id, rc);
+		goto done;
+	}
+
+	log_debug(2, "%s destroy session", __FUNCTION__);
+	rc = ipc->destroy_session(session->t->handle, session->id);
+	if (rc)
+		log_error("Could not safely destroy session %d (err %d)",
+			  session->id, rc);
 done:
-	/*
-	 * Close the socket.
-	 */
-	iscsi_io_disconnect(&session->conn[0]);
+	if (conn->socket_fd >= 0) {
+		ipc->ctldev_close();
+		conn->socket_fd = -1;
+	}
+	session->id = -1;
 }
 
-int discovery_sendtargets(void *fndata, struct iface_rec *iface,
-			  struct list_head *rec_list)
+static int iscsi_create_leading_conn(struct iscsi_session *session)
 {
-	discovery_rec_t *drec = fndata;
-	iscsi_session_t *session;
-	struct pollfd pfd;
-	struct iscsi_hdr pdu_buffer;
-	struct iscsi_hdr *pdu = &pdu_buffer;
-	char *data = NULL;
-	int active = 0, valid_text = 0;
-	struct timeval connection_timer;
-	int timeout;
-	int rc;
-	struct str_buffer sendtargets;
-	uint8_t status_class = 0, status_detail = 0;
-	unsigned int login_failures = 0, data_len;
-	int login_delay = 0;
-	struct sockaddr_storage ss;
-	char host[NI_MAXHOST], serv[NI_MAXSERV], default_port[NI_MAXSERV];
-	struct iscsi_sendtargets_config *config = &drec->u.sendtargets;
+	struct iface_rec *iface = &session->nrec.iface;
+	struct iscsi_transport *t = session->t;
+	struct iscsi_conn *conn = &session->conn[0];
+	uint32_t host_no;
+	int rc, sleep_count = 0;
 
-	/* initial setup */
-	log_debug(1, "starting sendtargets discovery, address %s:%d, ",
-		 drec->address, drec->port);
-	memset(&pdu_buffer, 0, sizeof (pdu_buffer));
-	clear_timer(&connection_timer);
+	if (!(t->caps & CAP_TEXT_NEGO)) {
+		/*
+		 * If the LLD does not support TEXT PDUs then we do
+		 * discovery in userspace.
+		 */
+		session->use_ipc = 0;
 
-	/* allocate a new session, and initialize default values */
-	session = init_new_session(config, iface);
-	if (session == NULL) {
-		log_error("Discovery process to %s:%d failed to "
-			  "create a discovery session.",
-			  drec->address, drec->port);
-		return 1;
+		if (!iscsi_io_connect(conn))
+			return ISCSI_ERR_TRANS;
+
+		session->id = 1;
+		return 0;
 	}
+	session->use_ipc = 1;
 
-	log_debug(4, "sendtargets discovery to %s:%d using "
-		 "isid 0x%02x%02x%02x%02x%02x%02x",
-		 drec->address, drec->port, session->isid[0],
-		 session->isid[1], session->isid[2], session->isid[3],
-		 session->isid[4], session->isid[5]);
+	/*
+	 * for software this is the tcp socket fd set in iscsi_io_connect
+	 * and for offload this is the iscsi netlink socket fd
+	 */
+	conn->socket_fd = ipc->ctldev_open();
+	if (conn->socket_fd < 0) {
+		log_error("Could not open netlink interface (err %d)\n",
+			  errno);
+		return ISCSI_ERR_INTERNAL;
+	}
 
-	/* allocate data buffers for SendTargets data */
-	data = malloc(session->conn[0].max_recv_dlength);
-	if (!data) {
-		rc = 1;
-		goto free_session;
+	host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
+	if (!rc) {
+		/*
+		 * if the netdev or mac was set, then we are going to want
+		 * to want to bind the all the conns/eps to a specific host
+		 * if offload is used.
+		 */
+		session->conn[0].bind_ep = 1;
+		session->hostno = host_no;
 	}
-	data_len = session->conn[0].max_recv_dlength;
 
-	str_init_buffer(&sendtargets, 0);
+	rc = iscsi_host_set_net_params(iface, session);
+	if (rc) {
+		log_error("Could not set host net params (err %d)\n",
+			  rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto close_ipc;
+	}
+
+	/* create interconnect endpoint */
+	log_debug(2, "%s discovery ep connect\n", __FUNCTION__);
+	rc = t->template->ep_connect(conn, 1);
+	if (rc < 0) {
+		rc = ISCSI_ERR_TRANS;
+		goto fail;
+	}
+
+	do {
+		rc = t->template->ep_poll(conn, 1);
+		if (rc < 0) {
+			rc = ISCSI_ERR_TRANS;
+			goto disconnect;
+		} else if (rc == 0) {
+			if (sleep_count == conn->login_timeout) {
+				rc = ISCSI_ERR_TRANS_TIMEOUT;
+				goto disconnect;
+			}
+			sleep_count++;
+			sleep(1);
+		} else
+			break;
+	} while (1);
 
-	sprintf(default_port, "%d", drec->port);
-	/* resolve the DiscoveryAddress to an IP address */
-	if (resolve_address(drec->address, default_port, &ss)) {
-		log_error("cannot resolve host name %s", drec->address);
-		rc = 1;
-		goto free_sendtargets;
+	log_debug(2, "%s discovery create session\n", __FUNCTION__);
+	/* create kernel structs */
+        rc = ipc->create_session(session->t->handle,
+				 conn->transport_ep_handle, 1, 32, 1,
+				 &session->id, &host_no);
+	if (rc) {
+		log_error("Could not create kernel session (err %d).\n", rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto disconnect;
+	}
+	log_debug(2, "%s discovery created session %u\n", __FUNCTION__,
+		  session->id);
+	session->isid[3] = session->id;
+
+	log_debug(2, "%s discovery create conn\n", __FUNCTION__);
+	rc = ipc->create_conn(t->handle, session->id, conn->id, &conn->id);
+	if (rc) {
+		log_error("Could not create connection (err %d)", rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto disconnect;
+	}
+
+	log_debug(2, "%s discovery bind conn\n", __FUNCTION__);
+	if (ipc->bind_conn(t->handle, session->id, conn->id,
+			   conn->transport_ep_handle, (conn->id == 0), &rc) ||
+	    rc) {
+		log_error("Could not bind conn %d:%d to session %d, "
+			  "(err %d)", session->id, conn->id,
+			  session->id, rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto disconnect;
 	}
 
-	log_debug(4, "discovery timeouts: login %d, reopen_cnt %d, auth %d.",
-		 session->conn[0].login_timeout, session->reopen_cnt,
-		 session->conn[0].auth_timeout);
+	/* all set */
+	return 0;
 
-	/* setup authentication variables for the session*/
-	rc = setup_authentication(session, drec, config);
-	if (rc == 0) {
-		rc = 1;
-		goto free_sendtargets;
+disconnect:
+	t->template->ep_disconnect(conn);
+
+	if (session->id != -1 &&
+	    iscsi_sysfs_session_has_leadconn(session->id)) {
+		if (ipc->destroy_conn(session->t->handle, session->id,
+				       conn->id))
+			log_error("Could not safely destroy connection %d:%d",
+				  session->id, conn->id);
+	}
+
+	if (session->id != -1) {
+		if (ipc->destroy_session(session->t->handle, session->id))
+			log_error("Could not safely destroy session %d",
+				  session->id);
+		session->id = -1;
+	}
+
+close_ipc:
+	if (conn->socket_fd >= 0) {
+		ipc->ctldev_close();
+		conn->socket_fd = -1;
+	}
+fail:
+	log_error("Connection to discovery portal %s failed: %s",
+		  conn->host, iscsi_err_to_str(rc));
+	return rc;
+}
+
+static struct iscsi_ev_context *
+iscsi_ev_context_get(struct iscsi_conn *conn, int ev_size)
+{
+	log_debug(2, "%s: ev_size %d\n", __FUNCTION__, ev_size);
+
+	ipc_ev_context.data = calloc(1, ev_size);
+	if (!ipc_ev_context.data)
+		return NULL;
+
+	return &ipc_ev_context;
+}
+
+static void iscsi_ev_context_put(struct iscsi_ev_context *ev_context)
+{
+	if (ev_context->data)
+		free(ev_context->data);
+	ev_context->data = NULL;
+}
+
+static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
+				  struct iscsi_conn *conn, unsigned long tmo,
+				  int event)
+{
+	if (event == EV_CONN_RECV_PDU) {
+		conn->recv_context = ev_context;
+		return 0;
 	}
 
+	return -EIO;
+}
+
+static struct iscsi_ipc_ev_clbk ipc_clbk = {
+        .get_ev_context         = iscsi_ev_context_get,
+        .put_ev_context         = iscsi_ev_context_put,
+        .sched_ev_context       = iscsi_sched_ev_context,
+};
+
+static int iscsi_create_session(struct iscsi_session *session,
+				struct iscsi_sendtargets_config *config,
+				char *data, unsigned int data_len)
+{
+	struct iscsi_conn *conn = &session->conn[0];
+	int login_status, rc = 0, login_delay = 0;
+	uint8_t status_class = 0, status_detail = 0;
+	unsigned int login_failures = 0;
+	char serv[NI_MAXSERV];
+	struct iscsi_transport *t = session->t;
+
 set_address:
 	/*
 	 * copy the saved address to the session,
 	 * undoing any temporary redirect
 	 */
-	session->conn[0].saddr = ss;
+	conn->saddr = conn->failback_saddr;
 
 reconnect:
-
+	/* fix decrement and test */
 	if (--session->reopen_cnt < 0) {
-		log_error("connection login retries (reopen_max %d) exceeded",
+		log_error("connection login retries (reopen_max) %d exceeded",
 			  config->reopen_max);
-		rc = 1;
-		goto free_sendtargets;
+		goto login_failed;
 	}
 
 redirect_reconnect:
-
-	iscsi_io_disconnect(&session->conn[0]);
-
 	session->cmdsn = 1;
 	session->itt = 1;
 	session->portal_group_tag = PORTAL_GROUP_TAG_UNKNOWN;
 
+	/*
+	 * On reconnect, just destroy the kernel structs and start over.
+	 */
+	iscsi_destroy_session(session);
+
 	/* slowly back off the frequency of login attempts */
 	if (login_failures == 0)
 		login_delay = 0;
@@ -1263,47 +1280,44 @@ redirect_reconnect:
 	else
 		login_delay = 60;	/* after 2 minutes, try once a minute */
 
+	getnameinfo((struct sockaddr *) &conn->saddr,
+		    sizeof(conn->saddr), conn->host,
+		    sizeof(conn->host), serv, sizeof(serv),
+		    NI_NUMERICHOST|NI_NUMERICSERV);
+
 	if (login_delay) {
-		log_debug(4, "discovery session to %s:%d sleeping for %d "
+		log_debug(4, "discovery session to %s:%s sleeping for %d "
 			 "seconds before next login attempt",
-			 drec->address, drec->port, login_delay);
+			 conn->host, serv, login_delay);
 		sleep(login_delay);
 	}
-
-	getnameinfo((struct sockaddr *) &session->conn[0].saddr,
-		    sizeof(session->conn[0].saddr), host,
-		    sizeof(host), serv, sizeof(serv),
-		    NI_NUMERICHOST|NI_NUMERICSERV);
-
-	if (!iscsi_io_connect(&session->conn[0])) {
-		log_error("connection to discovery address %s "
-			  "failed", host);
-
+	rc = iscsi_create_leading_conn(session);
+	if (rc) {
 		login_failures++;
-		/* If a temporary redirect sent us to something unreachable,
-		 * we want to go back to the original IP address, so make sure
-		 * we reset the session's IP.
-		 */
-		goto set_address;
+		goto reconnect;
 	}
 
-	log_debug(1, "connected to discovery address %s", host);
+	log_debug(1, "connected to discovery address %s", conn->host);
 
-	log_debug(4, "discovery session to %s:%d starting iSCSI login on fd %d",
-		 drec->address, drec->port, session->conn[0].socket_fd);
+	log_debug(4, "discovery session to %s:%s starting iSCSI login",
+		 conn->host, serv);
 
-	/* In case of discovery, we using socket's descriptor as ctrl. */
-	session->ctrl_fd = session->conn[0].socket_fd;
-	session->conn[0].session = session;
+	/*
+	 * Need to re-init settings because a previous login could
+	 * have set them to what was negotiated for.
+	 */
+	iscsi_copy_operational_params(&session->conn[0], &config->session_conf,
+				      &config->conn_conf);
 
 	status_class = 0;
 	status_detail = 0;
+	rc = ISCSI_ERR_LOGIN;
 
 	memset(data, 0, data_len);
-	rc = iscsi_login(session, 0, data, data_len,
-			 &status_class, &status_detail);
+	login_status = iscsi_login(session, 0, data, data_len,
+				   &status_class, &status_detail);
 
-	switch (rc) {
+	switch (login_status) {
 	case LOGIN_OK:
 	case LOGIN_REDIRECT:
 		break;
@@ -1311,8 +1325,7 @@ redirect_reconnect:
 	case LOGIN_IO_ERROR:
 	case LOGIN_REDIRECTION_FAILED:
 		/* try again */
-		log_warning("retrying discovery login to %s", host);
-		iscsi_io_disconnect(&session->conn[0]);
+		log_warning("retrying discovery login to %s", conn->host);
 		login_failures++;
 		goto set_address;
 
@@ -1322,16 +1335,16 @@ redirect_reconnect:
 	case LOGIN_AUTHENTICATION_FAILED:
 	case LOGIN_VERSION_MISMATCH:
 	case LOGIN_INVALID_PDU:
-		log_error("discovery login to %s failed, giving up", host);
-		iscsi_io_disconnect(&session->conn[0]);
-		rc = 1;
-		goto free_sendtargets;
+		log_error("discovery login to %s failed, giving up %d",
+			  conn->host, login_status);
+		rc = ISCSI_ERR_FATAL_LOGIN;
+		goto login_failed;
 	}
 
 	/* check the login status */
 	switch (status_class) {
 	case ISCSI_STATUS_CLS_SUCCESS:
-		log_debug(4, "discovery login success to %s", host);
+		log_debug(4, "discovery login success to %s", conn->host);
 		login_failures = 0;
 		break;
 	case ISCSI_STATUS_CLS_REDIRECT:
@@ -1343,14 +1356,16 @@ redirect_reconnect:
 		case ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP:
 			log_warning(
 				"discovery login temporarily redirected to "
-				"%s port %s", host, serv);
+				"%s port %s", conn->host, serv);
 			goto redirect_reconnect;
 		case ISCSI_LOGIN_STATUS_TGT_MOVED_PERM:
 			log_warning(
 				"discovery login permanently redirected to "
-				"%s port %s", host, serv);
+				"%s port %s", conn->host, serv);
 			/* make the new address permanent */
-			ss = session->conn[0].saddr;
+			memset(&conn->failback_saddr, 0,
+				sizeof(struct sockaddr_storage));
+			conn->failback_saddr = conn->saddr;
 			goto redirect_reconnect;
 		default:
 			log_error(
@@ -1361,32 +1376,130 @@ redirect_reconnect:
 		}
 		break;
 	case ISCSI_STATUS_CLS_INITIATOR_ERR:
-		log_error(
-			"discovery login to %s rejected: "
-			"initiator error (%02x/%02x), non-retryable, giving up",
-			host, status_class, status_detail);
-		iscsi_io_disconnect(&session->conn[0]);
-		rc = 1;
-		goto free_sendtargets;
+		switch (status_detail) {
+		case ISCSI_LOGIN_STATUS_AUTH_FAILED:
+		case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN:
+			log_error("discovery login to %s rejected: "
+				  "initiator failed authorization\n",
+				 conn->host);
+			rc = ISCSI_ERR_LOGIN_AUTH_FAILED;
+			goto login_failed;
+		default:
+			log_error("discovery login to %s rejected: initiator "
+				  "error (%02x/%02x), non-retryable, giving up",
+				  conn->host, status_class, status_detail);
+			rc = ISCSI_ERR_FATAL_LOGIN;
+		}
+		goto login_failed;
 	case ISCSI_STATUS_CLS_TARGET_ERR:
 		log_error(
 			"discovery login to %s rejected: "
 			"target error (%02x/%02x)",
-			host, status_class, status_detail);
-		iscsi_io_disconnect(&session->conn[0]);
+			conn->host, status_class, status_detail);
 		login_failures++;
 		goto reconnect;
 	default:
 		log_error(
 			"discovery login to %s failed, response "
 			"with unknown status class 0x%x, detail 0x%x",
-			host,
+			conn->host,
 			status_class, status_detail);
-		iscsi_io_disconnect(&session->conn[0]);
 		login_failures++;
 		goto reconnect;
 	}
 
+	if (!(t->caps & CAP_TEXT_NEGO))
+		return 0;
+
+	log_debug(2, "%s discovery set params\n", __FUNCTION__);
+	rc = iscsi_session_set_params(conn);
+	if (rc) {
+		log_error("Could not set iscsi params for conn %d:%d (err "
+			  "%d)\n", session->id, conn->id, rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto login_failed;
+	}
+
+	log_debug(2, "%s discovery start conn\n", __FUNCTION__);
+	if (ipc->start_conn(t->handle, session->id, conn->id, &rc) || rc) {
+		log_error("Cannot start conn %d:%d (err %d)",
+			  session->id, conn->id, rc);
+		rc = ISCSI_ERR_INTERNAL;
+		goto login_failed;
+	}
+
+	return 0;
+
+login_failed:
+	iscsi_destroy_session(session);
+	return rc;
+}
+
+int discovery_sendtargets(void *fndata, struct iface_rec *iface,
+			  struct list_head *rec_list)
+{
+	discovery_rec_t *drec = fndata;
+	iscsi_session_t *session;
+	struct pollfd pfd;
+	struct iscsi_hdr pdu_buffer;
+	struct iscsi_hdr *pdu = &pdu_buffer;
+	char *data = NULL;
+	int active = 0, valid_text = 0;
+	struct timeval connection_timer;
+	int timeout;
+	int rc = 0;
+	struct str_buffer sendtargets;
+	unsigned int data_len;
+	struct iscsi_sendtargets_config *config = &drec->u.sendtargets;
+
+	/* initial setup */
+	log_debug(1, "starting sendtargets discovery, address %s:%d, ",
+		 drec->address, drec->port);
+	memset(&pdu_buffer, 0, sizeof (pdu_buffer));
+	iscsi_timer_clear(&connection_timer);
+
+	/* allocate a new session, and initialize default values */
+	session = iscsi_alloc_session(config, iface, &rc);
+	if (rc)
+		return rc;
+
+	ipc_ev_context.conn = &session->conn[0];
+	ipc_register_ev_callback(&ipc_clbk);
+
+	log_debug(4, "sendtargets discovery to %s:%d using "
+		 "isid 0x%02x%02x%02x%02x%02x%02x",
+		 drec->address, drec->port, session->isid[0],
+		 session->isid[1], session->isid[2], session->isid[3],
+		 session->isid[4], session->isid[5]);
+
+	/* allocate data buffers for SendTargets data */
+	data = malloc(session->conn[0].max_recv_dlength);
+	if (!data) {
+		rc = ISCSI_ERR_NOMEM;
+		goto free_session;
+	}
+	data_len = session->conn[0].max_recv_dlength;
+
+	str_init_buffer(&sendtargets, 0);
+
+	/* resolve the DiscoveryAddress to an IP address */
+	rc = iscsi_setup_portal(&session->conn[0], drec->address,
+				drec->port);
+	if (rc) {
+		log_error("cannot resolve host name %s", drec->address);
+		goto free_sendtargets;
+	}
+
+	log_debug(4, "discovery timeouts: login %d, reopen_cnt %d, auth %d.",
+		 session->conn[0].login_timeout, session->reopen_cnt,
+		 session->conn[0].auth_timeout);
+
+reconnect:
+	rc = iscsi_create_session(session, &drec->u.sendtargets,
+				  data, data_len);
+	if (rc)
+		goto free_sendtargets;
+
 	/* reinitialize */
 	str_truncate_buffer(&sendtargets, 0);
 
@@ -1397,7 +1510,7 @@ redirect_reconnect:
 	active = 1;
 
 	/* set timeouts */
-	set_timer(&connection_timer, session->conn[0].active_timeout);
+	iscsi_timer_set(&connection_timer, session->conn[0].active_timeout);
 
 	/* prepare to poll */
 	memset(&pfd, 0, sizeof (pfd));
@@ -1405,7 +1518,7 @@ redirect_reconnect:
 	pfd.events = POLLIN | POLLPRI;
 
 repoll:
-	timeout = msecs_until(&connection_timer);
+	timeout = iscsi_timer_msecs_until(&connection_timer);
 	/* block until we receive a PDU, a TCP FIN, a TCP RST,
 	 * or a timeout
 	 */
@@ -1422,31 +1535,30 @@ repoll:
 		 "discovery process to %s:%d returned from poll, rc %d",
 		 drec->address, drec->port, rc);
 
-	if (timer_expired(&connection_timer)) {
-		log_warning("discovery session to %s:%d session "
-			    "logout, connection timer expired",
+	if (iscsi_timer_expired(&connection_timer)) {
+		log_warning("Discovery session to %s:%d timed out.",
 			    drec->address, drec->port);
-			    iscsi_logout_and_disconnect(session);
-		rc = 1;
-		goto free_sendtargets;
+		rc = ISCSI_ERR_TRANS_TIMEOUT;
+		goto reconnect;
 	}
 
 	if (rc > 0) {
 		if (pfd.revents & (POLLIN | POLLPRI)) {
-			timeout = msecs_until(&connection_timer);
+			timeout = iscsi_timer_msecs_until(&connection_timer);
 
-			memset(data, 0, data_len);
-			if (!iscsi_io_recv_pdu(&session->conn[0],
-					       pdu, ISCSI_DIGEST_NONE, data,
-			     		       data_len, ISCSI_DIGEST_NONE,
-					       timeout)) {
+			rc = iscsi_io_recv_pdu(&session->conn[0],
+					        pdu, ISCSI_DIGEST_NONE, data,
+					        data_len, ISCSI_DIGEST_NONE,
+					        timeout);
+			if (rc == -EAGAIN)
+				goto repoll;
+			else if (rc < 0) {
 				log_debug(1, "discovery session to "
 					  "%s:%d failed to recv a PDU "
 					  "response, terminating",
 					   drec->address,
 					   drec->port);
-				iscsi_io_disconnect(&session->conn[0]);
-				rc = 1;
+				rc = ISCSI_ERR_PDU_TIMEOUT;
 				goto free_sendtargets;
 			}
 
@@ -1455,14 +1567,13 @@ repoll:
 			 */
 			rc = process_recvd_pdu(pdu, drec, rec_list,
 					       session, &sendtargets,
-					       default_port,
 					       &active, &valid_text, data);
 			if (rc == DISCOVERY_NEED_RECONNECT)
 				goto reconnect;
 
 			/* reset timers after receiving a PDU */
 			if (active) {
-				set_timer(&connection_timer,
+				iscsi_timer_set(&connection_timer,
 				       session->conn[0].active_timeout);
 				goto repoll;
 			}
@@ -1472,8 +1583,7 @@ repoll:
 			log_warning("discovery session to %s:%d "
 				    "terminating after hangup",
 				     drec->address, drec->port);
-			iscsi_io_disconnect(&session->conn[0]);
-			rc = 1;
+			rc = ISCSI_ERR_TRANS;
 			goto free_sendtargets;
 		}
 
@@ -1489,18 +1599,9 @@ repoll:
 			goto reconnect;
 		}
 	} else if (rc < 0) {
-		if (errno == EINTR) {
-			/* if we got SIGHUP, reconnect and rediscover */
-			if (rediscover) {
-				rediscover = 0;
-				log_debug(1, "rediscovery requested");
-				goto reconnect;
-			}
-		} else {
-			log_error("poll error");
-			rc = 1;
-			goto free_sendtargets;
-		}
+		log_error("poll error");
+		rc = ISCSI_ERR;
+		goto free_sendtargets;
 	}
 
 	log_debug(1, "discovery process to %s:%d exiting",
@@ -1510,8 +1611,9 @@ repoll:
 free_sendtargets:
 	str_free_buffer(&sendtargets);
 	free(data);
+	iscsi_destroy_session(session);
 free_session:
-	free(session);
+	iscsi_free_session(session);
 	return rc;
 }
 
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/discoveryd.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/discoveryd.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/discoveryd.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/discoveryd.c	2011-02-03 20:14:23.000000000 -0600
@@ -44,6 +44,7 @@
 #include "isns.h"
 #include "paths.h"
 #include "message.h"
+#include "iscsi_err.h"
 
 #define DISC_DEF_POLL_INVL	30
 
@@ -242,12 +243,12 @@ static int isns_build_objs(isns_portal_i
 		nportals = isns_get_nr_portals();
 		log_debug(4, "got %d portals", nportals);
 		if (!nportals)
-			return ENODEV;
+			return ISCSI_ERR_NO_OBJS_FOUND;
 
 		iflist = calloc(nportals, sizeof(isns_portal_info_t));
 		if (!iflist) {
 			log_error("Unable to allocate %d portals.", nportals);
-			return ENOMEM;
+			return ISCSI_ERR_NOMEM;
 		}
 
 		nportals = isns_enumerate_portals(iflist, nportals);
@@ -255,7 +256,7 @@ static int isns_build_objs(isns_portal_i
 			log_error("Unable to enumerate portals - "
 				  "no usable interfaces found\n");
 			free(iflist);
-			return ENODEV;
+			return ISCSI_ERR_NO_OBJS_FOUND;
 		}
 		for (i = 0; i < nportals; ++i) {
 			iflist[i].addr.sin6_port = portal_info->addr.sin6_port;
@@ -267,7 +268,7 @@ static int isns_build_objs(isns_portal_i
 	if (!isns_entity_id) {
 		isns_entity_id = calloc(1, 256);
 		if (!isns_entity_id)
-			return ENOMEM;
+			return ISCSI_ERR_NOMEM;
 
 		rc = getnameinfo((struct sockaddr *) &portal_info->addr,
 				 sizeof(portal_info->addr),
@@ -277,14 +278,14 @@ static int isns_build_objs(isns_portal_i
 			isns_entity_id = NULL;
 
 			log_error("Could not get hostname for EID.");
-			return EIO;
+			return ISCSI_ERR;
 		}
 	}
 
 	entity = isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI, isns_entity_id);
 	if (!entity) {
 		log_error("Could not create iSNS entity.");
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	}
 	isns_object_list_append(objs, entity);
 
@@ -293,14 +294,14 @@ static int isns_build_objs(isns_portal_i
 
 		portal = isns_create_portal(portal_info, entity);
 		if (!portal) {
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto fail;
 		}
 		isns_object_list_append(objs, portal);
 
 		if (!isns_object_set_uint32(portal, ISNS_TAG_SCN_PORT,
 				isns_portal_tcpudp_port(portal_info))) {
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			goto fail;
 		}
 	}
@@ -310,7 +311,7 @@ static int isns_build_objs(isns_portal_i
 						  ISNS_ISCSI_INITIATOR_MASK,
 						  NULL);
 		if (!inode) {
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto fail;
 		}
 		isns_object_list_append(objs, inode);		
@@ -366,7 +367,6 @@ static int isns_disc_new_portals(const c
 	qry_data.targetname = targetname;
 	qry_data.iname = iname;
 
-log_error("isns_disc_new_portals");
 	iface_link_ifaces(&ifaces);
 	rc = idbm_bind_ifaces_to_nodes(isns_query_node, &qry_data, &ifaces,
 				       &rec_list);
@@ -559,7 +559,7 @@ static int isns_setup_registration_refre
 		log_error("Unable to extract object list from "
                            "registration response: %s\n",
                            isns_strerror(status));
-		return EIO;
+		return ISCSI_ERR;
 	}
 
 	for (i = 0; i < objs.iol_count; ++i) {
@@ -578,7 +578,7 @@ static int isns_setup_registration_refre
 
 	refresh_data = calloc(1, sizeof(*refresh_data));
 	if (!refresh_data) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_objs;
 	}
 	INIT_LIST_HEAD(&refresh_data->list);
@@ -654,7 +654,7 @@ static int isns_register_objs(isns_clien
 
 	reg = isns_create_registration(clnt, entity);
 	if (!reg)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	for (i = 0; i < objs->iol_count; ++i)
 		isns_registration_add_object(reg, objs->iol_data[i]);
@@ -664,7 +664,7 @@ static int isns_register_objs(isns_clien
 	if (status != ISNS_SUCCESS) {
 		log_error("Could not register with iSNS server: %s",
 			  isns_strerror(status));
-		rc = EIO;
+		rc = ISCSI_ERR;
 		goto free_reg;
 	}
 	log_debug(4, "Registered objs");
@@ -687,7 +687,7 @@ static int isns_register_objs(isns_clien
 
 		if (!reg) {
 			isns_cancel_refresh_timers();
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto done;
 		}
 
@@ -703,7 +703,7 @@ static int isns_register_objs(isns_clien
 			 */
 			if (poll_inval < 0) {
 				isns_cancel_refresh_timers();
-				rc = EIO;
+				rc = ISCSI_ERR;
 				break;
 			}
 		}
@@ -727,7 +727,7 @@ static int isns_scn_register(isns_socket
 	clnt = isns_create_default_client(NULL);
 	if (!clnt) {
 		log_error("iSNS setup failed. Could not connect to server.");
-		return ENOTCONN;
+		return ISCSI_ERR_TRANS;
 	}
 	isns_socket_set_disconnect_fatal(clnt->ic_socket);
 
@@ -735,7 +735,7 @@ static int isns_scn_register(isns_socket
 
 	if (!isns_socket_get_portal_info(svr_sock, &portal_info)) {
 		log_error("Could not get portal info for iSNS registration.");
-		rc = ENODEV;
+		rc = ISCSI_ERR_NO_OBJS_FOUND;
 		goto destroy_clnt;
 	}
 
@@ -797,7 +797,7 @@ static int isns_create_node_list(const c
 	if (def_iname) {
 		node = isns_create_node(def_iname);
 		if (!node) {
-			rc = ENOMEM;
+			rc = ISCSI_ERR_NOMEM;
 			goto fail;
 		}
 		list_add_tail(&node->list, &isns_initiators);
@@ -808,7 +808,7 @@ static int isns_create_node_list(const c
 		    !isns_lookup_node(iface->iname)) {
 			node = isns_create_node(iface->iname);
 			if (!node) {
-				rc = ENOMEM;
+				rc = ISCSI_ERR_NOMEM;
 				goto fail;
 			}
 			list_add_tail(&node->list, &isns_initiators);
@@ -943,7 +943,7 @@ static int isns_eventd(const char *def_i
 	isns_create_node_list(def_iname);
 	if (list_empty(&isns_initiators)) {
 		log_error("iSNS registration failed. Initiatorname not set.");
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	/* use def_iname or if not set the first iface's iname for the src */
@@ -955,7 +955,7 @@ static int isns_eventd(const char *def_i
 	isns_config.ic_control_socket = ISNS_EVENTD_CTL;
 
 	if (discovery_isns_set_servername(disc_addr, port)) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto fail;
 	}
 
@@ -964,13 +964,13 @@ static int isns_eventd(const char *def_i
 	db = isns_db_open(NULL);
 	if (!db) {
 		log_error("iSNS setup failed. Could not create db.");
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto fail;
 	}
 	svr = isns_create_server(node->source, db, &isns_callback_service_ops);
 	if (!svr) {
 		log_error("iSNS setup failed. Could not create server.");
-		rc = ENOTCONN;
+		rc = ISCSI_ERR_TRANS;
 		goto fail;
 	}
 	isns_server_set_scn_callback(svr, isns_scn_callback);
@@ -978,7 +978,7 @@ static int isns_eventd(const char *def_i
 	svr_sock = isns_create_server_socket(NULL, NULL, AF_INET6, SOCK_DGRAM);
 	if (!svr_sock) {
 		log_error("iSNS setup failed. Could not create server socket.");
-		rc = ENOTCONN;
+		rc = ISCSI_ERR_TRANS;
 		goto fail;
 	}
 
@@ -1077,7 +1077,7 @@ static int st_start(void *data, struct d
 	log_debug(1, "st_start %s:%d %d", drec->address, drec->port,
 		  drec->u.sendtargets.use_discoveryd);
 	if (!drec->u.sendtargets.use_discoveryd)
-		return ENOSYS;
+		return ISCSI_ERR_INVAL;
 
 	fork_disc(NULL, drec, drec->u.sendtargets.discoveryd_poll_inval,
 		  do_st_disc_and_login);
@@ -1094,7 +1094,7 @@ static int isns_start(void *data, struct
 	log_debug(1, "isns_start %s:%d %d", drec->address, drec->port,
 		  drec->u.isns.use_discoveryd);
 	if (!drec->u.isns.use_discoveryd)
-		return ENOSYS;
+		return ISCSI_ERR_INVAL;
 
 	fork_disc(data, drec, drec->u.isns.discoveryd_poll_inval, start_isns);
 	return 0;
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/event_poll.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/event_poll.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/event_poll.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/event_poll.c	2011-02-03 20:14:23.000000000 -0600
@@ -35,6 +35,7 @@
 #include "iscsi_ipc.h"
 #include "actor.h"
 #include "initiator.h"
+#include "iscsi_err.h"
 
 static int reap_count;
 
@@ -174,5 +175,5 @@ void event_loop(struct iscsi_ipc *ipc, i
 		sysfs_cleanup();
 	}
 	if (shutdown_qtask)
-		mgmt_ipc_write_rsp(shutdown_qtask, MGMT_IPC_OK);
+		mgmt_ipc_write_rsp(shutdown_qtask, ISCSI_SUCCESS);
 }
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/host.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/host.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.c	2011-02-03 20:14:23.000000000 -0600
@@ -33,6 +33,7 @@
 #include "transport.h"
 #include "initiator.h"
 #include "iface.h"
+#include "iscsi_err.h"
 
 static int match_host_to_session(void *data, struct session_info *info)
 {
@@ -200,13 +201,16 @@ int host_info_print(int info_level, uint
 		break;
 	default:
 		log_error("Invalid info level %d. Try 0 - 4.", info_level);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	if (err) {
-		log_error("Can not get list of iSCSI hosts (%d)", err);
+		log_error("Can not get list of iSCSI hosts: %s",
+			  iscsi_err_to_str(err));
 		return err;
-	} else if (!num_found)
+	} else if (!num_found) {
 		log_error("No iSCSI hosts.");
+		return ISCSI_ERR_NO_OBJS_FOUND;
+	}
 	return 0;
 }
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c	2011-02-03 20:14:23.000000000 -0600
@@ -40,6 +40,7 @@
 #include "iface.h"
 #include "sysdeps.h"
 #include "fw_context.h"
+#include "iscsi_err.h"
 
 #define IDBM_HIDE	0    /* Hide parameter when print. */
 #define IDBM_SHOW	1    /* Show parameter when print. */
@@ -179,7 +180,7 @@ idbm_recinfo_discovery(discovery_rec_t *
 			      u.sendtargets.conn_timeo.active_timeout,
 			      IDBM_SHOW, num, 1);
 		__recinfo_int(DISC_ST_MAX_RECV_DLEN, ri, r,
-			      u.sendtargets.iscsi.MaxRecvDataSegmentLength,
+			      u.sendtargets.conn_conf.MaxRecvDataSegmentLength,
 			      IDBM_SHOW, num, 1);
 		break;
 	case DISCOVERY_TYPE_ISNS:
@@ -426,6 +427,31 @@ void idbm_print(int type, void *rec, int
 }
 
 static void
+idbm_setup_session_defaults(struct iscsi_session_operational_config *conf)
+{
+	conf->InitialR2T = 0;
+	conf->ImmediateData = 1;
+	conf->FirstBurstLength = DEF_INI_FIRST_BURST_LEN;
+	conf->MaxBurstLength = DEF_INI_MAX_BURST_LEN;
+	conf->DefaultTime2Wait = ISCSI_DEF_TIME2WAIT;
+	conf->DefaultTime2Retain = 0;
+	conf->MaxConnections = 1;
+	conf->MaxOutstandingR2T = 1;
+	conf->ERL = 0;
+	conf->FastAbort = 1;
+}
+
+static void idbm_setup_conn_defaults(struct iscsi_conn_operational_config *conf)
+{
+	conf->MaxXmitDataSegmentLength = 0;
+	conf->MaxRecvDataSegmentLength = DEF_INI_MAX_RECV_SEG_LEN;
+	conf->HeaderDigest = CONFIG_DIGEST_NEVER;
+	conf->DataDigest = CONFIG_DIGEST_NEVER;
+	conf->IFMarker = 0;
+	conf->OFMarker = 0;
+}
+
+static void
 idbm_discovery_setup_defaults(discovery_rec_t *rec, discovery_type_e type)
 {
 	memset(rec, 0, sizeof(discovery_rec_t));
@@ -443,7 +469,10 @@ idbm_discovery_setup_defaults(discovery_
 		rec->u.sendtargets.conn_timeo.login_timeout=15;
 		rec->u.sendtargets.conn_timeo.auth_timeout = 45;
 		rec->u.sendtargets.conn_timeo.active_timeout=30;
-		rec->u.sendtargets.iscsi.MaxRecvDataSegmentLength =
+		idbm_setup_session_defaults(&rec->u.sendtargets.session_conf);
+		idbm_setup_conn_defaults(&rec->u.sendtargets.conn_conf);
+		/* override def setting */
+		rec->u.sendtargets.conn_conf.MaxRecvDataSegmentLength =
 						DEF_INI_DISC_MAX_RECV_SEG_LEN;
 		break;
 	case DISCOVERY_TYPE_SLP:
@@ -515,7 +544,7 @@ setup_passwd_len:
 		}
 	}
 
-	return 1;
+	return ISCSI_ERR_INVAL;
 
 updated:
 	strlcpy((char*)info[i].value, value, VALUE_MAXVAL);
@@ -556,12 +585,12 @@ int idbm_verify_param(recinfo_t *info, c
 		else {
 			log_error("Cannot modify %s. It is used to look up "
 				  "the record and cannot be changed.", name);
-			return EINVAL;
+			return ISCSI_ERR_INVAL;
 		}
 	}
 
 	log_error("Cannot modify %s. Invalid param name.", name);
-	return EINVAL;
+	return ISCSI_ERR_INVAL;
 }
 
 void idbm_recinfo_config(recinfo_t *info, FILE *f)
@@ -627,7 +656,7 @@ void idbm_recinfo_config(recinfo_t *info
 		}
 		*(value+i) = 0;
 
-		(void)idbm_rec_update_param(info, name, value, line_number);
+		idbm_rec_update_param(info, name, value, line_number);
 	} while (line);
 }
 
@@ -781,19 +810,19 @@ get_params_from_disc_link(char *link, ch
 	(*target) = link;
 	*address = strchr(*target, ',');
 	if (!(*address))
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	*(*address)++ = '\0';
 	*port = strchr(*address, ',');
 	if (!(*port))
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	*(*port)++ = '\0';
 	*tpgt = strchr(*port, ',');
 	if (!(*tpgt))
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	*(*tpgt)++ = '\0';
 	*ifaceid = strchr(*tpgt, ',');
 	if (!(*ifaceid))
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	*(*ifaceid)++ = '\0';
 	return 0;
 }
@@ -809,8 +838,9 @@ int idbm_lock(void)
 
 	if (access(LOCK_DIR, F_OK) != 0) {
 		if (mkdir(LOCK_DIR, 0660) != 0) {
-			log_error("Could not open %s. Exiting\n", LOCK_DIR);
-			return errno;
+			log_error("Could not open %s: %s\n", LOCK_DIR,
+				  strerror(errno));
+			return ISCSI_ERR_IDBM;
 		}
 	}
 
@@ -827,7 +857,7 @@ int idbm_lock(void)
 			log_error("Maybe you are not root?");
 			log_error("Could not lock discovery DB: %s: %s",
 					LOCK_WRITE_FILE, strerror(errno));
-			return errno;
+			return ISCSI_ERR_IDBM;
 		} else if (i == 0)
 			log_debug(2, "Waiting for discovery DB lock");
 
@@ -880,7 +910,7 @@ static int __idbm_rec_read(node_rec_t *o
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	rc = idbm_lock();
 	if (rc)
@@ -888,8 +918,9 @@ static int __idbm_rec_read(node_rec_t *o
 
 	f = fopen(conf, "r");
 	if (!f) {
-		log_debug(5, "Could not open %s err %d\n", conf, errno);
-		rc = errno;
+		log_debug(5, "Could not open %s err %s\n", conf,
+			  strerror(errno));
+		rc = ISCSI_ERR_IDBM;
 		goto unlock;
 	}
 
@@ -916,7 +947,7 @@ idbm_rec_read(node_rec_t *out_rec, char 
 
 	portal = calloc(1, PATH_MAX);
 	if (!portal)
-		return ENOMEM;
+		return ISCSI_ERR_IDBM;
 
 	/* try old style portal as config */
 	snprintf(portal, PATH_MAX, "%s/%s/%s,%d", NODE_CONFIG_DIR,
@@ -929,14 +960,14 @@ idbm_rec_read(node_rec_t *out_rec, char 
 		 targetname, ip, port, tpgt, iface->name);
 	log_debug(5, "rec read looking for config file %s.", portal);
 	if (!strlen(iface->name)) {
-		rc = EINVAL;
+		rc = ISCSI_ERR_INVAL;
 		goto free_portal;
 	}
 
 	if (stat(portal, &statb)) {
-		log_debug(5, "Could not stat %s err %d.", portal, errno);
+		log_debug(5, "Could not stat %s: %s.", portal, strerror(errno));
 		free(portal);
-		return errno;
+		return ISCSI_ERR_IDBM;
 	}
 
 read:
@@ -1078,17 +1109,12 @@ static int __idbm_print_all_by_drec(void
 	if (info_level >= 1) {
 		printf("DiscoveryAddress: %s,%d\n",
 		       drec->address, drec->port);
-		rc = idbm_print_discovered(drec, info_level);
-		if (rc)
-			return 0;
-		else
-			return ENODEV;
-	} else {
+		idbm_print_discovered(drec, info_level);
+	} else
 		printf("%s:%d via %s\n", drec->address, drec->port,
 		       drec->type == DISCOVERY_TYPE_ISNS ?
 		       "isns" : "sendtargets");
-		return 0;
-	}
+	return 0;
 }
 
 static int idbm_print_all_st(int info_level)
@@ -1168,11 +1194,23 @@ int idbm_print_all_discovery(int info_le
 	return found;
 }
 
-/*
- * This iterates over the ifaces in use in the nodes dir.
- * It does not iterate over the ifaces setup in /etc/iscsi/ifaces.
+/**
+ * idbm_for_each_iface - iterate over bound iface recs
+ * @found: nr of recs found so far
+ * @data: data pointer passed to fn
+ * @fn: iterator function ran over each bound iface rec
+ * @targetname: rec's target name
+ * @tpgt: rec's portal group tag
+ * @ip: rec's ip address
+ * @port: rec's port
+ *
+ * This will run fn over all recs with the {targetname,tpgt,ip,port}
+ * id. It does not iterate over the ifaces setup in /etc/iscsi/ifaces.
+ *
+ * fn should return -1 if it skipped the rec, a ISCSI_ERR error code if
+ * the operation failed or 0 if fn was run successfully.
  */
-int idbm_for_each_iface(int *found, void *data,
+static int idbm_for_each_iface(int *found, void *data,
 				idbm_iface_op_fn *fn,
 				char *targetname, int tpgt, char *ip, int port)
 {
@@ -1185,7 +1223,7 @@ int idbm_for_each_iface(int *found, void
 
 	portal = calloc(1, PATH_MAX);
 	if (!portal)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	if (tpgt >= 0)
 		goto read_iface;
@@ -1195,7 +1233,7 @@ int idbm_for_each_iface(int *found, void
 		 ip, port);
 	if (stat(portal, &statb)) {
 		log_error("iface iter could not stat %s.", portal);
-		rc = ENODEV;
+		rc = ISCSI_ERR_IDBM;
 		goto free_portal;
 	}
 
@@ -1217,11 +1255,13 @@ read_iface:
 	iface_dirfd = opendir(portal);
 	if (!iface_dirfd) {
 		log_error("iface iter could not read dir %s.", portal);
-		rc = errno;
+		rc = ISCSI_ERR_IDBM;
 		goto free_portal;
 	}
 
 	while ((iface_dent = readdir(iface_dirfd))) {
+		int curr_rc;
+
 		if (!strcmp(iface_dent->d_name, ".") ||
 		    !strcmp(iface_dent->d_name, ".."))
 			continue;
@@ -1233,14 +1273,12 @@ read_iface:
 		if (__idbm_rec_read(&rec, portal))
 			continue;
 
+		curr_rc = fn(data, &rec);
 		/* less than zero means it was not a match */
-		rc = fn(data, &rec);
-		if (rc > 0)
-			break;
-		else if (rc == 0)
+		if (curr_rc > 0 && !rc)
+			rc = curr_rc;
+		else if (curr_rc == 0)
 			(*found)++;
-		else 
-			rc = 0;
 	}
 
 	closedir(iface_dirfd);
@@ -1263,17 +1301,18 @@ int idbm_for_each_portal(int *found, voi
 
 	portal = calloc(1, PATH_MAX);
 	if (!portal)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	snprintf(portal, PATH_MAX, "%s/%s", NODE_CONFIG_DIR, targetname);
 	portal_dirfd = opendir(portal);
 	if (!portal_dirfd) {
-		rc = errno;
+		rc = ISCSI_ERR_IDBM;
 		goto done;
 	}
 
 	while ((portal_dent = readdir(portal_dirfd))) {
 		char *tmp_port, *tmp_tpgt;
+		int curr_rc;
 
 		if (!strcmp(portal_dent->d_name, ".") ||
 		    !strcmp(portal_dent->d_name, ".."))
@@ -1288,11 +1327,12 @@ int idbm_for_each_portal(int *found, voi
 		if (tmp_tpgt)
 			*tmp_tpgt++ = '\0';
 
-		rc = fn(found, data, targetname,
+		curr_rc = fn(found, data, targetname,
 			tmp_tpgt ? atoi(tmp_tpgt) : -1,
 			portal_dent->d_name, atoi(tmp_port));
-		if (rc)
-			break;
+		/* less than zero means it was not a match */
+		if (curr_rc > 0 && !rc)
+			rc = curr_rc;
 	}
 	closedir(portal_dirfd);
 done:
@@ -1314,14 +1354,17 @@ int idbm_for_each_node(int *found, void 
 		return 0;
 
 	while ((node_dent = readdir(node_dirfd))) {
+		int curr_rc;
+
 		if (!strcmp(node_dent->d_name, ".") ||
 		    !strcmp(node_dent->d_name, ".."))
 			continue;
 
 		log_debug(5, "searching %s\n", node_dent->d_name);
-		rc = fn(found, data, node_dent->d_name);
-		if (rc)
-			break;
+		curr_rc = fn(found, data, node_dent->d_name);
+		/* less than zero means it was not a match */
+		if (curr_rc > 0 && !rc)
+			rc = curr_rc;
 	}
 
 	closedir(node_dirfd);
@@ -1376,17 +1419,17 @@ idbm_discovery_read(discovery_rec_t *out
 	FILE *f;
 
 	if (drec_type > 1)
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 
 	memset(out_rec, 0, sizeof(discovery_rec_t));
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	portal = malloc(PATH_MAX);
 	if (!portal) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_info;
 	}
 
@@ -1402,8 +1445,9 @@ idbm_discovery_read(discovery_rec_t *out
 	f = idbm_open_rec_r(portal,
 			    disc_type_to_config_vals[drec_type].config_name);
 	if (!f) {
-		log_debug(1, "Could not open %s err %d\n", portal, errno);
-		rc = errno;
+		log_debug(1, "Could not open %s: %s\n", portal,
+			  strerror(errno));
+		rc = ISCSI_ERR_IDBM;
 		goto unlock;
 	}
 
@@ -1474,14 +1518,15 @@ static int idbm_rec_write(node_rec_t *re
 	portal = malloc(PATH_MAX);
 	if (!portal) {
 		log_error("Could not alloc portal\n");
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	}
 
 	snprintf(portal, PATH_MAX, "%s", NODE_CONFIG_DIR);
 	if (access(portal, F_OK) != 0) {
 		if (mkdir(portal, 0660) != 0) {
-			log_error("Could not make %s\n", portal);
-			rc = errno;
+			log_error("Could not make %s: %s\n", portal,
+				  strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 			goto free_portal;
 		}
 	}
@@ -1489,8 +1534,9 @@ static int idbm_rec_write(node_rec_t *re
 	snprintf(portal, PATH_MAX, "%s/%s", NODE_CONFIG_DIR, rec->name);
 	if (access(portal, F_OK) != 0) {
 		if (mkdir(portal, 0660) != 0) {
-			log_error("Could not make %s\n", portal);
-			rc = errno;
+			log_error("Could not make %s: %s\n", portal,
+				  strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 			goto free_portal;
 		}
 	}
@@ -1531,13 +1577,13 @@ static int idbm_rec_write(node_rec_t *re
 		 * Old style portal as a file, but with tpgt. Let's update it.
 		 */
 		if (unlink(portal)) {
-			log_error("Could not convert %s. err %d\n", portal,
-				  errno);
-			rc = errno;
+			log_error("Could not convert %s: %s\n", portal,
+				  strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 			goto unlock;
 		}
 	} else {
-		rc = EINVAL;
+		rc = ISCSI_ERR_INVAL;
 		goto unlock;
 	}	
 
@@ -1546,9 +1592,9 @@ mkdir_portal:
 		 rec->name, rec->conn[0].address, rec->conn[0].port, rec->tpgt);
 	if (stat(portal, &statb)) {
 		if (mkdir(portal, 0660) != 0) {
-			log_error("Could not make dir %s err %d\n",
-				  portal, errno);
-			rc = errno;
+			log_error("Could not make dir %s: %s\n",
+				  portal, strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 			goto unlock;
 		}
 	}
@@ -1559,8 +1605,8 @@ mkdir_portal:
 open_conf:
 	f = fopen(portal, "w");
 	if (!f) {
-		log_error("Could not open %s err %d\n", portal, errno);
-		rc = errno;
+		log_error("Could not open %s: %sd\n", portal, strerror(errno));
+		rc = ISCSI_ERR_IDBM;
 		goto unlock;
 	}
 
@@ -1581,12 +1627,12 @@ idbm_discovery_write(discovery_rec_t *re
 	int rc = 0;
 
 	if (rec->type > 1)
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 
 	portal = malloc(PATH_MAX);
 	if (!portal) {
 		log_error("Could not alloc portal\n");
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	}
 
 	rc = idbm_lock();
@@ -1597,8 +1643,9 @@ idbm_discovery_write(discovery_rec_t *re
 		 disc_type_to_config_vals[rec->type].config_root);
 	if (access(portal, F_OK) != 0) {
 		if (mkdir(portal, 0660) != 0) {
-			log_error("Could not make %s\n", portal);
-			rc = errno;
+			log_error("Could not make %s: %s\n", portal,
+				  strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 			goto unlock;
 		}
 	}
@@ -1610,8 +1657,8 @@ idbm_discovery_write(discovery_rec_t *re
 	f = idbm_open_rec_w(portal,
 			    disc_type_to_config_vals[rec->type].config_name);
 	if (!f) {
-		log_error("Could not open %s err %d\n", portal, errno);
-		rc = errno;
+		log_error("Could not open %s: %s\n", portal, strerror(errno));
+		rc = ISCSI_ERR_IDBM;
 		goto unlock;
 	}
 
@@ -1655,9 +1702,9 @@ static int setup_disc_to_node_link(char 
 	case DISCOVERY_TYPE_FW:
 		if (access(FW_CONFIG_DIR, F_OK) != 0) {
 			if (mkdir(FW_CONFIG_DIR, 0660) != 0) {
-				log_error("Could not make %s\n",
-					  FW_CONFIG_DIR);
-				rc = errno;
+				log_error("Could not make %s: %s",
+					  FW_CONFIG_DIR, strerror(errno));
+				rc = ISCSI_ERR_IDBM;
 			}
 		}
 
@@ -1669,9 +1716,9 @@ static int setup_disc_to_node_link(char 
 	case DISCOVERY_TYPE_STATIC:
 		if (access(STATIC_CONFIG_DIR, F_OK) != 0) {
 			if (mkdir(STATIC_CONFIG_DIR, 0660) != 0) {
-				log_error("Could not make %s\n",
-					  STATIC_CONFIG_DIR);
-				rc = errno;
+				log_error("Could not make %s; %s",
+					  STATIC_CONFIG_DIR, strerror(errno));
+				rc = ISCSI_ERR_IDBM;
 			}
 		}
 
@@ -1683,9 +1730,9 @@ static int setup_disc_to_node_link(char 
 	case DISCOVERY_TYPE_ISNS:
 		if (access(ISNS_CONFIG_DIR, F_OK) != 0) {
 			if (mkdir(ISNS_CONFIG_DIR, 0660) != 0) {
-				log_error("Could not make %s\n",
-					  ISNS_CONFIG_DIR);
-				rc = errno;
+				log_error("Could not make %s: %s",
+					  ISNS_CONFIG_DIR, strerror(errno));
+				rc = ISCSI_ERR_IDBM;
 			}
 		}
 
@@ -1732,7 +1779,7 @@ static int setup_disc_to_node_link(char 
 		break;
 	case DISCOVERY_TYPE_SLP:
 	default:
-		rc = EINVAL;
+		rc = ISCSI_ERR_INVAL;
 	}
 
 	return rc;
@@ -1773,7 +1820,7 @@ int idbm_add_node(node_rec_t *newrec, di
 
 	node_portal = calloc(2, PATH_MAX);
 	if (!node_portal)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	disc_portal = node_portal + PATH_MAX;
 	snprintf(node_portal, PATH_MAX, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR,
@@ -1795,9 +1842,10 @@ int idbm_add_node(node_rec_t *newrec, di
 			log_debug(7, "link from %s to %s exists", node_portal,
 				  disc_portal);
 		else {
-			rc = errno;
+			rc = ISCSI_ERR_IDBM;
 			log_error("Could not make link from disc source %s to "
-				 "node %s", disc_portal, node_portal);
+				 "node %s: %s", disc_portal, node_portal,
+				 strerror(errno));
 		}
 	}
 	idbm_unlock();
@@ -1812,10 +1860,12 @@ static int idbm_bind_iface_to_nodes(idbm
 {
 	struct node_rec *rec, *tmp;
 	struct list_head new_recs;
+	int rc;
 
 	INIT_LIST_HEAD(&new_recs);
-	if (disc_node_fn(data, iface, &new_recs))
-		return ENODEV;
+	rc = disc_node_fn(data, iface, &new_recs);
+	if (rc)
+		return rc;
 
 	list_for_each_entry_safe(rec, tmp, &new_recs, list) {
 		list_del_init(&rec->list);
@@ -1960,7 +2010,7 @@ int idbm_delete_discovery(discovery_rec_
 
 	portal = calloc(1, PATH_MAX);
 	if (!portal)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	snprintf(portal, PATH_MAX, "%s/%s,%d",
 		 disc_type_to_config_vals[drec->type].config_root,
@@ -2017,7 +2067,7 @@ static int idbm_remove_disc_to_node_link
 
 	tmprec = malloc(sizeof(*tmprec));
 	if (!tmprec)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	memset(portal, 0, PATH_MAX);
 	snprintf(portal, PATH_MAX, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR,
@@ -2045,9 +2095,9 @@ static int idbm_remove_disc_to_node_link
 
 	if (!stat(portal, &statb)) {
 		if (unlink(portal)) {
-			log_error("Could not remove link %s err %d\n",
-				  portal, errno);
-			rc = errno;
+			log_error("Could not remove link %s: %s\n",
+				  portal, strerror(errno));
+			rc = ISCSI_ERR_IDBM;
 		} else
 			log_debug(7, "rmd %s", portal);
 	} else
@@ -2073,7 +2123,7 @@ int idbm_delete_node(node_rec_t *rec)
 
 	portal = calloc(1, PATH_MAX);
 	if (!portal)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	rc = idbm_remove_disc_to_node_link(rec, portal);
 	if (rc)
@@ -2100,15 +2150,15 @@ int idbm_delete_node(node_rec_t *rec)
 	if (!stat(portal, &statb))
 		goto rm_conf;
 
-	log_error("Could not stat %s to delete node err %d\n",
-		  portal, errno);
-	rc = errno;
+	log_error("Could not stat %s to delete node: %s\n",
+		  portal, strerror(errno));
+	rc = ISCSI_ERR_IDBM;
 	goto unlock;
 
 rm_conf:
 	if (unlink(portal)) {
-		log_error("Could not remove %s err %d\n", portal, errno);
-		rc = errno;
+		log_error("Could not remove %s: %s\n", portal, strerror(errno));
+		rc = ISCSI_ERR_IDBM;
 		goto unlock;
 	}
 
@@ -2178,7 +2228,7 @@ int idbm_node_set_param(void *data, node
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	idbm_recinfo_node(rec, info);
 
@@ -2207,7 +2257,7 @@ int idbm_discovery_set_param(void *data,
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	idbm_recinfo_discovery((discovery_rec_t *)rec, info);
 
@@ -2242,7 +2292,7 @@ int idbm_init(idbm_get_config_file_fn *f
 	db = malloc(sizeof(idbm_t));
 	if (!db) {
 		log_error("out of memory on idbm allocation");
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	}
 	memset(db, 0, sizeof(idbm_t));
 	db->get_config_file = fn;
@@ -2362,16 +2412,7 @@ void idbm_node_setup_defaults(node_rec_t
 	rec->session.err_timeo.tgt_reset_timeout = DEF_TGT_RESET_TIMEO;
 	rec->session.err_timeo.host_reset_timeout = DEF_HOST_RESET_TIMEO;
 	rec->session.timeo.replacement_timeout = DEF_REPLACEMENT_TIMEO;
-	rec->session.iscsi.InitialR2T = 0;
-	rec->session.iscsi.ImmediateData = 1;
-	rec->session.iscsi.FirstBurstLength = DEF_INI_FIRST_BURST_LEN;
-	rec->session.iscsi.MaxBurstLength = DEF_INI_MAX_BURST_LEN;
-	rec->session.iscsi.DefaultTime2Wait = ISCSI_DEF_TIME2WAIT;
-	rec->session.iscsi.DefaultTime2Retain = 0;
-	rec->session.iscsi.MaxConnections = 1;
-	rec->session.iscsi.MaxOutstandingR2T = 1;
-	rec->session.iscsi.ERL = 0;
-	rec->session.iscsi.FastAbort = 1;
+	idbm_setup_session_defaults(&rec->session.iscsi);
 
 	for (i=0; i<ISCSI_CONN_MAX; i++) {
 		rec->conn[i].startup = ISCSI_STARTUP_MANUAL;
@@ -2385,13 +2426,7 @@ void idbm_node_setup_defaults(node_rec_t
 		rec->conn[i].timeo.noop_out_interval = DEF_NOOP_OUT_INTERVAL;
 		rec->conn[i].timeo.noop_out_timeout = DEF_NOOP_OUT_TIMEO;
 
-		rec->conn[i].iscsi.MaxXmitDataSegmentLength = 0;
-		rec->conn[i].iscsi.MaxRecvDataSegmentLength =
-						DEF_INI_MAX_RECV_SEG_LEN;
-		rec->conn[i].iscsi.HeaderDigest = CONFIG_DIGEST_NEVER;
-		rec->conn[i].iscsi.DataDigest = CONFIG_DIGEST_NEVER;
-		rec->conn[i].iscsi.IFMarker = 0;
-		rec->conn[i].iscsi.OFMarker = 0;
+		idbm_setup_conn_defaults(&rec->conn[i].iscsi);
 	}
 
 	iface_setup_defaults(&rec->iface);
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h	2011-02-03 20:14:23.000000000 -0600
@@ -93,9 +93,6 @@ struct rec_op_data {
 	node_rec_t *match_rec;
 	idbm_iface_op_fn *fn;
 };
-extern int idbm_for_each_iface(int *found, void *data,
-				idbm_iface_op_fn *fn,
-				char *targetname, int tpgt, char *ip, int port);
 extern int idbm_for_each_portal(int *found, void *data,
 				idbm_portal_op_fn *fn, char *targetname);
 extern int idbm_for_each_node(int *found, void *data,
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c	2011-02-03 20:14:23.000000000 -0600
@@ -39,6 +39,7 @@
 #include "host.h"
 #include "fw_context.h"
 #include "sysdeps.h"
+#include "iscsi_err.h"
 
 /*
  * Default ifaces for use with transports that do not bind to hardware
@@ -101,13 +102,13 @@ struct iface_rec *iface_alloc(char *ifna
 	struct iface_rec *iface;
 
 	if (!strlen(ifname) || strlen(ifname) + 1 > ISCSI_MAX_IFACE_LEN) {
-		*err = EINVAL;
+		*err = ISCSI_ERR_INVAL;
 		return NULL;
 	}
 
 	iface = calloc(1, sizeof(*iface));
 	if (!iface) {
-		*err = ENOMEM;
+		*err = ISCSI_ERR_NOMEM;
 		return NULL;
 	}
 
@@ -125,11 +126,11 @@ static int __iface_conf_read(struct ifac
 
 	iface_conf = calloc(1, PATH_MAX);
 	if (!iface_conf)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info) {
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_conf;
 	}
 
@@ -147,7 +148,7 @@ static int __iface_conf_read(struct ifac
 			iface_setup_defaults(iface);
 			rc = 0;
 		} else
-			rc = errno;
+			rc = ISCSI_ERR_IDBM;
 		goto free_info;
 	}
 
@@ -213,12 +214,12 @@ int iface_conf_delete(struct iface_rec *
 	if (def_iface) {
 		log_error("iface %s is a special interface and "
 			  "cannot be deleted.\n", iface->name);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	iface_conf = calloc(1, PATH_MAX);
 	if (!iface_conf)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	sprintf(iface_conf, "%s/%s", IFACE_CONFIG_DIR, iface->name);
 	rc = idbm_lock();
@@ -226,7 +227,7 @@ int iface_conf_delete(struct iface_rec *
 		goto free_conf;
 
 	if (unlink(iface_conf))
-		rc = errno;
+		rc = ISCSI_ERR_IDBM;
 	idbm_unlock();
 
 free_conf:
@@ -246,17 +247,17 @@ int iface_conf_write(struct iface_rec *i
 		log_error("iface %s is a special interface and "
 			  "is not stored in %s.\n", iface->name,
 			  IFACE_CONFIG_DIR);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	iface_conf = calloc(1, PATH_MAX);
 	if (!iface_conf)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	sprintf(iface_conf, "%s/%s", IFACE_CONFIG_DIR, iface->name);
 	f = fopen(iface_conf, "w");
 	if (!f) {
-		rc = errno;
+		rc = ISCSI_ERR_IDBM;
 		goto free_conf;
 	}
 
@@ -285,12 +286,12 @@ int iface_conf_update(struct db_set_para
 	if (def_iface) {
 		log_error("iface %s is a special interface and "
 			  "cannot be modified.\n", iface->name);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	info = idbm_recinfo_alloc(MAX_KEYS);
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	idbm_recinfo_iface(iface, info);
 	rc = idbm_verify_param(info, param->name);
@@ -298,10 +299,8 @@ int iface_conf_update(struct db_set_para
 		goto free_info;
 
 	rc = idbm_rec_update_param(info, param->name, param->value, 0);
-	if (rc) {
-		rc = EIO;
+	if (rc)
 		goto free_info;
-	}
 
 	rc = iface_conf_write(iface);
 free_info:
@@ -418,7 +417,7 @@ int iface_get_by_net_binding(struct ifac
 				  __iface_get_by_net_binding);
 	if (rc == 1)
 		return 0;
-	return ENODEV;
+	return ISCSI_ERR_NO_OBJS_FOUND;
 }
 
 static int __iface_setup_host_bindings(void *data, struct host_info *hinfo)
@@ -438,7 +437,8 @@ static int __iface_setup_host_bindings(v
 			return 0;
 	}
 
-	if (iface_get_by_net_binding(&hinfo->iface, &iface) == ENODEV) {
+	if (iface_get_by_net_binding(&hinfo->iface, &iface) ==
+	    ISCSI_ERR_NO_OBJS_FOUND) {
 		/* Must be a new port */
 		if (!strlen(hinfo->iface.hwaddress)) {
 			log_error("Invalid offload iSCSI host %u. Missing "
@@ -704,7 +704,7 @@ int iface_for_each_iface(void *data, int
 			 iface_dent->d_name);
 		iface = iface_alloc(iface_dent->d_name, &err);
 		if (!iface || err) {
-			if (err == EINVAL)
+			if (err == ISCSI_ERR_INVAL)
 				log_error("Invalid iface name %s. Must be "
 					  "from 1 to %d characters.",
 					   iface_dent->d_name,
@@ -756,7 +756,7 @@ static int iface_link(void *data, struct
 
 	iface_copy = calloc(1, sizeof(*iface_copy));
 	if (!iface_copy)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	memcpy(iface_copy, iface, sizeof(*iface_copy));
 	INIT_LIST_HEAD(&iface_copy->list);
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/initiator.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/initiator.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator.c	2011-02-03 20:14:23.000000000 -0600
@@ -46,6 +46,7 @@
 #include "iscsi_settings.h"
 #include "iface.h"
 #include "sysdeps.h"
+#include "iscsi_err.h"
 
 #define ISCSI_CONN_ERR_REOPEN_DELAY	3
 #define ISCSI_INTERNAL_ERR_REOPEN_DELAY	5
@@ -53,31 +54,17 @@
 #define PROC_DIR "/proc"
 
 static void iscsi_login_timedout(void *data);
+static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
+				  struct iscsi_conn *conn, unsigned long tmo,
+				  int event);
 
-/*
- * calculate parameter's padding
- */
-static unsigned int
-__padding(unsigned int param)
-{
-	int pad;
-
-	pad = param & 3;
-	if (pad) {
-		pad = 4 - pad;
-		log_debug(1, "parameter's value %d padded to %d bytes\n",
-			   param, param + pad);
-	}
-	return param + pad;
-}
-
-static int iscsi_conn_context_alloc(iscsi_conn_t *conn)
+static int iscsi_ev_context_alloc(iscsi_conn_t *conn)
 {
 	int i;
 
 	for (i = 0; i < CONTEXT_POOL_MAX; i++) {
 		conn->context_pool[i] = calloc(1,
-					   sizeof(struct iscsi_conn_context) +
+					   sizeof(struct iscsi_ev_context) +
 					   ipc->ctldev_bufmax);
 		if (!conn->context_pool[i]) {
 			int j;
@@ -91,7 +78,7 @@ static int iscsi_conn_context_alloc(iscs
 	return 0;
 }
 
-static void iscsi_conn_context_free(iscsi_conn_t *conn)
+static void iscsi_ev_context_free(iscsi_conn_t *conn)
 {
 	int i;
 
@@ -107,10 +94,10 @@ static void iscsi_conn_context_free(iscs
 	}
 }
 
-struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn,
-						  int ev_size)
+static struct iscsi_ev_context *
+iscsi_ev_context_get(iscsi_conn_t *conn, int ev_size)
 {
-	struct iscsi_conn_context *conn_context;
+	struct iscsi_ev_context *ev_context;
 	int i;
 
 	if (ev_size > ipc->ctldev_bufmax)
@@ -121,26 +108,26 @@ struct iscsi_conn_context *iscsi_conn_co
 			continue;
 
 		if (!conn->context_pool[i]->allocated) {
-			conn_context = conn->context_pool[i];
+			ev_context = conn->context_pool[i];
 
-			memset(&conn_context->actor, 0,
+			memset(&ev_context->actor, 0,
 				sizeof(struct actor));
-			conn_context->allocated = 1;
+			ev_context->allocated = 1;
 			/* some callers abuse this pointer */
-			conn_context->data = (void *)conn_context +
-					sizeof(struct iscsi_conn_context);
-			log_debug(7, "get conn context %p",
-				  &conn_context->actor);
-			return conn_context;
+			ev_context->data = (void *)ev_context +
+					sizeof(struct iscsi_ev_context);
+			log_debug(7, "get ev context %p",
+				  &ev_context->actor);
+			return ev_context;
 		}
 	}
 	return NULL;
 }
 
-void iscsi_conn_context_put(struct iscsi_conn_context *conn_context)
+static void iscsi_ev_context_put(struct iscsi_ev_context *ev_context)
 {
-	log_debug(7, "put conn context %p", &conn_context->actor);
-	conn_context->allocated = 0;
+	log_debug(7, "put ev context %p", &ev_context->actor);
+	ev_context->allocated = 0;
 }
 
 static void session_online_devs(int host_no, int sid)
@@ -205,11 +192,11 @@ __check_iscsi_status_class(iscsi_session
 			log_error("session %d login rejected: Initiator "
 			       "failed authentication with target",
 				session->id);
-			return CONN_LOGIN_FAILED;
+			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_FORBIDDEN:
 			log_error("conn %d login rejected: initiator "
 			       "failed authorization with target", conn->id);
-			return CONN_LOGIN_FAILED;
+			return CONN_LOGIN_AUTH_FAILED;
 		case ISCSI_LOGIN_STATUS_TGT_NOT_FOUND:
 			log_error("conn %d login rejected: initiator "
 			       "error - target not found (%02x/%02x)",
@@ -250,183 +237,6 @@ __check_iscsi_status_class(iscsi_session
 	return CONN_LOGIN_FAILED;
 }
 
-static void
-__setup_authentication(iscsi_session_t *session,
-			struct iscsi_auth_config *auth_cfg)
-{
-	/* if we have any incoming credentials, we insist on authenticating
-	 * the target or not logging in at all
-	 */
-	if (auth_cfg->username_in[0]
-	    || auth_cfg->password_in_length) {
-		/* sanity check the config */
-		if (auth_cfg->password_length == 0) {
-			log_debug(1,
-			       "node record has incoming "
-			       "authentication credentials but has no outgoing "
-			       "credentials configured, exiting");
-			return;
-		}
-		session->bidirectional_auth = 1;
-	} else {
-		/* no or 1-way authentication */
-		session->bidirectional_auth = 0;
-	}
-
-	/* copy in whatever credentials we have */
-	strlcpy(session->username, auth_cfg->username,
-		sizeof (session->username));
-	session->username[sizeof (session->username) - 1] = '\0';
-	if ((session->password_length = auth_cfg->password_length))
-		memcpy(session->password, auth_cfg->password,
-		       session->password_length);
-
-	strlcpy(session->username_in, auth_cfg->username_in,
-		sizeof (session->username_in));
-	session->username_in[sizeof (session->username_in) - 1] = '\0';
-	if ((session->password_in_length =
-	     auth_cfg->password_in_length))
-		memcpy(session->password_in, auth_cfg->password_in,
-		       session->password_in_length);
-
-	if (session->password_length || session->password_in_length) {
-		/* setup the auth buffers */
-		session->auth_buffers[0].address = &session->auth_client_block;
-		session->auth_buffers[0].length =
-		    sizeof (session->auth_client_block);
-		session->auth_buffers[1].address =
-		    &session->auth_recv_string_block;
-		session->auth_buffers[1].length =
-		    sizeof (session->auth_recv_string_block);
-
-		session->auth_buffers[2].address =
-		    &session->auth_send_string_block;
-		session->auth_buffers[2].length =
-		    sizeof (session->auth_send_string_block);
-
-		session->auth_buffers[3].address =
-		    &session->auth_recv_binary_block;
-		session->auth_buffers[3].length =
-		    sizeof (session->auth_recv_binary_block);
-
-		session->auth_buffers[4].address =
-		    &session->auth_send_binary_block;
-		session->auth_buffers[4].length =
-		    sizeof (session->auth_send_binary_block);
-
-		session->num_auth_buffers = 5;
-		log_debug(6, "authentication setup complete...");
-	} else {
-		session->num_auth_buffers = 0;
-		log_debug(6, "no authentication configured...");
-	}
-}
-
-static int
-setup_portal(iscsi_conn_t *conn, conn_rec_t *conn_rec)
-{
-	char port[NI_MAXSERV];
-
-	sprintf(port, "%d", conn_rec->port);
-	if (resolve_address(conn_rec->address, port, &conn->saddr)) {
-		log_error("cannot resolve host name %s",
-			  conn_rec->address);
-		return EINVAL;
-	}
-	conn->failback_saddr = conn->saddr;
-
-	getnameinfo((struct sockaddr *)&conn->saddr, sizeof(conn->saddr),
-		    conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST);
-	log_debug(4, "resolved %s to %s", conn_rec->address, conn->host);
-	return 0;
-}
-
-static void
-iscsi_copy_operational_params(iscsi_conn_t *conn)
-{
-	iscsi_session_t *session = conn->session;
-	conn_rec_t *conn_rec = &session->nrec.conn[conn->id];
-	node_rec_t *rec = &session->nrec;
-
-	conn->hdrdgst_en = conn_rec->iscsi.HeaderDigest;
-	conn->datadgst_en = conn_rec->iscsi.DataDigest;
-
-	conn->max_recv_dlength =
-			__padding(conn_rec->iscsi.MaxRecvDataSegmentLength);
-	if (conn->max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
-	    conn->max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
-		log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be "
-			 "within %u and %u. Setting to %u\n",
-			  ISCSI_MIN_MAX_RECV_SEG_LEN,
-			  ISCSI_MAX_MAX_RECV_SEG_LEN,
-			  DEF_INI_MAX_RECV_SEG_LEN);
-		conn_rec->iscsi.MaxRecvDataSegmentLength =
-						DEF_INI_MAX_RECV_SEG_LEN;
-		conn->max_recv_dlength = DEF_INI_MAX_RECV_SEG_LEN;
-	}
-
-	/* zero indicates to use the target's value */
-	conn->max_xmit_dlength =
-			__padding(conn_rec->iscsi.MaxXmitDataSegmentLength);
-	if (conn->max_xmit_dlength == 0)
-		conn->max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
-	if (conn->max_xmit_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
-	    conn->max_xmit_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
-		log_error("Invalid iscsi.MaxXmitDataSegmentLength. Must be "
-			 "within %u and %u. Setting to %u\n",
-			  ISCSI_MIN_MAX_RECV_SEG_LEN,
-			  ISCSI_MAX_MAX_RECV_SEG_LEN,
-			  DEF_INI_MAX_RECV_SEG_LEN);
-		conn_rec->iscsi.MaxXmitDataSegmentLength =
-						DEF_INI_MAX_RECV_SEG_LEN;
-		conn->max_xmit_dlength = DEF_INI_MAX_RECV_SEG_LEN;
-	}
-
-	/* session's operational parameters */
-	session->initial_r2t_en = rec->session.iscsi.InitialR2T;
-	session->imm_data_en = rec->session.iscsi.ImmediateData;
-	session->first_burst = __padding(rec->session.iscsi.FirstBurstLength);
-	/*
-	 * some targets like netapp fail the login if sent bad first_burst
-	 * and max_burst lens, even when immediate data=no and
-	 * initial r2t = Yes, so we always check the user values.
-	 */
-	if (session->first_burst < ISCSI_MIN_FIRST_BURST_LEN ||
-	    session->first_burst > ISCSI_MAX_FIRST_BURST_LEN) {
-		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
-			 "within %u and %u. Setting to %u\n",
-			  session->first_burst,
-			  ISCSI_MIN_FIRST_BURST_LEN,
-			  ISCSI_MAX_FIRST_BURST_LEN,
-			  DEF_INI_FIRST_BURST_LEN);
-		rec->session.iscsi.FirstBurstLength = DEF_INI_FIRST_BURST_LEN;
-		session->first_burst = DEF_INI_FIRST_BURST_LEN;
-	}
-
-	session->max_burst = __padding(rec->session.iscsi.MaxBurstLength);
-	if (session->max_burst < ISCSI_MIN_MAX_BURST_LEN ||
-	    session->max_burst > ISCSI_MAX_MAX_BURST_LEN) {
-		log_error("Invalid iscsi.MaxBurstLength of %u. Must be "
-			  "within %u and %u. Setting to %u\n",
-			   session->max_burst, ISCSI_MIN_MAX_BURST_LEN,
-			   ISCSI_MAX_MAX_BURST_LEN, DEF_INI_MAX_BURST_LEN);
-		rec->session.iscsi.MaxBurstLength = DEF_INI_MAX_BURST_LEN;
-		session->max_burst = DEF_INI_MAX_BURST_LEN;
-	}
-
-	if (session->first_burst > session->max_burst) {
-		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
-			  "less than iscsi.MaxBurstLength. Setting to %u\n",
-			   session->first_burst, session->max_burst);
-		rec->session.iscsi.FirstBurstLength = session->max_burst;
-		session->first_burst = session->max_burst;
-	}
-
-	session->def_time2wait = rec->session.iscsi.DefaultTime2Wait;
-	session->def_time2retain = rec->session.iscsi.DefaultTime2Retain;
-	session->erl = rec->session.iscsi.ERL;
-}
-
 static int
 __session_conn_create(iscsi_session_t *session, int cid)
 {
@@ -434,9 +244,9 @@ __session_conn_create(iscsi_session_t *s
 	conn_rec_t *conn_rec = &session->nrec.conn[cid];
 	int err;
 
-	if (iscsi_conn_context_alloc(conn)) {
+	if (iscsi_ev_context_alloc(conn)) {
 		log_error("cannot allocate context_pool for conn cid %d", cid);
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	}
 
 	conn->state = STATE_FREE;
@@ -486,14 +296,15 @@ __session_conn_create(iscsi_session_t *s
 		conn->noop_out_interval = DEF_NOOP_OUT_INTERVAL;
 	}
 
-	iscsi_copy_operational_params(conn);
+	iscsi_copy_operational_params(conn, &session->nrec.session.iscsi,
+				      &conn_rec->iscsi);
 
 	/* TCP options */
 	conn->tcp_window_size = conn_rec->tcp.window_size;
 	/* FIXME: type_of_service */
 
 	/* resolve the string address to an IP address */
-	err = setup_portal(conn, conn_rec);
+	err = iscsi_setup_portal(conn, conn_rec->address, conn_rec->port);
 	if (err)
 		return err;
 	return 0;
@@ -506,7 +317,7 @@ session_release(iscsi_session_t *session
 
 	if (session->target_alias)
 		free(session->target_alias);
-	iscsi_conn_context_free(&session->conn[0]);
+	iscsi_ev_context_free(&session->conn[0]);
 	free(session);
 }
 
@@ -524,11 +335,10 @@ __session_create(node_rec_t *rec, struct
 	log_debug(2, "Allocted session %p", session);
 
 	INIT_LIST_HEAD(&session->list);
-	/* opened at daemon load time (iscsid.c) */
-	session->ctrl_fd = control_fd;
 	session->t = t;
 	session->reopen_qtask.mgmt_ipc_fd = -1;
 	session->id = -1;
+	session->use_ipc = 1;
 
 	/* save node record. we might need it for redirection */
 	memcpy(&session->nrec, rec, sizeof(node_rec_t));
@@ -570,7 +380,7 @@ __session_create(node_rec_t *rec, struct
 	session->isid[5] = 0;
 
 	/* setup authentication variables for the session*/
-	__setup_authentication(session, &rec->session.auth);
+	iscsi_setup_authentication(session, &rec->session.auth);
 
 	session->param_mask = ~0ULL;
 	if (!(t->caps & CAP_MULTI_R2T))
@@ -601,18 +411,18 @@ __session_create(node_rec_t *rec, struct
 
 static void iscsi_flush_context_pool(struct iscsi_session *session)
 {
-	struct iscsi_conn_context *conn_context;
+	struct iscsi_ev_context *ev_context;
 	struct iscsi_conn *conn = &session->conn[0];
 	int i;
 
 	for (i = 0; i < CONTEXT_POOL_MAX; i++) {
-		conn_context = conn->context_pool[i];
-		if (!conn_context)
+		ev_context = conn->context_pool[i];
+		if (!ev_context)
 			continue;
 
-		if (conn_context->allocated) {
+		if (ev_context->allocated) {
 			actor_delete(&(conn->context_pool[i]->actor));
-			iscsi_conn_context_put(conn_context);
+			iscsi_ev_context_put(ev_context);
 		}
 	}
 }
@@ -633,9 +443,9 @@ conn_delete_timers(iscsi_conn_t *conn)
 	actor_delete(&conn->nop_out_timer);
 }
 
-static mgmt_ipc_err_e
+static int 
 session_conn_shutdown(iscsi_conn_t *conn, queue_task_t *qtask,
-		      mgmt_ipc_err_e err)
+		      int err)
 {
 	iscsi_session_t *session = conn->session;
 
@@ -657,7 +467,7 @@ session_conn_shutdown(iscsi_conn_t *conn
 				   conn->id, STOP_CONN_TERM)) {
 			log_error("can't stop connection %d:%d (%d)",
 				  session->id, conn->id, errno);
-			return MGMT_IPC_ERR_INTERNAL;
+			return ISCSI_ERR_INTERNAL;
 		}
 	}
 
@@ -665,7 +475,7 @@ session_conn_shutdown(iscsi_conn_t *conn
 	if (ipc->destroy_conn(session->t->handle, session->id,
 		conn->id)) {
 		log_error("can not safely destroy connection %d", conn->id);
-		return MGMT_IPC_ERR_INTERNAL;
+		return ISCSI_ERR_INTERNAL;
 	}
 
 cleanup:
@@ -674,7 +484,7 @@ cleanup:
 		if (ipc->destroy_session(session->t->handle, session->id)) {
 			log_error("can not safely destroy session %d",
 				  session->id);
-			return MGMT_IPC_ERR_INTERNAL;
+			return ISCSI_ERR_INTERNAL;
 		}
 	}
 
@@ -688,7 +498,7 @@ cleanup:
 	mgmt_ipc_write_rsp(qtask, err);
 	conn_delete_timers(conn);
 	__session_destroy(session);
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
 static void
@@ -709,17 +519,17 @@ queue_delayed_reopen(queue_task_t *qtask
 
 static int iscsi_conn_connect(struct iscsi_conn *conn, queue_task_t *qtask)
 {
-	struct iscsi_conn_context *conn_context;
+	struct iscsi_ev_context *ev_context;
 	int rc;
 
-	conn_context = iscsi_conn_context_get(conn, 0);
-	if (!conn_context) {
+	ev_context = iscsi_ev_context_get(conn, 0);
+	if (!ev_context) {
 		/* while reopening the recv pool should be full */
 		log_error("BUG: __session_conn_reopen could not get conn "
 			  "context for recv.");
 		return ENOMEM;
 	}
-	conn_context->data = qtask;
+	ev_context->data = qtask;
 
 	rc = conn->session->t->template->ep_connect(conn, 1);
 	if (rc < 0 && errno != EINPROGRESS) {
@@ -732,11 +542,11 @@ static int iscsi_conn_connect(struct isc
 
 		log_error("cannot make a connection to %s:%s (%d,%d)",
 			  conn->host, serv, rc, errno);
-		iscsi_conn_context_put(conn_context);
+		iscsi_ev_context_put(ev_context);
 		return ENOTCONN;
 	}
 
-	iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL);
+	iscsi_sched_ev_context(ev_context, conn, 0, EV_CONN_POLL);
 	log_debug(3, "Setting login timer %p timeout %d", &conn->login_timer,
 		  conn->login_timeout);
 	actor_timer(&conn->login_timer, conn->login_timeout * 1000,
@@ -844,8 +654,16 @@ static int iscsi_retry_initial_login(str
 	return 1;
 }
 
+static int iscsi_login_is_fatal_err(int err)
+{
+	if (err == ISCSI_ERR_LOGIN_AUTH_FAILED ||
+	    err == ISCSI_ERR_FATAL_LOGIN)
+		return 1;
+	return 0;
+}
+
 static void iscsi_login_eh(struct iscsi_conn *conn, struct queue_task *qtask,
-			   mgmt_ipc_err_e err)
+			   int err)
 {
 	struct iscsi_session *session = conn->session;
 
@@ -863,7 +681,7 @@ static void iscsi_login_eh(struct iscsi_
 				  "R_STAGE_NO_CHANGE");
 			/* timeout during initial connect.
 			 * clean connection. write ipc rsp or retry */
-			if (err == MGMT_IPC_ERR_FATAL_LOGIN_FAILURE ||
+			if (iscsi_login_is_fatal_err(err) ||
 			    !iscsi_retry_initial_login(conn))
 				session_conn_shutdown(conn, qtask, err);
 			else {
@@ -879,7 +697,7 @@ static void iscsi_login_eh(struct iscsi_
 				  "R_STAGE_SESSION_REDIRECT");
 			/* timeout during initial redirect connect
 			 * clean connection. write ipc rsp or retry */
-			if (err == MGMT_IPC_ERR_FATAL_LOGIN_FAILURE ||
+			if (iscsi_login_is_fatal_err(err) ||
 			    !iscsi_retry_initial_login(conn))
 				session_conn_shutdown(conn, qtask, err);
 			else
@@ -912,7 +730,7 @@ static void iscsi_login_eh(struct iscsi_
 			 * initial redirected connect. Clean connection
 			 * and write rsp or retry.
 			 */
-			if (err == MGMT_IPC_ERR_FATAL_LOGIN_FAILURE ||
+			if (iscsi_login_is_fatal_err(err) ||
 			    !iscsi_retry_initial_login(conn))
 				session_conn_shutdown(conn, qtask, err);
 			else
@@ -927,7 +745,7 @@ static void iscsi_login_eh(struct iscsi_
 			break;
 		case R_STAGE_SESSION_CLEANUP:
 			session_conn_shutdown(conn, qtask,
-					      MGMT_IPC_ERR_PDU_TIMEOUT);
+					      ISCSI_ERR_PDU_TIMEOUT);
 			break;
 		default:
 			break;
@@ -951,7 +769,7 @@ __conn_error_handle(iscsi_session_t *ses
 	 * just cleanup and return to the user.
 	 */
 	if (conn->logout_qtask) {
-		session_conn_shutdown(conn, conn->logout_qtask, MGMT_IPC_OK);
+		session_conn_shutdown(conn, conn->logout_qtask, ISCSI_SUCCESS);
 		return;
 	}
 
@@ -992,7 +810,7 @@ __conn_error_handle(iscsi_session_t *ses
 				qtask = session->sync_qtask;
 			else
 				qtask = &session->reopen_qtask;
-			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_TRANS_FAILURE);
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_TRANS);
 			return;
 		}
 		log_debug(1, "ignoring conn error in login. "
@@ -1020,19 +838,19 @@ __conn_error_handle(iscsi_session_t *ses
 
 static void session_conn_error(void *data)
 {
-	struct iscsi_conn_context *conn_context = data;
-	enum iscsi_err error = *(enum iscsi_err *)conn_context->data;
-	iscsi_conn_t *conn = conn_context->conn;
+	struct iscsi_ev_context *ev_context = data;
+	enum iscsi_err error = *(enum iscsi_err *)ev_context->data;
+	iscsi_conn_t *conn = ev_context->conn;
 	iscsi_session_t *session = conn->session;
 
 	log_warning("Kernel reported iSCSI connection %d:%d error (%d) "
 		    "state (%d)", session->id, conn->id, error,
 		    conn->state);
-	iscsi_conn_context_put(conn_context);
+	iscsi_ev_context_put(ev_context);
 
 	switch (error) {
 	case ISCSI_ERR_INVALID_HOST:
-		if (session_conn_shutdown(conn, NULL, MGMT_IPC_OK))
+		if (session_conn_shutdown(conn, NULL, ISCSI_SUCCESS))
 			log_error("BUG: Could not shutdown session.");
 		break;
 	default:
@@ -1047,13 +865,13 @@ static void iscsi_login_timedout(void *d
 
 	switch (conn->state) {
 	case STATE_XPT_WAIT:
-		iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_TRANS_TIMEOUT);
+		iscsi_login_eh(conn, qtask, ISCSI_ERR_TRANS_TIMEOUT);
 		break;
 	case STATE_IN_LOGIN:
-		iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_PDU_TIMEOUT);
+		iscsi_login_eh(conn, qtask, ISCSI_ERR_PDU_TIMEOUT);
 		break;
 	default:
-		iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_INTERNAL);
+		iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL);
 		break;
 	}
 }
@@ -1136,17 +954,6 @@ static void conn_send_nop_out(void *data
 		 &conn->nop_out_timer, conn->noop_out_timeout);
 }
 
-static void
-print_param_value(enum iscsi_param param, void *value, int type)
-{
-	log_debug(3, "set operational parameter %d to:", param);
-
-	if (type == ISCSI_STRING)
-		log_debug(3, "%s", value ? (char *)value : "NULL");
-	else
-		log_debug(3, "%u", *(uint32_t *)value);
-}
-
 void free_initiator(void)
 {
 	struct iscsi_transport *t;
@@ -1170,7 +977,7 @@ static void session_scan_host(struct isc
 
 	pid = iscsi_sysfs_scan_host(hostno, 1);
 	if (pid == 0) {
-		mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
+		mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
 
 		if (session)
 			iscsi_sysfs_for_each_device(
@@ -1185,302 +992,33 @@ static void session_scan_host(struct isc
 			free(qtask);
 		}
 	} else
-		mgmt_ipc_write_rsp(qtask, MGMT_IPC_ERR_INTERNAL);
-}
-
-static int __iscsi_host_set_param(struct iscsi_transport *t,
-				  int host_no, int param, char *value,
-				  int type)
-{
-	int rc;
-
-	rc = ipc->set_host_param(t->handle, host_no, param, value, type);
-	/* 2.6.20 and below returns EINVAL */
-	if (rc && rc != -ENOSYS && rc != -EINVAL) {
-		log_error("can't set operational parameter %d for "
-			  "host %d, retcode %d (%d)", param, host_no,
-			  rc, errno);
-		return rc;
-	}
-	return 0;
+		mgmt_ipc_write_rsp(qtask, ISCSI_ERR_INTERNAL);
 }
 
-mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value)
-{
-	struct iscsi_transport *t;
-
-	t = iscsi_sysfs_get_transport_by_hba(host_no);
-	if (!t)
-		return MGMT_IPC_ERR_TRANS_FAILURE;
-	if (__iscsi_host_set_param(t, host_no, param, value, ISCSI_STRING))
-		return MGMT_IPC_ERR;
-        return MGMT_IPC_OK;
-}
-
-#define MAX_SESSION_PARAMS 32
-#define MAX_HOST_PARAMS 3
-
 static void
 setup_full_feature_phase(iscsi_conn_t *conn)
 {
 	iscsi_session_t *session = conn->session;
 	iscsi_login_context_t *c = &conn->login_context;
-	int i, rc;
-	uint32_t one = 1, zero = 0;
-	struct hostparam {
-		int param;
-		int type;
-		void *value;
-		int set;
-	} hosttbl[MAX_HOST_PARAMS] = {
-		{
-			.param = ISCSI_HOST_PARAM_NETDEV_NAME,
-			.value = session->nrec.iface.netdev,
-			.type = ISCSI_STRING,
-			.set = 1,
-		}, {
-			.param = ISCSI_HOST_PARAM_HWADDRESS,
-			.value = session->nrec.iface.hwaddress,
-			.type = ISCSI_STRING,
-			.set = 1,
-		}, {
-			.param = ISCSI_HOST_PARAM_INITIATOR_NAME,
-			.value = session->initiator_name,
-			.type = ISCSI_STRING,
-			.set = 0,
-		},
-	};
-	struct connparam {
-		int param;
-		int type;
-		void *value;
-		int conn_only;
-	} conntbl[MAX_SESSION_PARAMS] = {
-		{
-			.param = ISCSI_PARAM_MAX_RECV_DLENGTH,
-			.value = &conn->max_recv_dlength,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_MAX_XMIT_DLENGTH,
-			.value = &conn->max_xmit_dlength,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_HDRDGST_EN,
-			.value = &conn->hdrdgst_en,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_DATADGST_EN,
-			.value = &conn->datadgst_en,
-			.type = ISCSI_INT,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_INITIAL_R2T_EN,
-			.value = &session->initial_r2t_en,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_MAX_R2T,
-			.value = &one, /* FIXME: session->max_r2t */
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_IMM_DATA_EN,
-			.value = &session->imm_data_en,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_FIRST_BURST,
-			.value = &session->first_burst,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_MAX_BURST,
-			.value = &session->max_burst,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_PDU_INORDER_EN,
-			.value = &session->pdu_inorder_en,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param =ISCSI_PARAM_DATASEQ_INORDER_EN,
-			.value = &session->dataseq_inorder_en,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_ERL,
-			.value = &zero, /* FIXME: session->erl */
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_IFMARKER_EN,
-			.value = &zero,/* FIXME: session->ifmarker_en */
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_OFMARKER_EN,
-			.value = &zero,/* FIXME: session->ofmarker_en */
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_EXP_STATSN,
-			.value = &conn->exp_statsn,
-			.type = ISCSI_INT,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_TARGET_NAME,
-			.conn_only = 0,
-			.type = ISCSI_STRING,
-			.value = session->target_name,
-		}, {
-			.param = ISCSI_PARAM_TPGT,
-			.value = &session->portal_group_tag,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_PERSISTENT_ADDRESS,
-			.value = session->nrec.conn[conn->id].address,
-			.type = ISCSI_STRING,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_PERSISTENT_PORT,
-			.value = &session->nrec.conn[conn->id].port,
-			.type = ISCSI_INT,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_SESS_RECOVERY_TMO,
-			.value = &session->replacement_timeout,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_USERNAME,
-			.value = session->username,
-			.type = ISCSI_STRING,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_USERNAME_IN,
-			.value = session->username_in,
-			.type = ISCSI_STRING,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_PASSWORD,
-			.value = session->password,
-			.type = ISCSI_STRING,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_PASSWORD_IN,
-			.value = session->password_in,
-			.type = ISCSI_STRING,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_FAST_ABORT,
-			.value = &session->fast_abort,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_ABORT_TMO,
-			.value = &session->abort_timeout,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_LU_RESET_TMO,
-			.value = &session->lu_reset_timeout,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_TGT_RESET_TMO,
-			.value = &session->tgt_reset_timeout,
-			.type = ISCSI_INT,
-			.conn_only = 0,
-		}, {
-			.param = ISCSI_PARAM_PING_TMO,
-			.value = &conn->noop_out_timeout,
-			.type = ISCSI_INT,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_RECV_TMO,
-			.value = &conn->noop_out_interval,
-			.type = ISCSI_INT,
-			.conn_only = 1,
-		}, {
-			.param = ISCSI_PARAM_IFACE_NAME,
-			.value = session->nrec.iface.name,
-			.type = ISCSI_STRING,
-		}, {
-			.param = ISCSI_PARAM_INITIATOR_NAME,
-			.value = session->initiator_name,
-			.type = ISCSI_STRING,
-		},
-	};
+	int rc;
 
 	actor_delete(&conn->login_timer);
-	/* Entered full-feature phase! */
-	for (i = 0; i < MAX_SESSION_PARAMS; i++) {
-		if (conn->id != 0 && !conntbl[i].conn_only)
-			continue;
-		
-		if (!(session->param_mask & (1ULL << conntbl[i].param)))
-			continue;
 
-		rc = ipc->set_param(session->t->handle, session->id,
-				   conn->id, conntbl[i].param, conntbl[i].value,
-				   conntbl[i].type);
-		if (rc && rc != -ENOSYS) {
-			log_error("can't set operational parameter %d for "
-				  "connection %d:%d, retcode %d (%d)",
-				  conntbl[i].param, session->id, conn->id,
-				  rc, errno);
-
-			iscsi_login_eh(conn, c->qtask,
-				       MGMT_IPC_ERR_LOGIN_FAILURE);
-			return;
-		}
-
-		if (rc == -ENOSYS) {
-			switch (conntbl[i].param) {
-			case ISCSI_PARAM_PING_TMO:
-				/*
-				 * older kernels may not support nops
-				 * in kernel
-				 */
-				conn->userspace_nop = 1;
-				break;
-			case ISCSI_PARAM_INITIATOR_NAME:
-				/* use host level one instead */
-				hosttbl[ISCSI_HOST_PARAM_INITIATOR_NAME].set = 1;
-				break;
-			}
-		}
-
-		print_param_value(conntbl[i].param, conntbl[i].value,
-				  conntbl[i].type);
+	if (iscsi_session_set_params(conn)) {
+		iscsi_login_eh(conn, c->qtask, ISCSI_ERR_LOGIN);
+		return;
 	}
 
-	for (i = 0; i < MAX_HOST_PARAMS; i++) {
-		if (!hosttbl[i].set)
-			continue;
-
-		if (__iscsi_host_set_param(session->t, session->hostno,
-					   hosttbl[i].param, hosttbl[i].value,
-					   hosttbl[i].type)) {
-			iscsi_login_eh(conn, c->qtask,
-				       MGMT_IPC_ERR_LOGIN_FAILURE);
-			return;
-		}
-
-		print_param_value(hosttbl[i].param, hosttbl[i].value,
-				  hosttbl[i].type);
+	if (iscsi_host_set_params(session)) {
+		iscsi_login_eh(conn, c->qtask, ISCSI_ERR_LOGIN);
+		return;
 	}
 
 	if (ipc->start_conn(session->t->handle, session->id, conn->id,
 			    &rc) || rc) {
 		log_error("can't start connection %d:%d retcode %d (%d)",
 			  session->id, conn->id, rc, errno);
-		iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_INTERNAL);
+		iscsi_login_eh(conn, c->qtask, ISCSI_ERR_INTERNAL);
 		return;
 	}
 
@@ -1504,7 +1042,7 @@ setup_full_feature_phase(iscsi_conn_t *c
 		session->sync_qtask = NULL;
 
 		session_online_devs(session->hostno, session->id);
-		mgmt_ipc_write_rsp(c->qtask, MGMT_IPC_OK);
+		mgmt_ipc_write_rsp(c->qtask, ISCSI_SUCCESS);
 		log_warning("connection%d:%d is operational after recovery "
 			    "(%d attempts)", session->id, conn->id,
 			     session->reopen_cnt);
@@ -1527,10 +1065,10 @@ setup_full_feature_phase(iscsi_conn_t *c
 
 static void iscsi_logout_timedout(void *data)
 {
-	struct iscsi_conn_context *conn_context = data;
-	struct iscsi_conn *conn = conn_context->conn;
+	struct iscsi_ev_context *ev_context = data;
+	struct iscsi_conn *conn = ev_context->conn;
 
-	iscsi_conn_context_put(conn_context); 
+	iscsi_ev_context_put(ev_context);
 	/*
 	 * assume we were in STATE_IN_LOGOUT or there
 	 * was some nasty error
@@ -1542,7 +1080,7 @@ static void iscsi_logout_timedout(void *
 static int iscsi_send_logout(iscsi_conn_t *conn)
 {
 	struct iscsi_logout hdr;
-	struct iscsi_conn_context *conn_context;
+	struct iscsi_ev_context *ev_context;
 
 	if (conn->state != STATE_LOGGED_IN)
 		return EINVAL;
@@ -1558,12 +1096,12 @@ static int iscsi_send_logout(iscsi_conn_
 		return EIO;
 	conn->state = STATE_IN_LOGOUT;
 
-	conn_context = iscsi_conn_context_get(conn, 0);
-	if (!conn_context)
+	ev_context = iscsi_ev_context_get(conn, 0);
+	if (!ev_context)
 		/* unbounded logout */
 		log_warning("Could not allocate conn context for logout.");
 	else {
-		iscsi_sched_conn_context(conn_context, conn,
+		iscsi_sched_ev_context(ev_context, conn,
 					 conn->logout_timeout,
 					 EV_CONN_LOGOUT_TIMER);
 		log_debug(3, "logout timeout timer %u\n",
@@ -1575,16 +1113,16 @@ static int iscsi_send_logout(iscsi_conn_
 
 static void iscsi_stop(void *data)
 {
-	struct iscsi_conn_context *conn_context = data;
-	struct iscsi_conn *conn = conn_context->conn;
+	struct iscsi_ev_context *ev_context = data;
+	struct iscsi_conn *conn = ev_context->conn;
 	int rc = 0;
 
-	iscsi_conn_context_put(conn_context);
+	iscsi_ev_context_put(ev_context);
 
 	if (!iscsi_send_logout(conn))
 		return;
 
-	rc = session_conn_shutdown(conn, conn->logout_qtask, MGMT_IPC_OK);
+	rc = session_conn_shutdown(conn, conn->logout_qtask, ISCSI_SUCCESS);
 	if (rc)
 		log_error("BUG: Could not shutdown session.");
 }
@@ -1683,6 +1221,7 @@ static void iscsi_recv_login_rsp(struct 
 { 
 	struct iscsi_session *session = conn->session;
 	iscsi_login_context_t *c = &conn->login_context;
+	int err = ISCSI_ERR_FATAL_LOGIN;
 
 	if (iscsi_login_rsp(session, c)) {
 		log_debug(1, "login_rsp ret (%d)", c->ret);
@@ -1703,6 +1242,9 @@ static void iscsi_recv_login_rsp(struct 
 		switch (__check_iscsi_status_class(session, conn->id,
 						   c->status_class,
 						   c->status_detail)) {
+		case CONN_LOGIN_AUTH_FAILED:
+			err = ISCSI_ERR_LOGIN_AUTH_FAILED;
+			goto failed;
 		case CONN_LOGIN_FAILED:
 			goto failed;
 		case CONN_LOGIN_IMM_REDIRECT_RETRY:
@@ -1720,8 +1262,7 @@ static void iscsi_recv_login_rsp(struct 
 		/* more nego. needed! */
 		conn->state = STATE_IN_LOGIN;
 		if (iscsi_login_req(session, c)) {
-			iscsi_login_eh(conn, c->qtask,
-				       MGMT_IPC_ERR_LOGIN_FAILURE);
+			iscsi_login_eh(conn, c->qtask, ISCSI_ERR_LOGIN);
 			return;
 		}
 	} else
@@ -1730,22 +1271,22 @@ static void iscsi_recv_login_rsp(struct 
 	return;
 retry:
 	/* retry if not initial login or initial login has not timed out */
-	iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_LOGIN_FAILURE);
+	iscsi_login_eh(conn, c->qtask, ISCSI_ERR_LOGIN);
 	return;
 failed:
 	/* force failure if initial login */
 	session->reopen_cnt = session->nrec.session.initial_login_retry_max;
-	iscsi_login_eh(conn, c->qtask, MGMT_IPC_ERR_FATAL_LOGIN_FAILURE);
+	iscsi_login_eh(conn, c->qtask, err);
 	return;
 }
 
 static void session_conn_recv_pdu(void *data)
 {
-	struct iscsi_conn_context *conn_context = data;
-	iscsi_conn_t *conn = conn_context->conn;
+	struct iscsi_ev_context *ev_context = data;
+	iscsi_conn_t *conn = ev_context->conn;
 	struct iscsi_hdr hdr;
 
-	conn->recv_context = conn_context;
+	conn->recv_context = ev_context;
 
 	switch (conn->state) {
 	case STATE_IN_LOGIN:
@@ -1755,11 +1296,10 @@ static void session_conn_recv_pdu(void *
 	case STATE_IN_LOGOUT:
 	case STATE_LOGOUT_REQUESTED:
 		/* read incoming PDU */
-		if (!iscsi_io_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE,
-			    conn->data, ISCSI_DEF_MAX_RECV_SEG_LEN,
-			    ISCSI_DIGEST_NONE, 0)) {
+		if (iscsi_io_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE,
+				      conn->data, ISCSI_DEF_MAX_RECV_SEG_LEN,
+				      ISCSI_DIGEST_NONE, 0) < 0)
 			return;
-		}
 
 		switch (hdr.opcode & ISCSI_OPCODE_MASK) {
 		case ISCSI_OP_NOOP_IN:
@@ -1777,17 +1317,17 @@ static void session_conn_recv_pdu(void *
 		}
 		break;
 	case STATE_XPT_WAIT:
-		iscsi_conn_context_put(conn_context);
+		iscsi_ev_context_put(ev_context);
 		log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
 			  "let connection re-establish or fail");
 		break;
 	case STATE_CLEANUP_WAIT:
-		iscsi_conn_context_put(conn_context);
+		iscsi_ev_context_put(ev_context);
 		log_debug(1, "ignoring incoming PDU in XPT_WAIT. "
 			  "let connection cleanup");
 		break;
 	default:
-		iscsi_conn_context_put(conn_context);
+		iscsi_ev_context_put(ev_context);
 		log_error("Invalid state. Dropping PDU.\n");
 	}
 }
@@ -1910,15 +1450,15 @@ retry_create:
 
 static void session_conn_poll(void *data)
 {
-	struct iscsi_conn_context *conn_context = data;
-	iscsi_conn_t *conn = conn_context->conn;
+	struct iscsi_ev_context *ev_context = data;
+	iscsi_conn_t *conn = ev_context->conn;
 	struct iscsi_session *session = conn->session;
-	mgmt_ipc_err_e err = MGMT_IPC_OK;
-	queue_task_t *qtask = conn_context->data;
+	int err = ISCSI_SUCCESS;
+	queue_task_t *qtask = ev_context->data;
 	iscsi_login_context_t *c = &conn->login_context;
 	int rc;
 
-	iscsi_conn_context_put(conn_context);
+	iscsi_ev_context_put(ev_context);
 
 	if (conn->state != STATE_XPT_WAIT)
 		return;
@@ -1927,16 +1467,16 @@ static void session_conn_poll(void *data
 	if (rc == 0) {
 		log_debug(4, "poll not connected %d", rc);
 		/* timedout: Poll again. */
-		conn_context = iscsi_conn_context_get(conn, 0);
-		if (!conn_context) {
+		ev_context = iscsi_ev_context_get(conn, 0);
+		if (!ev_context) {
 			/* while polling the recv pool should be full */
 			log_error("BUG: session_conn_poll could not get conn "
 				  "context.");
-			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_INTERNAL);
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_INTERNAL);
 			return;
 		}
-		conn_context->data = qtask;
-		iscsi_sched_conn_context(conn_context, conn, 0, EV_CONN_POLL);
+		ev_context->data = qtask;
+		iscsi_sched_ev_context(ev_context, conn, 0, EV_CONN_POLL);
 	} else if (rc > 0) {
 		/* connected! */
 		memset(c, 0, sizeof(iscsi_login_context_t));
@@ -1945,7 +1485,7 @@ static void session_conn_poll(void *data
 		if (session->id == -1) {
 			if (conn->id == 0 && session_ipc_create(session)) {
 				log_error("Can't create session.");
-				err = MGMT_IPC_ERR_INTERNAL;
+				err = ISCSI_ERR_INTERNAL;
 				goto cleanup;
 			}
 			log_debug(3, "created new iSCSI session sid %d host "
@@ -1954,17 +1494,16 @@ static void session_conn_poll(void *data
 			if (ipc->create_conn(session->t->handle,
 					session->id, conn->id, &conn->id)) {
 				log_error("Can't create connection.");
-				err = MGMT_IPC_ERR_INTERNAL;
+				err = ISCSI_ERR_INTERNAL;
 				goto cleanup;
 			}
 			log_debug(3, "created new iSCSI connection "
 				  "%d:%d", session->id, conn->id);
 		}
 
-		iscsi_copy_operational_params(conn);
-
-		if (session->t->template->create_conn)
-			session->t->template->create_conn(conn);
+		iscsi_copy_operational_params(conn,
+					&session->nrec.session.iscsi,
+					&session->nrec.conn[conn->id].iscsi);
 		/*
 		 * TODO: use the iface number or some other value
 		 * so this will be persistent
@@ -1977,7 +1516,7 @@ static void session_conn_poll(void *data
 			log_error("can't bind conn %d:%d to session %d, "
 				  "retcode %d (%d)", session->id, conn->id,
 				   session->id, rc, errno);
-			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_LOGIN_FAILURE);
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_LOGIN);
 			return;
 		}
 		log_debug(3, "bound iSCSI connection %d:%d to session %d",
@@ -1991,13 +1530,13 @@ static void session_conn_poll(void *data
 		conn->exp_statsn = iscsi_sysfs_get_exp_statsn(session->id);
 
 		if (iscsi_login_begin(session, c)) {
-			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_LOGIN_FAILURE);
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_LOGIN);
 			return;
 		}
 
 		conn->state = STATE_IN_LOGIN;
 		if (iscsi_login_req(session, c)) {
-			iscsi_login_eh(conn, qtask, MGMT_IPC_ERR_LOGIN_FAILURE);
+			iscsi_login_eh(conn, qtask, ISCSI_ERR_LOGIN);
 			return;
 		}
 	} else {
@@ -2011,70 +1550,55 @@ cleanup:
 	session_conn_shutdown(conn, qtask, err);
 }
 
-void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context,
-			      struct iscsi_conn *conn, unsigned long tmo,
-			      int event)
+static int iscsi_sched_ev_context(struct iscsi_ev_context *ev_context,
+				  struct iscsi_conn *conn, unsigned long tmo,
+				  int event)
 {
 	enum iscsi_err error;
 
 	log_debug(7, "sched conn context %p event %d, tmo %lu",
-		  &conn_context->actor, event, tmo);
+		  &ev_context->actor, event, tmo);
 
-	conn_context->conn = conn;
+	ev_context->conn = conn;
 	switch (event) {
 	case EV_CONN_RECV_PDU:
-		actor_new(&conn_context->actor, session_conn_recv_pdu,
-			  conn_context);
-		actor_schedule(&conn_context->actor);
+		actor_new(&ev_context->actor, session_conn_recv_pdu,
+			  ev_context);
+		actor_schedule(&ev_context->actor);
 		break;
 	case EV_CONN_ERROR:
-		error = *(enum iscsi_err *)conn_context->data;
+		error = *(enum iscsi_err *)ev_context->data;
 
-		actor_new(&conn_context->actor, session_conn_error,
-			  conn_context);
+		actor_new(&ev_context->actor, session_conn_error,
+			  ev_context);
 		/*
 		 * We handle invalid host, by killing the session.
 		 * It must go at the head of the queue, so we do not
 		 * initiate error handling or logout or some other op.
 		 */
 		if (error == ISCSI_ERR_INVALID_HOST)
-			actor_schedule_head(&conn_context->actor);
+			actor_schedule_head(&ev_context->actor);
 		else
-			actor_schedule(&conn_context->actor);
+			actor_schedule(&ev_context->actor);
 		break;
 	case EV_CONN_POLL:
-		actor_new(&conn_context->actor, session_conn_poll,
-			  conn_context);
-		actor_schedule(&conn_context->actor);
+		actor_new(&ev_context->actor, session_conn_poll,
+			  ev_context);
+		actor_schedule(&ev_context->actor);
 		break;
 	case EV_CONN_LOGOUT_TIMER:
-		actor_timer(&conn_context->actor, tmo * 1000,
-			    iscsi_logout_timedout, conn_context);
+		actor_timer(&ev_context->actor, tmo * 1000,
+			    iscsi_logout_timedout, ev_context);
 		break;
 	case EV_CONN_STOP:
-		actor_new(&conn_context->actor, iscsi_stop,
-			  conn_context);
-		actor_schedule(&conn_context->actor);
+		actor_new(&ev_context->actor, iscsi_stop,
+			  ev_context);
+		actor_schedule(&ev_context->actor);
 		break;
 	default:
 		log_error("Invalid event type %d.", event);
-		return;
 	}
-}
-
-iscsi_session_t*
-session_find_by_sid(int sid)
-{
-	struct iscsi_transport *t;
-	iscsi_session_t *session;
-
-	list_for_each_entry(t, &transports, list) {
-		list_for_each_entry(session, &t->sessions, list) {
-			if (session->id == sid)
-				return session;
-		}
-	}
-	return NULL;
+	return 0;
 }
 
 static iscsi_session_t* session_find_by_rec(node_rec_t *rec)
@@ -2111,65 +1635,20 @@ static int session_is_running(node_rec_t
 	return 0;
 }
 
-static int iface_set_param(struct iscsi_transport *t, struct iface_rec *iface,
-			   struct iscsi_session *session)
-{
-	int rc = 0;
-
-	log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, "
-		  "transport %s.\n",
-		  iface->name, iface->netdev, iface->ipaddress,
-		  iface->hwaddress, iface->transport_name);
-
-	if (!t->template->set_host_ip)
-		return 0;
-
-	/* if we need to set the ip addr then set all the iface net settings */
-	if (!iface_is_bound_by_ipaddr(iface)) {
-		log_warning("Please set the iface.ipaddress for iface %s, "
-			    "then retry the login command.\n", iface->name);
-		return EINVAL;
-	}
-
-	rc = __iscsi_host_set_param(t, session->hostno,
-				    ISCSI_HOST_PARAM_IPADDRESS,
-				    iface->ipaddress, ISCSI_STRING);
-	if (rc)
-		return rc;
-
-	if (iface_is_bound_by_netdev(iface)) {
-		rc = __iscsi_host_set_param(t, session->hostno,
-					    ISCSI_HOST_PARAM_NETDEV_NAME,
-					    iface->netdev, ISCSI_STRING);
-		if (rc)
-			return rc;
-	}
-
-	if (iface_is_bound_by_hwaddr(iface)) {
-		rc = __iscsi_host_set_param(t, session->hostno,
-					    ISCSI_HOST_PARAM_HWADDRESS,
-					    iface->hwaddress, ISCSI_STRING);
-		if (rc)
-			return rc;
-	}
-	return 0;
-}
-
 int
 session_login_task(node_rec_t *rec, queue_task_t *qtask)
 {
 	iscsi_session_t *session;
 	iscsi_conn_t *conn;
 	struct iscsi_transport *t;
+	int rc;
 
 	if (session_is_running(rec))
-		return MGMT_IPC_ERR_EXISTS;
+		return ISCSI_ERR_SESS_EXISTS;
 
 	t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
 	if (!t)
-		return MGMT_IPC_ERR_TRANS_NOT_FOUND;
-	if (set_transport_template(t))
-		return MGMT_IPC_ERR_TRANS_NOT_FOUND;
+		return ISCSI_ERR_TRANS_NOT_FOUND;
 
 	if ((!(t->caps & CAP_RECOVERY_L0) &&
 	     rec->session.iscsi.ERL != 0) ||
@@ -2222,27 +1701,28 @@ session_login_task(node_rec_t *rec, queu
 
 	session = __session_create(rec, t);
 	if (!session)
-		return MGMT_IPC_ERR_LOGIN_FAILURE;
+		return ISCSI_ERR_LOGIN;
 
 	/* FIXME: login all connections! marked as "automatic" */
 
 	/* create leading connection */
-	if (__session_conn_create(session, 0)) {
+	rc = __session_conn_create(session, 0);
+	if (rc) {
 		__session_destroy(session);
-		return MGMT_IPC_ERR_LOGIN_FAILURE;
+		return rc;
 	}
 	conn = &session->conn[0];
 	qtask->conn = conn;
 
-	if (iface_set_param(t, &rec->iface, session)) {
+	if (iscsi_host_set_net_params(&rec->iface, session)) {
 		__session_destroy(session);
-		return MGMT_IPC_ERR_LOGIN_FAILURE;
+		return ISCSI_ERR_LOGIN;
 	}
 
 	conn->state = STATE_XPT_WAIT;
 	if (iscsi_conn_connect(conn, qtask)) {
 		__session_destroy(session);
-		return MGMT_IPC_ERR_TRANS_FAILURE;
+		return ISCSI_ERR_TRANS;
 	}
 
 	if (gettimeofday(&conn->initial_connect_time, NULL))
@@ -2251,17 +1731,19 @@ session_login_task(node_rec_t *rec, queu
 			  "login early. You should manually login.");
 
 	qtask->rsp.command = MGMT_IPC_SESSION_LOGIN;
-	qtask->rsp.err = MGMT_IPC_OK;
-	return MGMT_IPC_OK;
+	qtask->rsp.err = ISCSI_SUCCESS;
+	return ISCSI_SUCCESS;
 }
 
 static int
 sync_conn(iscsi_session_t *session, uint32_t cid)
 {
 	iscsi_conn_t *conn;
+	int rc;
 
-	if (__session_conn_create(session, cid))
-		return ENOMEM;
+	rc = __session_conn_create(session, cid);
+	if (rc)
+		return rc;
 	conn = &session->conn[cid];
 
 	/* TODO: must export via sysfs so we can pick this up */
@@ -2269,7 +1751,7 @@ sync_conn(iscsi_session_t *session, uint
 	return 0;
 }
 
-mgmt_ipc_err_e
+int
 iscsi_sync_session(node_rec_t *rec, queue_task_t *qtask, uint32_t sid)
 {
 	iscsi_session_t *session;
@@ -2278,32 +1760,24 @@ iscsi_sync_session(node_rec_t *rec, queu
 
 	t = iscsi_sysfs_get_transport_by_name(rec->iface.transport_name);
 	if (!t)
-		return MGMT_IPC_ERR_TRANS_NOT_FOUND;
-	if (set_transport_template(t))
-		return MGMT_IPC_ERR_TRANS_NOT_FOUND;
+		return ISCSI_ERR_TRANS_NOT_FOUND;
 
 	session = __session_create(rec, t);
 	if (!session)
-		return MGMT_IPC_ERR_LOGIN_FAILURE;
+		return ISCSI_ERR_LOGIN;
 
 	session->id = sid;
 	session->hostno = iscsi_sysfs_get_host_no_from_sid(sid, &err);
 	if (err) {
 		log_error("Could not get hostno for session %d\n", sid);
-		err = MGMT_IPC_ERR_NOT_FOUND;
 		goto destroy_session;
 	}
 
 	session->r_stage = R_STAGE_SESSION_REOPEN;
 
 	err = sync_conn(session, 0);
-	if (err) {
-		if (err == ENOMEM)
-			err = MGMT_IPC_ERR_NOMEM;
-		else
-			err = MGMT_IPC_ERR_INVAL;
+	if (err)
 		goto destroy_session;
-	}
 
 	session->sync_qtask = qtask;
 	qtask->rsp.command = MGMT_IPC_SESSION_SYNC;
@@ -2334,12 +1808,12 @@ session_logout_task(int sid, queue_task_
 {
 	iscsi_session_t *session;
 	iscsi_conn_t *conn;
-	mgmt_ipc_err_e rc = MGMT_IPC_OK;
+	int rc = ISCSI_SUCCESS;
 
 	session = session_find_by_sid(sid);
 	if (!session) {
                 log_debug(1, "session sid %d not found.\n", sid);
-		return MGMT_IPC_ERR_NOT_FOUND;
+		return ISCSI_ERR_SESS_NOT_FOUND;
 	}
 	conn = &session->conn[0];
 	/*
@@ -2354,7 +1828,7 @@ session_logout_task(int sid, queue_task_
 invalid_state:
 		log_error("session in invalid state for logout. "
 			   "Try again later\n");
-		return MGMT_IPC_ERR_INTERNAL;
+		return ISCSI_ERR_INTERNAL;
 	}
 
 	/* FIXME: logout all active connections */
@@ -2370,39 +1844,39 @@ invalid_state:
 	switch (conn->state) {
 	case STATE_LOGGED_IN:
 		if (!session_unbind(session))
-			return MGMT_IPC_OK;
+			return ISCSI_SUCCESS;
 
 		/* unbind is not supported so just do old logout */
 		if (!iscsi_send_logout(conn))
-			return MGMT_IPC_OK;
+			return ISCSI_SUCCESS;
 		log_error("Could not send logout pdu. Dropping session\n");
 		/* fallthrough */
 	default:
-		rc = session_conn_shutdown(conn, qtask, MGMT_IPC_OK);
+		rc = session_conn_shutdown(conn, qtask, ISCSI_SUCCESS);
 		break;
 	}
 
 	return rc;
 }
 
-mgmt_ipc_err_e
+int
 iscsi_host_send_targets(queue_task_t *qtask, int host_no, int do_login,
 			struct sockaddr_storage *ss)
 {
 	struct iscsi_transport *t;
 
 	t = iscsi_sysfs_get_transport_by_hba(host_no);
-	if (!t || set_transport_template(t)) {
+	if (!t) {
 		log_error("Invalid host no %d for sendtargets\n", host_no);
-		return MGMT_IPC_ERR_TRANS_FAILURE;
+		return ISCSI_ERR_TRANS_NOT_FOUND;
 	}
 	if (!(t->caps & CAP_SENDTARGETS_OFFLOAD))
-		return MGMT_IPC_ERR_TRANS_CAPS;
+		return ISCSI_ERR_TRANS_CAPS;
 
 	if (ipc->sendtargets(t->handle, host_no, (struct sockaddr *)ss))
-		return MGMT_IPC_ERR;
+		return ISCSI_ERR;
 
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
 /*
@@ -2412,7 +1886,7 @@ iscsi_host_send_targets(queue_task_t *qt
  * the card will have sessions preset in the FLASH and will log into them
  * automaotically then send us notification that a session is setup.
  */
-void iscsi_async_session_creation(uint32_t host_no, uint32_t sid)
+static void iscsi_async_session_creation(uint32_t host_no, uint32_t sid)
 {
 	struct iscsi_transport *transport;
 
@@ -2428,7 +1902,20 @@ void iscsi_async_session_creation(uint32
 	session_scan_host(NULL, host_no, NULL);
 }
 
-void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid)
+static void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid)
 {
 	log_debug(3, "session destroyed sid %u host no %d", sid, host_no);
 }
+
+static struct iscsi_ipc_ev_clbk ipc_clbk = {
+	.create_session		= iscsi_async_session_creation,
+	.destroy_session	= iscsi_async_session_destruction,
+	.get_ev_context		= iscsi_ev_context_get,
+	.put_ev_context		= iscsi_ev_context_put,
+	.sched_ev_context	= iscsi_sched_ev_context,
+};
+
+void iscsi_initiator_init(void)
+{
+	ipc_register_ev_callback(&ipc_clbk);
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/initiator_common.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator_common.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/initiator_common.c	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator_common.c	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,601 @@
+/*
+ * Common code for setting up discovery and normal sessions.
+ *
+ * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
+ * Copyright (C) 2006 - 2009 Mike Christie
+ * Copyright (C) 2006 - 2009 Red Hat, Inc. All rights reserved.
+ * maintained by open-iscsi@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "initiator.h"
+#include "transport.h"
+#include "iscsid.h"
+#include "iscsi_ipc.h"
+#include "log.h"
+#include "iscsi_sysfs.h"
+#include "iscsi_settings.h"
+#include "iface.h"
+#include "host.h"
+#include "sysdeps.h"
+#include "iscsi_err.h"
+
+struct iscsi_session *session_find_by_sid(uint32_t sid)
+{
+	struct iscsi_transport *t;
+	struct iscsi_session *session;
+
+	list_for_each_entry(t, &transports, list) {
+		list_for_each_entry(session, &t->sessions, list) {
+			if (session->id == sid)
+				return session;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * calculate parameter's padding
+ */
+static unsigned int
+__padding(unsigned int param)
+{
+	int pad;
+
+	pad = param & 3;
+	if (pad) {
+		pad = 4 - pad;
+		log_debug(1, "parameter's value %d padded to %d bytes\n",
+			   param, param + pad);
+	}
+	return param + pad;
+}
+
+int iscsi_setup_authentication(struct iscsi_session *session,
+			       struct iscsi_auth_config *auth_cfg)
+{
+	/* if we have any incoming credentials, we insist on authenticating
+	 * the target or not logging in at all
+	 */
+	if (auth_cfg->username_in[0] || auth_cfg->password_in_length) {
+		/* sanity check the config */
+		if (auth_cfg->password_length == 0) {
+			log_warning("CHAP configuratoin has incoming "
+				    "authentication credentials but has no "
+				    "outgoing credentials configured.");
+			return EINVAL;
+		}
+		session->bidirectional_auth = 1;
+	} else {
+		/* no or 1-way authentication */
+		session->bidirectional_auth = 0;
+	}
+
+	/* copy in whatever credentials we have */
+	strlcpy(session->username, auth_cfg->username,
+		sizeof (session->username));
+	session->username[sizeof (session->username) - 1] = '\0';
+	if ((session->password_length = auth_cfg->password_length))
+		memcpy(session->password, auth_cfg->password,
+		       session->password_length);
+
+	strlcpy(session->username_in, auth_cfg->username_in,
+		sizeof (session->username_in));
+	session->username_in[sizeof (session->username_in) - 1] = '\0';
+	if ((session->password_in_length =
+	     auth_cfg->password_in_length))
+		memcpy(session->password_in, auth_cfg->password_in,
+		       session->password_in_length);
+
+	if (session->password_length || session->password_in_length) {
+		/* setup the auth buffers */
+		session->auth_buffers[0].address = &session->auth_client_block;
+		session->auth_buffers[0].length =
+		    sizeof (session->auth_client_block);
+		session->auth_buffers[1].address =
+		    &session->auth_recv_string_block;
+		session->auth_buffers[1].length =
+		    sizeof (session->auth_recv_string_block);
+
+		session->auth_buffers[2].address =
+		    &session->auth_send_string_block;
+		session->auth_buffers[2].length =
+		    sizeof (session->auth_send_string_block);
+
+		session->auth_buffers[3].address =
+		    &session->auth_recv_binary_block;
+		session->auth_buffers[3].length =
+		    sizeof (session->auth_recv_binary_block);
+
+		session->auth_buffers[4].address =
+		    &session->auth_send_binary_block;
+		session->auth_buffers[4].length =
+		    sizeof (session->auth_send_binary_block);
+
+		session->num_auth_buffers = 5;
+		log_debug(6, "authentication setup complete...");
+	} else {
+		session->num_auth_buffers = 0;
+		log_debug(6, "no authentication configured...");
+	}
+
+	return 0;
+}
+
+void
+iscsi_copy_operational_params(struct iscsi_conn *conn,
+			struct iscsi_session_operational_config *session_conf,
+			struct iscsi_conn_operational_config *conn_conf)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_transport *t = session->t;
+
+	conn->hdrdgst_en = conn_conf->HeaderDigest;
+	conn->datadgst_en = conn_conf->DataDigest;
+
+	conn->max_recv_dlength =
+			__padding(conn_conf->MaxRecvDataSegmentLength);
+	if (conn->max_recv_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
+	    conn->max_recv_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
+		log_error("Invalid iscsi.MaxRecvDataSegmentLength. Must be "
+			 "within %u and %u. Setting to %u\n",
+			  ISCSI_MIN_MAX_RECV_SEG_LEN,
+			  ISCSI_MAX_MAX_RECV_SEG_LEN,
+			  DEF_INI_MAX_RECV_SEG_LEN);
+		conn_conf->MaxRecvDataSegmentLength =
+						DEF_INI_MAX_RECV_SEG_LEN;
+		conn->max_recv_dlength = DEF_INI_MAX_RECV_SEG_LEN;
+	}
+
+	/* zero indicates to use the target's value */
+	conn->max_xmit_dlength =
+			__padding(conn_conf->MaxXmitDataSegmentLength);
+	if (conn->max_xmit_dlength == 0)
+		conn->max_xmit_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
+	if (conn->max_xmit_dlength < ISCSI_MIN_MAX_RECV_SEG_LEN ||
+	    conn->max_xmit_dlength > ISCSI_MAX_MAX_RECV_SEG_LEN) {
+		log_error("Invalid iscsi.MaxXmitDataSegmentLength. Must be "
+			 "within %u and %u. Setting to %u\n",
+			  ISCSI_MIN_MAX_RECV_SEG_LEN,
+			  ISCSI_MAX_MAX_RECV_SEG_LEN,
+			  DEF_INI_MAX_RECV_SEG_LEN);
+		conn_conf->MaxXmitDataSegmentLength =
+						DEF_INI_MAX_RECV_SEG_LEN;
+		conn->max_xmit_dlength = DEF_INI_MAX_RECV_SEG_LEN;
+	}
+
+	/* session's operational parameters */
+	session->initial_r2t_en = session_conf->InitialR2T;
+	session->imm_data_en = session_conf->ImmediateData;
+	session->first_burst = __padding(session_conf->FirstBurstLength);
+	/*
+	 * some targets like netapp fail the login if sent bad first_burst
+	 * and max_burst lens, even when immediate data=no and
+	 * initial r2t = Yes, so we always check the user values.
+	 */
+	if (session->first_burst < ISCSI_MIN_FIRST_BURST_LEN ||
+	    session->first_burst > ISCSI_MAX_FIRST_BURST_LEN) {
+		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
+			 "within %u and %u. Setting to %u\n",
+			  session->first_burst,
+			  ISCSI_MIN_FIRST_BURST_LEN,
+			  ISCSI_MAX_FIRST_BURST_LEN,
+			  DEF_INI_FIRST_BURST_LEN);
+		session_conf->FirstBurstLength = DEF_INI_FIRST_BURST_LEN;
+		session->first_burst = DEF_INI_FIRST_BURST_LEN;
+	}
+
+	session->max_burst = __padding(session_conf->MaxBurstLength);
+	if (session->max_burst < ISCSI_MIN_MAX_BURST_LEN ||
+	    session->max_burst > ISCSI_MAX_MAX_BURST_LEN) {
+		log_error("Invalid iscsi.MaxBurstLength of %u. Must be "
+			  "within %u and %u. Setting to %u\n",
+			   session->max_burst, ISCSI_MIN_MAX_BURST_LEN,
+			   ISCSI_MAX_MAX_BURST_LEN, DEF_INI_MAX_BURST_LEN);
+		session_conf->MaxBurstLength = DEF_INI_MAX_BURST_LEN;
+		session->max_burst = DEF_INI_MAX_BURST_LEN;
+	}
+
+	if (session->first_burst > session->max_burst) {
+		log_error("Invalid iscsi.FirstBurstLength of %u. Must be "
+			  "less than iscsi.MaxBurstLength. Setting to %u\n",
+			   session->first_burst, session->max_burst);
+		session_conf->FirstBurstLength = session->max_burst;
+		session->first_burst = session->max_burst;
+	}
+
+	session->def_time2wait = session_conf->DefaultTime2Wait;
+	session->def_time2retain = session_conf->DefaultTime2Retain;
+	session->erl = session_conf->ERL;
+
+	if (session->type == ISCSI_SESSION_TYPE_DISCOVERY) {
+		/*
+		 * Right now, we only support 8K max for kernel based
+		 * sendtargets discovery, because the recv pdu buffers are
+		 * limited to this size.
+		 */
+		if ((t->caps & CAP_TEXT_NEGO) &&
+		     conn->max_recv_dlength > ISCSI_DEF_MAX_RECV_SEG_LEN)
+			conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN;
+
+		/* We do not support discovery sessions with digests */
+		conn->hdrdgst_en = ISCSI_DIGEST_NONE;
+		conn->datadgst_en = ISCSI_DIGEST_NONE;
+	}
+
+	if (t->template->create_conn)
+		t->template->create_conn(conn);
+}
+
+int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port)
+{
+	char serv[NI_MAXSERV];
+
+	sprintf(serv, "%d", port);
+	if (resolve_address(address, serv, &conn->saddr)) {
+		log_error("cannot resolve host name %s", address);
+		return ISCSI_ERR_TRANS;
+	}
+	conn->failback_saddr = conn->saddr;
+
+	getnameinfo((struct sockaddr *)&conn->saddr, sizeof(conn->saddr),
+		    conn->host, sizeof(conn->host), NULL, 0, NI_NUMERICHOST);
+	log_debug(4, "resolved %s to %s", address, conn->host);
+	return 0;
+}
+
+int host_set_param(struct iscsi_transport *t,
+		   uint32_t host_no, int param, char *value,
+		   int type)
+{
+	int rc;
+
+	rc = ipc->set_host_param(t->handle, host_no, param, value, type);
+	/* 2.6.20 and below returns EINVAL */
+	if (rc && rc != -ENOSYS && rc != -EINVAL) {
+		log_error("can't set operational parameter %d for "
+			  "host %d, retcode %d (%d)", param, host_no,
+			  rc, errno);
+		return rc;
+	}
+	return 0;
+}
+
+static void print_param_value(enum iscsi_param param, void *value, int type)
+{
+	log_debug(3, "set operational parameter %d to:", param);
+
+	if (type == ISCSI_STRING)
+		log_debug(3, "%s", value ? (char *)value : "NULL");
+	else
+		log_debug(3, "%u", *(uint32_t *)value);
+}
+
+#define MAX_HOST_PARAMS 2
+
+int iscsi_host_set_params(struct iscsi_session *session)
+{
+	struct iscsi_transport *t = session->t;
+	int i;
+	struct hostparam {
+		int param;
+		int type;
+		void *value;
+	} hosttbl[MAX_HOST_PARAMS] = {
+		{
+			.param = ISCSI_HOST_PARAM_NETDEV_NAME,
+			.value = session->nrec.iface.netdev,
+			.type = ISCSI_STRING,
+		}, {
+			.param = ISCSI_HOST_PARAM_HWADDRESS,
+			.value = session->nrec.iface.hwaddress,
+			.type = ISCSI_STRING,
+		},
+	};
+
+	for (i = 0; i < MAX_HOST_PARAMS; i++) {
+		if (host_set_param(t, session->hostno,
+				   hosttbl[i].param, hosttbl[i].value,
+				   hosttbl[i].type)) {
+			return EPERM;
+		}
+
+		print_param_value(hosttbl[i].param, hosttbl[i].value,
+				  hosttbl[i].type);
+	}
+
+	return 0;
+}
+
+#define MAX_SESSION_PARAMS 32
+
+int iscsi_session_set_params(struct iscsi_conn *conn)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_transport *t = session->t;
+	int i, rc;
+	uint32_t one = 1, zero = 0;
+	struct connparam {
+		int param;
+		int type;
+		void *value;
+		int conn_only;
+	} conntbl[MAX_SESSION_PARAMS] = {
+		{
+			.param = ISCSI_PARAM_MAX_RECV_DLENGTH,
+			.value = &conn->max_recv_dlength,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_MAX_XMIT_DLENGTH,
+			.value = &conn->max_xmit_dlength,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_HDRDGST_EN,
+			.value = &conn->hdrdgst_en,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_DATADGST_EN,
+			.value = &conn->datadgst_en,
+			.type = ISCSI_INT,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_INITIAL_R2T_EN,
+			.value = &session->initial_r2t_en,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_MAX_R2T,
+			.value = &one, /* FIXME: session->max_r2t */
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_IMM_DATA_EN,
+			.value = &session->imm_data_en,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_FIRST_BURST,
+			.value = &session->first_burst,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_MAX_BURST,
+			.value = &session->max_burst,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_PDU_INORDER_EN,
+			.value = &session->pdu_inorder_en,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param =ISCSI_PARAM_DATASEQ_INORDER_EN,
+			.value = &session->dataseq_inorder_en,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_ERL,
+			.value = &zero, /* FIXME: session->erl */
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_IFMARKER_EN,
+			.value = &zero,/* FIXME: session->ifmarker_en */
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_OFMARKER_EN,
+			.value = &zero,/* FIXME: session->ofmarker_en */
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_EXP_STATSN,
+			.value = &conn->exp_statsn,
+			.type = ISCSI_INT,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_TARGET_NAME,
+			.conn_only = 0,
+			.type = ISCSI_STRING,
+			.value = session->target_name,
+		}, {
+			.param = ISCSI_PARAM_TPGT,
+			.value = &session->portal_group_tag,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_PERSISTENT_ADDRESS,
+			.value = session->nrec.conn[conn->id].address,
+			.type = ISCSI_STRING,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_PERSISTENT_PORT,
+			.value = &session->nrec.conn[conn->id].port,
+			.type = ISCSI_INT,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_SESS_RECOVERY_TMO,
+			.value = &session->replacement_timeout,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_USERNAME,
+			.value = session->username,
+			.type = ISCSI_STRING,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_USERNAME_IN,
+			.value = session->username_in,
+			.type = ISCSI_STRING,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_PASSWORD,
+			.value = session->password,
+			.type = ISCSI_STRING,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_PASSWORD_IN,
+			.value = session->password_in,
+			.type = ISCSI_STRING,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_FAST_ABORT,
+			.value = &session->fast_abort,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_ABORT_TMO,
+			.value = &session->abort_timeout,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_LU_RESET_TMO,
+			.value = &session->lu_reset_timeout,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_TGT_RESET_TMO,
+			.value = &session->tgt_reset_timeout,
+			.type = ISCSI_INT,
+			.conn_only = 0,
+		}, {
+			.param = ISCSI_PARAM_PING_TMO,
+			.value = &conn->noop_out_timeout,
+			.type = ISCSI_INT,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_RECV_TMO,
+			.value = &conn->noop_out_interval,
+			.type = ISCSI_INT,
+			.conn_only = 1,
+		}, {
+			.param = ISCSI_PARAM_IFACE_NAME,
+			.value = session->nrec.iface.name,
+			.type = ISCSI_STRING,
+		}, {
+			.param = ISCSI_PARAM_INITIATOR_NAME,
+			.value = session->initiator_name,
+			.type = ISCSI_STRING,
+		},
+	};
+
+	session->param_mask = ~0ULL;
+	if (!(t->caps & CAP_MULTI_R2T))
+		session->param_mask &= ~ISCSI_MAX_R2T;
+	if (!(t->caps & CAP_HDRDGST))
+		session->param_mask &= ~ISCSI_HDRDGST_EN;
+	if (!(t->caps & CAP_DATADGST))
+		session->param_mask &= ~ISCSI_DATADGST_EN;
+	if (!(t->caps & CAP_MARKERS)) {
+		session->param_mask &= ~ISCSI_IFMARKER_EN;
+		session->param_mask &= ~ISCSI_OFMARKER_EN;
+	}
+
+	/* Entered full-feature phase! */
+	for (i = 0; i < MAX_SESSION_PARAMS; i++) {
+		if (conn->id != 0 && !conntbl[i].conn_only)
+			continue;
+
+		if (!(session->param_mask & (1ULL << conntbl[i].param)))
+			continue;
+
+		rc = ipc->set_param(session->t->handle, session->id,
+				   conn->id, conntbl[i].param, conntbl[i].value,
+				   conntbl[i].type);
+		if (rc && rc != -ENOSYS) {
+			log_error("can't set operational parameter %d for "
+				  "connection %d:%d, retcode %d (%d)",
+				  conntbl[i].param, session->id, conn->id,
+				  rc, errno);
+			return EPERM;
+		}
+
+		if (rc == -ENOSYS) {
+			switch (conntbl[i].param) {
+			case ISCSI_PARAM_PING_TMO:
+				/*
+				 * older kernels may not support nops
+				 * in kernel
+				 */
+				conn->userspace_nop = 1;
+				break;
+#if 0
+TODO handle this
+			case ISCSI_PARAM_INITIATOR_NAME:
+				/* use host level one instead */
+				hosttbl[ISCSI_HOST_PARAM_INITIATOR_NAME].set = 1;
+				break;
+#endif
+			}
+		}
+
+		print_param_value(conntbl[i].param, conntbl[i].value,
+				  conntbl[i].type);
+	}
+
+	return 0;
+}
+
+int iscsi_host_set_net_params(struct iface_rec *iface,
+			      struct iscsi_session *session)
+{
+	struct iscsi_transport *t = session->t;
+	int rc = 0;
+
+	log_debug(3, "setting iface %s, dev %s, set ip %s, hw %s, "
+		  "transport %s.\n",
+		  iface->name, iface->netdev, iface->ipaddress,
+		  iface->hwaddress, iface->transport_name);
+
+	if (!t->template->set_host_ip)
+		return 0;
+
+	/* if we need to set the ip addr then set all the iface net settings */
+	if (!iface_is_bound_by_ipaddr(iface)) {
+		log_warning("Please set the iface.ipaddress for iface %s, "
+			    "then retry the login command.\n", iface->name);
+		return EINVAL;
+	}
+
+	rc = host_set_param(t, session->hostno,
+			    ISCSI_HOST_PARAM_IPADDRESS,
+			    iface->ipaddress, ISCSI_STRING);
+	if (rc)
+		return rc;
+
+	if (iface_is_bound_by_netdev(iface)) {
+		rc = host_set_param(t, session->hostno,
+				    ISCSI_HOST_PARAM_NETDEV_NAME,
+				    iface->netdev, ISCSI_STRING);
+		if (rc)
+			return rc;
+	}
+
+	if (iface_is_bound_by_hwaddr(iface)) {
+		rc = host_set_param(t, session->hostno,
+				    ISCSI_HOST_PARAM_HWADDRESS,
+				    iface->hwaddress, ISCSI_STRING);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/initiator.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/initiator.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/initiator.h	2011-02-03 20:14:23.000000000 -0600
@@ -67,6 +67,7 @@ typedef enum conn_login_status_e {
 	CONN_LOGIN_RETRY		= 3,
 	CONN_LOGIN_IMM_RETRY		= 4,
 	CONN_LOGIN_IMM_REDIRECT_RETRY	= 5,
+	CONN_LOGIN_AUTH_FAILED		= 6,
 } conn_login_status_e;
 
 enum iscsi_login_status {
@@ -112,14 +113,14 @@ typedef struct iscsi_login_context {
 
 struct iscsi_session;
 struct iscsi_conn;
-struct iscsi_conn_context;
+struct iscsi_ev_context;
 
 /* daemon's connection structure */
 typedef struct iscsi_conn {
 	uint32_t id;
 	struct iscsi_session *session;
 	iscsi_login_context_t login_context;
-	struct iscsi_conn_context *recv_context;
+	struct iscsi_ev_context *recv_context;
 	struct queue_task *logout_qtask;
 	char data[ISCSI_DEF_MAX_RECV_SEG_LEN];
 	char host[NI_MAXHOST];	/* scratch */
@@ -131,7 +132,7 @@ typedef struct iscsi_conn {
 	actor_t nop_out_timer;
 
 #define CONTEXT_POOL_MAX 32
-	struct iscsi_conn_context *context_pool[CONTEXT_POOL_MAX];
+	struct iscsi_ev_context *context_pool[CONTEXT_POOL_MAX];
 
 	/* login state machine */
 	int current_stage;
@@ -140,6 +141,11 @@ typedef struct iscsi_conn {
 	conn_login_status_e status;
 
 	/* tcp/socket settings */
+
+	/*
+	 * Either a tcp/ip or a netlink socket to do
+	 * IO through.
+	 */
 	int socket_fd;
 	/* address being used for normal session connection */
 	struct sockaddr_storage saddr;
@@ -173,7 +179,7 @@ typedef struct iscsi_conn {
 	uint32_t max_xmit_dlength;	/* the value declared by the target */
 } iscsi_conn_t;
 
-struct iscsi_conn_context {
+struct iscsi_ev_context {
 	struct actor actor;
 	struct iscsi_conn *conn;
 	int allocated;
@@ -201,6 +207,7 @@ typedef struct iscsi_session {
 	uint32_t hostno;
 	char netdev[IFNAMSIZ];
 	struct iscsi_transport *t;
+	uint8_t use_ipc;
 	node_rec_t nrec; /* copy of original Node record in database */
 	unsigned int irrelevant_keys_bitmap;
 	int send_async_text;
@@ -242,7 +249,6 @@ typedef struct iscsi_session {
 	uint8_t password_in[AUTH_STR_MAX_LEN];
 	int password_in_length;
 	iscsi_conn_t conn[ISCSI_CONN_MAX];
-	int ctrl_fd;
 	uint64_t param_mask;
 
 	/* connection reopens during recovery */
@@ -330,20 +336,25 @@ extern int iscsi_io_recv_pdu(iscsi_conn_
 /* initiator.c */
 extern int session_login_task(node_rec_t *rec, queue_task_t *qtask);
 extern int session_logout_task(int sid, queue_task_t *qtask);
-extern iscsi_session_t *session_find_by_sid(int sid);
-extern struct iscsi_conn_context *iscsi_conn_context_get(iscsi_conn_t *conn,
-						   int ev_size);
-extern void iscsi_conn_context_put(struct iscsi_conn_context *conn_context);
-extern void iscsi_sched_conn_context(struct iscsi_conn_context *context,
-				     struct iscsi_conn *conn, unsigned long tmo,
-				     int event);
-extern mgmt_ipc_err_e iscsi_sync_session(node_rec_t *rec, queue_task_t
+extern iscsi_session_t *session_find_by_sid(uint32_t sid);
+extern int iscsi_sync_session(node_rec_t *rec, queue_task_t
 					 *tsk, uint32_t sid);
-extern mgmt_ipc_err_e iscsi_host_send_targets(queue_task_t *qtask,
+extern int iscsi_host_send_targets(queue_task_t *qtask,
 			int host_no, int do_login, struct sockaddr_storage *ss);
-extern mgmt_ipc_err_e iscsi_host_set_param(int host_no, int param, char *value);
-extern void iscsi_async_session_creation(uint32_t host_no, uint32_t sid);
-extern void iscsi_async_session_destruction(uint32_t host_no, uint32_t sid);
+
 extern void free_initiator(void);
+extern void iscsi_initiator_init(void);
+
+/* initiator code common to discovery and normal sessions */
+extern int iscsi_session_set_params(struct iscsi_conn *conn);
+extern int iscsi_host_set_params(struct iscsi_session *session);
+extern int iscsi_host_set_net_params(struct iface_rec *iface,
+				     struct iscsi_session *session);
+extern void iscsi_copy_operational_params(struct iscsi_conn *conn,
+			struct iscsi_session_operational_config *session_conf,
+			struct iscsi_conn_operational_config *conn_conf);
+extern int iscsi_setup_authentication(struct iscsi_session *session,
+				      struct iscsi_auth_config *auth_cfg);
+extern int iscsi_setup_portal(struct iscsi_conn *conn, char *address, int port);
 
 #endif /* INITIATOR_H */
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/io.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/io.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/io.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/io.c	2011-02-03 20:14:23.000000000 -0600
@@ -401,7 +401,6 @@ iscsi_io_connect(iscsi_conn_t *conn)
 	int rc, ret;
 	struct sigaction action;
 	struct sigaction old;
-	char serv[NI_MAXSERV];
 
 	/* set a timeout, since the socket calls may take a long time to
 	 * timeout on their own
@@ -420,22 +419,21 @@ iscsi_io_connect(iscsi_conn_t *conn)
 	 */
 	rc = iscsi_io_tcp_connect(conn, 0);
 	if (timedout) {
+		log_error("connect to %s timed out", conn->host);
+			  
 		log_debug(1, "socket %d connect timed out", conn->socket_fd);
 		ret = 0;
 		goto done;
 	} else if (rc < 0) {
-		getnameinfo((struct sockaddr *) &conn->saddr,
-			    sizeof(conn->saddr),
-			    conn->host, sizeof(conn->host), serv, sizeof(serv),
-			    NI_NUMERICHOST|NI_NUMERICSERV);
-		log_error("cannot make connection to %s:%s (%d)",
-			  conn->host, serv, errno);
+		log_error("cannot make connection to %s: %s",
+			  conn->host, strerror(errno));
 		close(conn->socket_fd);
 		ret = 0;
 		goto done;
 	} else if (log_level > 0) {
 		struct sockaddr_storage ss;
 		char lserv[NI_MAXSERV];
+		char serv[NI_MAXSERV];
 		socklen_t salen = sizeof(ss);
 
 		if (getsockname(conn->socket_fd, (struct sockaddr *) &ss,
@@ -503,7 +501,7 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 	/* set a timeout, since the socket calls may take a long time
 	 * to timeout on their own
 	 */
-	if (!ipc) {
+	if (!session->use_ipc) {
 		memset(&action, 0, sizeof (struct sigaction));
 		memset(&old, 0, sizeof (struct sigaction));
 		action.sa_sigaction = NULL;
@@ -566,7 +564,7 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 	else
 		pad_bytes = 0;
 
-	if (ipc)
+	if (session->use_ipc)
 		ipc->send_pdu_begin(session->t->handle, session->id,
 				    conn->id, end - header,
 				    ntoh24(hdr->dlength) + pad_bytes);
@@ -575,8 +573,8 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 		vec[0].iov_base = header;
 		vec[0].iov_len = end - header;
 
-		if (!ipc)
-			rc = writev(session->ctrl_fd, vec, 1);
+		if (!session->use_ipc)
+			rc = writev(conn->socket_fd, vec, 1);
 		else
 			rc = ipc->writev(0, vec, 1);
 		if (timedout) {
@@ -603,13 +601,13 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 		vec[1].iov_base = (void *) &pad;
 		vec[1].iov_len = pad_bytes;
 
-		if (!ipc)
-			rc = writev(session->ctrl_fd, vec, 2);
+		if (!session->use_ipc)
+			rc = writev(conn->socket_fd, vec, 2);
 		else
 			rc = ipc->writev(0, vec, 2);
 		if (timedout) {
 			log_error("socket %d write timed out",
-			       conn->socket_fd);
+				  conn->socket_fd);
 			ret = 0;
 			goto done;
 		} else if ((rc <= 0) && (errno != EAGAIN)) {
@@ -627,7 +625,7 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 		}
 	}
 
-	if (ipc) {
+	if (session->use_ipc) {
 		if (ipc->send_pdu_end(session->t->handle, session->id,
 				      conn->id, &rc)) {
 			ret = 0;
@@ -638,7 +636,7 @@ iscsi_io_send_pdu(iscsi_conn_t *conn, st
 	ret = 1;
 
       done:
-	if (!ipc) {
+	if (!session->use_ipc) {
 		alarm(0);
 		sigaction(SIGALRM, &old, NULL);
 		timedout = 0;
@@ -670,7 +668,7 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 	/* set a timeout, since the socket calls may take a long
 	 * time to timeout on their own
 	 */
-	if (!ipc) {
+	if (!session->use_ipc) {
 		memset(&action, 0, sizeof (struct sigaction));
 		memset(&old, 0, sizeof (struct sigaction));
 		action.sa_sigaction = NULL;
@@ -680,7 +678,10 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 		timedout = 0;
 		alarm(timeout);
 	} else {
-		if (ipc->recv_pdu_begin(conn)) {
+		failed = ipc->recv_pdu_begin(conn);
+		if (failed == -EAGAIN)
+			return -EAGAIN;
+		else if (failed < 0) {
 			failed = 1;
 			goto done;
 		}
@@ -688,14 +689,14 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 
 	/* read a response header */
 	do {
-		if (!ipc)
-			rlen = read(session->ctrl_fd, header,
+		if (!session->use_ipc)
+			rlen = read(conn->socket_fd, header,
 					sizeof (*hdr) - h_bytes);
 		else
 			rlen = ipc->read(header, sizeof (*hdr) - h_bytes);
 		if (timedout) {
 			log_error("socket %d header read timed out",
-			       conn->socket_fd);
+				  conn->socket_fd);
 			failed = 1;
 			goto done;
 		} else if (rlen == 0) {
@@ -714,7 +715,7 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 	} while (h_bytes < sizeof (*hdr));
 
 	log_debug(4, "read %d PDU header bytes, opcode 0x%x, dlength %u, "
-		 "data %p, max %u", h_bytes, hdr->opcode,
+		 "data %p, max %u", h_bytes, hdr->opcode & ISCSI_OPCODE_MASK,
 		 ntoh24(hdr->dlength), data, max_data_length);
 
 	/* check for additional headers */
@@ -745,14 +746,14 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 	/* read the rest into our buffer */
 	d_bytes = 0;
 	while (d_bytes < dlength) {
-		if (!ipc)
-			rlen = read(session->ctrl_fd, data + d_bytes,
+		if (!session->use_ipc)
+			rlen = read(conn->socket_fd, data + d_bytes,
 					dlength - d_bytes);
 		else
 			rlen = ipc->read(data + d_bytes, dlength - d_bytes);
 		if (timedout) {
 			log_error("socket %d data read timed out",
-			       conn->socket_fd);
+				  conn->socket_fd);
 			failed = 1;
 			goto done;
 		} else if (rlen == 0) {
@@ -772,7 +773,7 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 	/* handle PDU data padding.
 	 * data is padded in case of kernel_io */
 	pad = dlength % ISCSI_PAD_LEN;
-	if (pad && !ipc) {
+	if (pad && !session->use_ipc) {
 		int pad_bytes = pad = ISCSI_PAD_LEN - pad;
 		char bytes[ISCSI_PAD_LEN];
 
@@ -780,7 +781,7 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 			rlen = read(conn->socket_fd, &bytes, pad_bytes);
 			if (timedout) {
 				log_error("socket %d pad read timed out",
-				       conn->socket_fd);
+					  conn->socket_fd);
 				failed = 1;
 				goto done;
 			} else if (rlen == 0) {
@@ -828,7 +829,7 @@ iscsi_io_recv_pdu(iscsi_conn_t *conn, st
 	}
 
 done:
-	if (!ipc) {
+	if (!session->use_ipc) {
 		alarm(0);
 		sigaction(SIGALRM, &old, NULL);
 	} else {
@@ -840,7 +841,7 @@ done:
 
 	if (timedout || failed) {
 		timedout = 0;
-		return 0;
+		return -EIO;
 	}
 
 	return h_bytes + ahs_bytes + d_bytes;
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c	2011-02-03 20:14:23.000000000 -0600
@@ -48,10 +48,11 @@
 #include "session_mgmt.h"
 #include "iscsid_req.h"
 #include "isns-proto.h"
+#include "iscsi_err.h"
 
-struct iscsi_ipc *ipc = NULL; /* dummy */
 static char program_name[] = "iscsiadm";
 static char config_file[TARGET_NAME_MAXLEN];
+extern struct iscsi_ipc *ipc;
 
 enum iscsiadm_mode {
 	MODE_DISCOVERY,
@@ -119,7 +120,7 @@ iscsiadm -m fw [ -l ]\n\
 iscsiadm -m host [ -P printlevel ] [ -H hostno ]\n\
 iscsiadm -k priority\n");
 	}
-	exit(status == 0 ? 0 : -1);
+	exit(status);
 }
 
 static int
@@ -212,7 +213,7 @@ static void kill_iscsid(int priority)
 	req.command = MGMT_IPC_IMMEDIATE_STOP;
 	rc = iscsid_exec_req(&req, &rsp, 0);
 	if (rc) {
-		iscsid_handle_error(rc);
+		iscsi_err_print_msg(rc);
 		log_error("Could not stop iscsid. Trying sending iscsid "
 			  "SIGTERM or SIGKILL signals manually\n");
 	}
@@ -251,12 +252,12 @@ static int print_ifaces(struct iface_rec
 		break;
 	default:
 		log_error("Invalid info level %d. Try 0 - 1.", info_level);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	if (!num_found) {
 		log_error("No interfaces found.");
-		err = ENODEV;
+		err = ISCSI_ERR_NO_OBJS_FOUND;
 	}
 	return err;
 }
@@ -296,11 +297,11 @@ for_each_session(struct node_rec *rec, i
 
 	err = iscsi_sysfs_for_each_session(rec, &num_found, fn);
 	if (err)
-		log_error("Could not execute operation on all sessions. Err "
-			  "%d.", err);
+		log_error("Could not execute operation on all sessions: %s",
+			  iscsi_err_to_str(err));
 	else if (!num_found) {
-		log_error("No portal found.");
-		err = ENODEV;
+		log_error("No session found.");
+		err = ISCSI_ERR_NO_OBJS_FOUND;
 	}
 
 	return err;
@@ -313,7 +314,7 @@ static int link_recs(void *data, struct 
 
 	rec_copy = calloc(1, sizeof(*rec_copy));
 	if (!rec_copy)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	memcpy(rec_copy, rec, sizeof(*rec_copy));
 	INIT_LIST_HEAD(&rec_copy->list);
 	list_add_tail(&rec_copy->list, list);
@@ -326,7 +327,6 @@ __logout_by_startup(void *data, struct l
 {
 	char *mode = data;
 	node_rec_t rec;
-	int rc = 0;
 
 	memset(&rec, 0, sizeof(node_rec_t));
 	if (idbm_rec_read(&rec, info->targetname, info->tpgt,
@@ -352,28 +352,33 @@ __logout_by_startup(void *data, struct l
 	if (rec.startup == ISCSI_STARTUP_ONBOOT)
 		return -1;
 
-	if (!match_startup_mode(&rec, mode))
-		rc = iscsi_logout_portal(info, list);
-	return rc;
+	if (match_startup_mode(&rec, mode))
+		return -1;
+
+	return iscsi_logout_portal(info, list);
 }
 
 static int
 logout_by_startup(char *mode)
 {
 	int nr_found;
+	int rc;
 
 	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
 	    !strcmp(mode,"manual"))) {
 		log_error("Invalid logoutall option %s.", mode);
-		usage(0);
-		return EINVAL;
+		usage(ISCSI_ERR_INVAL);
+		return ISCSI_ERR_INVAL;
 	}
 
-	return iscsi_logout_portals(mode, &nr_found, 1, __logout_by_startup);
+	rc = iscsi_logout_portals(mode, &nr_found, 1, __logout_by_startup);
+	if (rc == ISCSI_ERR_NO_OBJS_FOUND)
+		log_error("No matching sessions found");
+	return rc; 
 }
 
 /*
- * TODO: merged this and logout into the common for_each_rec by making
+ * TODO: merged this and logout into the common for_each_matched_rec by making
  * the matching more generic
  */
 static int
@@ -390,36 +395,45 @@ __login_by_startup(void *data, struct li
 	if (match_startup_mode(rec, mode))
 		return -1;
 
-	iscsi_login_portal(NULL, list, rec);
-	return 0;
+	return iscsi_login_portal(NULL, list, rec);
 }
 
 static int
 login_by_startup(char *mode)
 {
-	int nr_found = 0, rc, err;
+	int nr_found = 0, err, rc;
 	struct list_head rec_list;
 
 	if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
 	    !strcmp(mode,"manual"))) {
 		log_error("Invalid loginall option %s.", mode);
-		usage(0);
-		return EINVAL;
+		usage(ISCSI_ERR_INVAL);
+		return ISCSI_ERR_INVAL;
 	}
 
 	INIT_LIST_HEAD(&rec_list);
-	rc = idbm_for_each_rec(&nr_found, &rec_list, link_recs);
+	err = idbm_for_each_rec(&nr_found, &rec_list, link_recs);
+	if (err && !list_empty(&rec_list))
+		/* log msg and try to log into what we found */
+		log_error("Could not read all records: %s",
+			  iscsi_err_to_str(err));
+	else if (err && list_empty(&rec_list)) {
+		log_error("Could not read node DB: %s.",
+			  iscsi_err_to_str(err));
+		return err;
+	} else if (list_empty(&rec_list)) {
+		log_error("No records found");
+		return ISCSI_ERR_NO_OBJS_FOUND;
+	}
+	rc = err;
+
 	err = iscsi_login_portals(mode, &nr_found, 1, &rec_list,
 				  __login_by_startup);
+	if (err)
+		log_error("Could not log into all portals");
+
 	if (err && !rc)
 		rc = err;
-
-	if (rc)
-		log_error("Could not log into all portals. Err %d.", rc);
-	else if (!nr_found) {
-		log_error("No records found!");
-		rc = ENODEV;
-	}
 	return rc;
 }
 
@@ -454,7 +468,7 @@ static int iscsi_logout_matched_portal(v
 	return iscsi_logout_portal(info, list);
 }
 
-static int iface_fn(void *data, node_rec_t *rec)
+static int rec_match_fn(void *data, node_rec_t *rec)
 {
 	struct rec_op_data *op_data = data;
 
@@ -465,7 +479,8 @@ static int iface_fn(void *data, node_rec
 	return op_data->fn(op_data->data, rec);
 }
 
-static int for_each_rec(struct node_rec *rec, void *data, idbm_iface_op_fn *fn)
+static int __for_each_matched_rec(int verbose, struct node_rec *rec,
+				  void *data, idbm_iface_op_fn *fn)
 {
 	struct rec_op_data op_data;
 	int nr_found = 0, rc;
@@ -475,30 +490,51 @@ static int for_each_rec(struct node_rec 
 	op_data.match_rec = rec;
 	op_data.fn = fn;
 
-	rc = idbm_for_each_rec(&nr_found, &op_data, iface_fn);
+	rc = idbm_for_each_rec(&nr_found, &op_data, rec_match_fn);
 	if (rc) {
-		log_error("Could not execute operation on all "
-			  "records. Err %d.", rc);
+		if (verbose)
+			log_error("Could not execute operation on all "
+				  "records: %s", iscsi_err_to_str(rc));
 	} else if (!nr_found) {
-		log_error("no records found!");
-		rc = ENODEV;
+		if (verbose)
+			log_error("No records found");
+		rc = ISCSI_ERR_NO_OBJS_FOUND;
 	}
 
 	return rc;
 }
 
+static int for_each_matched_rec(struct node_rec *rec, void *data,
+			        idbm_iface_op_fn *fn)
+{
+	return __for_each_matched_rec(1, rec, data, fn);
+}
+
+
 static int login_portals(struct node_rec *pattern_rec)
 {
 	struct list_head rec_list;
-	int err, ret, nr_found;
+	int nr_found, rc, err;
 
 	INIT_LIST_HEAD(&rec_list);
-	ret = for_each_rec(pattern_rec, &rec_list, link_recs);
+	err = for_each_matched_rec(pattern_rec, &rec_list, link_recs);
+	if (err == ISCSI_ERR_NO_OBJS_FOUND)
+		return err;
+	else if (err && list_empty(&rec_list))
+		return err;
+
+	rc = err;
+	/* if there is an err but some recs then try to login to what we have */
+
 	err = iscsi_login_portals(NULL, &nr_found, 1, &rec_list,
 				  iscsi_login_portal);
-	if (err && !ret)
-		ret = err;
-	return ret;
+	if (err)
+		log_error("Could not log into all portals");
+
+	if (err && !rc)
+		rc = err;
+
+	return rc;
 }
 
 static int print_nodes(int info_level, struct node_rec *rec)
@@ -509,17 +545,16 @@ static int print_nodes(int info_level, s
 	switch (info_level) {
 	case 0:
 	case -1:
-		if (for_each_rec(rec, NULL, idbm_print_node_flat))
-			rc = -1;
+		rc = for_each_matched_rec(rec, NULL, idbm_print_node_flat);
 		break;
 	case 1:
 		memset(&tmp_rec, 0, sizeof(node_rec_t));
-		if (for_each_rec(rec, &tmp_rec, idbm_print_node_and_iface_tree))
-			rc = -1;
+		rc = for_each_matched_rec(rec, &tmp_rec,
+					  idbm_print_node_and_iface_tree);
 		break;
 	default:
 		log_error("Invalid info level %d. Try 0 or 1.", info_level);
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 	}
 
 	return rc;
@@ -586,7 +621,7 @@ session_stats(void *data, struct session
 
 	rc = iscsid_exec_req(&req, &rsp, 1);
 	if (rc)
-		return EIO;
+		return rc;
 
 	printf("Stats for session [sid: %d, target: %s, portal: "
 		"%s,%d]\n",
@@ -665,14 +700,14 @@ static int add_static_rec(int *found, ch
 	rec = calloc(1, sizeof(*rec));
 	if (!rec) {
 		log_error("Could not allocate memory for node addition");
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto done;
 	}
 
 	drec = calloc(1, sizeof(*drec));
 	if (!drec) {
 		log_error("Could not allocate memory for node addition");
-		rc = ENOMEM;
+		rc = ISCSI_ERR_NOMEM;
 		goto free_rec;
 	}
 	drec->type = DISCOVERY_TYPE_STATIC;
@@ -715,10 +750,10 @@ static int add_static_portal(int *found,
 
 	if (strlen(rec->conn[0].address) &&
 	    strcmp(rec->conn[0].address, ip))
-		return 0;
+		return -1;
 
 	if (rec->conn[0].port != -1 && rec->conn[0].port != port)
-		return 0;
+		return -1;
 
 	return add_static_rec(found, targetname, tpgt, ip, port,
 			      &rec->iface);
@@ -733,7 +768,7 @@ static int add_static_node(int *found, v
 		goto search;
 
 	if (strcmp(rec->name, targetname))
-		return 0;
+		return -1;
 
 	if (!strlen(rec->conn[0].address))
 		goto search;
@@ -751,11 +786,8 @@ static int add_static_recs(struct node_r
 	int rc, nr_found = 0;
 
 	rc = idbm_for_each_node(&nr_found, rec, add_static_node);
-	if (rc) {
-		log_error("Error while adding records. DB may be in an "
-			  "inconsistent state. Err %d", rc);
-		return rc;
-	}
+	if (rc)
+		goto done;
 	/* success */
 	if (nr_found > 0)
 		return 0;
@@ -765,13 +797,12 @@ static int add_static_recs(struct node_r
 		rc = add_static_rec(&nr_found, rec->name, rec->tpgt,
 				    rec->conn[0].address, rec->conn[0].port,
 				    &rec->iface);
-		if (rc)
-			goto done;
-		return 0;
+		if (!rc)
+			return 0;
 	}
 done:
-	printf("No records added.\n");
-	return ENODEV;
+	log_error("Error while adding record: %s", iscsi_err_to_str(rc));
+	return rc;
 }
 
 /*
@@ -799,7 +830,7 @@ static int delete_node(void *data, struc
 			  "using it. Logout session then rerun command to "
 			  "remove record.", rec->iface.name, rec->name,
 			  rec->conn[0].address, rec->conn[0].port);
-		return EINVAL;
+		return ISCSI_ERR_SESS_EXISTS;
 	}
 
 	return idbm_delete_node(rec);
@@ -822,18 +853,17 @@ static int delete_stale_rec(void *data, 
 			 * if we are not from the same discovery source
 			 * ignore it
 			 */
-			return 0;
+			return -1;
 
 		if (__iscsi_match_session(rec,
 					  new_rec->name,
 					  new_rec->conn[0].address,
 					  new_rec->conn[0].port,
 					  &new_rec->iface))
-			return 0;
+			return -1;
 	}
 	/* if there is a error we can continue on */
-	delete_node(NULL, rec);
-	return 0;
+	return delete_node(NULL, rec);
 }
 
 static int
@@ -918,8 +948,12 @@ do_software_sendtargets(discovery_rec_t 
 	rc = idbm_bind_ifaces_to_nodes(discovery_sendtargets, drec, ifaces,
 				       &rec_list);
 	if (rc) {
-		log_error("Could not perform SendTargets discovery.");
+		log_error("Could not perform SendTargets discovery: %s",
+			  iscsi_err_to_str(rc));
 		return rc;
+	} else if (list_empty(&rec_list)) {
+		log_error("No portals found");
+		return ISCSI_ERR_NO_OBJS_FOUND;
 	}
 
 	rc = exec_disc_op_on_recs(drec, &rec_list, info_level, do_login, op);
@@ -986,7 +1020,7 @@ do_sendtargets(discovery_rec_t *drec, st
 	}
 
 	if (list_empty(ifaces))
-		return ENODEV;
+		return ISCSI_ERR_NO_OBJS_FOUND;
 
 sw_st:
 	return do_software_sendtargets(drec, ifaces, info_level, do_login,
@@ -1013,8 +1047,12 @@ static int do_isns(discovery_rec_t *drec
 	rc = idbm_bind_ifaces_to_nodes(discovery_isns, drec, ifaces,
 				       &rec_list);
 	if (rc) {
-		log_error("Could not perform iSNS discovery.");
+		log_error("Could not perform iSNS discovery: %s",
+			  iscsi_err_to_str(rc));
 		return rc;
+	} else if (list_empty(&rec_list)) {
+		log_error("No portals found");
+		return ISCSI_ERR_NO_OBJS_FOUND;
 	}
 
 	rc = exec_disc_op_on_recs(drec, &rec_list, info_level, do_login, op);
@@ -1071,7 +1109,7 @@ static int exec_iface_op(int op, int do_
 
 		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 0);
 		if (rec && iscsi_check_for_running_session(rec)) {
-			rc = EBUSY;
+			rc = ISCSI_ERR_SESS_EXISTS;
 			goto new_fail;
 		}
 
@@ -1088,19 +1126,19 @@ new_fail:
 		if (!iface) {
 			log_error("Could not delete interface. No interface "
 				  "passed in.");
-			return EINVAL;
+			return ISCSI_ERR_INVAL;
 		}
 
 		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
 		if (!rec) {
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			goto delete_fail;
 		}
 
 		/* logout and delete records using it first */
-		rc = for_each_rec(rec, NULL, delete_node);
-		if (rc)
-			break;
+		rc = __for_each_matched_rec(0, rec, NULL, delete_node);
+		if (rc && rc != ISCSI_ERR_NO_OBJS_FOUND)
+			goto delete_fail;
 
 		rc = iface_conf_delete(iface);
 		if (rc)
@@ -1109,20 +1147,19 @@ new_fail:
 		printf("%s unbound and deleted.\n", iface->name);
 		break;
 delete_fail:
-		log_error("Could not delete iface %s. A session is "
-			  "is using it or it could not be found.",
-			   iface->name);
+		log_error("Could not delete iface %s: %s", iface->name,
+			  iscsi_err_to_str(rc));
 		break;
 	case OP_UPDATE:
 		if (!iface || !name || !value) {
 			log_error("Update requires name, value, and iface.");
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			break;
 		}
 
 		rec = idbm_create_rec(NULL, -1, NULL, -1, iface, 1);
 		if (!rec) {
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			goto update_fail;
 		}
 
@@ -1136,7 +1173,7 @@ delete_fail:
 			log_error("Can not update "
 				  "iface.iscsi_ifacename. Delete it, "
 				  "and then create a new one.");
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			break;
 		}
 
@@ -1146,7 +1183,7 @@ delete_fail:
 				  "from hwaddress to net_ifacename. ");
 			log_error("You must delete the interface and "
 				  "create a new one");
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			break;
 		}
 
@@ -1156,7 +1193,7 @@ delete_fail:
 				  "from net_ifacename to hwaddress. ");
 			log_error("You must delete the interface and "
 				  "create a new one");
-			rc = EINVAL;
+			rc = ISCSI_ERR_INVAL;
 			break;
 		}
 		set_param.name = name;
@@ -1167,23 +1204,25 @@ delete_fail:
 		if (rc)
 			goto update_fail;
 
-		rc = for_each_rec(rec, &set_param, idbm_node_set_param);
-		if (rc)
-			break;
+		rc = __for_each_matched_rec(0, rec, &set_param,
+					    idbm_node_set_param);
+		if (rc == ISCSI_ERR_NO_OBJS_FOUND)
+			rc = 0;
+		else if (rc)
+			goto update_fail;
 
 		printf("%s updated.\n", iface->name);
 		break;
 update_fail:
-		log_error("Could not update iface %s. A session is "
-			  "is using it or it could not be found.",
-			  iface->name);
+		log_error("Could not update iface %s: %s",
+			  iface->name, iscsi_err_to_str(rc));
 		break;
 	default:
 		if (!iface || (iface && info_level > 0)) {
 			if (op == OP_NOOP || op == OP_SHOW)
 				rc = print_ifaces(iface, info_level);
 			else
-				rc = EINVAL;
+				rc = ISCSI_ERR_INVAL;
 		} else {
 			rc = iface_conf_read(iface);
 			if (!rc)
@@ -1214,33 +1253,29 @@ static int exec_node_op(int op, int do_l
 			  rec->name, rec->conn[0].address, rec->conn[0].port);
 
 	if (op == OP_NEW) {
-		if (add_static_recs(rec))
-			rc = -1;
+		rc = add_static_recs(rec);
 		goto out;
 	}
 
 	if (do_rescan) {
-		if (for_each_session(rec, rescan_portal))
-			rc = -1;
+		rc = for_each_session(rec, rescan_portal);
 		goto out;
 	}
 
 	if (do_stats) {
-		if (for_each_session(rec, session_stats))
-			rc = -1;
+		rc = for_each_session(rec, session_stats);
 		goto out;
 	}
 
 	if (do_login && do_logout) {
-		log_error("either login or logout at the time allowed!");
-		rc = -1;
+		log_error("Invalid parameters. Both login and logout passed in");
+		rc = ISCSI_ERR_INVAL;
 		goto out;
 	}
 
 	if ((do_login || do_logout) && op > OP_NOOP) {
-		log_error("either operation or login/logout "
-			  "at the time allowed!");
-		rc = -1;
+		log_error("Invalid parameters. Login/logout and op passed in");
+		rc = ISCSI_ERR_INVAL;
 		goto out;
 	}
 
@@ -1252,30 +1287,29 @@ static int exec_node_op(int op, int do_l
 	}
 
 	if (do_login) {
-		if (login_portals(rec))
-			rc = -1;
+		rc = login_portals(rec);
 		goto out;
 	}
 
 	if (do_logout) {
 		int nr_found;
 
-		if (iscsi_logout_portals(rec, &nr_found, 1,
-					 iscsi_logout_matched_portal))
-			rc = -1;
+		rc = iscsi_logout_portals(rec, &nr_found, 1,
+					  iscsi_logout_matched_portal);
+		if (rc == ISCSI_ERR_NO_OBJS_FOUND)
+			log_error("No matching sessions found");
 		goto out;
 	}
 
 	if (op == OP_NOOP || (!do_login && !do_logout && op == OP_SHOW)) {
-		if (for_each_rec(rec, &do_show, idbm_print_node_info))
-			rc = -1;
+		rc = for_each_matched_rec(rec, &do_show, idbm_print_node_info);
 		goto out;
 	}
 
 	if (op == OP_UPDATE) {
 		if (!name || !value) {
 			log_error("update requires name and value");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -1284,7 +1318,7 @@ static int exec_node_op(int op, int do_l
 		     strcmp(name, "iface.transport_name")) {
 			log_error("Cannot modify %s. Use iface mode to update "
 				  "this value.", name);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -1304,7 +1338,7 @@ static int exec_node_op(int op, int do_l
 					    "transport name while a session "
 					    "is using it. Log out the session "
 					    "then update record.");
-				rc = -1;
+				rc = ISCSI_ERR_SESS_EXISTS;
 				goto out;
 			}
 		}
@@ -1312,16 +1346,14 @@ static int exec_node_op(int op, int do_l
 		set_param.name = name;
 		set_param.value = value;
 
-		if (for_each_rec(rec, &set_param, idbm_node_set_param))	
-			rc = -1;
+		rc = for_each_matched_rec(rec, &set_param, idbm_node_set_param);
 		goto out;
 	} else if (op == OP_DELETE) {
-		if (for_each_rec(rec, NULL, delete_node))
-			rc = -1;
+		rc = for_each_matched_rec(rec, NULL, delete_node);
 		goto out;
 	} else {
 		log_error("operation is not supported.");
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 		goto out;
 	}
 out:
@@ -1443,7 +1475,7 @@ static int exec_fw_op(discovery_rec_t *d
 			if (!rec) {
 				log_error("Could not convert firmware info to "
 					  "node record.\n");
-				rc = ENOMEM;
+				rc = ISCSI_ERR_NOMEM;
 				break;
 			}
 
@@ -1493,9 +1525,9 @@ static void setup_drec_defaults(int type
  * and will read and add a drec, and perform discovery if needed.
  *
  * returns:
- * 	-1 - error
+ * 	Greater than 0 - error
  * 	0 - op/discovery completed
- * 	1 - exec db op
+ * 	-1 - exec db op
  */
 static int exec_discover(int disc_type, char *ip, int port,
 			 struct list_head *ifaces, int info_level,
@@ -1506,15 +1538,16 @@ static int exec_discover(int disc_type, 
 
 	if (ip == NULL) {
 		log_error("Please specify portal as <ipaddr>[:<ipport>]");
-		return -1;
+		return ISCSI_ERR_INVAL;
 	}
 
 	if (op & OP_NEW && !do_discover) {
 		setup_drec_defaults(disc_type, ip, port, drec);
 
-		if (idbm_add_discovery(drec)) {
+		rc = idbm_add_discovery(drec);
+		if (rc) {
 			log_error("Could not add new discovery record.");
-			return -1;
+			return rc;
 		} else {
 			printf("New discovery record for [%s,%d] added.\n", ip,
 			       port);
@@ -1527,7 +1560,7 @@ static int exec_discover(int disc_type, 
 		if (!do_discover) {
 			log_error("Discovery record [%s,%d] not found.",
 				  ip, port);
-			return -1;
+			return rc;
 		}
 
 		/* Just add default rec for user */
@@ -1539,11 +1572,11 @@ static int exec_discover(int disc_type, 
 			if (rc) {
 				log_error("Could not add new discovery "
 					  "record.");
-				return -1;
+				return rc;
 			}
 		}
 	} else if (!do_discover)
-		return 1;
+		return -1;
 
 	rc = 0;
 	switch (disc_type) {
@@ -1563,9 +1596,7 @@ static int exec_discover(int disc_type, 
 		break;
 	}
 
-	if (rc)
-		return -1;
-	return 0;
+	return rc;
 }
 
 static int exec_disc2_op(int disc_type, char *ip, int port,
@@ -1587,12 +1618,12 @@ static int exec_disc2_op(int disc_type, 
 
 		rc = exec_discover(disc_type, ip, port, ifaces, info_level,
 				   do_login, do_discover, op, &drec);
-		if (rc == 1)
+		if (rc < 0)
 			goto do_db_op;
 		goto done;
 	case DISCOVERY_TYPE_SLP:
 		log_error("SLP discovery is not fully implemented yet.");
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 		goto done;
 	case DISCOVERY_TYPE_ISNS:
 		if (port < 0)
@@ -1600,29 +1631,30 @@ static int exec_disc2_op(int disc_type, 
 
 		rc = exec_discover(disc_type, ip, port, ifaces, info_level,
 				   do_login, do_discover, op, &drec);
-		if (rc == 1)
+		if (rc < 0)
 			goto do_db_op;
 		goto done;
 	case DISCOVERY_TYPE_FW:
 		if (!do_discover) {
 			log_error("Invalid command. Possibly missing "
 				  "--discover argument.");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto done;
 		}
 
 		drec.type = DISCOVERY_TYPE_FW;
-		if (exec_fw_op(&drec, ifaces, info_level, do_login, op))
-			rc = -1;
+		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op);
 		goto done;
 	default:
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 
 		if (!ip) {
 			 if (op == OP_NOOP || op == OP_SHOW) {
 				if (idbm_print_all_discovery(info_level))
 					/* successfully found some recs */
 					rc = 0;
+				else
+					rc = ISCSI_ERR_NO_OBJS_FOUND;
 			} else
 				log_error("Invalid operation. Operation not "
 					  "supported.");
@@ -1640,29 +1672,27 @@ do_db_op:
 
 	if (op == OP_NOOP || op == OP_SHOW) {
 		if (!idbm_print_discovery_info(&drec, do_show)) {
-			log_error("No records found!");
-			rc = -1;
+			log_error("No records found");
+			rc = ISCSI_ERR_NO_OBJS_FOUND;
 		}
 	} else if (op == OP_DELETE) {
-		if (idbm_delete_discovery(&drec)) {
+		rc = idbm_delete_discovery(&drec);
+		if (rc)
 			log_error("Unable to delete record!");
-			rc = -1;
-		}
 	} else if (op == OP_UPDATE) {
 		struct db_set_param set_param;
 
 		if (!name || !value) {
 			log_error("Update requires name and value.");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto done;
 		}
 		set_param.name = name;
 		set_param.value = value;
-		if (idbm_discovery_set_param(&set_param, &drec))
-			rc = -1;
+		rc = idbm_discovery_set_param(&set_param, &drec);
 	} else {
 		log_error("Operation is not supported.");
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 		goto done;
 	}
 done:
@@ -1689,7 +1719,7 @@ static int exec_disc_op(int disc_type, c
 		if (ip == NULL) {
 			log_error("Please specify portal as "
 				  "<ipaddr>[:<ipport>]");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto done;
 		}
 
@@ -1697,21 +1727,20 @@ static int exec_disc_op(int disc_type, c
 		strlcpy(drec.address, ip, sizeof(drec.address));
 		drec.port = port;
 
-		if (do_sendtargets(&drec, ifaces, info_level,
-				   do_login, op, 1)) {
-			rc = -1;
+		rc = do_sendtargets(&drec, ifaces, info_level,
+				    do_login, op, 1);
+		if (rc)
 			goto done;
-		}
 		break;
 	case DISCOVERY_TYPE_SLP:
 		log_error("SLP discovery is not fully implemented yet.");
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 		break;
 	case DISCOVERY_TYPE_ISNS:
 		if (!ip) {
 			log_error("Please specify portal as "
 				  "<ipaddr>:[<ipport>]");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto done;
 		}
 
@@ -1721,15 +1750,13 @@ static int exec_disc_op(int disc_type, c
 		else
 			drec.port = port;
 
-		if (do_isns(&drec, ifaces, info_level, do_login, op)) {
-			rc = -1;
+		rc = do_isns(&drec, ifaces, info_level, do_login, op);
+		if (rc)
 			goto done;
-		}
 		break;
 	case DISCOVERY_TYPE_FW:
 		drec.type = DISCOVERY_TYPE_FW;
-		if (exec_fw_op(&drec, ifaces, info_level, do_login, op))
-			rc = -1;
+		rc = exec_fw_op(&drec, ifaces, info_level, do_login, op);
 		break;
 	default:
 		if (ip) {
@@ -1749,42 +1776,41 @@ static int exec_disc_op(int disc_type, c
 						ip, port)) {
 				log_error("Discovery record [%s,%d] "
 					  "not found!", ip, port);
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto done;
 			}
 			if ((do_discover || do_login) &&
 			    drec.type == DISCOVERY_TYPE_SENDTARGETS) {
-				do_sendtargets(&drec, ifaces, info_level,
-					       do_login, op, 0);
+				rc = do_sendtargets(&drec, ifaces, info_level,
+						    do_login, op, 0);
 			} else if (op == OP_NOOP || op == OP_SHOW) {
 				if (!idbm_print_discovery_info(&drec,
 							       do_show)) {
-					log_error("No records found!");
-					rc = -1;
+					log_error("No records found");
+					rc = ISCSI_ERR_NO_OBJS_FOUND;
 				}
 			} else if (op == OP_DELETE) {
-				if (idbm_delete_discovery(&drec)) {
+				rc = idbm_delete_discovery(&drec);
+				if (rc)
 					log_error("Unable to delete record!");
-					rc = -1;
-				}
 			} else if (op == OP_UPDATE || op == OP_NEW) {
 				log_error("Operations new and update for "
 					  "discovery mode is not supported. "
 					  "Use discoverydb mode.");
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto done;
 			} else {
 				log_error("Invalid operation.");
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto done;
 			}
 		} else if (op == OP_NOOP || op == OP_SHOW) {
 			if (!idbm_print_all_discovery(info_level))
-				rc = -1;
+				rc = ISCSI_ERR_NO_OBJS_FOUND;
 			goto done;
 		} else {
 			log_error("Invalid operation.");
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto done;
 		}
 		/* fall through */
@@ -1837,7 +1863,7 @@ main(int argc, char **argv)
 				log_error("Invalid killiscsid priority %d "
 					  "Priority must be greater than or "
 					  "equal to zero.", killiscsid);
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto free_ifaces;
 			}
 			break;
@@ -1849,7 +1875,7 @@ main(int argc, char **argv)
 			if (op == OP_NOOP) {
 				log_error("can not recognize operation: '%s'",
 					optarg);
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto free_ifaces;
 			}
 			break;
@@ -1865,7 +1891,7 @@ main(int argc, char **argv)
 			if (errno) {
 				log_error("invalid host no %s. %s.",
 					  optarg, strerror(errno));
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto free_ifaces;
 			}
 			break;
@@ -1874,7 +1900,7 @@ main(int argc, char **argv)
 			if (sid < 0) {
 				log_error("invalid sid '%s'",
 					  optarg);
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto free_ifaces;
 			}
 			break;
@@ -1921,15 +1947,14 @@ main(int argc, char **argv)
 			break;
 		case 'I':
 			iface = iface_alloc(optarg, &rc);
-			if (rc == EINVAL) {
+			if (rc == ISCSI_ERR_INVAL) {
 				printf("Invalid iface name %s. Must be from "
 					"1 to %d characters.\n",
 					optarg, ISCSI_MAX_IFACE_LEN - 1);
-				rc = -1;
 				goto free_ifaces;
 			} else if (!iface || rc) {
 				printf("Could not add iface %s.", optarg);
-				rc = -1;
+				rc = ISCSI_ERR_INVAL;
 				goto free_ifaces;
 			}
 
@@ -1947,7 +1972,7 @@ main(int argc, char **argv)
 
 	if (optopt) {
 		log_error("unrecognized character '%c'", optopt);
-		rc = -1;
+		rc = ISCSI_ERR_INVAL;
 		goto free_ifaces;
 	}
 
@@ -1957,13 +1982,13 @@ main(int argc, char **argv)
 	}
 
 	if (mode < 0)
-		usage(0);
+		usage(ISCSI_ERR_INVAL);
 
 	if (mode == MODE_FW) {
 		if ((rc = verify_mode_params(argc, argv, "ml", 0))) {
 			log_error("fw mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto free_ifaces;
 		}
 
@@ -1974,7 +1999,7 @@ main(int argc, char **argv)
 	increase_max_files();
 	if (idbm_init(get_config_file)) {
 		log_warning("exiting due to idbm configuration error");
-		rc = -1;
+		rc = ISCSI_ERR_IDBM;
 		goto free_ifaces;
 	}
 
@@ -1983,7 +2008,7 @@ main(int argc, char **argv)
 		if ((rc = verify_mode_params(argc, argv, "HdmP", 0))) {
 			log_error("host mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -1995,7 +2020,7 @@ main(int argc, char **argv)
 		if ((rc = verify_mode_params(argc, argv, "IdnvmPo", 0))) {
 			log_error("iface mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -2014,7 +2039,7 @@ main(int argc, char **argv)
 		if ((rc = verify_mode_params(argc, argv, "DSIPdmntplov", 0))) {
 			log_error("discovery mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -2026,7 +2051,7 @@ main(int argc, char **argv)
 		if ((rc = verify_mode_params(argc, argv, "DSIPdmntplov", 0))) {
 			log_error("discovery mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -2039,7 +2064,7 @@ main(int argc, char **argv)
 					     0))) {
 			log_error("node mode: option '-%c' is not "
 				  "allowed/supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 
@@ -2069,7 +2094,7 @@ main(int argc, char **argv)
 
 		rec = idbm_create_rec(targetname, tpgt, ip, port, iface, 1);
 		if (!rec) {
-			rc = -1;
+			rc = ISCSI_ERR_NOMEM;
 			goto out;
 		}
 
@@ -2082,7 +2107,7 @@ main(int argc, char **argv)
 					      "PiRdrmusonuSv", 1))) {
 			log_error("session mode: option '-%c' is not "
 				  "allowed or supported", rc);
-			rc = -1;
+			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
 		if (sid >= 0) {
@@ -2094,7 +2119,7 @@ main(int argc, char **argv)
 
 			info = calloc(1, sizeof(*info));
 			if (!info) {
-				rc = ENOMEM;
+				rc = ISCSI_ERR_NOMEM;
 				goto out;
 			}
 
@@ -2116,8 +2141,6 @@ main(int argc, char **argv)
 			if (!do_logout && !do_rescan && !do_stats &&
 			    op == OP_NOOP && info_level > 0) {
 				rc = session_info_print(info_level, info);
-				if (rc)
-					rc = -1;
 				goto free_info;
 			}
 
@@ -2127,7 +2150,7 @@ main(int argc, char **argv)
 					      info->persistent_port,
 					      &info->iface, 1);
 			if (!rec) {
-				rc = -1;
+				rc = ISCSI_ERR_NOMEM;
 				goto free_info;
 			}
 
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.c	2011-02-03 20:14:23.000000000 -0600
@@ -31,6 +31,8 @@
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "iscsid.h"
 #include "mgmt_ipc.h"
@@ -48,16 +50,17 @@
 #include "sysdeps.h"
 #include "discoveryd.h"
 #include "iscsid_req.h"
+#include "iscsi_err.h"
 
 /* global config info */
 struct iscsi_daemon_config daemon_config;
 struct iscsi_daemon_config *dconfig = &daemon_config;
 
 static char program_name[] = "iscsid";
-int control_fd, mgmt_ipc_fd;
 static pid_t log_pid;
 static gid_t gid;
 static int daemonize = 1;
+static int mgmt_ipc_fd;
 
 static struct option const long_options[] = {
 	{"config", required_argument, NULL, 'c'},
@@ -92,7 +95,7 @@ Open-iSCSI initiator daemon.\n\
   -v, --version           display version and exit\n\
 ");
 	}
-	exit(status == 0 ? 0 : -1);
+	exit(status);
 }
 
 static void
@@ -196,11 +199,6 @@ static int sync_session(void *data, stru
 	t = iscsi_sysfs_get_transport_by_sid(info->sid);
 	if (!t)
 		return 0;
-	if (set_transport_template(t)) {
-		log_error("Could not find userspace transport template for %s",
-			   t->name);
-		return 0;
-	}
 
 	/*
 	 * Just rescan the device in case this is the first startup.
@@ -213,7 +211,8 @@ static int sync_session(void *data, stru
 		host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &err);
 		if (err) {
 			log_error("Could not get host no from sid %u. Can not "
-				  "sync session. Error %d", info->sid, err);
+				  "sync session: %s", info->sid,
+				  iscsi_err_to_str(err));
 			return 0;
 		}
 		iscsi_sysfs_scan_host(host_no, 0);
@@ -272,7 +271,7 @@ static int sync_session(void *data, stru
 
 retry:
 	rc = iscsid_exec_req(&req, &rsp, 0);
-	if (rc == MGMT_IPC_ERR_ISCSID_NOTCONN && retries < 30) {
+	if (rc == ISCSI_ERR_ISCSID_NOTCONN && retries < 30) {
 		retries++;
 		sleep(1);
 		goto retry;
@@ -318,7 +317,7 @@ static void missing_iname_warn(char *ini
 	log_error("Warning: InitiatorName file %s does not exist or does not "
 		  "contain a properly formated InitiatorName. If using "
 		  "software iscsi (iscsi_tcp or ib_iser) or partial offload "
-		  "(bnx2i or cxgb3i iscsi), you may not be able to log "
+		  "(bnx2i or cxgbi iscsi), you may not be able to log "
 		  "into or discover targets. Please create a file %s that "
 		  "contains a sting with the format: InitiatorName="
 		  "iqn.yyyy-mm.<reversed domain name>[:identifier].\n\n"
@@ -337,6 +336,7 @@ int main(int argc, char *argv[])
 	uid_t uid = 0;
 	struct sigaction sa_old;
 	struct sigaction sa_new;
+	int control_fd;
 	pid_t pid;
 
 	/* do not allow ctrl-c for now... */
@@ -388,17 +388,17 @@ int main(int argc, char *argv[])
 	log_pid = log_init(program_name, DEFAULT_AREA_SIZE,
 		      daemonize ? log_do_log_daemon : log_do_log_std, NULL);
 	if (log_pid < 0)
-		exit(1);
+		exit(ISCSI_ERR);
 
 	sysfs_init();
 	if (idbm_init(iscsid_get_config_file)) {
 		log_close(log_pid);
-		exit(1);
+		exit(ISCSI_ERR);
 	}
 
 	if (iscsi_sysfs_check_class_version()) {
 		log_close(log_pid);
-		exit(1);
+		exit(ISCSI_ERR);
 	}
 
 	umask(0177);
@@ -410,7 +410,7 @@ int main(int argc, char *argv[])
 
 	if ((mgmt_ipc_fd = mgmt_ipc_listen()) < 0) {
 		log_close(log_pid);
-		exit(1);
+		exit(ISCSI_ERR);
 	}
 
 	if (daemonize) {
@@ -421,13 +421,13 @@ int main(int argc, char *argv[])
 		if (fd < 0) {
 			log_error("Unable to create pid file");
 			log_close(log_pid);
-			exit(1);
+			exit(ISCSI_ERR);
 		}
 		pid = fork();
 		if (pid < 0) {
 			log_error("Starting daemon failed");
 			log_close(log_pid);
-			exit(1);
+			exit(ISCSI_ERR);
 		} else if (pid) {
 			log_error("iSCSI daemon with pid=%d started!", pid);
 			exit(0);
@@ -435,14 +435,14 @@ int main(int argc, char *argv[])
 
 		if ((control_fd = ipc->ctldev_open()) < 0) {
 			log_close(log_pid);
-			exit(1);
+			exit(ISCSI_ERR);
 		}
 
 		chdir("/");
 		if (lockf(fd, F_TLOCK, 0) < 0) {
 			log_error("Unable to lock pid file");
 			log_close(log_pid);
-			exit(1);
+			exit(ISCSI_ERR);
 		}
 		ftruncate(fd, 0);
 		sprintf(buf, "%d\n", getpid());
@@ -498,6 +498,7 @@ int main(int argc, char *argv[])
 	} else
 		reap_inc();
 
+	iscsi_initiator_init();
 	increase_max_files();
 	discoveryd_start(daemon_config.initiator_name);
 
@@ -509,7 +510,7 @@ int main(int argc, char *argv[])
 	if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
 		log_error("failed to mlockall, exiting...");
 		log_close(log_pid);
-		exit(1);
+		exit(ISCSI_ERR);
 	}
 
 	actor_init();
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid.h	2011-02-03 20:14:23.000000000 -0600
@@ -31,6 +31,5 @@ struct iscsi_daemon_config {
 	char *initiator_alias;
 };
 extern struct iscsi_daemon_config *dconfig;
-extern int control_fd;
 
 #endif	/* ISCSID_H */
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid_req.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid_req.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid_req.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid_req.c	2011-02-03 20:14:23.000000000 -0600
@@ -31,6 +31,7 @@
 #include "mgmt_ipc.h"
 #include "iscsi_util.h"
 #include "config.h"
+#include "iscsi_err.h"
 
 static void iscsid_startup(void)
 {
@@ -51,7 +52,7 @@ static void iscsid_startup(void)
 
 #define MAXSLEEP 128
 
-static mgmt_ipc_err_e iscsid_connect(int *fd, int start_iscsid)
+static int iscsid_connect(int *fd, int start_iscsid)
 {
 	int nsec;
 	struct sockaddr_un addr;
@@ -59,7 +60,7 @@ static mgmt_ipc_err_e iscsid_connect(int
 	*fd = socket(AF_LOCAL, SOCK_STREAM, 0);
 	if (*fd < 0) {
 		log_error("can not create IPC socket (%d)!", errno);
-		return MGMT_IPC_ERR_ISCSID_NOTCONN;
+		return ISCSI_ERR_ISCSID_NOTCONN;
 	}
 
 	memset(&addr, 0, sizeof(addr));
@@ -72,7 +73,7 @@ static mgmt_ipc_err_e iscsid_connect(int
 	for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
 		if (connect(*fd, (struct sockaddr *) &addr, sizeof(addr)) == 0)
 			/* Connection established */
-			return MGMT_IPC_OK;
+			return ISCSI_SUCCESS;
 
 		/* If iscsid isn't there, there's no sense
 		 * in retrying. */
@@ -90,10 +91,10 @@ static mgmt_ipc_err_e iscsid_connect(int
 			sleep(nsec);
 	}
 	log_error("can not connect to iSCSI daemon (%d)!", errno);
-	return MGMT_IPC_ERR_ISCSID_NOTCONN;
+	return ISCSI_ERR_ISCSID_NOTCONN;
 }
 
-mgmt_ipc_err_e iscsid_request(int *fd, iscsiadm_req_t *req, int start_iscsid)
+int iscsid_request(int *fd, iscsiadm_req_t *req, int start_iscsid)
 {
 	int err;
 
@@ -105,33 +106,33 @@ mgmt_ipc_err_e iscsid_request(int *fd, i
 		log_error("got write error (%d/%d) on cmd %d, daemon died?",
 			err, errno, req->command);
 		close(*fd);
-		return MGMT_IPC_ERR_ISCSID_COMM_ERR;
+		return ISCSI_ERR_ISCSID_COMM_ERR;
 	}
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-mgmt_ipc_err_e iscsid_response(int fd, iscsiadm_cmd_e cmd, iscsiadm_rsp_t *rsp)
+int iscsid_response(int fd, iscsiadm_cmd_e cmd, iscsiadm_rsp_t *rsp)
 {
-	mgmt_ipc_err_e iscsi_err;
+	int iscsi_err;
 	int err;
 
 	if ((err = recv(fd, rsp, sizeof(*rsp), MSG_WAITALL)) != sizeof(*rsp)) {
 		log_error("got read error (%d/%d), daemon died?", err, errno);
-		iscsi_err = MGMT_IPC_ERR_ISCSID_COMM_ERR;
+		iscsi_err = ISCSI_ERR_ISCSID_COMM_ERR;
 	} else
 		iscsi_err = rsp->err;
 	close(fd);
 
 	if (!iscsi_err && cmd != rsp->command)
-		iscsi_err = MGMT_IPC_ERR_ISCSID_COMM_ERR;
+		iscsi_err = ISCSI_ERR_ISCSID_COMM_ERR;
 	return iscsi_err;
 }
 
-mgmt_ipc_err_e iscsid_exec_req(iscsiadm_req_t *req, iscsiadm_rsp_t *rsp,
+int iscsid_exec_req(iscsiadm_req_t *req, iscsiadm_rsp_t *rsp,
 				int start_iscsid)
 {
 	int fd;
-	mgmt_ipc_err_e err;
+	int err;
 
 	err = iscsid_request(&fd, req, start_iscsid);
 	if (err)
@@ -189,31 +190,3 @@ int iscsid_req_by_sid(iscsiadm_cmd_e cmd
 		return err;
 	return iscsid_req_wait(cmd, fd);
 }
-
-void iscsid_handle_error(mgmt_ipc_err_e err)
-{
-	static char *err_msgs[] = {
-		/* 0 */ "",
-		/* 1 */ "unknown error",
-		/* 2 */ "not found",
-		/* 3 */ "no available memory",
-		/* 4 */ "encountered connection failure",
-		/* 5 */ "encountered iSCSI login failure",
-		/* 6 */ "encountered iSCSI database failure",
-		/* 7 */ "invalid parameter",
-		/* 8 */ "connection timed out",
-		/* 9 */ "internal error",
-		/* 10 */ "encountered iSCSI logout failure",
-		/* 11 */ "iSCSI PDU timed out",
-		/* 12 */ "iSCSI driver not found. Please make sure it is loaded, and retry the operation",
-		/* 13 */ "daemon access denied",
-		/* 14 */ "iSCSI driver does not support requested capability.",
-		/* 15 */ "already exists",
-		/* 16 */ "Unknown request",
-		/* 17 */ "encountered iSNS failure",
-		/* 18 */ "could not communicate to iscsid",
-		/* 19 */ "encountered non-retryable iSCSI login failure",
-		/* 20 */ "could not connect to iscsid",
-	};
-	log_error("initiator reported error (%d - %s)", err, err_msgs[err]);
-}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid_req.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid_req.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsid_req.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsid_req.h	2011-02-03 20:14:23.000000000 -0600
@@ -27,7 +27,6 @@ struct node_rec;
 
 extern int iscsid_exec_req(struct iscsiadm_req *req, struct iscsiadm_rsp *rsp,
 			   int iscsid_start);
-extern void iscsid_handle_error(int err);
 extern int iscsid_req_wait(int cmd, int fd);
 extern int iscsid_req_by_rec_async(int cmd, struct node_rec *rec, int *fd);
 extern int iscsid_req_by_rec(int cmd, struct node_rec *rec);
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_err.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_err.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_err.c	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_err.c	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,72 @@
+/*
+ * iSCSI error helpers
+ *
+ * Copyright (C) 2011 Mike Christie
+ * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
+ * maintained by open-iscsi@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+#include "stdlib.h"
+#include "iscsi_err.h"
+#include "log.h"
+
+static char *iscsi_err_msgs[] = {
+	/* 0 */ "",
+	/* 1 */ "unknown error",
+	/* 2 */ "session not found",
+	/* 3 */ "no available memory",
+	/* 4 */ "encountered connection failure",
+	/* 5 */ "encountered iSCSI login failure",
+	/* 6 */ "encountered iSCSI database failure",
+	/* 7 */ "invalid parameter",
+	/* 8 */ "connection timed out",
+	/* 9 */ "internal error",
+	/* 10 */ "encountered iSCSI logout failure",
+	/* 11 */ "iSCSI PDU timed out",
+	/* 12 */ "iSCSI driver not found. Please make sure it is loaded, and retry the operation",
+	/* 13 */ "daemon access denied",
+	/* 14 */ "iSCSI driver does not support requested capability.",
+	/* 15 */ "session exists",
+	/* 16 */ "Unknown request",
+	/* 17 */ "iSNS service not supported",
+	/* 18 */ "could not communicate to iscsid",
+	/* 19 */ "encountered non-retryable iSCSI login failure",
+	/* 20 */ "could not connect to iscsid",
+	/* 21 */ "no objects found",
+	/* 23 */ "sysfs lookup failure",
+	/* 23 */ "host not found",
+	/* 24 */ "iSCSI login failed due to authorization failure",
+	/* 25 */ "iSNS query failed",
+	/* 26 */ "iSNS registration failed",
+};
+
+char *iscsi_err_to_str(int err)
+{
+	if (err >= ISCSI_MAX_ERR_VAL || err < 0) {
+		log_error("invalid error code %d", err);
+		return NULL;
+	}
+
+	return iscsi_err_msgs[err];
+}
+
+void iscsi_err_print_msg(int err)
+{
+	if (err >= ISCSI_MAX_ERR_VAL || err < 0) {
+		log_error("invalid error code %d", err);
+		return;
+	}
+	log_error("initiator reported error (%d - %s)", err,
+		  iscsi_err_msgs[err]);
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h	2011-02-03 20:14:23.000000000 -0600
@@ -34,6 +34,26 @@ enum {
 };
 
 struct iscsi_conn;
+struct iscsi_ev_context;
+
+/*
+ * When handling async events, the initiator may not be able to
+ * handle the event in the same context, so this allows the interface
+ * code to call into the initiator to shedule handling.
+ */
+struct iscsi_ipc_ev_clbk {
+	void (*create_session) (uint32_t host_no, uint32_t sid);
+	void (*destroy_session) (uint32_t host_no, uint32_t sid);
+
+	struct iscsi_ev_context *(*get_ev_context) (struct iscsi_conn *conn,
+						    int ev_size);
+	void (*put_ev_context) (struct iscsi_ev_context *ev_context);
+	int (*sched_ev_context) (struct iscsi_ev_context *ev_context,
+				 struct iscsi_conn *conn,
+				 unsigned long tmo, int event);
+};
+
+extern void ipc_register_ev_callback(struct iscsi_ipc_ev_clbk *ipc_ev_clbk);
 
 /**
  * struct iscsi_ipc - Open-iSCSI Interface for Kernel IPC
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_net_util.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_net_util.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_net_util.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_net_util.c	2011-02-03 20:14:23.000000000 -0600
@@ -41,6 +41,7 @@ struct iscsi_net_driver {
 static struct iscsi_net_driver net_drivers[] = {
 #ifdef OFFLOAD_BOOT_SUPPORTED
 	{"cxgb3", "cxgb3i" },
+	{"cxgb4", "cxgb4i" },
 	{"bnx2", "bnx2i" },
 	{"bnx2x", "bnx2i"},
 #endif
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsistart.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsistart.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsistart.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsistart.c	2011-02-03 20:14:23.000000000 -0600
@@ -47,6 +47,7 @@
 #include "iface.h"
 #include "sysdeps.h"
 #include "iscsid_req.h"
+#include "iscsi_err.h"
 
 /* global config info */
 /* initiator needs initiator name/alias */
@@ -57,10 +58,8 @@ static node_rec_t config_rec;
 static LIST_HEAD(targets);
 
 static char program_name[] = "iscsistart";
-static int mgmt_ipc_fd;
 
 /* used by initiator */
-int control_fd;
 extern struct iscsi_ipc *ipc;
 
 static struct option const long_options[] = {
@@ -108,7 +107,7 @@ Open-iSCSI initiator.\n\
   -v, --version            display version and exit\n\
 ");
 	}
-	exit(status == 0 ? 0 : -1);
+	exit(status);
 }
 
 static int stop_event_loop(void)
@@ -121,7 +120,7 @@ static int stop_event_loop(void)
 	req.command = MGMT_IPC_IMMEDIATE_STOP;
 	rc = iscsid_exec_req(&req, &rsp, 0);
 	if (rc) {
-		iscsid_handle_error(rc);
+		iscsi_err_print_msg(rc);
 		log_error("Could not stop event_loop\n");
 	}
 	return rc;
@@ -155,12 +154,12 @@ retry:
 	 * handle race where iscsid proc is starting up while we are
 	 * trying to connect.
 	 */
-	if (rc == MGMT_IPC_ERR_ISCSID_NOTCONN && retries < 30) {
+	if (rc == ISCSI_ERR_ISCSID_NOTCONN && retries < 30) {
 		retries++;
 		sleep(1);
 		goto retry;
 	} else if (rc)
-		iscsid_handle_error(rc);
+		iscsi_err_print_msg(rc);
 	return rc;
 }
 
@@ -229,7 +228,7 @@ do {									\
 	if (strlen(str) > max_len) {					\
 		printf("%s: invalid %s %s. Max %s length is %d.\n",	\
 			program_name, param, str, param, max_len);	\
-		exit(1);						\
+		exit(ISCSI_ERR_INVAL);					\
 	}								\
 } while (0);
 
@@ -242,6 +241,7 @@ int main(int argc, char *argv[])
 	struct boot_context *context, boot_context;
 	struct sigaction sa_old;
 	struct sigaction sa_new;
+	int control_fd, mgmt_ipc_fd;
 	pid_t pid;
 
 	idbm_node_setup_defaults(&config_rec);
@@ -260,7 +260,7 @@ int main(int argc, char *argv[])
 
 	sysfs_init();
 	if (iscsi_sysfs_check_class_version())
-		exit(1);
+		exit(ISCSI_ERR_SYSFS_LOOKUP);
 
 	while ((ch = getopt_long(argc, argv, "i:t:g:a:p:d:u:w:U:W:bNfvh",
 				 long_options, &longindex)) >= 0) {
@@ -316,25 +316,24 @@ int main(int argc, char *argv[])
 			ret = fw_get_entry(&boot_context);
 			if (ret) {
 				printf("Could not get boot entry.\n");
-				exit(1);
+				exit(ret);
 			}
 
 			initiatorname = boot_context.initiatorname;
 			ret = fw_get_targets(&targets);
 			if (ret || list_empty(&targets)) {
 				printf("Could not setup fw entries.\n");
-				exit(1);
+				exit(ret);
 			}
 			break;
 		case 'N':
-			ret = fw_setup_nics();
-			exit(ret);
+			exit(fw_setup_nics());
 		case 'f':
 			ret = fw_get_targets(&targets);
 			if (ret || list_empty(&targets)) {
 				printf("Could not get list of targets from "
 				       "firmware.\n");
-				exit(1);
+				exit(ret);
 			}
 
 			list_for_each_entry(context, &targets, list)
@@ -350,18 +349,18 @@ int main(int argc, char *argv[])
 			usage(0);
 			break;
 		default:
-			usage(1);
+			usage(ISCSI_ERR_INVAL);
 			break;
 		}
 	}
 
 	if (list_empty(&targets) && check_params(initiatorname))
-		exit(1);
+		exit(ISCSI_ERR_INVAL);
 
 	pid = fork();
 	if (pid < 0) {
 		log_error("iscsiboot fork failed");
-		exit(1);
+		exit(ISCSI_ERR_NOMEM);
 	} else if (pid) {
 		int status, rc, rc2;
 
@@ -376,7 +375,7 @@ int main(int argc, char *argv[])
 
 		waitpid(pid, &status, WUNTRACED);
 		if (rc || rc2)
-			exit(-1);
+			exit(ISCSI_ERR);
 
 		log_debug(1, "iscsi parent done");
 		exit(0);
@@ -385,12 +384,12 @@ int main(int argc, char *argv[])
 	mgmt_ipc_fd = mgmt_ipc_listen();
 	if (mgmt_ipc_fd  < 0) {
 		log_error("Could not setup mgmt ipc\n");
-		exit(-1);
+		exit(ISCSI_ERR_NOMEM);
 	}
 
 	control_fd = ipc->ctldev_open();
 	if (control_fd < 0)
-		exit(-1);
+		exit(ISCSI_ERR_NOMEM);
 
 	memset(&daemon_config, 0, sizeof (daemon_config));
 	daemon_config.initiator_name = initiatorname;
@@ -420,6 +419,7 @@ int main(int argc, char *argv[])
 	/*
 	 * Start Main Event Loop
 	 */
+	iscsi_initiator_init();
 	actor_init();
 	event_loop(ipc, control_fd, mgmt_ipc_fd);
 	ipc->ctldev_close();
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_sysfs.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_sysfs.c	2011-02-03 20:14:23.000000000 -0600
@@ -36,6 +36,7 @@
 #include "iface.h"
 #include "session_info.h"
 #include "host.h"
+#include "iscsi_err.h"
 
 /*
  * TODO: remove the _DIR defines and search for subsys dirs like
@@ -115,6 +116,10 @@ static int read_transports(void)
 			INIT_LIST_HEAD(&t->list);
 			strlcpy(t->name, namelist[i]->d_name,
 				ISCSI_TRANSPORT_NAME_MAXLEN);
+			if (set_transport_template(t)) {
+				free(t);
+				return -1;
+			}
 		} else
 			log_debug(7, "Updating transport %s",
 				  namelist[i]->d_name);
@@ -238,7 +243,7 @@ uint32_t iscsi_sysfs_get_host_no_from_si
 					       ISCSI_SESSION_SUBSYS, id)) {
 		log_error("Could not lookup devpath for %s. Possible sysfs "
 			  "incompatibility.\n", id);
-		*err = EIO;
+		*err = ISCSI_ERR_SYSFS_LOOKUP;
 		return 0;
 	}
 
@@ -246,7 +251,7 @@ uint32_t iscsi_sysfs_get_host_no_from_si
 	if (!session_dev) {
 		log_error("Could not get dev for %s. Possible sysfs "
 			  "incompatibility.\n", id);
-		*err = EIO;
+		*err = ISCSI_ERR_SYSFS_LOOKUP;
 		return 0;
 	}
 
@@ -271,7 +276,7 @@ uint32_t iscsi_sysfs_get_host_no_from_si
 		if (!host_dev) {
 			log_error("Could not get host dev for %s. Possible "
 				  "sysfs incompatibility.\n", id);
-			*err = EIO;
+			*err = ISCSI_ERR_SYSFS_LOOKUP;
 			return 0;
 		}
 	}
@@ -301,7 +306,7 @@ static uint32_t get_host_no_from_netdev(
 
 	info = calloc(1, sizeof(*info));
 	if (!info) {
-		*rc = ENOMEM;
+		*rc = ISCSI_ERR_NOMEM;
 		return -1;
 	}
 	strcpy(info->iface.netdev, netdev);
@@ -311,7 +316,7 @@ static uint32_t get_host_no_from_netdev(
 	if (local_rc == 1)
 		host_no = info->host_no;
 	else
-		*rc = ENODEV;
+		*rc = ISCSI_ERR_HOST_NOT_FOUND;
 	free(info);
 	return host_no;
 }
@@ -337,7 +342,7 @@ static uint32_t get_host_no_from_hwaddre
 
 	info = calloc(1, sizeof(*info));
 	if (!info) {
-		*rc = ENOMEM;
+		*rc = ISCSI_ERR_NOMEM;
 		return -1;
 	}
 	strcpy(info->iface.hwaddress, address);
@@ -347,7 +352,7 @@ static uint32_t get_host_no_from_hwaddre
 	if (local_rc == 1)
 		host_no = info->host_no;
 	else
-		*rc = ENODEV;
+		*rc = ISCSI_ERR_HOST_NOT_FOUND;
 	free(info);
 	return host_no;
 }
@@ -374,7 +379,7 @@ static uint32_t get_host_no_from_ipaddre
 
 	info = calloc(1, sizeof(*info));
 	if (!info) {
-		*rc = ENOMEM;
+		*rc = ISCSI_ERR_NOMEM;
 		return -1;
 	}
 	strcpy(info->iface.ipaddress, address);
@@ -384,7 +389,7 @@ static uint32_t get_host_no_from_ipaddre
 	if (local_rc == 1)
 		host_no = info->host_no;
 	else
-		*rc = ENODEV;
+		*rc = ISCSI_ERR_HOST_NOT_FOUND;
 	free(info);
 	return host_no;
 }
@@ -404,7 +409,7 @@ uint32_t iscsi_sysfs_get_host_no_from_hw
 		 strcasecmp(iface->ipaddress, DEFAULT_IPADDRESS))
 		host_no = get_host_no_from_ipaddress(iface->ipaddress, &tmp_rc);
 	else
-		tmp_rc = EINVAL;
+		tmp_rc = ISCSI_ERR_INVAL;
 
 	*rc = tmp_rc;
 	return host_no;
@@ -459,7 +464,7 @@ static int iscsi_sysfs_read_iface(struct
 	 * host level because we cannot create different initiator ports
 	 * (cannot set isid either). The LLD also exports the iname at the
 	 * hba level so apps can see it, but we no longer set the iname for
-	 * each iscsid controlled host since bnx2i cxgb3i can support multiple
+	 * each iscsid controlled host since bnx2i cxgbi can support multiple
 	 * initiator names and of course software iscsi can support anything.
 	 */
 	ret = 1;
@@ -523,7 +528,10 @@ static int iscsi_sysfs_read_iface(struct
 					  iface_str(iface));
 		}
 	}
-	return ret;
+	if (ret)
+		return ISCSI_ERR_SYSFS_LOOKUP;
+	else
+		return 0;
 }
 
 int iscsi_sysfs_get_hostinfo_by_host_no(struct host_info *hinfo)
@@ -540,7 +548,7 @@ int iscsi_sysfs_for_each_host(void *data
 
 	info = malloc(sizeof(*info));
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	n = scandir(ISCSI_HOST_DIR, &namelist, trans_filter,
 		    alphasort);
@@ -631,7 +639,7 @@ int iscsi_sysfs_get_sid_from_path(char *
 	if (!dev) {
 		log_error("Could not get dev for %s. Possible sysfs "
 			  "incompatibility.\n", devpath);
-		exit(1);
+		return -1;
 	}
 
 	if (!strncmp(dev->kernel, "session", 7))
@@ -645,8 +653,7 @@ int iscsi_sysfs_get_sid_from_path(char *
 	}
 
 	log_error("Unable to find sid in path %s", session);
-	exit(1);
-	return 0;
+	return -1;
 }
 
 int iscsi_sysfs_get_sessioninfo_by_id(struct session_info *info, char *session)
@@ -657,21 +664,21 @@ int iscsi_sysfs_get_sessioninfo_by_id(st
 
 	if (sscanf(session, "session%d", &info->sid) != 1) {
 		log_error("invalid session '%s'", session);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	ret = sysfs_get_str(session, ISCSI_SESSION_SUBSYS, "targetname",
 			    info->targetname, sizeof(info->targetname));
 	if (ret) {
 		log_error("could not read session targetname: %d", ret);
-		return ret;
+		return ISCSI_ERR_SYSFS_LOOKUP;
 	}
 
 	ret = sysfs_get_int(session, ISCSI_SESSION_SUBSYS, "tpgt",
 			    &info->tpgt);
 	if (ret) {
-		log_error("could not read session tpgt: %u", ret);
-		return ret;
+		log_error("could not read session tpgt: %d", ret);
+		return ISCSI_ERR_SYSFS_LOOKUP;
 	}
 
 	snprintf(id, sizeof(id), ISCSI_CONN_ID, info->sid);
@@ -727,8 +734,8 @@ int iscsi_sysfs_get_sessioninfo_by_id(st
 	ret = 0;
 	host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &ret);
 	if (ret) {
-		log_error("could not get host_no for session%d err %d.",
-			  info->sid, ret);
+		log_error("could not get host_no for session%d: %s.",
+			  info->sid, iscsi_err_to_str(ret));
 		return ret;
 	}
 
@@ -755,7 +762,7 @@ int iscsi_sysfs_for_each_session(void *d
 
 	info = calloc(1, sizeof(*info));
 	if (!info)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 
 	n = scandir(ISCSI_SESSION_DIR, &namelist, trans_filter,
 		    alphasort);
@@ -797,8 +804,10 @@ int iscsi_sysfs_get_session_state(char *
 	char id[NAME_SIZE];
 
 	snprintf(id, sizeof(id), ISCSI_SESSION_ID, sid);
-	return sysfs_get_str(id, ISCSI_SESSION_SUBSYS, "state", state,
-			     SCSI_MAX_STATE_VALUE);
+	if (sysfs_get_str(id, ISCSI_SESSION_SUBSYS, "state", state,
+			  SCSI_MAX_STATE_VALUE))
+		return ISCSI_ERR_SYSFS_LOOKUP;
+	return 0;
 }
 
 int iscsi_sysfs_get_host_state(char *state, int host_no)
@@ -806,8 +815,10 @@ int iscsi_sysfs_get_host_state(char *sta
 	char id[NAME_SIZE];
 
 	snprintf(id, sizeof(id), ISCSI_HOST_ID, host_no);
-	return sysfs_get_str(id, SCSI_HOST_SUBSYS, "state", state,
-			     SCSI_MAX_STATE_VALUE);
+	if (sysfs_get_str(id, SCSI_HOST_SUBSYS, "state", state,
+			  SCSI_MAX_STATE_VALUE))
+		return ISCSI_ERR_SYSFS_LOOKUP;
+	return 0;
 }
 
 int iscsi_sysfs_get_device_state(char *state, int host_no, int target, int lun)
@@ -818,7 +829,7 @@ int iscsi_sysfs_get_device_state(char *s
 	if (sysfs_get_str(id, SCSI_SUBSYS, "state", state,
 			  SCSI_MAX_STATE_VALUE)) {
 		log_debug(3, "Could not read attr state for %s\n", id);
-		return EIO;
+		return ISCSI_ERR_SYSFS_LOOKUP;
 	}
 
 	return 0;
@@ -919,7 +930,7 @@ static uint32_t get_target_no_from_sid(u
 	uint32_t host, bus, target = 0;
 	size_t sysfs_len;
 
-	*err = ENODEV;
+	*err = ISCSI_ERR_SESS_NOT_FOUND;
 
 	snprintf(id, sizeof(id), "session%u", sid);
 	if (!sysfs_lookup_devpath_by_subsys_id(devpath, sizeof(devpath),
@@ -970,7 +981,8 @@ struct iscsi_transport *iscsi_sysfs_get_
 	struct iscsi_transport *t;
 
 	/* sync up kernel and userspace */
-	read_transports();
+	if (read_transports())
+		return NULL;
 
 	/* check if the transport is loaded and matches */
 	list_for_each_entry(t, &transports, list) {
@@ -1061,7 +1073,7 @@ int iscsi_sysfs_for_each_device(void *da
 					       ISCSI_SESSION_SUBSYS, id)) {
 		log_debug(3, "Could not lookup devpath for %s %s\n",
 			  ISCSI_SESSION_SUBSYS, id);
-		return EIO;
+		return ISCSI_ERR_SYSFS_LOOKUP;
 	}
 
 	snprintf(path_full, sizeof(path_full), "%s%s/device/target%d:0:%d",
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_timer.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_timer.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_timer.c	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_timer.c	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,86 @@
+/*
+ * iSCSI timer
+ *
+ * Copyright (C) 2002 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+#include <string.h>
+#include <sys/time.h>
+
+void iscsi_timer_clear(struct timeval *timer)
+{
+	memset(timer, 0, sizeof (*timer));
+}
+
+/* set timer to now + seconds */
+void iscsi_timer_set(struct timeval *timer, int seconds)
+{
+	if (timer) {
+		memset(timer, 0, sizeof (*timer));
+		gettimeofday(timer, NULL);
+
+		timer->tv_sec += seconds;
+	}
+}
+
+int iscsi_timer_expired(struct timeval *timer)
+{
+	struct timeval now;
+
+	/* no timer, can't have expired */
+	if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0)))
+		return 0;
+
+	memset(&now, 0, sizeof (now));
+	gettimeofday(&now, NULL);
+
+	if (now.tv_sec > timer->tv_sec)
+		return 1;
+	if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec))
+		return 1;
+	return 0;
+}
+
+int iscsi_timer_msecs_until(struct timeval *timer)
+{
+	struct timeval now;
+	int msecs;
+	long partial;
+
+	/* no timer, can't have expired, infinite time til it expires */
+	if ((timer == NULL) || ((timer->tv_sec == 0) && (timer->tv_usec == 0)))
+		return -1;
+
+	memset(&now, 0, sizeof (now));
+	gettimeofday(&now, NULL);
+
+	/* already expired? */
+	if (now.tv_sec > timer->tv_sec)
+		return 0;
+	if ((now.tv_sec == timer->tv_sec) && (now.tv_usec >= timer->tv_usec))
+		return 0;
+
+	/* not expired yet, do the math */
+	partial = timer->tv_usec - now.tv_usec;
+	if (partial < 0) {
+		partial += 1000 * 1000;
+		msecs = (partial + 500) / 1000;
+		msecs += (timer->tv_sec - now.tv_sec - 1) * 1000;
+	} else {
+		msecs = (partial + 500) / 1000;
+		msecs += (timer->tv_sec - now.tv_sec) * 1000;
+	}
+
+	return msecs;
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_timer.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_timer.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_timer.h	1969-12-31 18:00:00.000000000 -0600
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_timer.h	2011-02-03 20:14:23.000000000 -0600
@@ -0,0 +1,28 @@
+/*
+ * iSCSI timer
+ *
+ * Copyright (C) 2002 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+#ifndef ISCSI_TIMER_H
+#define ISCSI_TIMER_H
+
+struct timeval;
+
+extern void iscsi_timer_clear(struct timeval *timer);
+extern void iscsi_timer_set(struct timeval *timer, int seconds);
+extern int iscsi_timer_expired(struct timeval *timer);
+extern int iscsi_timer_msecs_until(struct timeval *timer);
+
+#endif
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/login.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/login.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/login.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/login.c	2011-02-03 20:14:23.000000000 -0600
@@ -27,11 +27,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <poll.h>
+#include <errno.h>
 #include <sys/param.h>
 
 #include "initiator.h"
 #include "transport.h"
 #include "log.h"
+#include "iscsi_timer.h"
 
 /* caller is assumed to be well-behaved and passing NUL terminated strings */
 int
@@ -1434,11 +1437,15 @@ int
 iscsi_login_rsp(iscsi_session_t *session, iscsi_login_context_t *c)
 {
 	iscsi_conn_t *conn = &session->conn[c->cid];
+	int err;
 
 	/* read the target's response into the same buffer */
-	if (!iscsi_io_recv_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, c->data,
-			    c->max_data_length, ISCSI_DIGEST_NONE,
-			    c->timeout)) {
+	err = iscsi_io_recv_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, c->data,
+			        c->max_data_length, ISCSI_DIGEST_NONE,
+			        c->timeout);
+	if (err == -EAGAIN) {
+		goto done;
+	} else if (err < 0) {
 		/*
 		 * FIXME: caller might want us to distinguish I/O
 		 * error and timeout. Might want to switch portals on
@@ -1449,6 +1456,7 @@ iscsi_login_rsp(iscsi_session_t *session
 		goto done;
 	}
 
+	err = -EIO;
 	c->received_pdu = 1;
 
 	/* check the PDU response type */
@@ -1490,7 +1498,7 @@ iscsi_login_rsp(iscsi_session_t *session
 		if (c->ret == LOGIN_OK)
 			c->ret = LOGIN_FAILED;
 	}
-	return 1;
+	return err;
 }
 
 /**
@@ -1514,7 +1522,9 @@ iscsi_login(iscsi_session_t *session, in
 {
 	iscsi_conn_t *conn = &session->conn[cid];
 	iscsi_login_context_t *c = &conn->login_context;
-	int ret;
+	struct timeval connection_timer;
+	struct pollfd pfd;
+	int ret, timeout;
 
 	/*
 	 * assume iscsi_login is only called from discovery, so it is
@@ -1532,15 +1542,63 @@ iscsi_login(iscsi_session_t *session, in
 	do {
 		if (iscsi_login_req(session, c))
 			return c->ret;
-		ret = iscsi_login_rsp(session, c);
 
-		if (status_class)
-			*status_class = c->status_class;
-		if (status_detail)
-			*status_detail = c->status_detail;
+		/*
+		 * TODO: merge the poll and req/rsp code with the discovery
+		 * poll and text req/rsp.
+		 */
+		iscsi_timer_set(&connection_timer,
+				session->conn[0].active_timeout);
+		timeout = iscsi_timer_msecs_until(&connection_timer);
+
+		memset(&pfd, 0, sizeof (pfd));
+		pfd.fd = conn->socket_fd;
+		pfd.events = POLLIN | POLLPRI;
+
+repoll:
+		pfd.revents = 0;
+		ret = poll(&pfd, 1, timeout);
+		log_debug(7, "%s: Poll return %d\n", __FUNCTION__, ret);
+		if (iscsi_timer_expired(&connection_timer)) {
+			log_warning("Login response timeout. Waited %d "
+				    "seconds and did not get reponse PDU.\n",
+				    session->conn[0].active_timeout);
+			c->ret = LOGIN_FAILED;
+			return c->ret;
+		}
+
+		if (ret > 0) {
+			if (pfd.revents & (POLLIN | POLLPRI)) {
+				ret = iscsi_login_rsp(session, c);
+				if (ret ==  -EAGAIN)
+					goto repoll;
+
+				if (status_class)
+					*status_class = c->status_class;
+				if (status_detail)
+					*status_detail = c->status_detail;
+
+				if (ret)
+					return c->ret;
+			} else if (pfd.revents & POLLHUP) {
+				log_warning("Login POLLHUP");
+				c->ret = LOGIN_FAILED;
+				return c->ret;
+			} else if (pfd.revents & POLLNVAL) {
+				log_warning("Login POLLNVAL");
+				c->ret = LOGIN_IO_ERROR;
+				return c->ret;
+			} else if (pfd.revents & POLLERR) {
+				log_warning("Login POLLERR");
+				c->ret = LOGIN_IO_ERROR;
+				return c->ret;
+			}
 
-		if (ret)
+		} else if (ret < 0) {
+			log_error("Login poll error.\n");
+			c->ret = LOGIN_FAILED;
 			return c->ret;
+		}
 	} while (conn->current_stage != ISCSI_FULL_FEATURE_PHASE);
 
 	c->ret = LOGIN_OK;
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/Makefile open-iscsi-2.0-872-rc4-bnx2i.work/usr/Makefile
--- open-iscsi-2.0-872-rc4-bnx2i/usr/Makefile	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/Makefile	2011-02-03 20:14:23.000000000 -0600
@@ -37,12 +37,13 @@ PROGRAMS = iscsid iscsiadm iscsistart
 # libc compat files
 SYSDEPS_SRCS = $(wildcard ../utils/sysdeps/*.o)
 # sources shared between iscsid, iscsiadm and iscsistart
-ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o login.o log.o md5.o sha1.o iface.o \
-	idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o iscsi_net_util.o \
-	iscsid_req.o $(SYSDEPS_SRCS)
+ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o md5.o \
+	sha1.o iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
+	iscsi_net_util.o iscsid_req.o transport.o cxgbi.o be2iscsi.o \
+	initiator_common.o iscsi_err.o $(IPC_OBJ)  $(SYSDEPS_SRCS)
 # core initiator files
-INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o \
-		transport.o cxgb3i.o be2iscsi.o
+INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o
+
 # fw boot files
 FW_BOOT_SRCS = $(wildcard ../utils/fwparam_ibft/*.o)
 
@@ -51,14 +52,14 @@ DISCOVERY_SRCS = $(FW_BOOT_SRCS) strings
 
 all: $(PROGRAMS)
 
-iscsid: $(ISCSI_LIB_SRCS) $(IPC_OBJ) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
+iscsid: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(DISCOVERY_SRCS) \
 	iscsid.o session_mgmt.o discoveryd.o
 	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns -lcrypto
 
 iscsiadm: $(ISCSI_LIB_SRCS) $(DISCOVERY_SRCS) iscsiadm.o session_mgmt.o
 	$(CC) $(CFLAGS) $^ -o $@ -L../utils/open-isns -lisns -lcrypto
 
-iscsistart: $(IPC_OBJ) $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
+iscsistart: $(ISCSI_LIB_SRCS) $(INITIATOR_SRCS) $(FW_BOOT_SRCS) \
 		iscsistart.o statics.o
 	$(CC) $(CFLAGS) -static $^ -o $@
 clean:
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/mgmt_ipc.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/mgmt_ipc.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/mgmt_ipc.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/mgmt_ipc.c	2011-02-03 20:14:23.000000000 -0600
@@ -35,6 +35,7 @@
 #include "transport.h"
 #include "sysdeps.h"
 #include "iscsi_ipc.h"
+#include "iscsi_err.h"
 
 #define PEERUSER_MAX	64
 #define EXTMSG_MAX	(64 * 1024)
@@ -79,13 +80,13 @@ mgmt_ipc_close(int fd)
 		close(fd);
 }
 
-static mgmt_ipc_err_e
+static int 
 mgmt_ipc_session_login(queue_task_t *qtask)
 {
 	return session_login_task(&qtask->req.u.session.rec, qtask);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_session_getstats(queue_task_t *qtask)
 {
 	int sid = qtask->req.u.session.sid;
@@ -93,7 +94,7 @@ mgmt_ipc_session_getstats(queue_task_t *
 	int rc;
 
 	if (!(session = session_find_by_sid(sid)))
-		return MGMT_IPC_ERR_NOT_FOUND;
+		return ISCSI_ERR_SESS_NOT_FOUND;
 
 	rc = ipc->get_stats(session->t->handle,
 		session->id, session->conn[0].id,
@@ -102,33 +103,33 @@ mgmt_ipc_session_getstats(queue_task_t *
 	if (rc) {
 		log_error("get_stats(): IPC error %d "
 			"session [%02d]", rc, sid);
-		return MGMT_IPC_ERR_INTERNAL;
+		return ISCSI_ERR_INTERNAL;
 	}
 
-	mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
-	return MGMT_IPC_OK;
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_send_targets(queue_task_t *qtask)
 {
 	iscsiadm_req_t *req = &qtask->req;
-	mgmt_ipc_err_e err;
+	int err;
 
 	err = iscsi_host_send_targets(qtask, req->u.st.host_no,
 					  req->u.st.do_login,
 					  &req->u.st.ss);
 	mgmt_ipc_write_rsp(qtask, err);
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_session_logout(queue_task_t *qtask)
 {
 	return session_logout_task(qtask->req.u.session.sid, qtask);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_session_sync(queue_task_t *qtask)
 {
 	struct ipc_msg_session *session= &qtask->req.u.session;
@@ -136,16 +137,16 @@ mgmt_ipc_session_sync(queue_task_t *qtas
 	return iscsi_sync_session(&session->rec, qtask, session->sid);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_cfg_initiatorname(queue_task_t *qtask)
 {
 	if (dconfig->initiator_name)
 		strcpy(qtask->rsp.u.config.var, dconfig->initiator_name);
-	mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
-	return MGMT_IPC_OK;
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_session_info(queue_task_t *qtask)
 {
 	int sid = qtask->req.u.session.sid;
@@ -154,61 +155,50 @@ mgmt_ipc_session_info(queue_task_t *qtas
 
 	if (!(session = session_find_by_sid(sid))) {
 		log_debug(1, "session with sid %d not found!", sid);
-		return MGMT_IPC_ERR_NOT_FOUND;
+		return ISCSI_ERR_SESS_NOT_FOUND;
 	}
 
 	info = &qtask->rsp.u.session_state;
 	info->conn_state = session->conn[0].state;
 	info->session_state = session->r_stage;
 
-	mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
-	return MGMT_IPC_OK;
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_cfg_initiatoralias(queue_task_t *qtask)
 {
 	strcpy(qtask->rsp.u.config.var, dconfig->initiator_alias);
-	mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
-	return MGMT_IPC_OK;
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_cfg_filename(queue_task_t *qtask)
 {
 	strcpy(qtask->rsp.u.config.var, dconfig->config_file);
-	mgmt_ipc_write_rsp(qtask, MGMT_IPC_OK);
-	return MGMT_IPC_OK;
+	mgmt_ipc_write_rsp(qtask, ISCSI_SUCCESS);
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_conn_add(queue_task_t *qtask)
 {
-	return MGMT_IPC_ERR;
+	return ISCSI_ERR;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_immediate_stop(queue_task_t *qtask)
 {
 	event_loop_exit(qtask);
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_conn_remove(queue_task_t *qtask)
 {
-	return MGMT_IPC_ERR;
-}
-
-static mgmt_ipc_err_e
-mgmt_ipc_host_set_param(queue_task_t *qtask)
-{
-	struct ipc_msg_set_host_param *hp = &qtask->req.u.set_host_param;
-	int err;
-
-	err = iscsi_host_set_param(hp->host_no, hp->param, hp->value);
-	mgmt_ipc_write_rsp(qtask, err);
-	return MGMT_IPC_OK;
+	return ISCSI_ERR;
 }
 
 /*
@@ -263,12 +253,11 @@ again:
 	return argc;
 }
 
-static mgmt_ipc_err_e
-mgmt_ipc_notify_common(queue_task_t *qtask,
-		mgmt_ipc_err_e (*handler)(int, char **))
+static int
+mgmt_ipc_notify_common(queue_task_t *qtask, int (*handler)(int, char **))
 {
 	char	**argv = NULL;
-	int	argc, err = MGMT_IPC_ERR;
+	int	argc, err = ISCSI_ERR;
 
 	argc = mgmt_ipc_parse_strings(qtask, &argv);
 	if (argc > 0)
@@ -277,54 +266,54 @@ mgmt_ipc_notify_common(queue_task_t *qta
 	if (argv)
 		free(argv);
 	mgmt_ipc_write_rsp(qtask, err);
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
 /* Replace these dummies as you implement them
    elsewhere */
-static mgmt_ipc_err_e
+static int
 iscsi_discovery_add_node(int argc, char **argv)
 {
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 iscsi_discovery_del_node(int argc, char **argv)
 {
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 iscsi_discovery_add_portal(int argc, char **argv)
 {
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 iscsi_discovery_del_portal(int argc, char **argv)
 {
-	return MGMT_IPC_OK;
+	return ISCSI_SUCCESS;
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_notify_add_node(queue_task_t *qtask)
 {
 	return mgmt_ipc_notify_common(qtask, iscsi_discovery_add_node);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_notify_del_node(queue_task_t *qtask)
 {
 	return mgmt_ipc_notify_common(qtask, iscsi_discovery_del_node);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_notify_add_portal(queue_task_t *qtask)
 {
 	return mgmt_ipc_notify_common(qtask, iscsi_discovery_add_portal);
 }
 
-static mgmt_ipc_err_e
+static int
 mgmt_ipc_notify_del_portal(queue_task_t *qtask)
 {
 	return mgmt_ipc_notify_common(qtask, iscsi_discovery_del_portal);
@@ -433,7 +422,7 @@ mgmt_ipc_destroy_queue_task(queue_task_t
  * is for.
  */
 void
-mgmt_ipc_write_rsp(queue_task_t *qtask, mgmt_ipc_err_e err)
+mgmt_ipc_write_rsp(queue_task_t *qtask, int err)
 {
 	if (!qtask)
 		return;
@@ -510,7 +499,6 @@ static mgmt_ipc_fn_t *	mgmt_ipc_function
 [MGMT_IPC_CONFIG_IALIAS]	= mgmt_ipc_cfg_initiatoralias,
 [MGMT_IPC_CONFIG_FILE]		= mgmt_ipc_cfg_filename,
 [MGMT_IPC_IMMEDIATE_STOP]	= mgmt_ipc_immediate_stop,
-[MGMT_IPC_SET_HOST_PARAM]	= mgmt_ipc_host_set_param,
 [MGMT_IPC_NOTIFY_ADD_NODE]	= mgmt_ipc_notify_add_node,
 [MGMT_IPC_NOTIFY_DEL_NODE]	= mgmt_ipc_notify_del_node,
 [MGMT_IPC_NOTIFY_ADD_PORTAL]	= mgmt_ipc_notify_add_portal,
@@ -538,7 +526,7 @@ void mgmt_ipc_handle(int accept_fd)
 	qtask->mgmt_ipc_fd = fd;
 
 	if (!mgmt_peeruser(fd, user) || strncmp(user, "root", PEERUSER_MAX)) {
-		err = MGMT_IPC_ERR_ACCESS;
+		err = ISCSI_ERR_ACCESS;
 		goto err;
 	}
 
@@ -556,12 +544,12 @@ void mgmt_ipc_handle(int accept_fd)
 		/* If the handler returns OK, this means it
 		 * already sent the reply. */
 		err = handler(qtask);
-		if (err == MGMT_IPC_OK)
+		if (err == ISCSI_SUCCESS)
 			return;
 	} else {
 		log_error("unknown request: %s(%d) %u",
 			  __FUNCTION__, __LINE__, command);
-		err = MGMT_IPC_ERR_INVALID_REQ;
+		err = ISCSI_ERR_INVALID_MGMT_REQ;
 	}
 
 err:
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/mgmt_ipc.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/mgmt_ipc.h
--- open-iscsi-2.0-872-rc4-bnx2i/usr/mgmt_ipc.h	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/mgmt_ipc.h	2011-02-03 20:14:23.000000000 -0600
@@ -26,30 +26,6 @@
 #define ISCSIADM_NAMESPACE	"ISCSIADM_ABSTRACT_NAMESPACE"
 #define PEERUSER_MAX		64
 
-typedef enum mgmt_ipc_err {
-	MGMT_IPC_OK			= 0,
-	MGMT_IPC_ERR			= 1,
-	MGMT_IPC_ERR_NOT_FOUND		= 2,
-	MGMT_IPC_ERR_NOMEM		= 3,
-	MGMT_IPC_ERR_TRANS_FAILURE	= 4,
-	MGMT_IPC_ERR_LOGIN_FAILURE	= 5,
-	MGMT_IPC_ERR_IDBM_FAILURE	= 6,
-	MGMT_IPC_ERR_INVAL		= 7,
-	MGMT_IPC_ERR_TRANS_TIMEOUT	= 8,
-	MGMT_IPC_ERR_INTERNAL		= 9,
-	MGMT_IPC_ERR_LOGOUT_FAILURE	= 10,
-	MGMT_IPC_ERR_PDU_TIMEOUT	= 11,
-	MGMT_IPC_ERR_TRANS_NOT_FOUND	= 12,
-	MGMT_IPC_ERR_ACCESS		= 13,
-	MGMT_IPC_ERR_TRANS_CAPS		= 14,
-	MGMT_IPC_ERR_EXISTS		= 15,
-	MGMT_IPC_ERR_INVALID_REQ	= 16,
-	MGMT_IPC_ERR_ISNS_UNAVAILABLE	= 17,
-	MGMT_IPC_ERR_ISCSID_COMM_ERR	= 18,
-	MGMT_IPC_ERR_FATAL_LOGIN_FAILURE = 19,
-	MGMT_IPC_ERR_ISCSID_NOTCONN	= 20,
-} mgmt_ipc_err_e;
-
 typedef enum iscsiadm_cmd {
 	MGMT_IPC_UNKNOWN		= 0,
 	MGMT_IPC_SESSION_LOGIN		= 1,
@@ -66,11 +42,10 @@ typedef enum iscsiadm_cmd {
 	MGMT_IPC_SESSION_INFO		= 13,
 	MGMT_IPC_ISNS_DEV_ATTR_QUERY	= 14,
 	MGMT_IPC_SEND_TARGETS		= 15,
-	MGMT_IPC_SET_HOST_PARAM		= 16,
-	MGMT_IPC_NOTIFY_ADD_NODE	= 17,
-	MGMT_IPC_NOTIFY_DEL_NODE	= 18,
-	MGMT_IPC_NOTIFY_ADD_PORTAL	= 19,
-	MGMT_IPC_NOTIFY_DEL_PORTAL	= 20,
+	MGMT_IPC_NOTIFY_ADD_NODE	= 16,
+	MGMT_IPC_NOTIFY_DEL_NODE	= 17,
+	MGMT_IPC_NOTIFY_ADD_PORTAL	= 18,
+	MGMT_IPC_NOTIFY_DEL_PORTAL	= 19,
 
 	__MGMT_IPC_MAX_COMMAND
 } iscsiadm_cmd_e;
@@ -108,7 +83,7 @@ typedef struct iscsiadm_req {
 /* IPC Response */
 typedef struct iscsiadm_rsp {
 	iscsiadm_cmd_e command;
-	mgmt_ipc_err_e err;
+	int err;	/* ISCSI_ERR value */
 
 	union {
 #define MGMT_IPC_GETSTATS_BUF_MAX	(sizeof(struct iscsi_uevent) + \
@@ -132,10 +107,10 @@ typedef struct iscsiadm_rsp {
 } iscsiadm_rsp_t;
 
 struct queue_task;
-typedef mgmt_ipc_err_e	mgmt_ipc_fn_t(struct queue_task *);
+typedef int mgmt_ipc_fn_t(struct queue_task *);
 
 struct queue_task;
-void mgmt_ipc_write_rsp(struct queue_task *qtask, mgmt_ipc_err_e err);
+void mgmt_ipc_write_rsp(struct queue_task *qtask, int err);
 int mgmt_ipc_listen(void);
 void mgmt_ipc_close(int fd);
 void mgmt_ipc_handle(int accept_fd);
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c	2011-02-03 20:14:23.000000000 -0600
@@ -33,7 +33,6 @@
 
 #include "types.h"
 #include "iscsi_if.h"
-#include "iscsid.h"
 #include "log.h"
 #include "iscsi_ipc.h"
 #include "initiator.h"
@@ -50,6 +49,7 @@ static void *nlm_sendbuf;
 static void *nlm_recvbuf;
 static void *pdu_sendbuf;
 static void *setparam_buf;
+static struct iscsi_ipc_ev_clbk *ipc_ev_clbk;
 
 static int ctldev_handle(void);
 
@@ -66,7 +66,8 @@ static int ctldev_handle(void);
 static int
 kread(char *data, int count)
 {
-	log_debug(7, "in %s", __FUNCTION__);
+	log_debug(7, "in %s %u %u %p %p", __FUNCTION__, recvlen, count,
+		  data, recvbuf);
 
 	memcpy(data, recvbuf + recvlen, count);
 	recvlen += count;
@@ -142,7 +143,8 @@ nlpayload_read(int ctrl_fd, char *data, 
 	 */
 	rc = recvmsg(ctrl_fd, &msg, flags);
 
-	memcpy(data, NLMSG_DATA(iov.iov_base), count);
+	if (data)
+		memcpy(data, NLMSG_DATA(iov.iov_base), count);
 
 	return rc;
 }
@@ -716,18 +718,34 @@ kstart_conn(uint64_t transport_handle, u
 static int
 krecv_pdu_begin(struct iscsi_conn *conn)
 {
+	int rc;
+
 	log_debug(7, "in %s", __FUNCTION__);
 
 	if (recvbuf) {
 		log_error("recv's begin state machine bug?");
 		return -EIO;
 	}
+
+	if (!conn->recv_context) {
+		rc = ipc->ctldev_handle();
+		if (rc == -ENXIO)
+			/* event for some other conn */
+			return -EAGAIN;
+		else if (rc < 0)
+			/* fatal handling error or conn error */
+			return rc;
+		/*
+		 * Session create/destroy event for another conn
+		 */
+		if (!conn->recv_context)
+			return -EAGAIN;
+	}
+
 	recvbuf = conn->recv_context->data + sizeof(struct iscsi_uevent);
 	recvlen = 0;
 
-	log_debug(3, "recv PDU began, pdu handle 0x%p",
-		  recvbuf);
-
+	log_debug(3, "recv PDU began, pdu handle %p", recvbuf);
 	return 0;
 }
 
@@ -744,7 +762,7 @@ krecv_pdu_end(struct iscsi_conn *conn)
 	log_debug(3, "recv PDU finished for pdu handle 0x%p",
 		  recvbuf);
 
-	iscsi_conn_context_put(conn->recv_context);
+	ipc_ev_clbk->put_ev_context(conn->recv_context);
 	conn->recv_context = NULL;
 	recvbuf = NULL;
 	return 0;
@@ -894,7 +912,7 @@ static void drop_data(struct nlmsghdr *n
 	int ev_size;
 
 	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
-	nlpayload_read(ctrl_fd, setparam_buf, ev_size, 0);
+	nlpayload_read(ctrl_fd, NULL, ev_size, 0);
 }
 
 static int ctldev_handle(void)
@@ -905,7 +923,7 @@ static int ctldev_handle(void)
 	iscsi_conn_t *conn = NULL;
 	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
 	struct nlmsghdr *nlh;
-	struct iscsi_conn_context *conn_context;
+	struct iscsi_ev_context *ev_context;
 	uint32_t sid = 0, cid = 0;
 
 	log_debug(7, "in %s", __FUNCTION__);
@@ -925,13 +943,15 @@ static int ctldev_handle(void)
 	/* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
 	case ISCSI_UEVENT_CREATE_SESSION:
 		drop_data(nlh);
-		iscsi_async_session_creation(ev->r.c_session_ret.host_no,
-					     ev->r.c_session_ret.sid);
+		if (ipc_ev_clbk->create_session)
+			ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
+						    ev->r.c_session_ret.sid);
 		return 0;
 	case ISCSI_KEVENT_DESTROY_SESSION:
 		drop_data(nlh);
-		iscsi_async_session_destruction(ev->r.d_session.host_no,
-						ev->r.d_session.sid);
+		if (ipc_ev_clbk->destroy_session)
+			ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
+						     ev->r.d_session.sid);
 		return 0;
 	case ISCSI_KEVENT_RECV_PDU:
 		sid = ev->r.recv_req.sid;
@@ -947,16 +967,30 @@ static int ctldev_handle(void)
 		cid = 0;
 		break;
 	default:
-		log_error("Unknown kernel event %d. You may want to upgrade "
-			  "your iscsi tools.", ev->type);
+		if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
+		    (ev->type > ISCSI_KEVENT_MAX))
+			log_error("Unknown kernel event %d. You may want to "
+				  " upgrade your iscsi tools.", ev->type);
+		else
+			/*
+			 * If another app is using the interface we might
+			 * see their
+			 * stuff. Just drop it.
+			 */
+			log_debug(7, "Got unknwon event %d. Dropping.",
+				  ev->type);
 		drop_data(nlh);
-		return -EINVAL;
+		return 0;
 	}
 
 	/* verify connection */
 	session = session_find_by_sid(sid);
 	if (!session) {
-		log_error("Could not verify connection %d:%d. Dropping "
+		/*
+		 * this can happen normally when other apps are using the
+		 * nl interface.
+		 */
+		log_debug(1, "Could not verify connection %d:%d. Dropping "
 			   "event.\n", sid, cid);
 		drop_data(nlh);
 		return -ENXIO;
@@ -964,19 +998,20 @@ static int ctldev_handle(void)
 	conn = &session->conn[0];
 
 	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
-	conn_context = iscsi_conn_context_get(conn, ev_size);
-	if (!conn_context) {
+
+	ev_context = ipc_ev_clbk->get_ev_context(conn, ev_size);
+	if (!ev_context) {
 		/* retry later */
 		log_error("Can not allocate memory for receive context.");
 		return -ENOMEM;
 	}
 
 	log_debug(6, "message real length is %d bytes, recv_handle %p",
-		nlh->nlmsg_len, conn_context->data);
+		nlh->nlmsg_len, ev_context->data);
 
-	if ((rc = nlpayload_read(ctrl_fd, conn_context->data,
+	if ((rc = nlpayload_read(ctrl_fd, ev_context->data,
 				ev_size, 0)) < 0) {
-		iscsi_conn_context_put(conn_context);
+		ipc_ev_clbk->put_ev_context(ev_context);
 		log_error("can not read from NL socket, error %d", rc);
 		/* retry later */
 		return rc;
@@ -988,26 +1023,28 @@ static int ctldev_handle(void)
 	 */
 	switch (ev->type) {
 	case ISCSI_KEVENT_RECV_PDU:
-		iscsi_sched_conn_context(conn_context, conn, 0,
-					 EV_CONN_RECV_PDU);
+		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
+						   EV_CONN_RECV_PDU);
 		break;
 	case ISCSI_KEVENT_CONN_ERROR:
-		memcpy(conn_context->data, &ev->r.connerror.error,
+		memcpy(ev_context->data, &ev->r.connerror.error,
 			sizeof(ev->r.connerror.error));
-		iscsi_sched_conn_context(conn_context, conn, 0,
-					 EV_CONN_ERROR);
+		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
+						   EV_CONN_ERROR);
 		break;
 	case ISCSI_KEVENT_UNBIND_SESSION:
-		iscsi_sched_conn_context(conn_context, conn, 0,
-					 EV_CONN_STOP);
+		rc = ipc_ev_clbk->sched_ev_context(ev_context, conn, 0,
+						   EV_CONN_STOP);
 		break;
 	default:
-		iscsi_conn_context_put(conn_context);
+		ipc_ev_clbk->put_ev_context(ev_context);
 		log_error("unknown kernel event %d", ev->type);
 		return -EEXIST;
 	}
 
-	return 0;
+	if (rc)
+		ipc_ev_clbk->put_ev_context(ev_context);
+	return rc;
 }
 
 static int
@@ -1116,3 +1153,8 @@ struct iscsi_ipc nl_ipc = {
 	.recv_pdu_end           = krecv_pdu_end,
 };
 struct iscsi_ipc *ipc = &nl_ipc;
+
+void ipc_register_ev_callback(struct iscsi_ipc_ev_clbk *ev_clbk)
+{
+	ipc_ev_clbk = ev_clbk;
+}
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/session_info.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/session_info.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/session_info.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/session_info.c	2011-02-03 20:14:23.000000000 -0600
@@ -13,6 +13,7 @@
 #include "initiator.h"
 #include "iface.h"
 #include "iscsid_req.h"
+#include "iscsi_err.h"
 
 int session_info_create_list(void *data, struct session_info *info)
 {
@@ -25,7 +26,7 @@ int session_info_create_list(void *data,
 
 	new = calloc(1, sizeof(*new));
 	if (!new)
-		return ENOMEM;
+		return ISCSI_ERR_NOMEM;
 	memcpy(new, info, sizeof(*new));
 	INIT_LIST_HEAD(&new->list);
 
@@ -346,13 +347,15 @@ int session_info_print(int info_level, s
 		break;
 	default:
 		log_error("Invalid info level %d. Try 0 - 3.", info_level);
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 	}
 
 	if (err) {
 		log_error("Can not get list of active sessions (%d)", err);
 		return err;
-	} else if (!num_found)
+	} else if (!num_found) {
 		log_error("No active sessions.");
+		return ISCSI_ERR_NO_OBJS_FOUND;
+	}
 	return 0;
 }
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/session_mgmt.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/session_mgmt.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/session_mgmt.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/session_mgmt.c	2011-02-03 20:14:23.000000000 -0600
@@ -32,6 +32,7 @@
 #include "iscsi_sysfs.h"
 #include "log.h"
 #include "iscsid_req.h"
+#include "iscsi_err.h"
 
 static void log_login_msg(struct node_rec *rec, int rc)
 {
@@ -40,7 +41,7 @@ static void log_login_msg(struct node_re
 			  "portal: %s,%d].", rec->iface.name,
 			  rec->name, rec->conn[0].address,
 			  rec->conn[0].port);
-		iscsid_handle_error(rc);
+		iscsi_err_print_msg(rc);
 	} else
 		log_info("Login to [iface: %s, target: %s, portal: "
 			 "%s,%d] successful.", rec->iface.name,
@@ -82,6 +83,8 @@ static int iscsid_login_reqs_wait(struct
 
 		rec = curr->data;
 		err = iscsid_req_wait(MGMT_IPC_SESSION_LOGIN, curr->fd);
+		if (err && !ret)
+			ret = err;
 		log_login_msg(rec, err);
 		list_del(&curr->list);
 		free(curr);
@@ -123,11 +126,7 @@ int iscsi_login_portal(void *data, struc
 		log_login_msg(rec, rc);
 		if (async_req)
 			free(async_req);
-		/* we raced with another app or instance of iscsiadm */
-		if (rc == MGMT_IPC_ERR_EXISTS)
-			return 0;
-
-		return ENOTCONN;
+		return rc;
 	}
 
 	if (async_req) {
@@ -191,7 +190,6 @@ int iscsi_login_portals(void *data, int 
 		if (!err)
 			(*nr_found)++;
 	}
-
 	if (wait) {
 		err = iscsid_login_reqs_wait(&login_list);
 		if (err && !ret)
@@ -213,7 +211,7 @@ static void log_logout_msg(struct sessio
 			  "portal: %s,%d].", info->sid,
 			  info->targetname,
 			  info->persistent_address, info->port);
-		iscsid_handle_error(rc);
+		iscsi_err_print_msg(rc);
 	} else
 		log_info("Logout of [sid: %d, target: %s, "
 			 "portal: %s,%d] successful.",
@@ -277,11 +275,7 @@ int iscsi_logout_portal(struct session_i
 		log_logout_msg(info, rc);
 		if (async_req)
 			free(async_req);
-
-		if (rc == MGMT_IPC_ERR_NOT_FOUND)
-			return 0;
-
-		return EIO;
+		return rc;
 	}
 
 	if (async_req) {
@@ -325,10 +319,17 @@ int iscsi_logout_portals(void *data, int
 
 	err = iscsi_sysfs_for_each_session(&link_info, nr_found,
 					   session_info_create_list);
-	if (err || !*nr_found)
+	if (err && !list_empty(&session_list))
+		log_error("Could not read in all sessions: %s",
+			  iscsi_err_to_str(err));
+	else if (err && list_empty(&session_list)) {
+		log_error("Could not read session info.");
 		return err;
-
+	} else if (list_empty(&session_list))
+		return ISCSI_ERR_NO_OBJS_FOUND;
+	ret = err;
 	*nr_found = 0;
+
 	list_for_each_entry(curr_info, &session_list, list) {
 		err = logout_fn(data, &logout_list, curr_info);
 		if (err > 0 && !ret)
@@ -337,13 +338,22 @@ int iscsi_logout_portals(void *data, int
 			(*nr_found)++;
 	}
 
+	if (!*nr_found) {
+		ret = ISCSI_ERR_NO_OBJS_FOUND;
+		goto free_list;
+	}
+
 	if (wait) {
 		err = iscsid_logout_reqs_wait(&logout_list);
-		if (err)
+		if (err && !ret)
 			ret = err;
 	} else
 		iscsid_reqs_close(&logout_list);
 
+	if (ret)
+		log_error("Could not logout of all requested sessions");
+
+free_list:
 	session_info_free_list(&session_list);
 	return ret;
 }
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/usr/transport.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.c
--- open-iscsi-2.0-872-rc4-bnx2i/usr/transport.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/transport.c	2011-02-03 20:14:23.000000000 -0600
@@ -25,7 +25,7 @@
 #include "log.h"
 #include "iscsi_util.h"
 #include "iscsi_sysfs.h"
-#include "cxgb3i.h"
+#include "cxgbi.h"
 #include "be2iscsi.h"
 
 struct iscsi_transport_template iscsi_tcp = {
@@ -49,7 +49,16 @@ struct iscsi_transport_template cxgb3i =
 	.ep_connect	= ktransport_ep_connect,
 	.ep_poll	= ktransport_ep_poll,
 	.ep_disconnect	= ktransport_ep_disconnect,
-	.create_conn	= cxgb3i_create_conn,
+	.create_conn	= cxgbi_create_conn,
+};
+
+struct iscsi_transport_template cxgb4i = {
+	.name		= "cxgb4i",
+	.set_host_ip	= 1,
+	.ep_connect	= ktransport_ep_connect,
+	.ep_poll	= ktransport_ep_poll,
+	.ep_disconnect	= ktransport_ep_disconnect,
+	.create_conn	= cxgbi_create_conn,
 };
 
 struct iscsi_transport_template bnx2i = {
@@ -76,6 +85,7 @@ static struct iscsi_transport_template *
 	&iscsi_tcp,
 	&iscsi_iser,
 	&cxgb3i,
+	&cxgb4i,
 	&bnx2i,
 	&qla4xxx,
 	&be2iscsi,
@@ -97,6 +107,7 @@ int set_transport_template(struct iscsi_
 		}
 	}
 
-	log_error("Could not find uspace transport for %s\n", t->name);
+	log_error("Could not find template for %s. An updated iscsiadm "
+		  "is probably needed.\n", t->name);
 	return ENOSYS;
 }
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fw_entry.c open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fw_entry.c
--- open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fw_entry.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fw_entry.c	2011-02-03 20:14:23.000000000 -0600
@@ -34,6 +34,7 @@
 #include "fwparam.h"
 #include "idbm_fields.h"
 #include "iscsi_net_util.h"
+#include "iscsi_err.h"
 
 /**
  * fw_setup_nics - setup nics (ethXs) based on ibft net info
@@ -56,7 +57,7 @@ int fw_setup_nics(void)
 	ret = fw_get_targets(&targets);
 	if (ret || list_empty(&targets)) {
 		printf("Could not setup fw entries.\n");
-		return ENODEV;
+		return ISCSI_ERR_NO_OBJS_FOUND;
 	}
 
 	/*
@@ -85,7 +86,10 @@ int fw_setup_nics(void)
 	}
 
 	fw_free_targets(&targets);
-	return ret;
+	if (ret)
+		return ISCSI_ERR;
+	else
+		return 0;
 }
 
 /**
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fwparam_ppc.c open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fwparam_ppc.c
--- open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fwparam_ppc.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fwparam_ppc.c	2011-02-03 20:14:23.000000000 -0600
@@ -30,6 +30,7 @@
 #include "iscsi_obp.h"
 #include "prom_parse.h"
 #include "sysdeps.h"
+#include "iscsi_err.h"
 
 void* yy_scan_string(const char *str);
 int yyparse(struct ofw_dev *ofwdev);
@@ -449,7 +450,7 @@ int fwparam_ppc_boot_info(struct boot_co
 
 	devtree = find_devtree(filename);
 	if (!devtree)
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 
 	/*
 	 * Always search the device-tree to find the capable nic devices.
@@ -459,7 +460,7 @@ int fwparam_ppc_boot_info(struct boot_co
 		goto free_devtree;
 
 	if (find_file(filename) < 1)
-		error = ENODEV;
+		error = ISCSI_ERR_NO_OBJS_FOUND;
 	else {
 		if (debug)
 			printf("%s:\n%s\n\n", filename, bootpath_val);
@@ -469,12 +470,12 @@ int fwparam_ppc_boot_info(struct boot_co
 		 */
 
 		if (!strstr(bootpath_val, "iscsi")) {
-			error = EINVAL;
+			error = ISCSI_ERR_INVAL;
 			goto free_devtree;
 		}
 		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
 		if (!ofwdevs[0]) {
-			error = ENOMEM;
+			error = ISCSI_ERR_NOMEM;
 			goto free_devtree;
 		}
 
@@ -484,7 +485,7 @@ int fwparam_ppc_boot_info(struct boot_co
 		if (!error) {
 			context = calloc(1, sizeof(*context));
 			if (!context)
-				error = ENOMEM;
+				error = ISCSI_ERR_NOMEM;
 			else
 				fill_context(context, ofwdevs[0]);
 		}
@@ -524,7 +525,7 @@ int fwparam_ppc_get_targets(struct list_
 
 	devtree = find_devtree(filename);
 	if (!devtree)
-		return EINVAL;
+		return ISCSI_ERR_INVAL;
 
 	/*
 	 * Always search the device-tree to find the capable nic devices.
@@ -534,7 +535,7 @@ int fwparam_ppc_get_targets(struct list_
 		goto free_devtree;
 
 	if (find_file(filename) < 1)
-		error = ENODEV;
+		error = ISCSI_ERR_NO_OBJS_FOUND;
 	else {
 		if (debug)
 			printf("%s:\n%s\n\n", filename, bootpath_val);
@@ -544,12 +545,12 @@ int fwparam_ppc_get_targets(struct list_
 		 */
 
 		if (!strstr(bootpath_val, "iscsi")) {
-			error = EINVAL;
+			error = ISCSI_ERR_INVAL;
 			goto free_devtree;
 		}
 		ofwdevs[0] = calloc(1, sizeof(struct ofw_dev));
 		if (!ofwdevs[0]) {
-			error = ENOMEM;
+			error = ISCSI_ERR_NOMEM;
 			goto free_devtree;
 		}
 
@@ -559,7 +560,7 @@ int fwparam_ppc_get_targets(struct list_
 		if (!error) {
 			context = calloc(1, sizeof(*context));
 			if (!context)
-				error = ENOMEM;
+				error = ISCSI_ERR_NOMEM;
 			else {
 				fill_context(context, ofwdevs[0]);
 				list_add_tail(&context->list, list);
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fwparam_sysfs.c open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fwparam_sysfs.c
--- open-iscsi-2.0-872-rc4-bnx2i/utils/fwparam_ibft/fwparam_sysfs.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/utils/fwparam_ibft/fwparam_sysfs.c	2011-02-03 20:14:23.000000000 -0600
@@ -36,6 +36,7 @@
 #include "fwparam.h"
 #include "sysdeps.h"
 #include "iscsi_net_util.h"
+#include "iscsi_err.h"
 
 #define ISCSI_BOOT_MAX		255
 #define IBFT_SYSFS_ROOT		"/sys/firmware/ibft/"
@@ -351,7 +352,7 @@ int fwparam_sysfs_boot_info(struct boot_
 	 */
 	dirfd = opendir(ISCSI_LLD_ROOT);
 	if (!dirfd)
-		return errno;
+		return ISCSI_ERR_SYSFS_LOOKUP;
 
 	while ((dent = readdir(dirfd))) {
 		char lld_root[FILENAMESZ];
@@ -369,7 +370,7 @@ int fwparam_sysfs_boot_info(struct boot_
 		if (!get_boot_info(context, lld_root, dent->d_name))
 			goto done;
 	}
-	rc = ENODEV;
+	rc = ISCSI_ERR_NO_OBJS_FOUND;
 done:
 	closedir(dirfd);
 	return rc;
@@ -401,12 +402,12 @@ static int get_targets(struct list_head 
 
 		rc = fill_tgt_context(subsys, target_list[i], context);
 		if (rc)
-			break;
+			goto cleanup;
 
 		rc = sysfs_get_int(target_list[i], subsys, "nic-assoc",
 				   &nic_idx);
 		if (rc)
-			break;
+			goto cleanup;
 
 		for (nic = 0; nic < nic_cnt; nic++) {
 			int id;
@@ -420,21 +421,31 @@ static int get_targets(struct list_head 
 		if (nic == nic_cnt) {
 			printf("Invalid nic-assoc of %d. Max id %d.\n",
 			       nic_idx, nic_cnt);
-			break;
+			goto cleanup;
 		}
 
 		rc = fill_nic_context(subsys, nic_list[nic], context);
 		if (rc)
-			break;
+			goto cleanup;
 
 		fill_initiator_context(subsys, context);
 		list_add_tail(&context->list, list);
+		continue;
+cleanup:
+		free(context);
+		context = NULL;
 	}
 
 	if (rc) {
 		if (context)
 			free(context);
-		fw_free_targets(list);
+		/*
+		 * If there are some valid targets return them. Most likely,
+		 * the driver/ibft-implementation reported partial info
+		 * for targets/initiators that were not used for boot.
+		 */
+		if (!list_empty(list))
+			rc = 0;
 	}
 
 	deallocate_lists();
@@ -455,7 +466,7 @@ int fwparam_sysfs_get_targets(struct lis
 	 */
 	dirfd = opendir(ISCSI_LLD_ROOT);
 	if (!dirfd) {
-		rc = errno;
+		rc = ISCSI_ERR_SYSFS_LOOKUP;
 		goto done;
 	}
 
@@ -463,21 +474,20 @@ int fwparam_sysfs_get_targets(struct lis
 		char lld_root[FILENAMESZ];
 
 		memset(&lld_root, 0 , FILENAMESZ);
-
 		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
 			continue;
 
 		if (strncmp(dent->d_name, ISCSI_LLD_SUBSYS_PREFIX, 10))
 			continue;
 
-		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s",
+		snprintf(lld_root, FILENAMESZ, ISCSI_LLD_ROOT"%s/",
 			 dent->d_name);
 		get_targets(list, lld_root, dent->d_name);
 	}
 	closedir(dirfd);
 done:
 	if (!rc && list_empty(list))
-		rc = ENODEV;
+		rc = ISCSI_ERR_NO_OBJS_FOUND;
 	if (rc)
 		fw_free_targets(list);
 	return rc;
diff -Naurp open-iscsi-2.0-872-rc4-bnx2i/utils/open-isns/socket.c open-iscsi-2.0-872-rc4-bnx2i.work/utils/open-isns/socket.c
--- open-iscsi-2.0-872-rc4-bnx2i/utils/open-isns/socket.c	2010-07-11 04:05:58.000000000 -0500
+++ open-iscsi-2.0-872-rc4-bnx2i.work/utils/open-isns/socket.c	2011-02-03 20:14:23.000000000 -0600
@@ -805,7 +805,7 @@ isns_net_stream_xmit(isns_socket_t *sock
 void
 isns_net_stream_hup(isns_socket_t *sock)
 {
-	sock->is_poll_mask &= ~POLLIN;
+	sock->is_poll_mask &= ~(POLLIN|POLLOUT);
 	/* POLLHUP while connecting means we failed */
 	if (sock->is_state == ISNS_SOCK_CONNECTING)
 		isns_net_stream_error(sock, ECONNREFUSED);