Commit a7cf239b authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by Kelsey Skunberg

sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket

BugLink: https://bugs.launchpad.net/bugs/1885932

[ Upstream commit 471e39df ]

If a socket is set ipv6only, it will still send IPv4 addresses in the
INIT and INIT_ACK packets. This potentially misleads the peer into using
them, which then would cause association termination.

The fix is to not add IPv4 addresses to ipv6only sockets.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Reported-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Tested-by: default avatarCorey Minyard <cminyard@mvista.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
Signed-off-by: default avatarKelsey Skunberg <kelsey.skunberg@canonical.com>
parent f76b26eb
......@@ -357,11 +357,13 @@ typedef enum {
ipv4_is_anycast_6to4(a))
/* Flags used for the bind address copy functions. */
#define SCTP_ADDR6_ALLOWED 0x00000001 /* IPv6 address is allowed by
#define SCTP_ADDR4_ALLOWED 0x00000001 /* IPv4 address is allowed by
local sock family */
#define SCTP_ADDR4_PEERSUPP 0x00000002 /* IPv4 address is supported by
#define SCTP_ADDR6_ALLOWED 0x00000002 /* IPv6 address is allowed by
local sock family */
#define SCTP_ADDR4_PEERSUPP 0x00000004 /* IPv4 address is supported by
peer */
#define SCTP_ADDR6_PEERSUPP 0x00000004 /* IPv6 address is supported by
#define SCTP_ADDR6_PEERSUPP 0x00000008 /* IPv6 address is supported by
peer */
/* Reasons to retransmit. */
......
......@@ -1574,12 +1574,15 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len)
int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
sctp_scope_t scope, gfp_t gfp)
{
struct sock *sk = asoc->base.sk;
int flags;
/* Use scoping rules to determine the subset of addresses from
* the endpoint.
*/
flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
flags = (PF_INET6 == sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
if (!inet_v6_ipv6only(sk))
flags |= SCTP_ADDR4_ALLOWED;
if (asoc->peer.ipv4_address)
flags |= SCTP_ADDR4_PEERSUPP;
if (asoc->peer.ipv6_address)
......
......@@ -449,6 +449,7 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
* well as the remote peer.
*/
if ((((AF_INET == addr->sa.sa_family) &&
(flags & SCTP_ADDR4_ALLOWED) &&
(flags & SCTP_ADDR4_PEERSUPP))) ||
(((AF_INET6 == addr->sa.sa_family) &&
(flags & SCTP_ADDR6_ALLOWED) &&
......
......@@ -210,6 +210,7 @@ int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp,
* sock as well as the remote peer.
*/
if ((((AF_INET == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR4_ALLOWED) &&
(copy_flags & SCTP_ADDR4_PEERSUPP))) ||
(((AF_INET6 == addr->a.sa.sa_family) &&
(copy_flags & SCTP_ADDR6_ALLOWED) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment