aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c20
-rw-r--r--net/ipv6/raw.c7
-rw-r--r--net/ipv6/tcp_ipv6.c7
-rw-r--r--net/ipv6/xfrm6_policy.c43
5 files changed, 62 insertions, 17 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7196ac2f2d16..7744a2592693 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3076,7 +3076,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
3076 netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC); 3076 netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
3077} 3077}
3078 3078
3079static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { 3079static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = {
3080 [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, 3080 [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
3081 [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, 3081 [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
3082 [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, 3082 [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, },
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index c54830b89593..750943e2d34e 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -549,20 +549,18 @@ ipq_rcv_skb(struct sk_buff *skb)
549static void 549static void
550ipq_rcv_sk(struct sock *sk, int len) 550ipq_rcv_sk(struct sock *sk, int len)
551{ 551{
552 do { 552 struct sk_buff *skb;
553 struct sk_buff *skb; 553 unsigned int qlen;
554 554
555 if (down_trylock(&ipqnl_sem)) 555 down(&ipqnl_sem);
556 return;
557 556
558 while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) { 557 for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
559 ipq_rcv_skb(skb); 558 skb = skb_dequeue(&sk->sk_receive_queue);
560 kfree_skb(skb); 559 ipq_rcv_skb(skb);
561 } 560 kfree_skb(skb);
561 }
562 562
563 up(&ipqnl_sem); 563 up(&ipqnl_sem);
564
565 } while (ipqnl && ipqnl->sk_receive_queue.qlen);
566} 564}
567 565
568static int 566static int
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 1352c1d9bf4d..617645bc5ed6 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -455,11 +455,11 @@ csum_copy_err:
455static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, 455static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
456 struct raw6_sock *rp) 456 struct raw6_sock *rp)
457{ 457{
458 struct inet_sock *inet = inet_sk(sk);
459 struct sk_buff *skb; 458 struct sk_buff *skb;
460 int err = 0; 459 int err = 0;
461 int offset; 460 int offset;
462 int len; 461 int len;
462 int total_len;
463 u32 tmp_csum; 463 u32 tmp_csum;
464 u16 csum; 464 u16 csum;
465 465
@@ -470,7 +470,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
470 goto out; 470 goto out;
471 471
472 offset = rp->offset; 472 offset = rp->offset;
473 if (offset >= inet->cork.length - 1) { 473 total_len = inet_sk(sk)->cork.length - (skb->nh.raw - skb->data);
474 if (offset >= total_len - 1) {
474 err = -EINVAL; 475 err = -EINVAL;
475 ip6_flush_pending_frames(sk); 476 ip6_flush_pending_frames(sk);
476 goto out; 477 goto out;
@@ -514,7 +515,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
514 515
515 tmp_csum = csum_ipv6_magic(&fl->fl6_src, 516 tmp_csum = csum_ipv6_magic(&fl->fl6_src,
516 &fl->fl6_dst, 517 &fl->fl6_dst,
517 inet->cork.length, fl->proto, tmp_csum); 518 total_len, fl->proto, tmp_csum);
518 519
519 if (tmp_csum == 0) 520 if (tmp_csum == 0)
520 tmp_csum = -1; 521 tmp_csum = -1;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4760c85e19db..0f69e800a0ad 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -139,9 +139,12 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
139 int rover; 139 int rover;
140 140
141 spin_lock(&tcp_portalloc_lock); 141 spin_lock(&tcp_portalloc_lock);
142 rover = tcp_port_rover; 142 if (tcp_port_rover < low)
143 rover = low;
144 else
145 rover = tcp_port_rover;
143 do { rover++; 146 do { rover++;
144 if ((rover < low) || (rover > high)) 147 if (rover > high)
145 rover = low; 148 rover = low;
146 head = &tcp_bhash[tcp_bhashfn(rover)]; 149 head = &tcp_bhash[tcp_bhashfn(rover)];
147 spin_lock(&head->lock); 150 spin_lock(&head->lock);
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8a4f37de4d2d..4429b1a1fe5f 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -11,7 +11,11 @@
11 * 11 *
12 */ 12 */
13 13
14#include <asm/bug.h>
15#include <linux/compiler.h>
14#include <linux/config.h> 16#include <linux/config.h>
17#include <linux/netdevice.h>
18#include <net/addrconf.h>
15#include <net/xfrm.h> 19#include <net/xfrm.h>
16#include <net/ip.h> 20#include <net/ip.h>
17#include <net/ipv6.h> 21#include <net/ipv6.h>
@@ -166,6 +170,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
166 memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); 170 memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway));
167 x->u.rt6.rt6i_dst = rt0->rt6i_dst; 171 x->u.rt6.rt6i_dst = rt0->rt6i_dst;
168 x->u.rt6.rt6i_src = rt0->rt6i_src; 172 x->u.rt6.rt6i_src = rt0->rt6i_src;
173 x->u.rt6.rt6i_idev = rt0->rt6i_idev;
174 in6_dev_hold(rt0->rt6i_idev);
169 header_len -= x->u.dst.xfrm->props.header_len; 175 header_len -= x->u.dst.xfrm->props.header_len;
170 trailer_len -= x->u.dst.xfrm->props.trailer_len; 176 trailer_len -= x->u.dst.xfrm->props.trailer_len;
171 } 177 }
@@ -251,11 +257,48 @@ static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
251 path->ops->update_pmtu(path, mtu); 257 path->ops->update_pmtu(path, mtu);
252} 258}
253 259
260static void xfrm6_dst_destroy(struct dst_entry *dst)
261{
262 struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
263
264 if (likely(xdst->u.rt6.rt6i_idev))
265 in6_dev_put(xdst->u.rt6.rt6i_idev);
266 xfrm_dst_destroy(xdst);
267}
268
269static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
270 int unregister)
271{
272 struct xfrm_dst *xdst;
273
274 if (!unregister)
275 return;
276
277 xdst = (struct xfrm_dst *)dst;
278 if (xdst->u.rt6.rt6i_idev->dev == dev) {
279 struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
280 BUG_ON(!loopback_idev);
281
282 do {
283 in6_dev_put(xdst->u.rt6.rt6i_idev);
284 xdst->u.rt6.rt6i_idev = loopback_idev;
285 in6_dev_hold(loopback_idev);
286 xdst = (struct xfrm_dst *)xdst->u.dst.child;
287 } while (xdst->u.dst.xfrm);
288
289 __in6_dev_put(loopback_idev);
290 }
291
292 xfrm_dst_ifdown(dst, dev);
293}
294
254static struct dst_ops xfrm6_dst_ops = { 295static struct dst_ops xfrm6_dst_ops = {
255 .family = AF_INET6, 296 .family = AF_INET6,
256 .protocol = __constant_htons(ETH_P_IPV6), 297 .protocol = __constant_htons(ETH_P_IPV6),
257 .gc = xfrm6_garbage_collect, 298 .gc = xfrm6_garbage_collect,
258 .update_pmtu = xfrm6_update_pmtu, 299 .update_pmtu = xfrm6_update_pmtu,
300 .destroy = xfrm6_dst_destroy,
301 .ifdown = xfrm6_dst_ifdown,
259 .gc_thresh = 1024, 302 .gc_thresh = 1024,
260 .entry_size = sizeof(struct xfrm_dst), 303 .entry_size = sizeof(struct xfrm_dst),
261}; 304};