[Pkg-iscsi-maintainers] [SCM] Debian Open-iSCSI Packaging branch, upstream-mnc, updated. 2.0-872-193-gde2c0e7

Mike Christie michaelc at cs.wisc.edu
Sat Apr 7 15:44:04 UTC 2012


The following commit has been merged in the upstream-mnc branch:
commit d94720a7f3f5c53d702a727ab8845ac9df6fd22b
Author: Mike Christie <michaelc at cs.wisc.edu>
Date:   Tue Mar 6 03:31:29 2012 -0600

    iscsi tools: Add support to display a host's CHAP list and delete
    
    Drivers like qla4xxx store the CHAP info in a table that is
    managed at the host level. This patch allows you to see
    and delete the CHAP entries on the host.
    
    Patch from: Nilesh Javali <nilesh.javali at qlogic.com>
    
    [lots of bug fixes by Mike Christie]
    Signed-off-by: Nilesh Javali <nilesh.javali at qlogic.com>
    Signed-off-by: Vikas Chaudhary <vikas.chaudhary at qlogic.com>

diff --git a/include/iscsi_err.h b/include/iscsi_err.h
index e038f1c..aabea4e 100644
--- a/include/iscsi_err.h
+++ b/include/iscsi_err.h
@@ -60,6 +60,8 @@ enum {
 	ISCSI_ERR_ISNS_REG_FAILED	= 26,
 	/* operation not supported */
 	ISCSI_ERR_OP_NOT_SUPP		= 27,
+	/* device or resource in use */
+	ISCSI_ERR_BUSY			= 28,
 
 	/* Always last. Indicates end of error code space */
 	ISCSI_MAX_ERR_VAL,
diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index 26182aa..ce9ba15 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
@@ -66,8 +66,10 @@ enum iscsi_uevent_e {
 	ISCSI_UEVENT_PATH_UPDATE	= UEVENT_BASE + 20,
 	ISCSI_UEVENT_SET_IFACE_PARAMS	= UEVENT_BASE + 21,
 	ISCSI_UEVENT_PING		= UEVENT_BASE + 22,
+	ISCSI_UEVENT_GET_CHAP		= UEVENT_BASE + 23,
+	ISCSI_UEVENT_DELETE_CHAP	= UEVENT_BASE + 24,
 
-	ISCSI_UEVENT_MAX		= ISCSI_UEVENT_PING,
+	ISCSI_UEVENT_MAX		= ISCSI_UEVENT_DELETE_CHAP,
 
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
@@ -205,6 +207,18 @@ struct iscsi_uevent {
 			uint32_t	pid;	/* unique ping id associated
 						   with each ping request */
 		} iscsi_ping;
+		struct msg_get_chap {
+			uint32_t	host_no;
+			uint32_t	num_entries; /* number of CHAP entries
+						      * on request, number of
+						      * valid CHAP entries on
+						      * response */
+			uint16_t	chap_tbl_idx;
+		} get_chap;
+		struct msg_delete_chap {
+			uint32_t	host_no;
+			uint16_t	chap_tbl_idx;
+		} delete_chap;
 	} u;
 	union {
 		/* messages k -> u */
@@ -583,4 +597,20 @@ struct iscsi_stats {
 		__attribute__ ((aligned (sizeof(uint64_t))));
 };
 
+enum chap_type_e {
+	CHAP_TYPE_OUT,
+	CHAP_TYPE_IN,
+};
+
+#define ISCSI_CHAP_AUTH_NAME_MAX_LEN	256
+#define ISCSI_CHAP_AUTH_SECRET_MAX_LEN	256
+
+struct iscsi_chap_rec {
+	uint16_t chap_tbl_idx;
+	enum chap_type_e chap_type;
+	char username[ISCSI_CHAP_AUTH_NAME_MAX_LEN];
+	uint8_t password[ISCSI_CHAP_AUTH_SECRET_MAX_LEN];
+	uint8_t password_length;
+};
+
 #endif
diff --git a/usr/host.h b/usr/host.h
index a38efc9..894ab91 100644
--- a/usr/host.h
+++ b/usr/host.h
@@ -5,6 +5,9 @@
 #include "types.h"
 #include "config.h"
 
+#define MAX_CHAP_BUF_SZ 4096
+#define REQ_CHAP_BUF_SZ (MAX_CHAP_BUF_SZ + sizeof(struct iscsi_uevent))
+
 struct host_info {
         struct iface_rec iface;
         uint32_t host_no;
diff --git a/usr/idbm.c b/usr/idbm.c
index 7ebd3d5..3f53115 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -445,6 +445,30 @@ void idbm_recinfo_iface(iface_rec_t *r, recinfo_t *ri)
 	__recinfo_uint16(IFACE_PORT, ri, r, port, IDBM_SHOW, num, 1);
 }
 
+static void idbm_recinfo_host_chap(struct iscsi_chap_rec *r, recinfo_t *ri)
+{
+	int num = 0;
+
+	__recinfo_uint16(HOST_AUTH_INDEX, ri, r, chap_tbl_idx, IDBM_SHOW,
+			 num, 1);
+
+	if (r->chap_type == CHAP_TYPE_OUT) {
+		__recinfo_str(HOST_AUTH_USERNAME, ri, r, username, IDBM_SHOW,
+			      num, 0);
+		__recinfo_str(HOST_AUTH_PASSWORD, ri, r, password, IDBM_MASKED,
+			      num, 1);
+		__recinfo_int(HOST_AUTH_PASSWORD_LEN, ri, r, password_length,
+			      IDBM_HIDE, num, 1);
+	} else {
+		__recinfo_str(HOST_AUTH_USERNAME_IN, ri, r, username, IDBM_SHOW,
+			      num, 0);
+		__recinfo_str(HOST_AUTH_PASSWORD_IN, ri, r, password,
+			      IDBM_MASKED, num, 1);
+		__recinfo_int(HOST_AUTH_PASSWORD_IN_LEN, ri, r, password_length,
+			      IDBM_HIDE, num, 1);
+	}
+}
+
 recinfo_t *idbm_recinfo_alloc(int max_keys)
 {
 	recinfo_t *info;
@@ -475,6 +499,9 @@ void idbm_print(int type, void *rec, int show, FILE *f)
 	case IDBM_PRINT_TYPE_IFACE:
 		idbm_recinfo_iface((struct iface_rec *)rec, info);
 		break;
+	case IDBM_PRINT_TYPE_HOST_CHAP:
+		idbm_recinfo_host_chap((struct iscsi_chap_rec *)rec, info);
+		break;
 	}
 
 	fprintf(f, "%s\n", ISCSI_BEGIN_REC);
@@ -845,6 +872,13 @@ int idbm_print_iface_info(void *data, struct iface_rec *iface)
 	return 0;
 }
 
+int idbm_print_host_chap_info(struct iscsi_chap_rec *chap)
+{
+	/* User only calls this to print chap so always print */
+	idbm_print(IDBM_PRINT_TYPE_HOST_CHAP, chap, 1, stdout);
+	return 0;
+}
+
 int idbm_print_node_flat(void *data, node_rec_t *rec)
 {
 	if (strchr(rec->conn[0].address, '.'))
diff --git a/usr/idbm.h b/usr/idbm.h
index ced224d..0f8767a 100644
--- a/usr/idbm.h
+++ b/usr/idbm.h
@@ -162,6 +162,7 @@ enum {
 	IDBM_PRINT_TYPE_DISCOVERY,
 	IDBM_PRINT_TYPE_NODE,
 	IDBM_PRINT_TYPE_IFACE,
+	IDBM_PRINT_TYPE_HOST_CHAP,
 };
 
 extern void idbm_print(int type, void *rec, int show, FILE *f);
@@ -174,4 +175,6 @@ extern struct node_rec *idbm_create_rec(char *targetname, int tpgt,
 extern struct node_rec *
 idbm_create_rec_from_boot_context(struct boot_context *context);
 
+extern int idbm_print_host_chap_info(struct iscsi_chap_rec *chap);
+
 #endif /* IDBM_H */
diff --git a/usr/idbm_fields.h b/usr/idbm_fields.h
index 269d87c..358d014 100644
--- a/usr/idbm_fields.h
+++ b/usr/idbm_fields.h
@@ -116,4 +116,14 @@
 #define DISC_ISNS_ADDR		"discovery.sendtargets.address"
 #define DISC_ISNS_PORT		"discovery.sendtargets.port"
 
+/* host auth fields */
+#define HOST_AUTH_INDEX			"host.auth.tbl_idx"
+#define HOST_AUTH_METHOD		"host.auth.authmethod"
+#define HOST_AUTH_USERNAME		"host.auth.username"
+#define HOST_AUTH_PASSWORD		"host.auth.password"
+#define HOST_AUTH_PASSWORD_LEN		"host.auth.password_length"
+#define HOST_AUTH_USERNAME_IN		"host.auth.username_in"
+#define HOST_AUTH_PASSWORD_IN		"host.auth.password_in"
+#define HOST_AUTH_PASSWORD_IN_LEN	"host.auth.password_in_length"
+
 #endif
diff --git a/usr/iscsi_err.c b/usr/iscsi_err.c
index 4936e45..4fe1c53 100644
--- a/usr/iscsi_err.c
+++ b/usr/iscsi_err.c
@@ -50,6 +50,7 @@ static char *iscsi_err_msgs[] = {
 	/* 25 */ "iSNS query failed",
 	/* 26 */ "iSNS registration failed",
 	/* 27 */ "operation not supported",
+	/* 28 */ "device or resource in use",
 };
 
 char *iscsi_err_to_str(int err)
diff --git a/usr/iscsi_ipc.h b/usr/iscsi_ipc.h
index a00135f..08cf6f9 100644
--- a/usr/iscsi_ipc.h
+++ b/usr/iscsi_ipc.h
@@ -138,6 +138,13 @@ struct iscsi_ipc {
 	int (*exec_ping) (uint64_t transport_handle, uint32_t host_no,
 			  struct sockaddr *addr, uint32_t iface_num,
 			  uint32_t iface_type, uint32_t size);
+
+	int (*get_chap) (uint64_t transport_handle, uint32_t host_no,
+			 uint16_t chap_tbl_idx, uint32_t num_entries,
+			 char *chap_buf, uint32_t *valid_chap_entries);
+
+	int (*delete_chap) (uint64_t transport_handle, uint32_t host_no,
+			    uint16_t chap_tbl_idx);
 };
 
 #endif /* ISCSI_IPC_H */
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 7ff8728..85b6774 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -67,6 +67,7 @@ enum iscsiadm_mode {
 	MODE_IFACE,
 	MODE_FW,
 	MODE_PING,
+	MODE_CHAP
 };
 
 enum iscsiadm_op {
@@ -191,6 +192,8 @@ str_to_submode(char *str)
 
 	if (!strcmp("ping", str))
 		sub_mode = MODE_PING;
+	else if (!strcmp("chap", str))
+		sub_mode = MODE_CHAP;
 	else
 		sub_mode = -1;
 
@@ -1297,6 +1300,146 @@ free_buf:
 	return ISCSI_SUCCESS;
 }
 
+static int get_host_chap_info(uint32_t host_no)
+{
+	struct iscsi_transport *t = NULL;
+	struct iscsi_chap_rec *crec = NULL;
+	char *req_buf = NULL;
+	uint32_t valid_chap_entries;
+	uint32_t num_entries;
+	uint16_t chap_tbl_idx = 0;
+	int rc = 0;
+	int fd, i = 0;
+
+	t = iscsi_sysfs_get_transport_by_hba(host_no);
+	if (!t) {
+		log_error("Could not match hostno %d to "
+			  "transport.", host_no);
+		rc = ISCSI_ERR_TRANS_NOT_FOUND;
+		goto exit_chap_info;
+	}
+
+	num_entries = MAX_CHAP_BUF_SZ / sizeof(*crec);
+
+	req_buf = calloc(1, REQ_CHAP_BUF_SZ);
+	if (!req_buf) {
+		log_error("Could not allocate memory for CHAP request.");
+		rc = ISCSI_ERR_NOMEM;
+		goto exit_chap_info;
+	}
+
+	fd = ipc->ctldev_open();
+	if (fd < 0) {
+		rc = ISCSI_ERR_INTERNAL;
+		log_error("Netlink open failed.");
+		goto exit_chap_info;
+	}
+
+get_chap:
+	memset(req_buf, 0, REQ_CHAP_BUF_SZ);
+
+	rc = ipc->get_chap(t->handle, host_no, chap_tbl_idx, num_entries,
+			   req_buf, &valid_chap_entries);
+	if (rc < 0) {
+		log_error("get_chap_info failed. errno=%d", errno);
+		rc = ISCSI_ERR;
+		goto exit_chap_info;
+	}
+
+	log_info("Valid CHAP Entries = %d\n", valid_chap_entries);
+
+	crec = (struct iscsi_chap_rec *) (req_buf +
+					  sizeof(struct iscsi_uevent));
+
+	if (valid_chap_entries)
+		chap_tbl_idx =
+		(crec + (valid_chap_entries - 1))->chap_tbl_idx + 1;
+
+	/* print chap info */
+	for (i = 0; i < valid_chap_entries; i++) {
+		idbm_print_host_chap_info(crec);
+		crec++;
+	}
+
+	if (valid_chap_entries != num_entries)
+		goto exit_chap_info;
+	else
+		goto get_chap;
+
+	ipc->ctldev_close();
+
+exit_chap_info:
+	if (req_buf)
+		free(req_buf);
+
+	return rc;
+}
+
+static int delete_host_chap_info(uint32_t host_no, char *value)
+{
+	struct iscsi_transport *t = NULL;
+	int fd, rc = 0;
+	uint16_t chap_tbl_idx;
+
+	if (!value) {
+		log_error("CHAP deletion requires --value=table_index.");
+		return ISCSI_ERR_INVAL;
+	}
+
+	chap_tbl_idx = (uint16_t)atoi(value);
+
+	t = iscsi_sysfs_get_transport_by_hba(host_no);
+	if (!t) {
+		log_error("Could not match hostno %d to "
+			  "transport.", host_no);
+		rc = ISCSI_ERR_TRANS_NOT_FOUND;
+		goto exit_delete_chap;
+	}
+
+	fd = ipc->ctldev_open();
+	if (fd < 0) {
+		log_error("Netlink open failed.");
+		rc = ISCSI_ERR_INTERNAL;
+		goto exit_delete_chap;
+	}
+
+	log_info("Deleteing CHAP index: %d\n", chap_tbl_idx);
+	rc = ipc->delete_chap(t->handle, host_no, chap_tbl_idx);
+	if (rc < 0) {
+		log_error("CHAP Delete failed.");
+		if (rc == -EBUSY) {
+			rc = ISCSI_ERR_BUSY;
+			log_error("CHAP index %d is in use.", chap_tbl_idx);
+		} else
+			rc = ISCSI_ERR;
+	}
+
+	ipc->ctldev_close();
+
+exit_delete_chap:
+	return rc;
+}
+
+static int exec_host_chap_op(int op, int info_level, uint32_t host_no,
+			     char *value)
+{
+	int rc = ISCSI_ERR_INVAL;
+
+	switch (op) {
+	case OP_SHOW:
+		rc = get_host_chap_info(host_no);
+		break;
+	case OP_DELETE:
+		rc = delete_host_chap_info(host_no, value);
+		break;
+	default:
+		log_error("Invalid operation.");
+		break;
+	}
+
+	return rc;
+}
+
 /* TODO: merge iter helpers and clean them up, so we can use them here */
 static int exec_iface_op(int op, int do_show, int info_level,
 			 struct iface_rec *iface, uint32_t host_no,
@@ -2393,14 +2536,30 @@ main(int argc, char **argv)
 
 	switch (mode) {
 	case MODE_HOST:
-		if ((rc = verify_mode_params(argc, argv, "HdmP", 0))) {
+		if ((rc = verify_mode_params(argc, argv, "CHdmPov", 0))) {
 			log_error("host mode: option '-%c' is not "
 				  "allowed/supported", rc);
 			rc = ISCSI_ERR_INVAL;
 			goto out;
 		}
-
-		rc = host_info_print(info_level, host_no);
+		if (sub_mode != -1) {
+			switch (sub_mode) {
+			case MODE_CHAP:
+				if (!op || !host_no) {
+					log_error("CHAP mode requires host "
+						"no and valid operation");
+					rc = ISCSI_ERR_INVAL;
+					break;
+				}
+				rc = exec_host_chap_op(op, info_level, host_no,
+						       value);
+				break;
+			default:
+				log_error("Invalid Sub Mode");
+				break;
+			}
+		} else
+			rc = host_info_print(info_level, host_no);
 		break;
 	case MODE_IFACE:
 		iface_setup_host_bindings();
diff --git a/usr/netlink.c b/usr/netlink.c
index f680b31..2556f1f 100644
--- a/usr/netlink.c
+++ b/usr/netlink.c
@@ -336,6 +336,9 @@ __kipc_call(struct iovec *iovp, int count)
 		} else if (ev->type == ISCSI_UEVENT_GET_STATS) {
 			/* kget_stats() will read */
 			return 0;
+		} else if (ev->type == ISCSI_UEVENT_GET_CHAP) {
+			/* kget_chap() will read */
+			return 0;
 		} else {
 			if ((rc = nlpayload_read(ctrl_fd, (void*)ev,
 						 sizeof(*ev), 0)) < 0) {
@@ -1180,6 +1183,75 @@ close_nl:
 	return rc;
 }
 
+static int kget_chap(uint64_t transport_handle, uint32_t host_no,
+		     uint16_t chap_tbl_idx, uint32_t num_entries,
+		     char *chap_buf, uint32_t *valid_chap_entries)
+{
+	int rc = 0;
+	int ev_size;
+	struct iscsi_uevent ev;
+	struct iovec iov[2];
+	char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))];
+	struct nlmsghdr *nlh;
+
+	memset(&ev, 0, sizeof(struct iscsi_uevent));
+
+	ev.type = ISCSI_UEVENT_GET_CHAP;
+	ev.transport_handle = transport_handle;
+	ev.u.get_chap.host_no = host_no;
+	ev.u.get_chap.chap_tbl_idx = chap_tbl_idx;
+	ev.u.get_chap.num_entries = num_entries;
+
+	iov[1].iov_base = &ev;
+	iov[1].iov_len = sizeof(ev);
+	rc = __kipc_call(iov, 2);
+	if (rc < 0)
+		return rc;
+
+	if ((rc = nl_read(ctrl_fd, nlm_ev,
+			  NLMSG_SPACE(sizeof(struct iscsi_uevent)),
+			  MSG_PEEK)) < 0) {
+		log_error("can not read nlm_ev, error %d", rc);
+		return rc;
+	}
+
+	nlh = (struct nlmsghdr *)nlm_ev;
+	ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr));
+
+	if ((rc = nlpayload_read(ctrl_fd, (void *)chap_buf, ev_size, 0)) < 0) {
+		log_error("can not read from NL socket, error %d", rc);
+		return rc;
+	}
+
+	*valid_chap_entries = ev.u.get_chap.num_entries;
+
+	return rc;
+}
+
+static int kdelete_chap(uint64_t transport_handle, uint32_t host_no,
+			uint16_t chap_tbl_idx)
+{
+	int rc = 0;
+	struct iscsi_uevent ev;
+	struct iovec iov[2];
+
+	memset(&ev, 0, sizeof(struct iscsi_uevent));
+
+	ev.type = ISCSI_UEVENT_DELETE_CHAP;
+	ev.transport_handle = transport_handle;
+	ev.u.delete_chap.host_no = host_no;
+	ev.u.delete_chap.chap_tbl_idx = chap_tbl_idx;
+
+	iov[1].iov_base = &ev;
+	iov[1].iov_len = sizeof(ev);
+
+	rc = __kipc_call(iov, 2);
+	if (rc < 0)
+		return rc;
+
+	return rc;
+}
+
 static void drop_data(struct nlmsghdr *nlh)
 {
 	int ev_size;
@@ -1216,11 +1288,17 @@ static int ctldev_handle(void)
 	/* old kernels sent ISCSI_UEVENT_CREATE_SESSION on creation */
 	case ISCSI_UEVENT_CREATE_SESSION:
 		drop_data(nlh);
+		if (!ipc_ev_clbk)
+			return 0;
+
 		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:
+		if (!ipc_ev_clbk)
+			return 0;
+
 		drop_data(nlh);
 		if (ipc_ev_clbk->destroy_session)
 			ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
@@ -1464,6 +1542,8 @@ struct iscsi_ipc nl_ipc = {
 	.set_net_config         = kset_net_config,
 	.recv_conn_state        = krecv_conn_state,
 	.exec_ping		= kexec_ping,
+	.get_chap		= kget_chap,
+	.delete_chap		= kdelete_chap,
 };
 struct iscsi_ipc *ipc = &nl_ipc;
 

-- 
Debian Open-iSCSI Packaging



More information about the Pkg-iscsi-maintainers mailing list