diff options
-rw-r--r-- | net/ipv4/raw.c | 21 | ||||
-rw-r--r-- | net/ipv6/raw.c | 18 |
2 files changed, 26 insertions, 13 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 747911a8241c..a490a9d54712 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -116,16 +116,15 @@ static void raw_v4_unhash(struct sock *sk) | |||
116 | raw_unhash_sk(sk, &raw_v4_hashinfo); | 116 | raw_unhash_sk(sk, &raw_v4_hashinfo); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, | 119 | static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, |
120 | __be32 raddr, __be32 laddr, | 120 | unsigned short num, __be32 raddr, __be32 laddr, int dif) |
121 | int dif) | ||
122 | { | 121 | { |
123 | struct hlist_node *node; | 122 | struct hlist_node *node; |
124 | 123 | ||
125 | sk_for_each_from(sk, node) { | 124 | sk_for_each_from(sk, node) { |
126 | struct inet_sock *inet = inet_sk(sk); | 125 | struct inet_sock *inet = inet_sk(sk); |
127 | 126 | ||
128 | if (inet->num == num && | 127 | if (sk->sk_net == net && inet->num == num && |
129 | !(inet->daddr && inet->daddr != raddr) && | 128 | !(inet->daddr && inet->daddr != raddr) && |
130 | !(inet->rcv_saddr && inet->rcv_saddr != laddr) && | 129 | !(inet->rcv_saddr && inet->rcv_saddr != laddr) && |
131 | !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) | 130 | !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) |
@@ -169,12 +168,15 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) | |||
169 | struct sock *sk; | 168 | struct sock *sk; |
170 | struct hlist_head *head; | 169 | struct hlist_head *head; |
171 | int delivered = 0; | 170 | int delivered = 0; |
171 | struct net *net; | ||
172 | 172 | ||
173 | read_lock(&raw_v4_hashinfo.lock); | 173 | read_lock(&raw_v4_hashinfo.lock); |
174 | head = &raw_v4_hashinfo.ht[hash]; | 174 | head = &raw_v4_hashinfo.ht[hash]; |
175 | if (hlist_empty(head)) | 175 | if (hlist_empty(head)) |
176 | goto out; | 176 | goto out; |
177 | sk = __raw_v4_lookup(__sk_head(head), iph->protocol, | 177 | |
178 | net = skb->dev->nd_net; | ||
179 | sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, | ||
178 | iph->saddr, iph->daddr, | 180 | iph->saddr, iph->daddr, |
179 | skb->dev->ifindex); | 181 | skb->dev->ifindex); |
180 | 182 | ||
@@ -187,7 +189,7 @@ static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) | |||
187 | if (clone) | 189 | if (clone) |
188 | raw_rcv(sk, clone); | 190 | raw_rcv(sk, clone); |
189 | } | 191 | } |
190 | sk = __raw_v4_lookup(sk_next(sk), iph->protocol, | 192 | sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, |
191 | iph->saddr, iph->daddr, | 193 | iph->saddr, iph->daddr, |
192 | skb->dev->ifindex); | 194 | skb->dev->ifindex); |
193 | } | 195 | } |
@@ -273,6 +275,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) | |||
273 | int hash; | 275 | int hash; |
274 | struct sock *raw_sk; | 276 | struct sock *raw_sk; |
275 | struct iphdr *iph; | 277 | struct iphdr *iph; |
278 | struct net *net; | ||
276 | 279 | ||
277 | hash = protocol & (RAW_HTABLE_SIZE - 1); | 280 | hash = protocol & (RAW_HTABLE_SIZE - 1); |
278 | 281 | ||
@@ -280,8 +283,10 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) | |||
280 | raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); | 283 | raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); |
281 | if (raw_sk != NULL) { | 284 | if (raw_sk != NULL) { |
282 | iph = (struct iphdr *)skb->data; | 285 | iph = (struct iphdr *)skb->data; |
283 | while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr, | 286 | net = skb->dev->nd_net; |
284 | iph->saddr, | 287 | |
288 | while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, | ||
289 | iph->daddr, iph->saddr, | ||
285 | skb->dev->ifindex)) != NULL) { | 290 | skb->dev->ifindex)) != NULL) { |
286 | raw_err(raw_sk, skb, info); | 291 | raw_err(raw_sk, skb, info); |
287 | raw_sk = sk_next(raw_sk); | 292 | raw_sk = sk_next(raw_sk); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index cb0b110a2ac8..6f20086064b2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -76,8 +76,9 @@ static void raw_v6_unhash(struct sock *sk) | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | 79 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, |
80 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr, int dif) | 80 | unsigned short num, struct in6_addr *loc_addr, |
81 | struct in6_addr *rmt_addr, int dif) | ||
81 | { | 82 | { |
82 | struct hlist_node *node; | 83 | struct hlist_node *node; |
83 | int is_multicast = ipv6_addr_is_multicast(loc_addr); | 84 | int is_multicast = ipv6_addr_is_multicast(loc_addr); |
@@ -86,6 +87,9 @@ static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | |||
86 | if (inet_sk(sk)->num == num) { | 87 | if (inet_sk(sk)->num == num) { |
87 | struct ipv6_pinfo *np = inet6_sk(sk); | 88 | struct ipv6_pinfo *np = inet6_sk(sk); |
88 | 89 | ||
90 | if (sk->sk_net != net) | ||
91 | continue; | ||
92 | |||
89 | if (!ipv6_addr_any(&np->daddr) && | 93 | if (!ipv6_addr_any(&np->daddr) && |
90 | !ipv6_addr_equal(&np->daddr, rmt_addr)) | 94 | !ipv6_addr_equal(&np->daddr, rmt_addr)) |
91 | continue; | 95 | continue; |
@@ -165,6 +169,7 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
165 | struct sock *sk; | 169 | struct sock *sk; |
166 | int delivered = 0; | 170 | int delivered = 0; |
167 | __u8 hash; | 171 | __u8 hash; |
172 | struct net *net; | ||
168 | 173 | ||
169 | saddr = &ipv6_hdr(skb)->saddr; | 174 | saddr = &ipv6_hdr(skb)->saddr; |
170 | daddr = saddr + 1; | 175 | daddr = saddr + 1; |
@@ -182,7 +187,8 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
182 | if (sk == NULL) | 187 | if (sk == NULL) |
183 | goto out; | 188 | goto out; |
184 | 189 | ||
185 | sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | 190 | net = skb->dev->nd_net; |
191 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | ||
186 | 192 | ||
187 | while (sk) { | 193 | while (sk) { |
188 | int filtered; | 194 | int filtered; |
@@ -225,7 +231,7 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
225 | rawv6_rcv(sk, clone); | 231 | rawv6_rcv(sk, clone); |
226 | } | 232 | } |
227 | } | 233 | } |
228 | sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr, | 234 | sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, |
229 | IP6CB(skb)->iif); | 235 | IP6CB(skb)->iif); |
230 | } | 236 | } |
231 | out: | 237 | out: |
@@ -359,6 +365,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
359 | struct sock *sk; | 365 | struct sock *sk; |
360 | int hash; | 366 | int hash; |
361 | struct in6_addr *saddr, *daddr; | 367 | struct in6_addr *saddr, *daddr; |
368 | struct net *net; | ||
362 | 369 | ||
363 | hash = nexthdr & (RAW_HTABLE_SIZE - 1); | 370 | hash = nexthdr & (RAW_HTABLE_SIZE - 1); |
364 | 371 | ||
@@ -367,8 +374,9 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
367 | if (sk != NULL) { | 374 | if (sk != NULL) { |
368 | saddr = &ipv6_hdr(skb)->saddr; | 375 | saddr = &ipv6_hdr(skb)->saddr; |
369 | daddr = &ipv6_hdr(skb)->daddr; | 376 | daddr = &ipv6_hdr(skb)->daddr; |
377 | net = skb->dev->nd_net; | ||
370 | 378 | ||
371 | while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr, | 379 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
372 | IP6CB(skb)->iif))) { | 380 | IP6CB(skb)->iif))) { |
373 | rawv6_err(sk, skb, NULL, type, code, | 381 | rawv6_err(sk, skb, NULL, type, code, |
374 | inner_offset, info); | 382 | inner_offset, info); |