aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/iscsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r--drivers/target/iscsi/iscsi_target.c39
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_core.h6
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c4
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c39
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c11
6 files changed, 87 insertions, 13 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index ac44af165b27..44262908def5 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1061,7 +1061,7 @@ attach_cmd:
1061 if (ret < 0) 1061 if (ret < 0)
1062 return iscsit_add_reject_from_cmd( 1062 return iscsit_add_reject_from_cmd(
1063 ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1063 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1064 1, 1, buf, cmd); 1064 1, 0, buf, cmd);
1065 /* 1065 /*
1066 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if 1066 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1067 * the Immediate Bit is not set, and no Immediate 1067 * the Immediate Bit is not set, and no Immediate
@@ -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_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 3468caab47a2..6b35b37988ed 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/configfs.h> 22#include <linux/configfs.h>
23#include <linux/export.h> 23#include <linux/export.h>
24#include <linux/inet.h>
24#include <target/target_core_base.h> 25#include <target/target_core_base.h>
25#include <target/target_core_fabric.h> 26#include <target/target_core_fabric.h>
26#include <target/target_core_fabric_configfs.h> 27#include <target/target_core_fabric_configfs.h>
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index f1a02dad05a0..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;
@@ -561,8 +563,8 @@ struct iscsi_conn {
561 struct hash_desc conn_tx_hash; 563 struct hash_desc conn_tx_hash;
562 /* Used for scheduling TX and RX connection kthreads */ 564 /* Used for scheduling TX and RX connection kthreads */
563 cpumask_var_t conn_cpumask; 565 cpumask_var_t conn_cpumask;
564 int conn_rx_reset_cpumask:1; 566 unsigned int conn_rx_reset_cpumask:1;
565 int conn_tx_reset_cpumask:1; 567 unsigned int conn_tx_reset_cpumask:1;
566 /* list_head of struct iscsi_cmd for this connection */ 568 /* list_head of struct iscsi_cmd for this connection */
567 struct list_head conn_cmd_list; 569 struct list_head conn_cmd_list;
568 struct list_head immed_queue_list; 570 struct list_head immed_queue_list;
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 255c0d67e898..27901e37c125 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
1238{ 1238{
1239 struct iscsi_conn *conn = cmd->conn; 1239 struct iscsi_conn *conn = cmd->conn;
1240 struct iscsi_session *sess = conn->sess; 1240 struct iscsi_session *sess = conn->sess;
1241 struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); 1241 struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
1242 1242
1243 spin_lock_bh(&cmd->dataout_timeout_lock); 1243 spin_lock_bh(&cmd->dataout_timeout_lock);
1244 if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) { 1244 if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
@@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
1261 struct iscsi_conn *conn) 1261 struct iscsi_conn *conn)
1262{ 1262{
1263 struct iscsi_session *sess = conn->sess; 1263 struct iscsi_session *sess = conn->sess;
1264 struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); 1264 struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
1265 1265
1266 if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING) 1266 if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
1267 return; 1267 return;
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 373b0cc6abd8..38cb7ce8469e 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);
@@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(
841 goto fail; 842 goto fail;
842 } 843 }
843 844
845 ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
846 (char *)&opt, sizeof(opt));
847 if (ret < 0) {
848 pr_err("kernel_setsockopt() for IP_FREEBIND"
849 " failed\n");
850 goto fail;
851 }
852
844 ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len); 853 ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
845 if (ret < 0) { 854 if (ret < 0) {
846 pr_err("kernel_bind() failed: %d\n", ret); 855 pr_err("kernel_bind() failed: %d\n", ret);
@@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1020 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", 1029 snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
1021 &sock_in6.sin6_addr.in6_u); 1030 &sock_in6.sin6_addr.in6_u);
1022 conn->login_port = ntohs(sock_in6.sin6_port); 1031 conn->login_port = ntohs(sock_in6.sin6_port);
1032
1033 if (conn->sock->ops->getname(conn->sock,
1034 (struct sockaddr *)&sock_in6, &err, 0) < 0) {
1035 pr_err("sock_ops->getname() failed.\n");
1036 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
1037 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1038 goto new_sess_out;
1039 }
1040 snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
1041 &sock_in6.sin6_addr.in6_u);
1042 conn->local_port = ntohs(sock_in6.sin6_port);
1043
1023 } else { 1044 } else {
1024 memset(&sock_in, 0, sizeof(struct sockaddr_in)); 1045 memset(&sock_in, 0, sizeof(struct sockaddr_in));
1025 1046
@@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1032 } 1053 }
1033 sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr); 1054 sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
1034 conn->login_port = ntohs(sock_in.sin_port); 1055 conn->login_port = ntohs(sock_in.sin_port);
1056
1057 if (conn->sock->ops->getname(conn->sock,
1058 (struct sockaddr *)&sock_in, &err, 0) < 0) {
1059 pr_err("sock_ops->getname() failed.\n");
1060 iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
1061 ISCSI_LOGIN_STATUS_TARGET_ERROR);
1062 goto new_sess_out;
1063 }
1064 sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
1065 conn->local_port = ntohs(sock_in.sin_port);
1035 } 1066 }
1036 1067
1037 conn->network_transport = np->np_network_transport; 1068 conn->network_transport = np->np_network_transport;
@@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
1039 pr_debug("Received iSCSI login request from %s on %s Network" 1070 pr_debug("Received iSCSI login request from %s on %s Network"
1040 " Portal %s:%hu\n", conn->login_ip, 1071 " Portal %s:%hu\n", conn->login_ip,
1041 (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", 1072 (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
1042 np->np_ip, np->np_port); 1073 conn->local_ip, conn->local_port);
1043 1074
1044 pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); 1075 pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
1045 conn->conn_state = TARG_CONN_STATE_IN_LOGIN; 1076 conn->conn_state = TARG_CONN_STATE_IN_LOGIN;
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index a05ca1c4f01c..11287e1ece13 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
849 case ISCSI_OP_SCSI_TMFUNC: 849 case ISCSI_OP_SCSI_TMFUNC:
850 transport_generic_free_cmd(&cmd->se_cmd, 1); 850 transport_generic_free_cmd(&cmd->se_cmd, 1);
851 break; 851 break;
852 case ISCSI_OP_REJECT:
853 /*
854 * Handle special case for REJECT when iscsi_add_reject*() has
855 * overwritten the original iscsi_opcode assignment, and the
856 * associated cmd->se_cmd needs to be released.
857 */
858 if (cmd->se_cmd.se_tfo != NULL) {
859 transport_generic_free_cmd(&cmd->se_cmd, 1);
860 break;
861 }
862 /* Fall-through */
852 default: 863 default:
853 iscsit_release_cmd(cmd); 864 iscsit_release_cmd(cmd);
854 break; 865 break;