aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-01-17 02:33:48 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2012-01-18 03:35:58 -0500
commit2f9bc894c67dbacae5a6a9875818d2a18a918d18 (patch)
tree2891680fbe0b57299776d44123969452a9cb1a25 /drivers/target
parent4949314c7283ea4f9ade182ca599583b89f7edd6 (diff)
iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT
This patch addresses a bug with sendtargets discovery where INADDR_ANY (0.0.0.0) + IN6ADDR_ANY_INIT ([0:0:0:0:0:0:0:0]) network portals where incorrectly being reported back to initiators instead of the address of the connecting interface. To address this, save local socket ->getname() output during iscsi login setup, and makes iscsit_build_sendtargets_response() return these TargetAddress keys when INADDR_ANY or IN6ADDR_ANY_INIT portals are in use. Reported-by: Dax Kelson <dkelson@gurulabs.com> Reported-by: Andy Grover <agrover@redhat.com> Cc: David S. Miller <davem@davemloft.net> Cc: <stable@vger.kernel.org> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target.c37
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h2
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c31
3 files changed, 62 insertions, 8 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 6e070e0a8393..44262908def5 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
3164 return 0; 3164 return 0;
3165} 3165}
3166 3166
3167static bool iscsit_check_inaddr_any(struct iscsi_np *np)
3168{
3169 bool ret = false;
3170
3171 if (np->np_sockaddr.ss_family == AF_INET6) {
3172 const struct sockaddr_in6 sin6 = {
3173 .sin6_addr = IN6ADDR_ANY_INIT };
3174 struct sockaddr_in6 *sock_in6 =
3175 (struct sockaddr_in6 *)&np->np_sockaddr;
3176
3177 if (!memcmp(sock_in6->sin6_addr.s6_addr,
3178 sin6.sin6_addr.s6_addr, 16))
3179 ret = true;
3180 } else {
3181 struct sockaddr_in * sock_in =
3182 (struct sockaddr_in *)&np->np_sockaddr;
3183
3184 if (sock_in->sin_addr.s_addr == INADDR_ANY)
3185 ret = true;
3186 }
3187
3188 return ret;
3189}
3190
3167static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) 3191static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
3168{ 3192{
3169 char *payload = NULL; 3193 char *payload = NULL;
@@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
3213 spin_lock(&tpg->tpg_np_lock); 3237 spin_lock(&tpg->tpg_np_lock);
3214 list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, 3238 list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
3215 tpg_np_list) { 3239 tpg_np_list) {
3240 struct iscsi_np *np = tpg_np->tpg_np;
3241 bool inaddr_any = iscsit_check_inaddr_any(np);
3242
3216 len = sprintf(buf, "TargetAddress=" 3243 len = sprintf(buf, "TargetAddress="
3217 "%s%s%s:%hu,%hu", 3244 "%s%s%s:%hu,%hu",
3218 (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? 3245 (np->np_sockaddr.ss_family == AF_INET6) ?
3219 "[" : "", tpg_np->tpg_np->np_ip, 3246 "[" : "", (inaddr_any == false) ?
3220 (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? 3247 np->np_ip : conn->local_ip,
3221 "]" : "", tpg_np->tpg_np->np_port, 3248 (np->np_sockaddr.ss_family == AF_INET6) ?
3249 "]" : "", (inaddr_any == false) ?
3250 np->np_port : conn->local_port,
3222 tpg->tpgt); 3251 tpg->tpgt);
3223 len += 1; 3252 len += 1;
3224 3253
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index ebf81fdbb5c5..0ec3b77a0c27 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -508,6 +508,7 @@ struct iscsi_conn {
508 u16 cid; 508 u16 cid;
509 /* Remote TCP Port */ 509 /* Remote TCP Port */
510 u16 login_port; 510 u16 login_port;
511 u16 local_port;
511 int net_size; 512 int net_size;
512 u32 auth_id; 513 u32 auth_id;
513#define CONNFLAG_SCTP_STRUCT_FILE 0x01 514#define CONNFLAG_SCTP_STRUCT_FILE 0x01
@@ -527,6 +528,7 @@ struct iscsi_conn {
527 unsigned char bad_hdr[ISCSI_HDR_LEN]; 528 unsigned char bad_hdr[ISCSI_HDR_LEN];
528#define IPV6_ADDRESS_SPACE 48 529#define IPV6_ADDRESS_SPACE 48
529 unsigned char login_ip[IPV6_ADDRESS_SPACE]; 530 unsigned char login_ip[IPV6_ADDRESS_SPACE];
531 unsigned char local_ip[IPV6_ADDRESS_SPACE];
530 int conn_usage_count; 532 int conn_usage_count;
531 int conn_waiting_on_uc; 533 int conn_waiting_on_uc;
532 atomic_t check_immediate_queue; 534 atomic_t check_immediate_queue;
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 373b0cc6abd8..ec47a7c5966e 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -615,8 +615,8 @@ static int iscsi_post_login_handler(
615 } 615 }
616 616
617 pr_debug("iSCSI Login successful on CID: %hu from %s to" 617 pr_debug("iSCSI Login successful on CID: %hu from %s to"
618 " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip, 618 " %s:%hu,%hu\n", conn->cid, conn->login_ip,
619 np->np_port, tpg->tpgt); 619 conn->local_ip, conn->local_port, tpg->tpgt);
620 620
621 list_add_tail(&conn->conn_list, &sess->sess_conn_list); 621 list_add_tail(&conn->conn_list, &sess->sess_conn_list);
622 atomic_inc(&sess->nconn); 622 atomic_inc(&sess->nconn);
@@ -658,7 +658,8 @@ static int iscsi_post_login_handler(
658 sess->session_state = TARG_SESS_STATE_LOGGED_IN; 658 sess->session_state = TARG_SESS_STATE_LOGGED_IN;
659 659
660 pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n", 660 pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
661 conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt); 661 conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
662 tpg->tpgt);
662 663
663 spin_lock_bh(&sess->conn_lock); 664 spin_lock_bh(&sess->conn_lock);
664 list_add_tail(&conn->conn_list, &sess->sess_conn_list); 665 list_add_tail(&conn->conn_list, &sess->sess_conn_list);
@@ -1020,6 +1021,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1020 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", 1021 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
1021 &sock_in6.sin6_addr.in6_u); 1022 &sock_in6.sin6_addr.in6_u);
1022 conn->login_port = ntohs(sock_in6.sin6_port); 1023 conn->login_port = ntohs(sock_in6.sin6_port);
1024
1025 if (conn->sock->ops->getname(conn->sock,
1026 (struct sockaddr *)&sock_in6, &err, 0) < 0) {
1027 pr_err("sock_ops->getname() failed.\n");
1028 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
1029 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1030 goto new_sess_out;
1031 }
1032 snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
1033 &sock_in6.sin6_addr.in6_u);
1034 conn->local_port = ntohs(sock_in6.sin6_port);
1035
1023 } else { 1036 } else {
1024 memset(&sock_in, 0, sizeof(struct sockaddr_in)); 1037 memset(&sock_in, 0, sizeof(struct sockaddr_in));
1025 1038
@@ -1032,6 +1045,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1032 } 1045 }
1033 sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr); 1046 sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
1034 conn->login_port = ntohs(sock_in.sin_port); 1047 conn->login_port = ntohs(sock_in.sin_port);
1048
1049 if (conn->sock->ops->getname(conn->sock,
1050 (struct sockaddr *)&sock_in, &err, 0) < 0) {
1051 pr_err("sock_ops->getname() failed.\n");
1052 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
1053 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1054 goto new_sess_out;
1055 }
1056 sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
1057 conn->local_port = ntohs(sock_in.sin_port);
1035 } 1058 }
1036 1059
1037 conn->network_transport = np->np_network_transport; 1060 conn->network_transport = np->np_network_transport;
@@ -1039,7 +1062,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1039 pr_debug("Received iSCSI login request from %s on %s Network" 1062 pr_debug("Received iSCSI login request from %s on %s Network"
1040 " Portal %s:%hu\n", conn->login_ip, 1063 " Portal %s:%hu\n", conn->login_ip,
1041 (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", 1064 (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
1042 np->np_ip, np->np_port); 1065 conn->local_ip, conn->local_port);
1043 1066
1044 pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); 1067 pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
1045 conn->conn_state = TARG_CONN_STATE_IN_LOGIN; 1068 conn->conn_state = TARG_CONN_STATE_IN_LOGIN;