diff options
Diffstat (limited to 'drivers/target/iscsi')
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 39 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_configfs.c | 1 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 6 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_erl1.c | 4 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 39 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 11 |
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 | ||
| 3167 | static 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 | |||
| 3167 | static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) | 3191 | static 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; |
