Commit af2e3380 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6]: Fix inappropriate usage of inet{,6}_sk().

parent c54c83e8
...@@ -219,6 +219,7 @@ struct tcp_tw_bucket { ...@@ -219,6 +219,7 @@ struct tcp_tw_bucket {
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr tw_v6_daddr; struct in6_addr tw_v6_daddr;
struct in6_addr tw_v6_rcv_saddr; struct in6_addr tw_v6_rcv_saddr;
int tw_v6_ipv6only;
#endif #endif
}; };
...@@ -267,6 +268,38 @@ static __inline__ int tw_del_dead_node(struct tcp_tw_bucket *tw) ...@@ -267,6 +268,38 @@ static __inline__ int tw_del_dead_node(struct tcp_tw_bucket *tw)
#define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk)) #define tcptw_sk(__sk) ((struct tcp_tw_bucket *)(__sk))
static inline const u32 tcp_v4_rcv_saddr(const struct sock *sk)
{
return likely(sk->sk_state != TCP_TIME_WAIT) ?
inet_sk(sk)->rcv_saddr : tcptw_sk(sk)->tw_rcv_saddr;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static inline const struct in6_addr *__tcp_v6_rcv_saddr(const struct sock *sk)
{
return likely(sk->sk_state != TCP_TIME_WAIT) ?
&inet6_sk(sk)->rcv_saddr : &tcptw_sk(sk)->tw_v6_rcv_saddr;
}
static inline const struct in6_addr *tcp_v6_rcv_saddr(const struct sock *sk)
{
return sk->sk_family == AF_INET6 ? __tcp_v6_rcv_saddr(sk) : NULL;
}
#define tcptw_sk_ipv6only(__sk) (tcptw_sk(__sk)->tw_v6_ipv6only)
static inline int tcp_v6_ipv6only(const struct sock *sk)
{
return likely(sk->sk_state != TCP_TIME_WAIT) ?
ipv6_only_sock(sk) : tcptw_sk_ipv6only(sk);
}
#else
# define __tcp_v6_rcv_saddr(__sk) NULL
# define tcp_v6_rcv_saddr(__sk) NULL
# define tcptw_sk_ipv6only(__sk) 0
# define tcp_v6_ipv6only(__sk) 0
#endif
extern kmem_cache_t *tcp_timewait_cachep; extern kmem_cache_t *tcp_timewait_cachep;
static inline void tcp_tw_put(struct tcp_tw_bucket *tw) static inline void tcp_tw_put(struct tcp_tw_bucket *tw)
......
...@@ -178,12 +178,6 @@ void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb, ...@@ -178,12 +178,6 @@ void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
tcp_sk(sk)->bind_hash = tb; tcp_sk(sk)->bind_hash = tb;
} }
static inline const u32 tcp_v4_rcv_saddr(const struct sock *sk)
{
return likely(sk->sk_state != TCP_TIME_WAIT) ?
inet_sk(sk)->rcv_saddr : tcptw_sk(sk)->tw_rcv_saddr;
}
static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb) static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
{ {
const u32 sk_rcv_saddr = tcp_v4_rcv_saddr(sk); const u32 sk_rcv_saddr = tcp_v4_rcv_saddr(sk);
......
...@@ -368,6 +368,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) ...@@ -368,6 +368,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
ipv6_addr_copy(&tw->tw_v6_daddr, &np->daddr); ipv6_addr_copy(&tw->tw_v6_daddr, &np->daddr);
ipv6_addr_copy(&tw->tw_v6_rcv_saddr, &np->rcv_saddr); ipv6_addr_copy(&tw->tw_v6_rcv_saddr, &np->rcv_saddr);
tw->tw_v6_ipv6only = np->ipv6only;
} else {
memset(&tw->tw_v6_daddr, 0, sizeof(tw->tw_v6_daddr));
memset(&tw->tw_v6_rcv_saddr, 0, sizeof(tw->tw_v6_rcv_saddr));
tw->tw_v6_ipv6only = 0;
} }
#endif #endif
/* Linkage updates. */ /* Linkage updates. */
......
...@@ -970,36 +970,33 @@ struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device * ...@@ -970,36 +970,33 @@ struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *
int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
{ {
struct ipv6_pinfo *np = inet6_sk(sk); const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr;
int addr_type = ipv6_addr_type(&np->rcv_saddr); const struct in6_addr *sk2_rcv_saddr6 = tcp_v6_rcv_saddr(sk2);
u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
if (!inet_sk(sk2)->rcv_saddr && !ipv6_only_sock(sk)) u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2);
int sk_ipv6only = ipv6_only_sock(sk);
int sk2_ipv6only = tcp_v6_ipv6only(sk2);
int addr_type = ipv6_addr_type(sk_rcv_saddr6);
int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED;
if (!sk2_rcv_saddr && !sk_ipv6only)
return 1; return 1;
if (sk2->sk_family == AF_INET6 && if (addr_type2 == IPV6_ADDR_ANY &&
ipv6_addr_any(&inet6_sk(sk2)->rcv_saddr) && !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED))
!(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED))
return 1; return 1;
if (addr_type == IPV6_ADDR_ANY && if (addr_type == IPV6_ADDR_ANY &&
(!ipv6_only_sock(sk) || !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED))
!(sk2->sk_family == AF_INET6 ?
(ipv6_addr_type(&inet6_sk(sk2)->rcv_saddr) == IPV6_ADDR_MAPPED) :
1)))
return 1; return 1;
if (sk2->sk_family == AF_INET6 && if (sk2_rcv_saddr6 &&
!ipv6_addr_cmp(&np->rcv_saddr, !ipv6_addr_cmp(sk_rcv_saddr6, sk2_rcv_saddr6))
(sk2->sk_state != TCP_TIME_WAIT ?
&inet6_sk(sk2)->rcv_saddr :
&tcptw_sk(sk2)->tw_v6_rcv_saddr)))
return 1; return 1;
if (addr_type == IPV6_ADDR_MAPPED && if (addr_type == IPV6_ADDR_MAPPED &&
!ipv6_only_sock(sk2) && !sk2_ipv6only &&
(!inet_sk(sk2)->rcv_saddr || (!sk2_rcv_saddr || !sk_rcv_saddr || sk_rcv_saddr == sk2_rcv_saddr))
!inet_sk(sk)->rcv_saddr ||
inet_sk(sk)->rcv_saddr == inet_sk(sk2)->rcv_saddr))
return 1; return 1;
return 0; return 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