mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
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>
This commit is contained in:
parent
de04a8aa6b
commit
dfecf611a1
3 changed files with 16 additions and 16 deletions
|
@ -3444,12 +3444,10 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||||
bool inaddr_any = iscsit_check_inaddr_any(np);
|
bool inaddr_any = iscsit_check_inaddr_any(np);
|
||||||
|
|
||||||
len = sprintf(buf, "TargetAddress="
|
len = sprintf(buf, "TargetAddress="
|
||||||
"%s%s%s:%hu,%hu",
|
"%s:%hu,%hu",
|
||||||
(np->np_sockaddr.ss_family == AF_INET6) ?
|
(inaddr_any == false) ?
|
||||||
"[" : "", (inaddr_any == false) ?
|
|
||||||
np->np_ip : conn->local_ip,
|
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,
|
np->np_port : conn->local_port,
|
||||||
tpg->tpgt);
|
tpg->tpgt);
|
||||||
len += 1;
|
len += 1;
|
||||||
|
|
|
@ -1007,16 +1007,24 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
|
||||||
rc = conn->sock->ops->getname(conn->sock,
|
rc = conn->sock->ops->getname(conn->sock,
|
||||||
(struct sockaddr *)&sock_in6, &err, 1);
|
(struct sockaddr *)&sock_in6, &err, 1);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
|
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
|
||||||
&sock_in6.sin6_addr.in6_u);
|
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);
|
conn->login_port = ntohs(sock_in6.sin6_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = conn->sock->ops->getname(conn->sock,
|
rc = conn->sock->ops->getname(conn->sock,
|
||||||
(struct sockaddr *)&sock_in6, &err, 0);
|
(struct sockaddr *)&sock_in6, &err, 0);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
|
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
|
||||||
&sock_in6.sin6_addr.in6_u);
|
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);
|
conn->local_port = ntohs(sock_in6.sin6_port);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -432,13 +432,7 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock(&lstat->lock);
|
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);
|
||||||
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);
|
|
||||||
}
|
|
||||||
spin_unlock(&lstat->lock);
|
spin_unlock(&lstat->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue