aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/addrconf.c11
-rw-r--r--net/ipv6/addrlabel.c5
-rw-r--r--net/ipv6/datagram.c7
-rw-r--r--net/ipv6/ip6_output.c18
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c80
-rw-r--r--net/ipv6/reassembly.c71
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/udp.c10
-rw-r--r--net/ipv6/xfrm6_state.c33
9 files changed, 92 insertions, 145 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ab70a3fbcafa..324fac3b6c16 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4637,10 +4637,12 @@ int __init addrconf_init(void)
4637 if (err < 0) { 4637 if (err < 0) {
4638 printk(KERN_CRIT "IPv6 Addrconf:" 4638 printk(KERN_CRIT "IPv6 Addrconf:"
4639 " cannot initialize default policy table: %d.\n", err); 4639 " cannot initialize default policy table: %d.\n", err);
4640 return err; 4640 goto out;
4641 } 4641 }
4642 4642
4643 register_pernet_subsys(&addrconf_ops); 4643 err = register_pernet_subsys(&addrconf_ops);
4644 if (err < 0)
4645 goto out_addrlabel;
4644 4646
4645 /* The addrconf netdev notifier requires that loopback_dev 4647 /* The addrconf netdev notifier requires that loopback_dev
4646 * has it's ipv6 private information allocated and setup 4648 * has it's ipv6 private information allocated and setup
@@ -4692,7 +4694,9 @@ errout:
4692 unregister_netdevice_notifier(&ipv6_dev_notf); 4694 unregister_netdevice_notifier(&ipv6_dev_notf);
4693errlo: 4695errlo:
4694 unregister_pernet_subsys(&addrconf_ops); 4696 unregister_pernet_subsys(&addrconf_ops);
4695 4697out_addrlabel:
4698 ipv6_addr_label_cleanup();
4699out:
4696 return err; 4700 return err;
4697} 4701}
4698 4702
@@ -4703,6 +4707,7 @@ void addrconf_cleanup(void)
4703 4707
4704 unregister_netdevice_notifier(&ipv6_dev_notf); 4708 unregister_netdevice_notifier(&ipv6_dev_notf);
4705 unregister_pernet_subsys(&addrconf_ops); 4709 unregister_pernet_subsys(&addrconf_ops);
4710 ipv6_addr_label_cleanup();
4706 4711
4707 rtnl_lock(); 4712 rtnl_lock();
4708 4713
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
index f0e774cea386..8175f802651b 100644
--- a/net/ipv6/addrlabel.c
+++ b/net/ipv6/addrlabel.c
@@ -393,6 +393,11 @@ int __init ipv6_addr_label_init(void)
393 return register_pernet_subsys(&ipv6_addr_label_ops); 393 return register_pernet_subsys(&ipv6_addr_label_ops);
394} 394}
395 395
396void ipv6_addr_label_cleanup(void)
397{
398 unregister_pernet_subsys(&ipv6_addr_label_ops);
399}
400
396static const struct nla_policy ifal_policy[IFAL_MAX+1] = { 401static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
397 [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), }, 402 [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), },
398 [IFAL_LABEL] = { .len = sizeof(u32), }, 403 [IFAL_LABEL] = { .len = sizeof(u32), },
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 7d929a22cbc2..ef371aa01ac5 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -105,9 +105,12 @@ ipv4_connected:
105 if (ipv6_addr_any(&np->saddr)) 105 if (ipv6_addr_any(&np->saddr))
106 ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr); 106 ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
107 107
108 if (ipv6_addr_any(&np->rcv_saddr)) 108 if (ipv6_addr_any(&np->rcv_saddr)) {
109 ipv6_addr_set_v4mapped(inet->inet_rcv_saddr, 109 ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
110 &np->rcv_saddr); 110 &np->rcv_saddr);
111 if (sk->sk_prot->rehash)
112 sk->sk_prot->rehash(sk);
113 }
111 114
112 goto out; 115 goto out;
113 } 116 }
@@ -181,6 +184,8 @@ ipv4_connected:
181 if (ipv6_addr_any(&np->rcv_saddr)) { 184 if (ipv6_addr_any(&np->rcv_saddr)) {
182 ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src); 185 ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
183 inet->inet_rcv_saddr = LOOPBACK4_IPV6; 186 inet->inet_rcv_saddr = LOOPBACK4_IPV6;
187 if (sk->sk_prot->rehash)
188 sk->sk_prot->rehash(sk);
184 } 189 }
185 190
186 ip6_dst_store(sk, dst, 191 ip6_dst_store(sk, dst,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index d40b330c0ee6..980912ed7a38 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -639,7 +639,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
639 639
640 if (skb_has_frags(skb)) { 640 if (skb_has_frags(skb)) {
641 int first_len = skb_pagelen(skb); 641 int first_len = skb_pagelen(skb);
642 int truesizes = 0; 642 struct sk_buff *frag2;
643 643
644 if (first_len - hlen > mtu || 644 if (first_len - hlen > mtu ||
645 ((first_len - hlen) & 7) || 645 ((first_len - hlen) & 7) ||
@@ -651,18 +651,18 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
651 if (frag->len > mtu || 651 if (frag->len > mtu ||
652 ((frag->len & 7) && frag->next) || 652 ((frag->len & 7) && frag->next) ||
653 skb_headroom(frag) < hlen) 653 skb_headroom(frag) < hlen)
654 goto slow_path; 654 goto slow_path_clean;
655 655
656 /* Partially cloned skb? */ 656 /* Partially cloned skb? */
657 if (skb_shared(frag)) 657 if (skb_shared(frag))
658 goto slow_path; 658 goto slow_path_clean;
659 659
660 BUG_ON(frag->sk); 660 BUG_ON(frag->sk);
661 if (skb->sk) { 661 if (skb->sk) {
662 frag->sk = skb->sk; 662 frag->sk = skb->sk;
663 frag->destructor = sock_wfree; 663 frag->destructor = sock_wfree;
664 truesizes += frag->truesize;
665 } 664 }
665 skb->truesize -= frag->truesize;
666 } 666 }
667 667
668 err = 0; 668 err = 0;
@@ -693,7 +693,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
693 693
694 first_len = skb_pagelen(skb); 694 first_len = skb_pagelen(skb);
695 skb->data_len = first_len - skb_headlen(skb); 695 skb->data_len = first_len - skb_headlen(skb);
696 skb->truesize -= truesizes;
697 skb->len = first_len; 696 skb->len = first_len;
698 ipv6_hdr(skb)->payload_len = htons(first_len - 697 ipv6_hdr(skb)->payload_len = htons(first_len -
699 sizeof(struct ipv6hdr)); 698 sizeof(struct ipv6hdr));
@@ -756,6 +755,15 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
756 IPSTATS_MIB_FRAGFAILS); 755 IPSTATS_MIB_FRAGFAILS);
757 dst_release(&rt->dst); 756 dst_release(&rt->dst);
758 return err; 757 return err;
758
759slow_path_clean:
760 skb_walk_frags(skb, frag2) {
761 if (frag2 == frag)
762 break;
763 frag2->sk = NULL;
764 frag2->destructor = NULL;
765 skb->truesize += frag2->truesize;
766 }
759 } 767 }
760 768
761slow_path: 769slow_path:
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 13ef5bc05cf5..578f3c1a16db 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb)
113 kfree_skb(NFCT_FRAG6_CB(skb)->orig); 113 kfree_skb(NFCT_FRAG6_CB(skb)->orig);
114} 114}
115 115
116/* Memory Tracking Functions. */
117static void frag_kfree_skb(struct sk_buff *skb)
118{
119 atomic_sub(skb->truesize, &nf_init_frags.mem);
120 nf_skb_free(skb);
121 kfree_skb(skb);
122}
123
124/* Destruction primitives. */ 116/* Destruction primitives. */
125 117
126static __inline__ void fq_put(struct nf_ct_frag6_queue *fq) 118static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
@@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
282 } 274 }
283 275
284found: 276found:
285 /* We found where to put this one. Check for overlap with 277 /* RFC5722, Section 4:
286 * preceding fragment, and, if needed, align things so that 278 * When reassembling an IPv6 datagram, if
287 * any overlaps are eliminated. 279 * one or more its constituent fragments is determined to be an
288 */ 280 * overlapping fragment, the entire datagram (and any constituent
289 if (prev) { 281 * fragments, including those not yet received) MUST be silently
290 int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset; 282 * discarded.
291
292 if (i > 0) {
293 offset += i;
294 if (end <= offset) {
295 pr_debug("overlap\n");
296 goto err;
297 }
298 if (!pskb_pull(skb, i)) {
299 pr_debug("Can't pull\n");
300 goto err;
301 }
302 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
303 skb->ip_summed = CHECKSUM_NONE;
304 }
305 }
306
307 /* Look for overlap with succeeding segments.
308 * If we can merge fragments, do it.
309 */ 283 */
310 while (next && NFCT_FRAG6_CB(next)->offset < end) {
311 /* overlap is 'i' bytes */
312 int i = end - NFCT_FRAG6_CB(next)->offset;
313
314 if (i < next->len) {
315 /* Eat head of the next overlapped fragment
316 * and leave the loop. The next ones cannot overlap.
317 */
318 pr_debug("Eat head of the overlapped parts.: %d", i);
319 if (!pskb_pull(next, i))
320 goto err;
321 284
322 /* next fragment */ 285 /* Check for overlap with preceding fragment. */
323 NFCT_FRAG6_CB(next)->offset += i; 286 if (prev &&
324 fq->q.meat -= i; 287 (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0)
325 if (next->ip_summed != CHECKSUM_UNNECESSARY) 288 goto discard_fq;
326 next->ip_summed = CHECKSUM_NONE;
327 break;
328 } else {
329 struct sk_buff *free_it = next;
330
331 /* Old fragmnet is completely overridden with
332 * new one drop it.
333 */
334 next = next->next;
335 289
336 if (prev) 290 /* Look for overlap with succeeding segment. */
337 prev->next = next; 291 if (next && NFCT_FRAG6_CB(next)->offset < end)
338 else 292 goto discard_fq;
339 fq->q.fragments = next;
340
341 fq->q.meat -= free_it->len;
342 frag_kfree_skb(free_it);
343 }
344 }
345 293
346 NFCT_FRAG6_CB(skb)->offset = offset; 294 NFCT_FRAG6_CB(skb)->offset = offset;
347 295
@@ -371,6 +319,8 @@ found:
371 write_unlock(&nf_frags.lock); 319 write_unlock(&nf_frags.lock);
372 return 0; 320 return 0;
373 321
322discard_fq:
323 fq_kill(fq);
374err: 324err:
375 return -1; 325 return -1;
376} 326}
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 545c4141b755..64cfef1b0a4c 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a)
149} 149}
150EXPORT_SYMBOL(ip6_frag_match); 150EXPORT_SYMBOL(ip6_frag_match);
151 151
152/* Memory Tracking Functions. */
153static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
154{
155 atomic_sub(skb->truesize, &nf->mem);
156 kfree_skb(skb);
157}
158
159void ip6_frag_init(struct inet_frag_queue *q, void *a) 152void ip6_frag_init(struct inet_frag_queue *q, void *a)
160{ 153{
161 struct frag_queue *fq = container_of(q, struct frag_queue, q); 154 struct frag_queue *fq = container_of(q, struct frag_queue, q);
@@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
346 } 339 }
347 340
348found: 341found:
349 /* We found where to put this one. Check for overlap with 342 /* RFC5722, Section 4:
350 * preceding fragment, and, if needed, align things so that 343 * When reassembling an IPv6 datagram, if
351 * any overlaps are eliminated. 344 * one or more its constituent fragments is determined to be an
345 * overlapping fragment, the entire datagram (and any constituent
346 * fragments, including those not yet received) MUST be silently
347 * discarded.
352 */ 348 */
353 if (prev) {
354 int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
355 349
356 if (i > 0) { 350 /* Check for overlap with preceding fragment. */
357 offset += i; 351 if (prev &&
358 if (end <= offset) 352 (FRAG6_CB(prev)->offset + prev->len) - offset > 0)
359 goto err; 353 goto discard_fq;
360 if (!pskb_pull(skb, i))
361 goto err;
362 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
363 skb->ip_summed = CHECKSUM_NONE;
364 }
365 }
366 354
367 /* Look for overlap with succeeding segments. 355 /* Look for overlap with succeeding segment. */
368 * If we can merge fragments, do it. 356 if (next && FRAG6_CB(next)->offset < end)
369 */ 357 goto discard_fq;
370 while (next && FRAG6_CB(next)->offset < end) {
371 int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
372
373 if (i < next->len) {
374 /* Eat head of the next overlapped fragment
375 * and leave the loop. The next ones cannot overlap.
376 */
377 if (!pskb_pull(next, i))
378 goto err;
379 FRAG6_CB(next)->offset += i; /* next fragment */
380 fq->q.meat -= i;
381 if (next->ip_summed != CHECKSUM_UNNECESSARY)
382 next->ip_summed = CHECKSUM_NONE;
383 break;
384 } else {
385 struct sk_buff *free_it = next;
386
387 /* Old fragment is completely overridden with
388 * new one drop it.
389 */
390 next = next->next;
391
392 if (prev)
393 prev->next = next;
394 else
395 fq->q.fragments = next;
396
397 fq->q.meat -= free_it->len;
398 frag_kfree_skb(fq->q.net, free_it);
399 }
400 }
401 358
402 FRAG6_CB(skb)->offset = offset; 359 FRAG6_CB(skb)->offset = offset;
403 360
@@ -436,6 +393,8 @@ found:
436 write_unlock(&ip6_frags.lock); 393 write_unlock(&ip6_frags.lock);
437 return -1; 394 return -1;
438 395
396discard_fq:
397 fq_kill(fq);
439err: 398err:
440 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 399 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
441 IPSTATS_MIB_REASMFAILS); 400 IPSTATS_MIB_REASMFAILS);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index d126365ac046..8323136bdc54 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -670,7 +670,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
670 670
671 if (net_ratelimit()) 671 if (net_ratelimit())
672 printk(KERN_WARNING 672 printk(KERN_WARNING
673 "Neighbour table overflow.\n"); 673 "ipv6: Neighbour table overflow.\n");
674 dst_free(&rt->dst); 674 dst_free(&rt->dst);
675 return NULL; 675 return NULL;
676 } 676 }
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 1dd1affdead2..5acb3560ff15 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
111 return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr); 111 return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr);
112} 112}
113 113
114static void udp_v6_rehash(struct sock *sk)
115{
116 u16 new_hash = udp6_portaddr_hash(sock_net(sk),
117 &inet6_sk(sk)->rcv_saddr,
118 inet_sk(sk)->inet_num);
119
120 udp_lib_rehash(sk, new_hash);
121}
122
114static inline int compute_score(struct sock *sk, struct net *net, 123static inline int compute_score(struct sock *sk, struct net *net,
115 unsigned short hnum, 124 unsigned short hnum,
116 struct in6_addr *saddr, __be16 sport, 125 struct in6_addr *saddr, __be16 sport,
@@ -1447,6 +1456,7 @@ struct proto udpv6_prot = {
1447 .backlog_rcv = udpv6_queue_rcv_skb, 1456 .backlog_rcv = udpv6_queue_rcv_skb,
1448 .hash = udp_lib_hash, 1457 .hash = udp_lib_hash,
1449 .unhash = udp_lib_unhash, 1458 .unhash = udp_lib_unhash,
1459 .rehash = udp_v6_rehash,
1450 .get_port = udp_v6_get_port, 1460 .get_port = udp_v6_get_port,
1451 .memory_allocated = &udp_memory_allocated, 1461 .memory_allocated = &udp_memory_allocated,
1452 .sysctl_mem = sysctl_udp_mem, 1462 .sysctl_mem = sysctl_udp_mem,
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index f417b77fa0e1..a67575d472a3 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -20,23 +20,27 @@
20#include <net/addrconf.h> 20#include <net/addrconf.h>
21 21
22static void 22static void
23__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, 23__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
24 struct xfrm_tmpl *tmpl,
25 xfrm_address_t *daddr, xfrm_address_t *saddr)
26{ 24{
27 /* Initialize temporary selector matching only 25 /* Initialize temporary selector matching only
28 * to current session. */ 26 * to current session. */
29 ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst); 27 ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst);
30 ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src); 28 ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src);
31 x->sel.dport = xfrm_flowi_dport(fl); 29 sel->dport = xfrm_flowi_dport(fl);
32 x->sel.dport_mask = htons(0xffff); 30 sel->dport_mask = htons(0xffff);
33 x->sel.sport = xfrm_flowi_sport(fl); 31 sel->sport = xfrm_flowi_sport(fl);
34 x->sel.sport_mask = htons(0xffff); 32 sel->sport_mask = htons(0xffff);
35 x->sel.family = AF_INET6; 33 sel->family = AF_INET6;
36 x->sel.prefixlen_d = 128; 34 sel->prefixlen_d = 128;
37 x->sel.prefixlen_s = 128; 35 sel->prefixlen_s = 128;
38 x->sel.proto = fl->proto; 36 sel->proto = fl->proto;
39 x->sel.ifindex = fl->oif; 37 sel->ifindex = fl->oif;
38}
39
40static void
41xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
42 xfrm_address_t *daddr, xfrm_address_t *saddr)
43{
40 x->id = tmpl->id; 44 x->id = tmpl->id;
41 if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) 45 if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
42 memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); 46 memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr));
@@ -168,6 +172,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
168 .eth_proto = htons(ETH_P_IPV6), 172 .eth_proto = htons(ETH_P_IPV6),
169 .owner = THIS_MODULE, 173 .owner = THIS_MODULE,
170 .init_tempsel = __xfrm6_init_tempsel, 174 .init_tempsel = __xfrm6_init_tempsel,
175 .init_temprop = xfrm6_init_temprop,
171 .tmpl_sort = __xfrm6_tmpl_sort, 176 .tmpl_sort = __xfrm6_tmpl_sort,
172 .state_sort = __xfrm6_state_sort, 177 .state_sort = __xfrm6_state_sort,
173 .output = xfrm6_output, 178 .output = xfrm6_output,