Commit b7b5f487 authored by David S. Miller's avatar David S. Miller

[IPV4] UDP: Fix endianness bugs in hashing changes.

I accidently applied an earlier version of Eric Dumazet's patch, from
March 21st.  His version from March 30th didn't have these bugs, so
this just interdiffs to the correct patch.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 40caf5ea
...@@ -270,10 +270,10 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, ...@@ -270,10 +270,10 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
struct sock *sk, *result = NULL; struct sock *sk, *result = NULL;
struct hlist_node *node; struct hlist_node *node;
unsigned int hash, hashwild; unsigned int hash, hashwild;
int score, best = -1; int score, best = -1, hport = ntohs(dport);
hash = hash_port_and_addr(ntohs(dport), daddr); hash = hash_port_and_addr(hport, daddr);
hashwild = hash_port_and_addr(ntohs(dport), 0); hashwild = hash_port_and_addr(hport, 0);
read_lock(&udp_hash_lock); read_lock(&udp_hash_lock);
...@@ -283,7 +283,7 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, ...@@ -283,7 +283,7 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
if (sk->sk_hash != hash || ipv6_only_sock(sk) || if (sk->sk_hash != hash || ipv6_only_sock(sk) ||
inet->num != dport) inet->num != hport)
continue; continue;
score = (sk->sk_family == PF_INET ? 1 : 0); score = (sk->sk_family == PF_INET ? 1 : 0);
...@@ -327,11 +327,10 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport, ...@@ -327,11 +327,10 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
return result; return result;
} }
static inline struct sock *udp_v4_mcast_next( static inline struct sock *udp_v4_mcast_next(struct sock *sk, unsigned int hnum,
struct sock *sk, int hport, __be32 loc_addr,
unsigned int hnum, __be16 loc_port, __be32 loc_addr, __be16 rmt_port, __be32 rmt_addr,
__be16 rmt_port, __be32 rmt_addr, int dif)
int dif)
{ {
struct hlist_node *node; struct hlist_node *node;
struct sock *s = sk; struct sock *s = sk;
...@@ -340,7 +339,7 @@ static inline struct sock *udp_v4_mcast_next( ...@@ -340,7 +339,7 @@ static inline struct sock *udp_v4_mcast_next(
struct inet_sock *inet = inet_sk(s); struct inet_sock *inet = inet_sk(s);
if (s->sk_hash != hnum || if (s->sk_hash != hnum ||
inet->num != loc_port || inet->num != hport ||
(inet->daddr && inet->daddr != rmt_addr) || (inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) || (inet->dport != rmt_port && inet->dport) ||
(inet->rcv_saddr && inet->rcv_saddr != loc_addr) || (inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
...@@ -1173,8 +1172,9 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, ...@@ -1173,8 +1172,9 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
{ {
struct sock *sk, *skw, *sknext; struct sock *sk, *skw, *sknext;
int dif; int dif;
unsigned int hash = hash_port_and_addr(ntohs(uh->dest), daddr); int hport = ntohs(uh->dest);
unsigned int hashwild = hash_port_and_addr(ntohs(uh->dest), 0); unsigned int hash = hash_port_and_addr(hport, daddr);
unsigned int hashwild = hash_port_and_addr(hport, 0);
dif = skb->dev->ifindex; dif = skb->dev->ifindex;
...@@ -1183,20 +1183,20 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb, ...@@ -1183,20 +1183,20 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]); sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]);
skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]); skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]);
sk = udp_v4_mcast_next(sk, hash, uh->dest, daddr, uh->source, saddr, dif); sk = udp_v4_mcast_next(sk, hash, hport, daddr, uh->source, saddr, dif);
if (!sk) { if (!sk) {
hash = hashwild; hash = hashwild;
sk = udp_v4_mcast_next(skw, hash, uh->dest, daddr, uh->source, sk = udp_v4_mcast_next(skw, hash, hport, daddr, uh->source,
saddr, dif); saddr, dif);
} }
if (sk) { if (sk) {
do { do {
struct sk_buff *skb1 = skb; struct sk_buff *skb1 = skb;
sknext = udp_v4_mcast_next(sk_next(sk), hash, uh->dest, sknext = udp_v4_mcast_next(sk_next(sk), hash, hport,
daddr, uh->source, saddr, dif); daddr, uh->source, saddr, dif);
if (!sknext && hash != hashwild) { if (!sknext && hash != hashwild) {
hash = hashwild; hash = hashwild;
sknext = udp_v4_mcast_next(skw, hash, uh->dest, sknext = udp_v4_mcast_next(skw, hash, hport,
daddr, uh->source, saddr, dif); daddr, uh->source, saddr, dif);
} }
if (sknext) if (sknext)
...@@ -1295,7 +1295,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], ...@@ -1295,7 +1295,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable); return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest, sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
skb->dev->ifindex, udptable ); skb->dev->ifindex, udptable);
if (sk != NULL) { if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb); int ret = udp_queue_rcv_skb(sk, skb);
......
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