diff options
-rw-r--r-- | include/linux/ipv6.h | 2 | ||||
-rw-r--r-- | include/net/inet_hashtables.h | 36 | ||||
-rw-r--r-- | net/ipv4/inet_hashtables.c | 2 | ||||
-rw-r--r-- | net/ipv6/inet6_hashtables.c | 8 |
4 files changed, 31 insertions, 17 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index caca57df0d7d..6dc07ee7702e 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
@@ -461,7 +461,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk) | |||
461 | 461 | ||
462 | #define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\ | 462 | #define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\ |
463 | (((__sk)->sk_hash == (__hash)) && \ | 463 | (((__sk)->sk_hash == (__hash)) && \ |
464 | ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ | 464 | ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ |
465 | ((__sk)->sk_family == AF_INET6) && \ | 465 | ((__sk)->sk_family == AF_INET6) && \ |
466 | ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \ | 466 | ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr)) && \ |
467 | ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \ | 467 | ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \ |
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index b4491c9e2a5a..fb0c09c7090c 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h | |||
@@ -283,31 +283,45 @@ static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /* Socket demux engine toys. */ | 285 | /* Socket demux engine toys. */ |
286 | /* What happens here is ugly; there's a pair of adjacent fields in | ||
287 | struct inet_sock; __be16 dport followed by __u16 num. We want to | ||
288 | search by pair, so we combine the keys into a single 32bit value | ||
289 | and compare with 32bit value read from &...->dport. Let's at least | ||
290 | make sure that it's not mixed with anything else... | ||
291 | On 64bit targets we combine comparisons with pair of adjacent __be32 | ||
292 | fields in the same way. | ||
293 | */ | ||
294 | typedef __u32 __bitwise __portpair; | ||
286 | #ifdef __BIG_ENDIAN | 295 | #ifdef __BIG_ENDIAN |
287 | #define INET_COMBINED_PORTS(__sport, __dport) \ | 296 | #define INET_COMBINED_PORTS(__sport, __dport) \ |
288 | (((__u32)(__sport) << 16) | (__u32)(__dport)) | 297 | ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport))) |
289 | #else /* __LITTLE_ENDIAN */ | 298 | #else /* __LITTLE_ENDIAN */ |
290 | #define INET_COMBINED_PORTS(__sport, __dport) \ | 299 | #define INET_COMBINED_PORTS(__sport, __dport) \ |
291 | (((__u32)(__dport) << 16) | (__u32)(__sport)) | 300 | ((__force __portpair)(((__u32)(__dport) << 16) | (__force __u32)(__be16)(__sport))) |
292 | #endif | 301 | #endif |
293 | 302 | ||
294 | #if (BITS_PER_LONG == 64) | 303 | #if (BITS_PER_LONG == 64) |
304 | typedef __u64 __bitwise __addrpair; | ||
295 | #ifdef __BIG_ENDIAN | 305 | #ifdef __BIG_ENDIAN |
296 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ | 306 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
297 | const __u64 __name = (((__u64)(__saddr)) << 32) | ((__u64)(__daddr)); | 307 | const __addrpair __name = (__force __addrpair) ( \ |
308 | (((__force __u64)(__be32)(__saddr)) << 32) | \ | ||
309 | ((__force __u64)(__be32)(__daddr))); | ||
298 | #else /* __LITTLE_ENDIAN */ | 310 | #else /* __LITTLE_ENDIAN */ |
299 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ | 311 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \ |
300 | const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr)); | 312 | const __addrpair __name = (__force __addrpair) ( \ |
313 | (((__force __u64)(__be32)(__daddr)) << 32) | \ | ||
314 | ((__force __u64)(__be32)(__saddr))); | ||
301 | #endif /* __BIG_ENDIAN */ | 315 | #endif /* __BIG_ENDIAN */ |
302 | #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ | 316 | #define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ |
303 | (((__sk)->sk_hash == (__hash)) && \ | 317 | (((__sk)->sk_hash == (__hash)) && \ |
304 | ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ | 318 | ((*((__addrpair *)&(inet_sk(__sk)->daddr))) == (__cookie)) && \ |
305 | ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ | 319 | ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ |
306 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 320 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
307 | #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ | 321 | #define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\ |
308 | (((__sk)->sk_hash == (__hash)) && \ | 322 | (((__sk)->sk_hash == (__hash)) && \ |
309 | ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ | 323 | ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \ |
310 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ | 324 | ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ |
311 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 325 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
312 | #else /* 32-bit arch */ | 326 | #else /* 32-bit arch */ |
313 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) | 327 | #define INET_ADDR_COOKIE(__name, __saddr, __daddr) |
@@ -315,13 +329,13 @@ static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, | |||
315 | (((__sk)->sk_hash == (__hash)) && \ | 329 | (((__sk)->sk_hash == (__hash)) && \ |
316 | (inet_sk(__sk)->daddr == (__saddr)) && \ | 330 | (inet_sk(__sk)->daddr == (__saddr)) && \ |
317 | (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ | 331 | (inet_sk(__sk)->rcv_saddr == (__daddr)) && \ |
318 | ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports)) && \ | 332 | ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports)) && \ |
319 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 333 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
320 | #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ | 334 | #define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \ |
321 | (((__sk)->sk_hash == (__hash)) && \ | 335 | (((__sk)->sk_hash == (__hash)) && \ |
322 | (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ | 336 | (inet_twsk(__sk)->tw_daddr == (__saddr)) && \ |
323 | (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ | 337 | (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \ |
324 | ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ | 338 | ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \ |
325 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) | 339 | (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif)))) |
326 | #endif /* 64-bit arch */ | 340 | #endif /* 64-bit arch */ |
327 | 341 | ||
@@ -338,7 +352,7 @@ static inline struct sock * | |||
338 | const int dif) | 352 | const int dif) |
339 | { | 353 | { |
340 | INET_ADDR_COOKIE(acookie, saddr, daddr) | 354 | INET_ADDR_COOKIE(acookie, saddr, daddr) |
341 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | 355 | const __portpair ports = INET_COMBINED_PORTS(sport, hnum); |
342 | struct sock *sk; | 356 | struct sock *sk; |
343 | const struct hlist_node *node; | 357 | const struct hlist_node *node; |
344 | /* Optimize here for direct hit, only listening connections can | 358 | /* Optimize here for direct hit, only listening connections can |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index fb296c9a7f3f..729d1eb39483 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -201,7 +201,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row, | |||
201 | u32 saddr = inet->daddr; | 201 | u32 saddr = inet->daddr; |
202 | int dif = sk->sk_bound_dev_if; | 202 | int dif = sk->sk_bound_dev_if; |
203 | INET_ADDR_COOKIE(acookie, saddr, daddr) | 203 | INET_ADDR_COOKIE(acookie, saddr, daddr) |
204 | const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport); | 204 | const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport); |
205 | unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport); | 205 | unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport); |
206 | struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); | 206 | struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); |
207 | struct sock *sk2; | 207 | struct sock *sk2; |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index d2f3fc990bfa..8accd1fbeeda 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -64,7 +64,7 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, | |||
64 | { | 64 | { |
65 | struct sock *sk; | 65 | struct sock *sk; |
66 | const struct hlist_node *node; | 66 | const struct hlist_node *node; |
67 | const __u32 ports = INET_COMBINED_PORTS(sport, hnum); | 67 | const __portpair ports = INET_COMBINED_PORTS(sport, hnum); |
68 | /* Optimize here for direct hit, only listening connections can | 68 | /* Optimize here for direct hit, only listening connections can |
69 | * have wildcards anyways. | 69 | * have wildcards anyways. |
70 | */ | 70 | */ |
@@ -82,7 +82,7 @@ struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, | |||
82 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { | 82 | sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) { |
83 | const struct inet_timewait_sock *tw = inet_twsk(sk); | 83 | const struct inet_timewait_sock *tw = inet_twsk(sk); |
84 | 84 | ||
85 | if(*((__u32 *)&(tw->tw_dport)) == ports && | 85 | if(*((__portpair *)&(tw->tw_dport)) == ports && |
86 | sk->sk_family == PF_INET6) { | 86 | sk->sk_family == PF_INET6) { |
87 | const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); | 87 | const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); |
88 | 88 | ||
@@ -171,7 +171,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, | |||
171 | const struct in6_addr *daddr = &np->rcv_saddr; | 171 | const struct in6_addr *daddr = &np->rcv_saddr; |
172 | const struct in6_addr *saddr = &np->daddr; | 172 | const struct in6_addr *saddr = &np->daddr; |
173 | const int dif = sk->sk_bound_dev_if; | 173 | const int dif = sk->sk_bound_dev_if; |
174 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); | 174 | const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport); |
175 | const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, | 175 | const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, |
176 | inet->dport); | 176 | inet->dport); |
177 | struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); | 177 | struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash); |
@@ -188,7 +188,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row, | |||
188 | 188 | ||
189 | tw = inet_twsk(sk2); | 189 | tw = inet_twsk(sk2); |
190 | 190 | ||
191 | if(*((__u32 *)&(tw->tw_dport)) == ports && | 191 | if(*((__portpair *)&(tw->tw_dport)) == ports && |
192 | sk2->sk_family == PF_INET6 && | 192 | sk2->sk_family == PF_INET6 && |
193 | ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && | 193 | ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) && |
194 | ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && | 194 | ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) && |