Commit 52cae8f0 authored by Vlad Yasevich's avatar Vlad Yasevich

sctp: try harder to figure out address family when checking wildcards

sctp_is_any() function that is used to check for wildcard addresses
only looks at the address itself to determine the address family.
This function is used in the API to check the address passed in from
the user.  If the user simply zerroes out the sockaddr_storage and
pass that in, we'll end up failing.  So, let's try harder to determine
the address family by also checking the socket if it's possible.
Signed-off-by: default avatarVlad Yasevich <vladislav.yasevich@hp.com>
parent c226ef9b
...@@ -1228,7 +1228,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len, ...@@ -1228,7 +1228,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
sctp_scope_t sctp_scope(const union sctp_addr *); sctp_scope_t sctp_scope(const union sctp_addr *);
int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope); int sctp_in_scope(const union sctp_addr *addr, const sctp_scope_t scope);
int sctp_is_any(const union sctp_addr *addr); int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
int sctp_addr_is_valid(const union sctp_addr *addr); int sctp_addr_is_valid(const union sctp_addr *addr);
......
...@@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, ...@@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
{ {
int error = 0; int error = 0;
if (sctp_is_any(addr)) { if (sctp_is_any(NULL, addr)) {
error = sctp_copy_local_addr_list(dest, scope, gfp, flags); error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
} else if (sctp_in_scope(addr, scope)) { } else if (sctp_in_scope(addr, scope)) {
/* Now that the address is in scope, check to see if /* Now that the address is in scope, check to see if
...@@ -477,11 +477,21 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, ...@@ -477,11 +477,21 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
} }
/* Is this a wildcard address? */ /* Is this a wildcard address? */
int sctp_is_any(const union sctp_addr *addr) int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
{ {
struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family); unsigned short fam = 0;
struct sctp_af *af;
/* Try to get the right address family */
if (addr->sa.sa_family != AF_UNSPEC)
fam = addr->sa.sa_family;
else if (sk)
fam = sk->sk_family;
af = sctp_get_af_specific(fam);
if (!af) if (!af)
return 0; return 0;
return af->is_any(addr); return af->is_any(addr);
} }
......
...@@ -837,6 +837,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, ...@@ -837,6 +837,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
struct sctp_sock *opt) struct sctp_sock *opt)
{ {
struct sctp_af *af1, *af2; struct sctp_af *af1, *af2;
struct sock *sk = sctp_opt2sk(opt);
af1 = sctp_get_af_specific(addr1->sa.sa_family); af1 = sctp_get_af_specific(addr1->sa.sa_family);
af2 = sctp_get_af_specific(addr2->sa.sa_family); af2 = sctp_get_af_specific(addr2->sa.sa_family);
...@@ -845,11 +846,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, ...@@ -845,11 +846,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
return 0; return 0;
/* If the socket is IPv6 only, v4 addrs will not match */ /* If the socket is IPv6 only, v4 addrs will not match */
if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) if (__ipv6_only_sock(sk) && af1 != af2)
return 0; return 0;
/* Today, wildcard AF_INET/AF_INET6. */ /* Today, wildcard AF_INET/AF_INET6. */
if (sctp_is_any(addr1) || sctp_is_any(addr2)) if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
return 1; return 1;
if (addr1->sa.sa_family != addr2->sa.sa_family) if (addr1->sa.sa_family != addr2->sa.sa_family)
......
...@@ -2309,7 +2309,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, ...@@ -2309,7 +2309,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
/* If an address other than INADDR_ANY is specified, and /* If an address other than INADDR_ANY is specified, and
* no transport is found, then the request is invalid. * no transport is found, then the request is invalid.
*/ */
if (!sctp_is_any(( union sctp_addr *)&params.spp_address)) { if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
trans = sctp_addr_id2transport(sk, &params.spp_address, trans = sctp_addr_id2transport(sk, &params.spp_address,
params.spp_assoc_id); params.spp_assoc_id);
if (!trans) if (!trans)
...@@ -4062,7 +4062,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, ...@@ -4062,7 +4062,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
/* If an address other than INADDR_ANY is specified, and /* If an address other than INADDR_ANY is specified, and
* no transport is found, then the request is invalid. * no transport is found, then the request is invalid.
*/ */
if (!sctp_is_any(( union sctp_addr *)&params.spp_address)) { if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
trans = sctp_addr_id2transport(sk, &params.spp_address, trans = sctp_addr_id2transport(sk, &params.spp_address,
params.spp_assoc_id); params.spp_assoc_id);
if (!trans) { if (!trans) {
...@@ -4414,7 +4414,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, ...@@ -4414,7 +4414,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
if (sctp_list_single_entry(&bp->address_list)) { if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next, addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list); struct sctp_sockaddr_entry, list);
if (sctp_is_any(&addr->a)) { if (sctp_is_any(sk, &addr->a)) {
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(addr, list_for_each_entry_rcu(addr,
&sctp_local_addr_list, list) { &sctp_local_addr_list, list) {
...@@ -4602,7 +4602,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, ...@@ -4602,7 +4602,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
if (sctp_list_single_entry(&bp->address_list)) { if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next, addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list); struct sctp_sockaddr_entry, list);
if (sctp_is_any(&addr->a)) { if (sctp_is_any(sk, &addr->a)) {
cnt = sctp_copy_laddrs_old(sk, bp->port, cnt = sctp_copy_laddrs_old(sk, bp->port,
getaddrs.addr_num, getaddrs.addr_num,
addrs, &bytes_copied); addrs, &bytes_copied);
...@@ -4695,7 +4695,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, ...@@ -4695,7 +4695,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
if (sctp_list_single_entry(&bp->address_list)) { if (sctp_list_single_entry(&bp->address_list)) {
addr = list_entry(bp->address_list.next, addr = list_entry(bp->address_list.next,
struct sctp_sockaddr_entry, list); struct sctp_sockaddr_entry, list);
if (sctp_is_any(&addr->a)) { if (sctp_is_any(sk, &addr->a)) {
cnt = sctp_copy_laddrs(sk, bp->port, addrs, cnt = sctp_copy_laddrs(sk, bp->port, addrs,
space_left, &bytes_copied); space_left, &bytes_copied);
if (cnt < 0) { if (cnt < 0) {
......
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