diff options
| -rw-r--r-- | net/ipv6/datagram.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 16560336eb72..9ef1831746ef 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -33,6 +33,11 @@ | |||
| 33 | #include <linux/errqueue.h> | 33 | #include <linux/errqueue.h> |
| 34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| 35 | 35 | ||
| 36 | static inline int ipv6_mapped_addr_any(const struct in6_addr *a) | ||
| 37 | { | ||
| 38 | return (ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0)); | ||
| 39 | } | ||
| 40 | |||
| 36 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 41 | int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
| 37 | { | 42 | { |
| 38 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; | 43 | struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr; |
| @@ -102,10 +107,12 @@ ipv4_connected: | |||
| 102 | 107 | ||
| 103 | ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr); | 108 | ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr); |
| 104 | 109 | ||
| 105 | if (ipv6_addr_any(&np->saddr)) | 110 | if (ipv6_addr_any(&np->saddr) || |
| 111 | ipv6_mapped_addr_any(&np->saddr)) | ||
| 106 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); | 112 | ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); |
| 107 | 113 | ||
| 108 | if (ipv6_addr_any(&np->rcv_saddr)) { | 114 | if (ipv6_addr_any(&np->rcv_saddr) || |
| 115 | ipv6_mapped_addr_any(&np->rcv_saddr)) { | ||
| 109 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, | 116 | ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, |
| 110 | &np->rcv_saddr); | 117 | &np->rcv_saddr); |
| 111 | if (sk->sk_prot->rehash) | 118 | if (sk->sk_prot->rehash) |
