]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
iscsi-target: ST response on IN6ADDR_ANY socket
authorChris Leech <cleech@redhat.com>
Mon, 12 Aug 2013 18:26:28 +0000 (11:26 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Tue, 13 Aug 2013 03:31:53 +0000 (20:31 -0700)
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>
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_stat.c

index f73da43cdf9e9cfc625e6c8a1a0eaecbc183aedd..c4aeac314b2e894d390554a15ab8b3a280d2247f 100644 (file)
@@ -3444,12 +3444,10 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
                                bool inaddr_any = iscsit_check_inaddr_any(np);
 
                                len = sprintf(buf, "TargetAddress="
-                                       "%s%s%s:%hu,%hu",
-                                       (np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "[" : "", (inaddr_any == false) ?
+                                       "%s:%hu,%hu",
+                                       (inaddr_any == false) ?
                                                np->np_ip : conn->local_ip,
-                                       (np->np_sockaddr.ss_family == AF_INET6) ?
-                                       "]" : "", (inaddr_any == false) ?
+                                       (inaddr_any == false) ?
                                                np->np_port : conn->local_port,
                                        tpg->tpgt);
                                len += 1;
index 76cf1cd62e292b7034b4d6cf43d0134ba59c5bcc..0e85238bdf4829eb51d83375cbbfd4dcbcad882d 100644 (file)
@@ -1007,16 +1007,24 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
                rc = conn->sock->ops->getname(conn->sock,
                                (struct sockaddr *)&sock_in6, &err, 1);
                if (!rc) {
-                       snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
-                               &sock_in6.sin6_addr.in6_u);
+                       if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
+                               snprintf(conn->login_ip, sizeof(conn->login_ip), "[%pI6c]",
+                                       &sock_in6.sin6_addr.in6_u);
+                       else
+                               snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI4",
+                                       &sock_in6.sin6_addr.s6_addr32[3]);
                        conn->login_port = ntohs(sock_in6.sin6_port);
                }
 
                rc = conn->sock->ops->getname(conn->sock,
                                (struct sockaddr *)&sock_in6, &err, 0);
                if (!rc) {
-                       snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
-                               &sock_in6.sin6_addr.in6_u);
+                       if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
+                               snprintf(conn->local_ip, sizeof(conn->local_ip), "[%pI6c]",
+                                       &sock_in6.sin6_addr.in6_u);
+                       else
+                               snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI4",
+                                       &sock_in6.sin6_addr.s6_addr32[3]);
                        conn->local_port = ntohs(sock_in6.sin6_port);
                }
        } else {
index 464b4206a51ef0eb06b1c5b4a33f1fcde58aeeed..899bdb423ff3c60c6f63cc68b4fb1488310f3109 100644 (file)
@@ -432,13 +432,7 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
        int ret;
 
        spin_lock(&lstat->lock);
-       if (lstat->last_intr_fail_ip_family == AF_INET6) {
-               ret = snprintf(page, PAGE_SIZE, "[%s]\n",
-                              lstat->last_intr_fail_ip_addr);
-       } else {
-               ret = snprintf(page, PAGE_SIZE, "%s\n",
-                              lstat->last_intr_fail_ip_addr);
-       }
+       ret = snprintf(page, PAGE_SIZE, "%s\n", lstat->last_intr_fail_ip_addr);
        spin_unlock(&lstat->lock);
 
        return ret;