diff options
author | Chris Leech <cleech@redhat.com> | 2013-08-12 14:26:28 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-08-12 23:31:53 -0400 |
commit | dfecf611a1bb46dfe19fc5329a23ef12c1f0591d (patch) | |
tree | cbde70d4bbba8b1f259e9e5643d9c312440b65d0 /drivers/target | |
parent | de04a8aa6b292b9c7e559794cb50e4296b193002 (diff) |
iscsi-target: ST response on IN6ADDR_ANY socket
Odd little issue, found that if you create an IPv6 portal bound to the
IN6ADDR_ANY wildcard address it will accept IPv4 connections (as long as
bindv6only isn't set globally) but respond to SendTargets requests with
an IPv4-mapped IPv6 address.
Example over loopback:
In targetcli create a wildcard IPv6 portal
/iscsi/iqn.../portals/> create ::
Which should create a portal [::]:3260
Initiate SendTargets discovery to the portal using an IPv4 address
# iscsiadm -m discovery -t st -p 127.0.0.1
The response formats TargetAddress as [::ffff:127.0.0.1]:3260,1
This still works and uses v4 on the network between two v6 sockets, but
only if the initiator supports IPv6 with v4-mapped addresses.
This change detects v4-mapped address on v6 sockets for the wildcard
case, and instead formats the TargetAddress response as an IPv4 address.
In order to not further complicate iscsit_build_sendtargets_response,
I've actually simplified it by moving the bracket wrapping of IPv6
address into iscsit_accept_np where local_ip and login_ip strings are
set. That also simplifies iscsi_stat_tgt_attr_show_attr_fail_intr_addr.
Side effect of the string format change is that
lio_target_nacl_show_info will now print login_ip bracket wrapped for
IPv6 connections, as will a few debug prints.
Signed-off-by: Chris Leech <cleech@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 8 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 16 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_stat.c | 8 |
3 files changed, 16 insertions, 16 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f73da43cdf9e..c4aeac314b2e 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -3444,12 +3444,10 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) | |||
3444 | bool inaddr_any = iscsit_check_inaddr_any(np); | 3444 | bool inaddr_any = iscsit_check_inaddr_any(np); |
3445 | 3445 | ||
3446 | len = sprintf(buf, "TargetAddress=" | 3446 | len = sprintf(buf, "TargetAddress=" |
3447 | "%s%s%s:%hu,%hu", | 3447 | "%s:%hu,%hu", |
3448 | (np->np_sockaddr.ss_family == AF_INET6) ? | 3448 | (inaddr_any == false) ? |
3449 | "[" : "", (inaddr_any == false) ? | ||
3450 | np->np_ip : conn->local_ip, | 3449 | np->np_ip : conn->local_ip, |
3451 | (np->np_sockaddr.ss_family == AF_INET6) ? | 3450 | (inaddr_any == false) ? |
3452 | "]" : "", (inaddr_any == false) ? | ||
3453 | np->np_port : conn->local_port, | 3451 | np->np_port : conn->local_port, |
3454 | tpg->tpgt); | 3452 | tpg->tpgt); |
3455 | len += 1; | 3453 | len += 1; |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 76cf1cd62e29..0e85238bdf48 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
@@ -1007,16 +1007,24 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) | |||
1007 | rc = conn->sock->ops->getname(conn->sock, | 1007 | rc = conn->sock->ops->getname(conn->sock, |
1008 | (struct sockaddr *)&sock_in6, &err, 1); | 1008 | (struct sockaddr *)&sock_in6, &err, 1); |
1009 | if (!rc) { | 1009 | if (!rc) { |
1010 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", | 1010 | if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr)) |
1011 | &sock_in6.sin6_addr.in6_u); | 1011 | snprintf(conn->login_ip, sizeof(conn->login_ip), "[%pI6c]", |
1012 | &sock_in6.sin6_addr.in6_u); | ||
1013 | else | ||
1014 | snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI4", | ||
1015 | &sock_in6.sin6_addr.s6_addr32[3]); | ||
1012 | conn->login_port = ntohs(sock_in6.sin6_port); | 1016 | conn->login_port = ntohs(sock_in6.sin6_port); |
1013 | } | 1017 | } |
1014 | 1018 | ||
1015 | rc = conn->sock->ops->getname(conn->sock, | 1019 | rc = conn->sock->ops->getname(conn->sock, |
1016 | (struct sockaddr *)&sock_in6, &err, 0); | 1020 | (struct sockaddr *)&sock_in6, &err, 0); |
1017 | if (!rc) { | 1021 | if (!rc) { |
1018 | snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", | 1022 | if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr)) |
1019 | &sock_in6.sin6_addr.in6_u); | 1023 | snprintf(conn->local_ip, sizeof(conn->local_ip), "[%pI6c]", |
1024 | &sock_in6.sin6_addr.in6_u); | ||
1025 | else | ||
1026 | snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI4", | ||
1027 | &sock_in6.sin6_addr.s6_addr32[3]); | ||
1020 | conn->local_port = ntohs(sock_in6.sin6_port); | 1028 | conn->local_port = ntohs(sock_in6.sin6_port); |
1021 | } | 1029 | } |
1022 | } else { | 1030 | } else { |
diff --git a/drivers/target/iscsi/iscsi_target_stat.c b/drivers/target/iscsi/iscsi_target_stat.c index 464b4206a51e..899bdb423ff3 100644 --- a/drivers/target/iscsi/iscsi_target_stat.c +++ b/drivers/target/iscsi/iscsi_target_stat.c | |||
@@ -432,13 +432,7 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr( | |||
432 | int ret; | 432 | int ret; |
433 | 433 | ||
434 | spin_lock(&lstat->lock); | 434 | spin_lock(&lstat->lock); |
435 | if (lstat->last_intr_fail_ip_family == AF_INET6) { | 435 | ret = snprintf(page, PAGE_SIZE, "%s\n", lstat->last_intr_fail_ip_addr); |
436 | ret = snprintf(page, PAGE_SIZE, "[%s]\n", | ||
437 | lstat->last_intr_fail_ip_addr); | ||
438 | } else { | ||
439 | ret = snprintf(page, PAGE_SIZE, "%s\n", | ||
440 | lstat->last_intr_fail_ip_addr); | ||
441 | } | ||
442 | spin_unlock(&lstat->lock); | 436 | spin_unlock(&lstat->lock); |
443 | 437 | ||
444 | return ret; | 438 | return ret; |