Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/doc/iscsiadm.8 open-iscsi-2.0-872-rc4-bnx2i.work/doc/iscsiadm.8
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/doc/iscsiadm.8	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/doc/iscsiadm.8	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -12,11 +12,11 @@ iscsiadm \- open-iscsi administration ut
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 \fBiscsiadm\fR \-m session [ \-hV ] [ \-d debug_level ] [ \-P printlevel ] [ \-r sessionid | sysfsdir [ \-R ] [ \-u | \-s | \-o new ] ]
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-\fBiscsiadm\fR \-m iface [ \-hV ] [ \-d debug_level ] [ \-P printlevel ] [ \-I ifacename | \-H hostno|MAC ]   [ [ \-o  operation  ] [ \-n name ] [ \-v value ] ]
Mike Christie cfcc31b
+\fBiscsiadm\fR \-m iface [ \-hV ] [ \-d debug_level ] [ \-P printlevel ] [ \-I ifacename | \-H hostno|MAC ]   [ [ \-o  operation  ] [ \-n name ] [ \-v value ] ] [ \-C ping [ \-a ip ] [ \-b packetsize ] [ \-c count ] [ \-i interval ] ]
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 \fBiscsiadm\fR \-m fw [\-l]
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-\fBiscsiadm\fR \-m host [ \-P printlevel ] [ \-H hostno|MAC ]
Mike Christie cfcc31b
+\fBiscsiadm\fR \-m host [ \-P printlevel ] [ \-H hostno|MAC ] [ -C chap [ -o operation ] [ -v chap_tbl_idx ] ]
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 \fBiscsiadm\fR \-k priority
Mike Christie cfcc31b
 
Mike Christie cfcc31b
@@ -41,6 +41,32 @@ daemon (iscsid) be running.
Mike Christie cfcc31b
 .SH OPTIONS
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 .TP
Mike Christie cfcc31b
+\fB\-a\fR, \fB\-\-ip=\fIipaddr\fP
Mike Christie cfcc31b
+\fIipaddr\fR can be IPv4 or IPv6.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+This option is only valid for ping submode.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+.TP
Mike Christie cfcc31b
+\fB\-b\fR, \fB\-\-packetsize=\fIpacketsize\fP
Mike Christie cfcc31b
+Specify the ping \fIpacketsize\fR.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+This option is only valid for ping submode.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+.TP
Mike Christie cfcc31b
+\fB\-c\fR, \fB\-\-count=\fIcount\fP
Mike Christie cfcc31b
+\fIcount\fR specify number of ping iterations.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+This option is only valid for ping submode.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+.TP
Mike Christie cfcc31b
+\fB\-C\fR, \fB\-\-submode=\fIop\fP
Mike Christie cfcc31b
+Specify the submode for mode. op must be name of submode.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+Currently iscsiadm support ping as submode for iface. For example,
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+iscsiadm -m iface -I ifacename -C ping -a ipaddr -b packetsize -c count -i interval
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+.TP
Mike Christie cfcc31b
 \fB\-d\fR, \fB\-\-debug=\fIdebug_level\fP
Mike Christie cfcc31b
 print debugging information. Valid values for debug_level are 0 to 8.
Mike Christie cfcc31b
 
Mike Christie cfcc31b
@@ -55,6 +81,12 @@ the scsi host number assigned to the hos
Mike Christie cfcc31b
 MAC address of a scsi host.
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 .TP
Mike Christie cfcc31b
+\fB\-i\fR, \fB\-\-interval=\fIinterval\fP
Mike Christie cfcc31b
+\fIinterval\fP specify delay between two ping iterations.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+This option is only valid for ping submode.
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+.TP
Mike Christie cfcc31b
 \fB\-I\fR, \fB\-\-interface=\fI[iface]\fR
Mike Christie cfcc31b
 The interface argument specifies the iSCSI interface to use for the operation.
Mike Christie cfcc31b
 iSCSI interfaces (iface) are defined in /var/lib/iscsi/ifaces. For hardware
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_err.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_err.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_err.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_err.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -58,8 +58,12 @@ enum {
Mike Christie cfcc31b
 	ISCSI_ERR_ISNS_QUERY		= 25,
Mike Christie cfcc31b
 	/* iSNS registration/deregistration failed */
Mike Christie cfcc31b
 	ISCSI_ERR_ISNS_REG_FAILED	= 26,
Mike Christie cfcc31b
+	/* operation not supported */
Mike Christie cfcc31b
+	ISCSI_ERR_OP_NOT_SUPP		= 27,
Mike Christie cfcc31b
+	/* device or resource in use */
Mike Christie cfcc31b
+	ISCSI_ERR_BUSY			= 28,
Mike Christie cfcc31b
 	/* Operation failed, but retrying layer may succeed */
Mike Christie cfcc31b
-	ISCSI_ERR_AGAIN			= 27,
Mike Christie cfcc31b
+	ISCSI_ERR_AGAIN			= 29,
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	/* Always last. Indicates end of error code space */
Mike Christie cfcc31b
 	ISCSI_MAX_ERR_VAL,
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/include/iscsi_if.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/include/iscsi_if.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -65,8 +65,11 @@ enum iscsi_uevent_e {
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
Mike Christie cfcc31b
 	ISCSI_UEVENT_SET_IFACE_PARAMS	= UEVENT_BASE + 21,
Mike Christie cfcc31b
+	ISCSI_UEVENT_PING		= UEVENT_BASE + 22,
Mike Christie cfcc31b
+	ISCSI_UEVENT_GET_CHAP		= UEVENT_BASE + 23,
Mike Christie cfcc31b
+	ISCSI_UEVENT_DELETE_CHAP	= UEVENT_BASE + 24,
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-	ISCSI_UEVENT_MAX		= ISCSI_UEVENT_SET_IFACE_PARAMS,
Mike Christie cfcc31b
+	ISCSI_UEVENT_MAX		= ISCSI_UEVENT_DELETE_CHAP,
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	/* up events */
Mike Christie cfcc31b
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
Mike Christie cfcc31b
@@ -80,8 +83,9 @@ enum iscsi_uevent_e {
Mike Christie cfcc31b
 	ISCSI_KEVENT_IF_DOWN		= KEVENT_BASE + 8,
Mike Christie cfcc31b
 	ISCSI_KEVENT_CONN_LOGIN_STATE   = KEVENT_BASE + 9,
Mike Christie cfcc31b
 	ISCSI_KEVENT_HOST_EVENT		= KEVENT_BASE + 10,
Mike Christie cfcc31b
+	ISCSI_KEVENT_PING_COMP		= KEVENT_BASE + 11,
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-	ISCSI_KEVENT_MAX		= ISCSI_KEVENT_HOST_EVENT,
Mike Christie cfcc31b
+	ISCSI_KEVENT_MAX		= ISCSI_KEVENT_PING_COMP,
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 enum iscsi_tgt_dscvr {
Mike Christie cfcc31b
@@ -195,6 +199,26 @@ struct iscsi_uevent {
Mike Christie cfcc31b
 			uint32_t	host_no;
Mike Christie cfcc31b
 			uint32_t	count;
Mike Christie cfcc31b
 		} set_iface_params;
Mike Christie cfcc31b
+		struct msg_iscsi_ping {
Mike Christie cfcc31b
+			uint32_t	host_no;
Mike Christie cfcc31b
+			uint32_t	iface_num;
Mike Christie cfcc31b
+			uint32_t	iface_type;
Mike Christie cfcc31b
+			uint32_t	payload_size;
Mike Christie cfcc31b
+			uint32_t	pid;	/* unique ping id associated
Mike Christie cfcc31b
+						   with each ping request */
Mike Christie cfcc31b
+		} iscsi_ping;
Mike Christie cfcc31b
+		struct msg_get_chap {
Mike Christie cfcc31b
+			uint32_t	host_no;
Mike Christie cfcc31b
+			uint32_t	num_entries; /* number of CHAP entries
Mike Christie cfcc31b
+						      * on request, number of
Mike Christie cfcc31b
+						      * valid CHAP entries on
Mike Christie cfcc31b
+						      * response */
Mike Christie cfcc31b
+			uint16_t	chap_tbl_idx;
Mike Christie cfcc31b
+		} get_chap;
Mike Christie cfcc31b
+		struct msg_delete_chap {
Mike Christie cfcc31b
+			uint32_t	host_no;
Mike Christie cfcc31b
+			uint16_t	chap_tbl_idx;
Mike Christie cfcc31b
+		} delete_chap;
Mike Christie cfcc31b
 	} u;
Mike Christie cfcc31b
 	union {
Mike Christie cfcc31b
 		/* messages k -> u */
Mike Christie cfcc31b
@@ -244,6 +268,13 @@ struct iscsi_uevent {
Mike Christie cfcc31b
 			uint32_t	data_size;
Mike Christie cfcc31b
 			enum iscsi_host_event_code code;
Mike Christie cfcc31b
 		} host_event;
Mike Christie cfcc31b
+		struct msg_ping_comp {
Mike Christie cfcc31b
+			uint32_t	host_no;
Mike Christie cfcc31b
+			uint32_t	status;
Mike Christie cfcc31b
+			uint32_t	pid;	/* unique ping id associated
Mike Christie cfcc31b
+						   with each ping request */
Mike Christie cfcc31b
+			uint32_t	data_size;
Mike Christie cfcc31b
+		} ping_comp;
Mike Christie cfcc31b
 	} r;
Mike Christie cfcc31b
 } __attribute__ ((aligned (sizeof(uint64_t))));
Mike Christie cfcc31b
 
Mike Christie cfcc31b
@@ -566,4 +597,20 @@ struct iscsi_stats {
Mike Christie cfcc31b
 		__attribute__ ((aligned (sizeof(uint64_t))));
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+enum chap_type_e {
Mike Christie cfcc31b
+	CHAP_TYPE_OUT,
Mike Christie cfcc31b
+	CHAP_TYPE_IN,
Mike Christie cfcc31b
+};
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+#define ISCSI_CHAP_AUTH_NAME_MAX_LEN	256
Mike Christie cfcc31b
+#define ISCSI_CHAP_AUTH_SECRET_MAX_LEN	256
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+struct iscsi_chap_rec {
Mike Christie cfcc31b
+	uint16_t chap_tbl_idx;
Mike Christie cfcc31b
+	enum chap_type_e chap_type;
Mike Christie cfcc31b
+	char username[ISCSI_CHAP_AUTH_NAME_MAX_LEN];
Mike Christie cfcc31b
+	uint8_t password[ISCSI_CHAP_AUTH_SECRET_MAX_LEN];
Mike Christie cfcc31b
+	uint8_t password_length;
Mike Christie cfcc31b
+};
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 #endif
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/README open-iscsi-2.0-872-rc4-bnx2i.work/README
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/README	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/README	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -366,7 +366,9 @@ Usage: iscsiadm [OPTION]
Mike Christie cfcc31b
 			  iscsi_ifacename.
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 			  See below for examples.
Mike Christie cfcc31b
-  -m host --host=hostno|MAC --print=level
Mike Christie cfcc31b
+  -m iface --interface=iscsi_ifacename -C ping --ip=[ipaddr] --packetsize=[size]
Mike Christie cfcc31b
+				--count=[count] --interval=[interval]
Mike Christie cfcc31b
+  -m host --host=hostno|MAC --print=level -C chap --op=[op] --value=[chap_tbl_idx]
Mike Christie cfcc31b
 			  Display information for a specific host. The host
Mike Christie cfcc31b
 			  can be passed in by host number or by MAC address.
Mike Christie cfcc31b
 			  If a host is not passed in then info
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/host.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/host.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/host.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -5,6 +5,9 @@
Mike Christie cfcc31b
 #include "types.h"
Mike Christie cfcc31b
 #include "config.h"
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+#define MAX_CHAP_BUF_SZ 4096
Mike Christie cfcc31b
+#define REQ_CHAP_BUF_SZ (MAX_CHAP_BUF_SZ + sizeof(struct iscsi_uevent))
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 struct host_info {
Mike Christie cfcc31b
         struct iface_rec iface;
Mike Christie cfcc31b
         uint32_t host_no;
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.c	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.c	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -449,6 +449,30 @@ void idbm_recinfo_iface(iface_rec_t *r,
Mike Christie cfcc31b
 	__recinfo_uint16(IFACE_PORT, ri, r, port, IDBM_SHOW, num, 1);
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+static void idbm_recinfo_host_chap(struct iscsi_chap_rec *r, recinfo_t *ri)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int num = 0;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	__recinfo_uint16(HOST_AUTH_INDEX, ri, r, chap_tbl_idx, IDBM_SHOW,
Mike Christie cfcc31b
+			 num, 1);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (r->chap_type == CHAP_TYPE_OUT) {
Mike Christie cfcc31b
+		__recinfo_str(HOST_AUTH_USERNAME, ri, r, username, IDBM_SHOW,
Mike Christie cfcc31b
+			      num, 0);
Mike Christie cfcc31b
+		__recinfo_str(HOST_AUTH_PASSWORD, ri, r, password, IDBM_MASKED,
Mike Christie cfcc31b
+			      num, 1);
Mike Christie cfcc31b
+		__recinfo_int(HOST_AUTH_PASSWORD_LEN, ri, r, password_length,
Mike Christie cfcc31b
+			      IDBM_HIDE, num, 1);
Mike Christie cfcc31b
+	} else {
Mike Christie cfcc31b
+		__recinfo_str(HOST_AUTH_USERNAME_IN, ri, r, username, IDBM_SHOW,
Mike Christie cfcc31b
+			      num, 0);
Mike Christie cfcc31b
+		__recinfo_str(HOST_AUTH_PASSWORD_IN, ri, r, password,
Mike Christie cfcc31b
+			      IDBM_MASKED, num, 1);
Mike Christie cfcc31b
+		__recinfo_int(HOST_AUTH_PASSWORD_IN_LEN, ri, r, password_length,
Mike Christie cfcc31b
+			      IDBM_HIDE, num, 1);
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 recinfo_t *idbm_recinfo_alloc(int max_keys)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	recinfo_t *info;
Mike Christie cfcc31b
@@ -479,6 +503,9 @@ void idbm_print(int type, void *rec, int
Mike Christie cfcc31b
 	case IDBM_PRINT_TYPE_IFACE:
Mike Christie cfcc31b
 		idbm_recinfo_iface((struct iface_rec *)rec, info);
Mike Christie cfcc31b
 		break;
Mike Christie cfcc31b
+	case IDBM_PRINT_TYPE_HOST_CHAP:
Mike Christie cfcc31b
+		idbm_recinfo_host_chap((struct iscsi_chap_rec *)rec, info);
Mike Christie cfcc31b
+		break;
Mike Christie cfcc31b
 	}
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	fprintf(f, "%s\n", ISCSI_BEGIN_REC);
Mike Christie cfcc31b
@@ -849,6 +876,13 @@ int idbm_print_iface_info(void *data, st
Mike Christie cfcc31b
 	return 0;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+int idbm_print_host_chap_info(struct iscsi_chap_rec *chap)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	/* User only calls this to print chap so always print */
Mike Christie cfcc31b
+	idbm_print(IDBM_PRINT_TYPE_HOST_CHAP, chap, 1, stdout);
Mike Christie cfcc31b
+	return 0;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 int idbm_print_node_flat(void *data, node_rec_t *rec)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	if (strchr(rec->conn[0].address, '.'))
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm_fields.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm_fields.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm_fields.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm_fields.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -116,4 +116,14 @@
Mike Christie cfcc31b
 #define DISC_ISNS_ADDR		"discovery.sendtargets.address"
Mike Christie cfcc31b
 #define DISC_ISNS_PORT		"discovery.sendtargets.port"
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+/* host auth fields */
Mike Christie cfcc31b
+#define HOST_AUTH_INDEX			"host.auth.tbl_idx"
Mike Christie cfcc31b
+#define HOST_AUTH_METHOD		"host.auth.authmethod"
Mike Christie cfcc31b
+#define HOST_AUTH_USERNAME		"host.auth.username"
Mike Christie cfcc31b
+#define HOST_AUTH_PASSWORD		"host.auth.password"
Mike Christie cfcc31b
+#define HOST_AUTH_PASSWORD_LEN		"host.auth.password_length"
Mike Christie cfcc31b
+#define HOST_AUTH_USERNAME_IN		"host.auth.username_in"
Mike Christie cfcc31b
+#define HOST_AUTH_PASSWORD_IN		"host.auth.password_in"
Mike Christie cfcc31b
+#define HOST_AUTH_PASSWORD_IN_LEN	"host.auth.password_in_length"
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 #endif
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/idbm.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/idbm.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -168,6 +168,7 @@ enum {
Mike Christie cfcc31b
 	IDBM_PRINT_TYPE_DISCOVERY,
Mike Christie cfcc31b
 	IDBM_PRINT_TYPE_NODE,
Mike Christie cfcc31b
 	IDBM_PRINT_TYPE_IFACE,
Mike Christie cfcc31b
+	IDBM_PRINT_TYPE_HOST_CHAP,
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 extern void idbm_print(int type, void *rec, int show, FILE *f);
Mike Christie cfcc31b
@@ -180,4 +181,6 @@ extern struct node_rec *idbm_create_rec(
Mike Christie cfcc31b
 extern struct node_rec *
Mike Christie cfcc31b
 idbm_create_rec_from_boot_context(struct boot_context *context);
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+extern int idbm_print_host_chap_info(struct iscsi_chap_rec *chap);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 #endif /* IDBM_H */
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iface.c	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.c	2012-03-06 05:23:54.000000000 -0600
Mike Christie cfcc31b
@@ -425,12 +425,23 @@ int iface_get_by_net_binding(struct ifac
Mike Christie cfcc31b
 	return ISCSI_ERR_NO_OBJS_FOUND;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-static int iface_get_iptype(struct iface_rec *iface)
Mike Christie cfcc31b
+int iface_get_iptype(struct iface_rec *iface)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
-	if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
Mike Christie cfcc31b
-		return ISCSI_IFACE_TYPE_IPV6;
Mike Christie cfcc31b
-	else
Mike Christie cfcc31b
-		return ISCSI_IFACE_TYPE_IPV4;
Mike Christie cfcc31b
+	/* address might not be set if user config with another tool */
Mike Christie cfcc31b
+	if (!strlen(iface->ipaddress) ||
Mike Christie cfcc31b
+	    !strcmp(UNKNOWN_VALUE, iface->ipaddress)) {
Mike Christie cfcc31b
+		/* try to figure out by name */
Mike Christie cfcc31b
+		if (strstr(iface->name, "ipv4"))
Mike Christie cfcc31b
+			return ISCSI_IFACE_TYPE_IPV4;
Mike Christie cfcc31b
+		else
Mike Christie cfcc31b
+			return ISCSI_IFACE_TYPE_IPV6;
Mike Christie cfcc31b
+	} else {
Mike Christie cfcc31b
+		if (strcmp(iface->bootproto, "dhcp") &&
Mike Christie cfcc31b
+		    !strstr(iface->ipaddress, "."))
Mike Christie cfcc31b
+			return ISCSI_IFACE_TYPE_IPV6;
Mike Christie cfcc31b
+		else
Mike Christie cfcc31b
+			return ISCSI_IFACE_TYPE_IPV4;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 static int iface_setup_binding_from_kern_iface(void *data,
Mike Christie cfcc31b
@@ -606,7 +617,7 @@ int iface_match(struct iface_rec *patter
Mike Christie cfcc31b
 		return 1;
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	if (!strcmp(pattern->name, iface->name)) {
Mike Christie cfcc31b
-		if (strcmp(pattern->name, DEFAULT_IFACENAME))
Mike Christie cfcc31b
+		if (!strcmp(pattern->name, DEFAULT_IFACENAME))
Mike Christie cfcc31b
 			return 1;
Mike Christie cfcc31b
 		/*
Mike Christie cfcc31b
 		 * For default we allow the same name, but different
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/iface.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iface.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iface.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -60,6 +60,7 @@ extern int iface_get_param_count(struct
Mike Christie cfcc31b
 				 int iface_all);
Mike Christie cfcc31b
 extern int iface_build_net_config(struct iface_rec *iface_primary,
Mike Christie cfcc31b
 				  int iface_all, struct iovec *iovs);
Mike Christie cfcc31b
+extern int iface_get_iptype(struct iface_rec *iface);
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 #define iface_fmt "[hw=%s,ip=%s,net_if=%s,iscsi_if=%s]"
Mike Christie cfcc31b
 #define iface_str(_iface) \
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsiadm.c	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsiadm.c	2012-03-06 05:23:31.000000000 -0600
Mike Christie cfcc31b
@@ -27,6 +27,7 @@
Mike Christie cfcc31b
 #include <unistd.h>
Mike Christie cfcc31b
 #include <string.h>
Mike Christie cfcc31b
 #include <signal.h>
Mike Christie cfcc31b
+#include <time.h>
Mike Christie cfcc31b
 #include <sys/stat.h>
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 #include "initiator.h"
Mike Christie cfcc31b
@@ -51,6 +52,7 @@
Mike Christie cfcc31b
 #include "isns-proto.h"
Mike Christie cfcc31b
 #include "iscsi_err.h"
Mike Christie cfcc31b
 #include "iscsi_ipc.h"
Mike Christie cfcc31b
+#include "iscsi_timer.h"
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 static char program_name[] = "iscsiadm";
Mike Christie cfcc31b
 static char config_file[TARGET_NAME_MAXLEN];
Mike Christie cfcc31b
@@ -64,6 +66,8 @@ enum iscsiadm_mode {
Mike Christie cfcc31b
 	MODE_HOST,
Mike Christie cfcc31b
 	MODE_IFACE,
Mike Christie cfcc31b
 	MODE_FW,
Mike Christie cfcc31b
+	MODE_PING,
Mike Christie cfcc31b
+	MODE_CHAP
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 enum iscsiadm_op {
Mike Christie cfcc31b
@@ -102,9 +106,13 @@ static struct option const long_options[
Mike Christie cfcc31b
 	{"show", no_argument, NULL, 'S'},
Mike Christie cfcc31b
 	{"version", no_argument, NULL, 'V'},
Mike Christie cfcc31b
 	{"help", no_argument, NULL, 'h'},
Mike Christie cfcc31b
+	{"submode", required_argument, NULL, 'C'},
Mike Christie cfcc31b
+	{"ip", required_argument, NULL, 'a'},
Mike Christie cfcc31b
+	{"packetsize", required_argument, NULL, 'b'},
Mike Christie cfcc31b
+	{"count", required_argument, NULL, 'c'},
Mike Christie cfcc31b
 	{NULL, 0, NULL, 0},
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
-static char *short_options = "RlDVhm:p:P:T:H:I:U:k:L:d:r:n:v:o:sSt:u";
Mike Christie cfcc31b
+static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:u";
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 static void usage(int status)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
@@ -116,12 +124,12 @@ static void usage(int status)
Mike Christie cfcc31b
 iscsiadm -m discoverydb [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -Dl ] ] | [ [ -p ip:port -t type] \
Mike Christie cfcc31b
 [ -o operation ] [ -n name ] [ -v value ] [ -lD ] ] \n\
Mike Christie cfcc31b
 iscsiadm -m discovery [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -l ] ] | [ [ -p ip:port ] [ -l | -D ] ] \n\
Mike Christie cfcc31b
-iiscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] \
Mike Christie cfcc31b
+iscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] \
Mike Christie cfcc31b
 [ [ -o  operation  ] [ -n name ] [ -v value ] ]\n\
Mike Christie cfcc31b
 iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P  printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n\
Mike Christie cfcc31b
-iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename | -H hostno|MAC ] [ [ -o  operation  ] [ -n name ] [ -v value ] ]\n\
Mike Christie cfcc31b
+iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename | -H hostno|MAC ] [ [ -o  operation  ] [ -n name ] [ -v value ] ] [ -C ping [ -a ip ] [ -b packetsize ] [ -c count ] [ -i interval ] ]\n\
Mike Christie cfcc31b
 iscsiadm -m fw [ -l ]\n\
Mike Christie cfcc31b
-iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ]\n\
Mike Christie cfcc31b
+iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ] [ -C chap [ -o operation ] [ -v chap_tbl_idx ] ]\n\
Mike Christie cfcc31b
 iscsiadm -k priority\n");
Mike Christie cfcc31b
 	}
Mike Christie cfcc31b
 	exit(status);
Mike Christie cfcc31b
@@ -178,6 +186,21 @@ str_to_mode(char *str)
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 static int
Mike Christie cfcc31b
+str_to_submode(char *str)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int sub_mode;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (!strcmp("ping", str))
Mike Christie cfcc31b
+		sub_mode = MODE_PING;
Mike Christie cfcc31b
+	else if (!strcmp("chap", str))
Mike Christie cfcc31b
+		sub_mode = MODE_CHAP;
Mike Christie cfcc31b
+	else
Mike Christie cfcc31b
+		sub_mode = -1;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return sub_mode;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int
Mike Christie cfcc31b
 str_to_type(char *str)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	int type;
Mike Christie cfcc31b
@@ -1277,6 +1300,146 @@ free_buf:
Mike Christie cfcc31b
 	return ISCSI_SUCCESS;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+static int get_host_chap_info(uint32_t host_no)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	struct iscsi_transport *t = NULL;
Mike Christie cfcc31b
+	struct iscsi_chap_rec *crec = NULL;
Mike Christie cfcc31b
+	char *req_buf = NULL;
Mike Christie cfcc31b
+	uint32_t valid_chap_entries;
Mike Christie cfcc31b
+	uint32_t num_entries;
Mike Christie cfcc31b
+	uint16_t chap_tbl_idx = 0;
Mike Christie cfcc31b
+	int rc = 0;
Mike Christie cfcc31b
+	int fd, i = 0;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	t = iscsi_sysfs_get_transport_by_hba(host_no);
Mike Christie cfcc31b
+	if (!t) {
Mike Christie cfcc31b
+		log_error("Could not match hostno %d to "
Mike Christie cfcc31b
+			  "transport.", host_no);
Mike Christie cfcc31b
+		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Mike Christie cfcc31b
+		goto exit_chap_info;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	num_entries = MAX_CHAP_BUF_SZ / sizeof(*crec);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	req_buf = calloc(1, REQ_CHAP_BUF_SZ);
Mike Christie cfcc31b
+	if (!req_buf) {
Mike Christie cfcc31b
+		log_error("Could not allocate memory for CHAP request.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_NOMEM;
Mike Christie cfcc31b
+		goto exit_chap_info;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	fd = ipc->ctldev_open();
Mike Christie cfcc31b
+	if (fd < 0) {
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INTERNAL;
Mike Christie cfcc31b
+		log_error("Netlink open failed.");
Mike Christie cfcc31b
+		goto exit_chap_info;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+get_chap:
Mike Christie cfcc31b
+	memset(req_buf, 0, REQ_CHAP_BUF_SZ);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	rc = ipc->get_chap(t->handle, host_no, chap_tbl_idx, num_entries,
Mike Christie cfcc31b
+			   req_buf, &valid_chap_entries);
Mike Christie cfcc31b
+	if (rc < 0) {
Mike Christie cfcc31b
+		log_error("get_chap_info failed. errno=%d", errno);
Mike Christie cfcc31b
+		rc = ISCSI_ERR;
Mike Christie cfcc31b
+		goto exit_chap_info;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	log_info("Valid CHAP Entries = %d\n", valid_chap_entries);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	crec = (struct iscsi_chap_rec *) (req_buf +
Mike Christie cfcc31b
+					  sizeof(struct iscsi_uevent));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (valid_chap_entries)
Mike Christie cfcc31b
+		chap_tbl_idx =
Mike Christie cfcc31b
+		(crec + (valid_chap_entries - 1))->chap_tbl_idx + 1;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	/* print chap info */
Mike Christie cfcc31b
+	for (i = 0; i < valid_chap_entries; i++) {
Mike Christie cfcc31b
+		idbm_print_host_chap_info(crec);
Mike Christie cfcc31b
+		crec++;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (valid_chap_entries != num_entries)
Mike Christie cfcc31b
+		goto exit_chap_info;
Mike Christie cfcc31b
+	else
Mike Christie cfcc31b
+		goto get_chap;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	ipc->ctldev_close();
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+exit_chap_info:
Mike Christie cfcc31b
+	if (req_buf)
Mike Christie cfcc31b
+		free(req_buf);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int delete_host_chap_info(uint32_t host_no, char *value)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	struct iscsi_transport *t = NULL;
Mike Christie cfcc31b
+	int fd, rc = 0;
Mike Christie cfcc31b
+	uint16_t chap_tbl_idx;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (!value) {
Mike Christie cfcc31b
+		log_error("CHAP deletion requires --value=table_index.");
Mike Christie cfcc31b
+		return ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	chap_tbl_idx = (uint16_t)atoi(value);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	t = iscsi_sysfs_get_transport_by_hba(host_no);
Mike Christie cfcc31b
+	if (!t) {
Mike Christie cfcc31b
+		log_error("Could not match hostno %d to "
Mike Christie cfcc31b
+			  "transport.", host_no);
Mike Christie cfcc31b
+		rc = ISCSI_ERR_TRANS_NOT_FOUND;
Mike Christie cfcc31b
+		goto exit_delete_chap;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	fd = ipc->ctldev_open();
Mike Christie cfcc31b
+	if (fd < 0) {
Mike Christie cfcc31b
+		log_error("Netlink open failed.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INTERNAL;
Mike Christie cfcc31b
+		goto exit_delete_chap;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	log_info("Deleteing CHAP index: %d\n", chap_tbl_idx);
Mike Christie cfcc31b
+	rc = ipc->delete_chap(t->handle, host_no, chap_tbl_idx);
Mike Christie cfcc31b
+	if (rc < 0) {
Mike Christie cfcc31b
+		log_error("CHAP Delete failed.");
Mike Christie cfcc31b
+		if (rc == -EBUSY) {
Mike Christie cfcc31b
+			rc = ISCSI_ERR_BUSY;
Mike Christie cfcc31b
+			log_error("CHAP index %d is in use.", chap_tbl_idx);
Mike Christie cfcc31b
+		} else
Mike Christie cfcc31b
+			rc = ISCSI_ERR;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	ipc->ctldev_close();
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+exit_delete_chap:
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int exec_host_chap_op(int op, int info_level, uint32_t host_no,
Mike Christie cfcc31b
+			     char *value)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	switch (op) {
Mike Christie cfcc31b
+	case OP_SHOW:
Mike Christie cfcc31b
+		rc = get_host_chap_info(host_no);
Mike Christie cfcc31b
+		break;
Mike Christie cfcc31b
+	case OP_DELETE:
Mike Christie cfcc31b
+		rc = delete_host_chap_info(host_no, value);
Mike Christie cfcc31b
+		break;
Mike Christie cfcc31b
+	default:
Mike Christie cfcc31b
+		log_error("Invalid operation.");
Mike Christie cfcc31b
+		break;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 /* TODO: merge iter helpers and clean them up, so we can use them here */
Mike Christie cfcc31b
 static int exec_iface_op(int op, int do_show, int info_level,
Mike Christie cfcc31b
 			 struct iface_rec *iface, uint32_t host_no,
Mike Christie cfcc31b
@@ -2082,6 +2245,101 @@ static uint32_t parse_host_info(char *op
Mike Christie cfcc31b
 	return host_no;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+static int exec_ping_op(struct iface_rec *iface, char *ip, int size, int count,
Mike Christie cfcc31b
+			int interval)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int rc = ISCSI_ERR;
Mike Christie cfcc31b
+	uint32_t iface_type = ISCSI_IFACE_TYPE_IPV4;
Mike Christie cfcc31b
+	struct iscsi_transport *t = NULL;
Mike Christie cfcc31b
+	uint32_t host_no;
Mike Christie cfcc31b
+	struct sockaddr_storage addr;
Mike Christie cfcc31b
+	int i;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (!iface) {
Mike Christie cfcc31b
+		log_error("Ping requires iface.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (!ip) {
Mike Christie cfcc31b
+		log_error("Ping requires destination ipaddress.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (size <= 0) {
Mike Christie cfcc31b
+		log_error("Invalid packet size: %d.", size);
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (count <= 0) {
Mike Christie cfcc31b
+		log_error("Invalid number of packets to transmit: %d.", count);
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (interval < 0) {
Mike Christie cfcc31b
+		log_error("Invalid timing interval: %d.", interval);
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	rc = iface_conf_read(iface);
Mike Christie cfcc31b
+	if (rc) {
Mike Christie cfcc31b
+		log_error("Could not read iface %s (%d).", iface->name, rc);
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	iface_type = iface_get_iptype(iface);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	t = iscsi_sysfs_get_transport_by_name(iface->transport_name);
Mike Christie cfcc31b
+	if (!t) {
Mike Christie cfcc31b
+		log_error("Can't find transport.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	host_no = iscsi_sysfs_get_host_no_from_hwinfo(iface, &rc);
Mike Christie cfcc31b
+	if (host_no == -1) {
Mike Christie cfcc31b
+		log_error("Can't find host_no.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	rc = resolve_address(ip, NULL, &addr);
Mike Christie cfcc31b
+	if (rc) {
Mike Christie cfcc31b
+		log_error("Invalid IP address.");
Mike Christie cfcc31b
+		rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+		goto ping_exit;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	/* TODO: move this. It is needed by interface for pid */
Mike Christie cfcc31b
+	srand(time(NULL));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	for (i = 1; i <= count; i++) {
Mike Christie cfcc31b
+		/*
Mike Christie cfcc31b
+		 * To support drivers like bnx2i that do not use
Mike Christie cfcc31b
+		 * the iscsi if to send a ping, we can add a transport
Mike Christie cfcc31b
+		 * callout here.
Mike Christie cfcc31b
+		 */
Mike Christie cfcc31b
+		rc = ipc->exec_ping(t->handle, host_no,
Mike Christie cfcc31b
+				    (struct sockaddr *)&addr, iface->iface_num,
Mike Christie cfcc31b
+				    iface_type, size);
Mike Christie cfcc31b
+		if (!rc)
Mike Christie cfcc31b
+			printf("Ping %d completed\n", i);
Mike Christie cfcc31b
+		else
Mike Christie cfcc31b
+			printf("Ping %d failed: %s\n", i, iscsi_err_to_str(rc));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+		if (i < count)
Mike Christie cfcc31b
+			sleep(interval);
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+ping_exit:
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 int
Mike Christie cfcc31b
 main(int argc, char **argv)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
@@ -2091,7 +2349,8 @@ main(int argc, char **argv)
Mike Christie cfcc31b
 	int rc=0, sid=-1, op=OP_NOOP, type=-1, do_logout=0, do_stats=0;
Mike Christie cfcc31b
 	int do_login_all=0, do_logout_all=0, info_level=-1, num_ifaces = 0;
Mike Christie cfcc31b
 	int tpgt = PORTAL_GROUP_TAG_UNKNOWN, killiscsid=-1, do_show=0;
Mike Christie cfcc31b
-	int do_discover = 0;
Mike Christie cfcc31b
+	int packet_size=32, ping_count=1, ping_interval=0;
Mike Christie cfcc31b
+	int do_discover = 0, sub_mode = -1;
Mike Christie cfcc31b
 	struct sigaction sa_old;
Mike Christie cfcc31b
 	struct sigaction sa_new;
Mike Christie cfcc31b
 	struct list_head ifaces;
Mike Christie cfcc31b
@@ -2196,12 +2455,27 @@ main(int argc, char **argv)
Mike Christie cfcc31b
 		case 'm':
Mike Christie cfcc31b
 			mode = str_to_mode(optarg);
Mike Christie cfcc31b
 			break;
Mike Christie cfcc31b
+		case 'C':
Mike Christie cfcc31b
+			sub_mode = str_to_submode(optarg);
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
 		case 'T':
Mike Christie cfcc31b
 			targetname = optarg;
Mike Christie cfcc31b
 			break;
Mike Christie cfcc31b
 		case 'p':
Mike Christie cfcc31b
 			ip = str_to_ipport(optarg, &port, &tpgt);
Mike Christie cfcc31b
 			break;
Mike Christie cfcc31b
+		case 'a':
Mike Christie cfcc31b
+			ip = optarg;
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		case 'b':
Mike Christie cfcc31b
+			packet_size = atoi(optarg);
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		case 'c':
Mike Christie cfcc31b
+			ping_count = atoi(optarg);
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		case 'i':
Mike Christie cfcc31b
+			ping_interval = atoi(optarg);
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
 		case 'I':
Mike Christie cfcc31b
 			iface = iface_alloc(optarg, &rc);
Mike Christie cfcc31b
 			if (rc == ISCSI_ERR_INVAL) {
Mike Christie cfcc31b
@@ -2262,19 +2536,35 @@ main(int argc, char **argv)
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	switch (mode) {
Mike Christie cfcc31b
 	case MODE_HOST:
Mike Christie cfcc31b
-		if ((rc = verify_mode_params(argc, argv, "HdmP", 0))) {
Mike Christie cfcc31b
+		if ((rc = verify_mode_params(argc, argv, "CHdmPov", 0))) {
Mike Christie cfcc31b
 			log_error("host mode: option '-%c' is not "
Mike Christie cfcc31b
 				  "allowed/supported", rc);
Mike Christie cfcc31b
 			rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
 			goto out;
Mike Christie cfcc31b
 		}
Mike Christie cfcc31b
-
Mike Christie cfcc31b
-		rc = host_info_print(info_level, host_no);
Mike Christie cfcc31b
+		if (sub_mode != -1) {
Mike Christie cfcc31b
+			switch (sub_mode) {
Mike Christie cfcc31b
+			case MODE_CHAP:
Mike Christie cfcc31b
+				if (!op || !host_no) {
Mike Christie cfcc31b
+					log_error("CHAP mode requires host "
Mike Christie cfcc31b
+						"no and valid operation");
Mike Christie cfcc31b
+					rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+					break;
Mike Christie cfcc31b
+				}
Mike Christie cfcc31b
+				rc = exec_host_chap_op(op, info_level, host_no,
Mike Christie cfcc31b
+						       value);
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			default:
Mike Christie cfcc31b
+				log_error("Invalid Sub Mode");
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			}
Mike Christie cfcc31b
+		} else
Mike Christie cfcc31b
+			rc = host_info_print(info_level, host_no);
Mike Christie cfcc31b
 		break;
Mike Christie cfcc31b
 	case MODE_IFACE:
Mike Christie cfcc31b
 		iface_setup_host_bindings();
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-		if ((rc = verify_mode_params(argc, argv, "HIdnvmPo", 0))) {
Mike Christie cfcc31b
+		if ((rc = verify_mode_params(argc, argv, "HIdnvmPoCabci", 0))) {
Mike Christie cfcc31b
 			log_error("iface mode: option '-%c' is not "
Mike Christie cfcc31b
 				  "allowed/supported", rc);
Mike Christie cfcc31b
 			rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
@@ -2289,8 +2579,14 @@ main(int argc, char **argv)
Mike Christie cfcc31b
 					  "interface. Using the first one "
Mike Christie cfcc31b
 					  "%s.", iface->name);
Mike Christie cfcc31b
 		}
Mike Christie cfcc31b
-		rc = exec_iface_op(op, do_show, info_level, iface, host_no,
Mike Christie cfcc31b
-				   name, value);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+		if (sub_mode == MODE_PING)
Mike Christie cfcc31b
+			rc = exec_ping_op(iface, ip, packet_size, ping_count,
Mike Christie cfcc31b
+					  ping_interval);
Mike Christie cfcc31b
+		else
Mike Christie cfcc31b
+			rc = exec_iface_op(op, do_show, info_level, iface,
Mike Christie cfcc31b
+					   host_no, name, value);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 		break;
Mike Christie cfcc31b
 	case MODE_DISCOVERYDB:
Mike Christie cfcc31b
 		if ((rc = verify_mode_params(argc, argv, "DSIPdmntplov", 0))) {
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_err.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_err.c
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_err.c	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_err.c	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -49,7 +49,9 @@ static char *iscsi_err_msgs[] = {
Mike Christie cfcc31b
 	/* 24 */ "iSCSI login failed due to authorization failure",
Mike Christie cfcc31b
 	/* 25 */ "iSNS query failed",
Mike Christie cfcc31b
 	/* 26 */ "iSNS registration failed",
Mike Christie cfcc31b
-	/* 27 */ "Retryable failure",
Mike Christie cfcc31b
+	/* 27 */ "operation not supported",
Mike Christie cfcc31b
+	/* 28 */ "device or resource in use",
Mike Christie cfcc31b
+	/* 29 */ "Retryable failure",
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 char *iscsi_err_to_str(int err)
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/iscsi_ipc.h	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/iscsi_ipc.h	2012-03-06 05:22:26.000000000 -0600
Mike Christie cfcc31b
@@ -134,6 +134,17 @@ struct iscsi_ipc {
Mike Christie cfcc31b
 			       struct iovec *iovs, uint32_t param_count);
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	int (*recv_conn_state) (struct iscsi_conn *conn, uint32_t *state);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	int (*exec_ping) (uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+			  struct sockaddr *addr, uint32_t iface_num,
Mike Christie cfcc31b
+			  uint32_t iface_type, uint32_t size);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	int (*get_chap) (uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+			 uint16_t chap_tbl_idx, uint32_t num_entries,
Mike Christie cfcc31b
+			 char *chap_buf, uint32_t *valid_chap_entries);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	int (*delete_chap) (uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+			    uint16_t chap_tbl_idx);
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 struct iscsi_ipc *ipc;
Mike Christie cfcc31b
diff -aurp open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c
Mike Christie cfcc31b
--- open-iscsi-2.0-872-rc4-bnx2i/usr/netlink.c	2012-03-06 05:22:41.000000000 -0600
Mike Christie cfcc31b
+++ open-iscsi-2.0-872-rc4-bnx2i.work/usr/netlink.c	2012-03-06 05:23:02.000000000 -0600
Mike Christie cfcc31b
@@ -25,10 +25,12 @@
Mike Christie cfcc31b
 #include <unistd.h>
Mike Christie cfcc31b
 #include <stdint.h>
Mike Christie cfcc31b
 #include <errno.h>
Mike Christie cfcc31b
+#include <time.h>
Mike Christie cfcc31b
 #include <inttypes.h>
Mike Christie cfcc31b
 #include <asm/types.h>
Mike Christie cfcc31b
 #include <sys/socket.h>
Mike Christie cfcc31b
 #include <sys/types.h>
Mike Christie cfcc31b
+#include <sys/poll.h>
Mike Christie cfcc31b
 #include <linux/netlink.h>
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 #include "types.h"
Mike Christie cfcc31b
@@ -39,6 +41,8 @@
Mike Christie cfcc31b
 #include "iscsi_sysfs.h"
Mike Christie cfcc31b
 #include "transport.h"
Mike Christie cfcc31b
 #include "iscsi_netlink.h"
Mike Christie cfcc31b
+#include "iscsi_err.h"
Mike Christie cfcc31b
+#include "iscsi_timer.h"
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 static int ctrl_fd;
Mike Christie cfcc31b
 static struct sockaddr_nl src_addr, dest_addr;
Mike Christie cfcc31b
@@ -64,6 +68,15 @@ static int ctldev_handle(void);
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 #define NLM_SETPARAM_DEFAULT_MAX (NI_MAXHOST + 1 + sizeof(struct iscsi_uevent))
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+struct iscsi_ping_event {
Mike Christie cfcc31b
+	uint32_t host_no;
Mike Christie cfcc31b
+	uint32_t pid;
Mike Christie cfcc31b
+	int32_t status;
Mike Christie cfcc31b
+	int active;
Mike Christie cfcc31b
+};
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+struct iscsi_ping_event ping_event;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 struct nlattr *iscsi_nla_alloc(uint16_t type, uint16_t len)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	struct nlattr *attr;
Mike Christie cfcc31b
@@ -323,6 +336,9 @@ __kipc_call(struct iovec *iovp, int coun
Mike Christie cfcc31b
 		} else if (ev->type == ISCSI_UEVENT_GET_STATS) {
Mike Christie cfcc31b
 			/* kget_stats() will read */
Mike Christie cfcc31b
 			return 0;
Mike Christie cfcc31b
+		} else if (ev->type == ISCSI_UEVENT_GET_CHAP) {
Mike Christie cfcc31b
+			/* kget_chap() will read */
Mike Christie cfcc31b
+			return 0;
Mike Christie cfcc31b
 		} else {
Mike Christie cfcc31b
 			if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
Mike Christie cfcc31b
 						 sizeof(*ev), 0)) < 0) {
Mike Christie cfcc31b
@@ -1002,7 +1018,7 @@ kset_net_config(uint64_t transport_handl
Mike Christie cfcc31b
 	return 0;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
-static int krecv_conn_state(struct iscsi_conn *conn, int *state)
Mike Christie cfcc31b
+static int krecv_conn_state(struct iscsi_conn *conn, uint32_t *state)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	int rc;
Mike Christie cfcc31b
 
Mike Christie cfcc31b
@@ -1024,6 +1040,218 @@ exit:
Mike Christie cfcc31b
 	return rc;
Mike Christie cfcc31b
 }
Mike Christie cfcc31b
 
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int
Mike Christie cfcc31b
+ksend_ping(uint64_t transport_handle, uint32_t host_no, struct sockaddr *addr,
Mike Christie cfcc31b
+	   uint32_t iface_num, uint32_t iface_type, uint32_t pid, uint32_t size)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int rc, addrlen;
Mike Christie cfcc31b
+	struct iscsi_uevent *ev;
Mike Christie cfcc31b
+	struct iovec iov[2];
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	log_debug(8, "in %s", __FUNCTION__);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
Mike Christie cfcc31b
+	ev = (struct iscsi_uevent *)setparam_buf;
Mike Christie cfcc31b
+	ev->type = ISCSI_UEVENT_PING;
Mike Christie cfcc31b
+	ev->transport_handle = transport_handle;
Mike Christie cfcc31b
+	ev->u.iscsi_ping.host_no = host_no;
Mike Christie cfcc31b
+	ev->u.iscsi_ping.iface_num = iface_num;
Mike Christie cfcc31b
+	ev->u.iscsi_ping.iface_type = iface_type;
Mike Christie cfcc31b
+	ev->u.iscsi_ping.payload_size = size;
Mike Christie cfcc31b
+	ev->u.iscsi_ping.pid = pid;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if (addr->sa_family == PF_INET)
Mike Christie cfcc31b
+		addrlen = sizeof(struct sockaddr_in);
Mike Christie cfcc31b
+	else if (addr->sa_family == PF_INET6)
Mike Christie cfcc31b
+		addrlen = sizeof(struct sockaddr_in6);
Mike Christie cfcc31b
+	else {
Mike Christie cfcc31b
+		log_error("%s unknown addr family %d\n",
Mike Christie cfcc31b
+			  __FUNCTION__, addr->sa_family);
Mike Christie cfcc31b
+		return -EINVAL;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+	memcpy(setparam_buf + sizeof(*ev), addr, addrlen);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	iov[1].iov_base = ev;
Mike Christie cfcc31b
+	iov[1].iov_len = sizeof(*ev) + addrlen;
Mike Christie cfcc31b
+	rc = __kipc_call(iov, 2);
Mike Christie cfcc31b
+	if (rc < 0)
Mike Christie cfcc31b
+		return rc;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return 0;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int kexec_ping(uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+		      struct sockaddr *addr, uint32_t iface_num,
Mike Christie cfcc31b
+		      uint32_t iface_type, uint32_t size)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	struct pollfd pfd;
Mike Christie cfcc31b
+	struct timeval ping_timer;
Mike Christie cfcc31b
+	int timeout, fd, rc;
Mike Christie cfcc31b
+	uint32_t pid;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	fd = ipc->ctldev_open();
Mike Christie cfcc31b
+	if (fd < 0) {
Mike Christie cfcc31b
+		log_error("Could not open netlink socket.");
Mike Christie cfcc31b
+		return ISCSI_ERR;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	/* prepare to poll */
Mike Christie cfcc31b
+	memset(&pfd, 0, sizeof(pfd));
Mike Christie cfcc31b
+	pfd.fd = fd;
Mike Christie cfcc31b
+	pfd.events = POLLIN | POLLPRI;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	/* get unique ping id */
Mike Christie cfcc31b
+	pid = rand();
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	rc = ksend_ping(transport_handle, host_no, addr, iface_num,
Mike Christie cfcc31b
+			iface_type, pid, size);
Mike Christie cfcc31b
+	if (rc != 0) {
Mike Christie cfcc31b
+		switch (rc) {
Mike Christie cfcc31b
+		case -ENOSYS:
Mike Christie cfcc31b
+			rc = ISCSI_ERR_OP_NOT_SUPP;
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		case -EINVAL:
Mike Christie cfcc31b
+			rc = ISCSI_ERR_INVAL;
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		default:
Mike Christie cfcc31b
+			rc = ISCSI_ERR;
Mike Christie cfcc31b
+		}
Mike Christie cfcc31b
+		goto close_nl;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	ping_event.host_no = -1;
Mike Christie cfcc31b
+	ping_event.pid = -1;
Mike Christie cfcc31b
+	ping_event.status = -1;
Mike Christie cfcc31b
+	ping_event.active = -1;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	iscsi_timer_set(&ping_timer, 30);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	timeout = iscsi_timer_msecs_until(&ping_timer);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	while (1) {
Mike Christie cfcc31b
+		pfd.revents = 0;
Mike Christie cfcc31b
+		rc = poll(&pfd, 1, timeout);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+		if (iscsi_timer_expired(&ping_timer)) {
Mike Christie cfcc31b
+			rc = ISCSI_ERR_TRANS_TIMEOUT;
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+		if (rc > 0) {
Mike Christie cfcc31b
+			if (pfd.revents & (POLLIN | POLLPRI)) {
Mike Christie cfcc31b
+				timeout = iscsi_timer_msecs_until(&ping_timer);
Mike Christie cfcc31b
+				rc = ipc->ctldev_handle();
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+				if (ping_event.active != 1)
Mike Christie cfcc31b
+					continue;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+				if (pid != ping_event.pid)
Mike Christie cfcc31b
+					continue;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+				if (ping_event.status == 0)
Mike Christie cfcc31b
+					rc = 0;
Mike Christie cfcc31b
+				else
Mike Christie cfcc31b
+					rc = ISCSI_ERR;
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+			if (pfd.revents & POLLHUP) {
Mike Christie cfcc31b
+				rc = ISCSI_ERR_TRANS;
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+			if (pfd.revents & POLLNVAL) {
Mike Christie cfcc31b
+				rc = ISCSI_ERR_INTERNAL;
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+			if (pfd.revents & POLLERR) {
Mike Christie cfcc31b
+				rc = ISCSI_ERR_INTERNAL;
Mike Christie cfcc31b
+				break;
Mike Christie cfcc31b
+			}
Mike Christie cfcc31b
+		} else if (rc < 0) {
Mike Christie cfcc31b
+			rc = ISCSI_ERR_INTERNAL;
Mike Christie cfcc31b
+			break;
Mike Christie cfcc31b
+		}
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+close_nl:
Mike Christie cfcc31b
+	ipc->ctldev_close();
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int kget_chap(uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+		     uint16_t chap_tbl_idx, uint32_t num_entries,
Mike Christie cfcc31b
+		     char *chap_buf, uint32_t *valid_chap_entries)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int rc = 0;
Mike Christie cfcc31b
+	int ev_size;
Mike Christie cfcc31b
+	struct iscsi_uevent ev;
Mike Christie cfcc31b
+	struct iovec iov[2];
Mike Christie cfcc31b
+	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Mike Christie cfcc31b
+	struct nlmsghdr *nlh;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	memset(&ev, 0, sizeof(struct iscsi_uevent));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	ev.type = ISCSI_UEVENT_GET_CHAP;
Mike Christie cfcc31b
+	ev.transport_handle = transport_handle;
Mike Christie cfcc31b
+	ev.u.get_chap.host_no = host_no;
Mike Christie cfcc31b
+	ev.u.get_chap.chap_tbl_idx = chap_tbl_idx;
Mike Christie cfcc31b
+	ev.u.get_chap.num_entries = num_entries;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	iov[1].iov_base = &ev;
Mike Christie cfcc31b
+	iov[1].iov_len = sizeof(ev);
Mike Christie cfcc31b
+	rc = __kipc_call(iov, 2);
Mike Christie cfcc31b
+	if (rc < 0)
Mike Christie cfcc31b
+		return rc;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if ((rc = nl_read(ctrl_fd, nlm_ev,
Mike Christie cfcc31b
+			  NLMSG_SPACE(sizeof(struct iscsi_uevent)),
Mike Christie cfcc31b
+			  MSG_PEEK)) < 0) {
Mike Christie cfcc31b
+		log_error("can not read nlm_ev, error %d", rc);
Mike Christie cfcc31b
+		return rc;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	nlh = (struct nlmsghdr *)nlm_ev;
Mike Christie cfcc31b
+	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	if ((rc = nlpayload_read(ctrl_fd, (void *)chap_buf, ev_size, 0)) < 0) {
Mike Christie cfcc31b
+		log_error("can not read from NL socket, error %d", rc);
Mike Christie cfcc31b
+		return rc;
Mike Christie cfcc31b
+	}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	*valid_chap_entries = ev.u.get_chap.num_entries;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+static int kdelete_chap(uint64_t transport_handle, uint32_t host_no,
Mike Christie cfcc31b
+			uint16_t chap_tbl_idx)
Mike Christie cfcc31b
+{
Mike Christie cfcc31b
+	int rc = 0;
Mike Christie cfcc31b
+	struct iscsi_uevent ev;
Mike Christie cfcc31b
+	struct iovec iov[2];
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	memset(&ev, 0, sizeof(struct iscsi_uevent));
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	ev.type = ISCSI_UEVENT_DELETE_CHAP;
Mike Christie cfcc31b
+	ev.transport_handle = transport_handle;
Mike Christie cfcc31b
+	ev.u.delete_chap.host_no = host_no;
Mike Christie cfcc31b
+	ev.u.delete_chap.chap_tbl_idx = chap_tbl_idx;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	iov[1].iov_base = &ev;
Mike Christie cfcc31b
+	iov[1].iov_len = sizeof(ev);
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	rc = __kipc_call(iov, 2);
Mike Christie cfcc31b
+	if (rc < 0)
Mike Christie cfcc31b
+		return rc;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+	return rc;
Mike Christie cfcc31b
+}
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 static void drop_data(struct nlmsghdr *nlh)
Mike Christie cfcc31b
 {
Mike Christie cfcc31b
 	int ev_size;
Mike Christie cfcc31b
@@ -1041,7 +1269,7 @@ static int ctldev_handle(void)
Mike Christie cfcc31b
 	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
Mike Christie cfcc31b
 	struct nlmsghdr *nlh;
Mike Christie cfcc31b
 	struct iscsi_ev_context *ev_context;
Mike Christie cfcc31b
-	uint32_t sid = 0, cid = 0, state = 0;
Mike Christie cfcc31b
+	uint32_t sid = 0, cid = 0;
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 	log_debug(7, "in %s", __FUNCTION__);
Mike Christie cfcc31b
 
Mike Christie cfcc31b
@@ -1060,11 +1288,17 @@ static int ctldev_handle(void)
Mike Christie cfcc31b
 	/* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
Mike Christie cfcc31b
 	case ISCSI_UEVENT_CREATE_SESSION:
Mike Christie cfcc31b
 		drop_data(nlh);
Mike Christie cfcc31b
+		if (!ipc_ev_clbk)
Mike Christie cfcc31b
+			return 0;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 		if (ipc_ev_clbk->create_session)
Mike Christie cfcc31b
 			ipc_ev_clbk->create_session(ev->r.c_session_ret.host_no,
Mike Christie cfcc31b
 						    ev->r.c_session_ret.sid);
Mike Christie cfcc31b
 		return 0;
Mike Christie cfcc31b
 	case ISCSI_KEVENT_DESTROY_SESSION:
Mike Christie cfcc31b
+		if (!ipc_ev_clbk)
Mike Christie cfcc31b
+			return 0;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
 		drop_data(nlh);
Mike Christie cfcc31b
 		if (ipc_ev_clbk->destroy_session)
Mike Christie cfcc31b
 			ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
Mike Christie cfcc31b
@@ -1081,7 +1315,6 @@ static int ctldev_handle(void)
Mike Christie cfcc31b
 	case ISCSI_KEVENT_CONN_LOGIN_STATE:
Mike Christie cfcc31b
 		sid = ev->r.conn_login.sid;
Mike Christie cfcc31b
 		cid = ev->r.conn_login.cid;
Mike Christie cfcc31b
-		state = ev->r.conn_login.state;
Mike Christie cfcc31b
 		break;
Mike Christie cfcc31b
 	case ISCSI_KEVENT_UNBIND_SESSION:
Mike Christie cfcc31b
 		sid = ev->r.unbind_session.sid;
Mike Christie cfcc31b
@@ -1106,6 +1339,14 @@ static int ctldev_handle(void)
Mike Christie cfcc31b
 
Mike Christie cfcc31b
 		drop_data(nlh);
Mike Christie cfcc31b
 		return 0;
Mike Christie cfcc31b
+	case ISCSI_KEVENT_PING_COMP:
Mike Christie cfcc31b
+		ping_event.host_no = ev->r.ping_comp.host_no;
Mike Christie cfcc31b
+		ping_event.pid = ev->r.ping_comp.pid;
Mike Christie cfcc31b
+		ping_event.status = ev->r.ping_comp.status;
Mike Christie cfcc31b
+		ping_event.active = 1;
Mike Christie cfcc31b
+
Mike Christie cfcc31b
+		drop_data(nlh);
Mike Christie cfcc31b
+		return 0;
Mike Christie cfcc31b
 	default:
Mike Christie cfcc31b
 		if ((ev->type > ISCSI_UEVENT_MAX && ev->type < KEVENT_BASE) ||
Mike Christie cfcc31b
 		    (ev->type > ISCSI_KEVENT_MAX))
Mike Christie cfcc31b
@@ -1299,6 +1540,9 @@ struct iscsi_ipc nl_ipc = {
Mike Christie cfcc31b
 	.recv_pdu_end           = krecv_pdu_end,
Mike Christie cfcc31b
 	.set_net_config         = kset_net_config,
Mike Christie cfcc31b
 	.recv_conn_state        = krecv_conn_state,
Mike Christie cfcc31b
+	.exec_ping		= kexec_ping,
Mike Christie cfcc31b
+	.get_chap		= kget_chap,
Mike Christie cfcc31b
+	.delete_chap		= kdelete_chap,
Mike Christie cfcc31b
 };
Mike Christie cfcc31b
 struct iscsi_ipc *ipc = &nl_ipc;
Mike Christie cfcc31b