diff options
Diffstat (limited to 'net/ipv6')
42 files changed, 1767 insertions, 1230 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index a578096152ab..36d7437ac054 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -229,6 +229,20 @@ config IPV6_MROUTE | |||
229 | Experimental support for IPv6 multicast forwarding. | 229 | Experimental support for IPv6 multicast forwarding. |
230 | If unsure, say N. | 230 | If unsure, say N. |
231 | 231 | ||
232 | config IPV6_MROUTE_MULTIPLE_TABLES | ||
233 | bool "IPv6: multicast policy routing" | ||
234 | depends on IPV6_MROUTE | ||
235 | select FIB_RULES | ||
236 | help | ||
237 | Normally, a multicast router runs a userspace daemon and decides | ||
238 | what to do with a multicast packet based on the source and | ||
239 | destination addresses. If you say Y here, the multicast router | ||
240 | will also be able to take interfaces and packet marks into | ||
241 | account and run multiple instances of userspace daemons | ||
242 | simultaneously, each one handling a single table. | ||
243 | |||
244 | If unsure, say N. | ||
245 | |||
232 | config IPV6_PIMSM_V2 | 246 | config IPV6_PIMSM_V2 |
233 | bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)" | 247 | bool "IPv6: PIM-SM version 2 support (EXPERIMENTAL)" |
234 | depends on IPV6_MROUTE | 248 | depends on IPV6_MROUTE |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 413054f02aab..e1a698df5706 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -82,7 +82,7 @@ | |||
82 | #include <linux/random.h> | 82 | #include <linux/random.h> |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | #include <asm/uaccess.h> | 85 | #include <linux/uaccess.h> |
86 | #include <asm/unaligned.h> | 86 | #include <asm/unaligned.h> |
87 | 87 | ||
88 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
@@ -98,7 +98,11 @@ | |||
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
101 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | 101 | #define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b))) |
102 | |||
103 | #define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ/50 : 1) | ||
104 | #define ADDRCONF_TIMER_FUZZ (HZ / 4) | ||
105 | #define ADDRCONF_TIMER_FUZZ_MAX (HZ) | ||
102 | 106 | ||
103 | #ifdef CONFIG_SYSCTL | 107 | #ifdef CONFIG_SYSCTL |
104 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 108 | static void addrconf_sysctl_register(struct inet6_dev *idev); |
@@ -127,8 +131,8 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
127 | /* | 131 | /* |
128 | * Configured unicast address hash table | 132 | * Configured unicast address hash table |
129 | */ | 133 | */ |
130 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 134 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
131 | static DEFINE_RWLOCK(addrconf_hash_lock); | 135 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
132 | 136 | ||
133 | static void addrconf_verify(unsigned long); | 137 | static void addrconf_verify(unsigned long); |
134 | 138 | ||
@@ -138,8 +142,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); | |||
138 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 142 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
139 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 143 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
140 | 144 | ||
141 | static void addrconf_bonding_change(struct net_device *dev, | 145 | static void addrconf_type_change(struct net_device *dev, |
142 | unsigned long event); | 146 | unsigned long event); |
143 | static int addrconf_ifdown(struct net_device *dev, int how); | 147 | static int addrconf_ifdown(struct net_device *dev, int how); |
144 | 148 | ||
145 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 149 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
@@ -152,8 +156,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |||
152 | 156 | ||
153 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 157 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
154 | struct prefix_info *pinfo); | 158 | struct prefix_info *pinfo); |
155 | static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 159 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
156 | struct net_device *dev); | 160 | struct net_device *dev); |
157 | 161 | ||
158 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 162 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
159 | 163 | ||
@@ -250,8 +254,7 @@ static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |||
250 | __in6_ifa_put(ifp); | 254 | __in6_ifa_put(ifp); |
251 | } | 255 | } |
252 | 256 | ||
253 | enum addrconf_timer_t | 257 | enum addrconf_timer_t { |
254 | { | ||
255 | AC_NONE, | 258 | AC_NONE, |
256 | AC_DAD, | 259 | AC_DAD, |
257 | AC_RS, | 260 | AC_RS, |
@@ -271,7 +274,8 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
271 | case AC_RS: | 274 | case AC_RS: |
272 | ifp->timer.function = addrconf_rs_timer; | 275 | ifp->timer.function = addrconf_rs_timer; |
273 | break; | 276 | break; |
274 | default:; | 277 | default: |
278 | break; | ||
275 | } | 279 | } |
276 | ifp->timer.expires = jiffies + when; | 280 | ifp->timer.expires = jiffies + when; |
277 | add_timer(&ifp->timer); | 281 | add_timer(&ifp->timer); |
@@ -318,7 +322,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
318 | { | 322 | { |
319 | struct net_device *dev = idev->dev; | 323 | struct net_device *dev = idev->dev; |
320 | 324 | ||
321 | WARN_ON(idev->addr_list != NULL); | 325 | WARN_ON(!list_empty(&idev->addr_list)); |
322 | WARN_ON(idev->mc_list != NULL); | 326 | WARN_ON(idev->mc_list != NULL); |
323 | 327 | ||
324 | #ifdef NET_REFCNT_DEBUG | 328 | #ifdef NET_REFCNT_DEBUG |
@@ -326,7 +330,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
326 | #endif | 330 | #endif |
327 | dev_put(dev); | 331 | dev_put(dev); |
328 | if (!idev->dead) { | 332 | if (!idev->dead) { |
329 | printk("Freeing alive inet6 device %p\n", idev); | 333 | pr_warning("Freeing alive inet6 device %p\n", idev); |
330 | return; | 334 | return; |
331 | } | 335 | } |
332 | snmp6_free_dev(idev); | 336 | snmp6_free_dev(idev); |
@@ -351,6 +355,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
351 | 355 | ||
352 | rwlock_init(&ndev->lock); | 356 | rwlock_init(&ndev->lock); |
353 | ndev->dev = dev; | 357 | ndev->dev = dev; |
358 | INIT_LIST_HEAD(&ndev->addr_list); | ||
359 | |||
354 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 360 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
355 | ndev->cnf.mtu6 = dev->mtu; | 361 | ndev->cnf.mtu6 = dev->mtu; |
356 | ndev->cnf.sysctl = NULL; | 362 | ndev->cnf.sysctl = NULL; |
@@ -402,6 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
402 | #endif | 408 | #endif |
403 | 409 | ||
404 | #ifdef CONFIG_IPV6_PRIVACY | 410 | #ifdef CONFIG_IPV6_PRIVACY |
411 | INIT_LIST_HEAD(&ndev->tempaddr_list); | ||
405 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); | 412 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); |
406 | if ((dev->flags&IFF_LOOPBACK) || | 413 | if ((dev->flags&IFF_LOOPBACK) || |
407 | dev->type == ARPHRD_TUNNEL || | 414 | dev->type == ARPHRD_TUNNEL || |
@@ -439,8 +446,10 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
439 | 446 | ||
440 | ASSERT_RTNL(); | 447 | ASSERT_RTNL(); |
441 | 448 | ||
442 | if ((idev = __in6_dev_get(dev)) == NULL) { | 449 | idev = __in6_dev_get(dev); |
443 | if ((idev = ipv6_add_dev(dev)) == NULL) | 450 | if (!idev) { |
451 | idev = ipv6_add_dev(dev); | ||
452 | if (!idev) | ||
444 | return NULL; | 453 | return NULL; |
445 | } | 454 | } |
446 | 455 | ||
@@ -466,7 +475,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
466 | else | 475 | else |
467 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); | 476 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
468 | } | 477 | } |
469 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 478 | |
479 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
470 | if (ifa->flags&IFA_F_TENTATIVE) | 480 | if (ifa->flags&IFA_F_TENTATIVE) |
471 | continue; | 481 | continue; |
472 | if (idev->cnf.forwarding) | 482 | if (idev->cnf.forwarding) |
@@ -523,12 +533,16 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
523 | } | 533 | } |
524 | #endif | 534 | #endif |
525 | 535 | ||
526 | /* Nobody refers to this ifaddr, destroy it */ | 536 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) |
537 | { | ||
538 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
539 | kfree(ifp); | ||
540 | } | ||
527 | 541 | ||
542 | /* Nobody refers to this ifaddr, destroy it */ | ||
528 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 543 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
529 | { | 544 | { |
530 | WARN_ON(ifp->if_next != NULL); | 545 | WARN_ON(!hlist_unhashed(&ifp->addr_lst)); |
531 | WARN_ON(ifp->lst_next != NULL); | ||
532 | 546 | ||
533 | #ifdef NET_REFCNT_DEBUG | 547 | #ifdef NET_REFCNT_DEBUG |
534 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); | 548 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); |
@@ -537,54 +551,46 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
537 | in6_dev_put(ifp->idev); | 551 | in6_dev_put(ifp->idev); |
538 | 552 | ||
539 | if (del_timer(&ifp->timer)) | 553 | if (del_timer(&ifp->timer)) |
540 | printk("Timer is still running, when freeing ifa=%p\n", ifp); | 554 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
541 | 555 | ||
542 | if (!ifp->dead) { | 556 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
543 | printk("Freeing alive inet6 address %p\n", ifp); | 557 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
544 | return; | 558 | return; |
545 | } | 559 | } |
546 | dst_release(&ifp->rt->u.dst); | 560 | dst_release(&ifp->rt->u.dst); |
547 | 561 | ||
548 | kfree(ifp); | 562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
549 | } | 563 | } |
550 | 564 | ||
551 | static void | 565 | static void |
552 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | 566 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) |
553 | { | 567 | { |
554 | struct inet6_ifaddr *ifa, **ifap; | 568 | struct list_head *p; |
555 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); | 569 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); |
556 | 570 | ||
557 | /* | 571 | /* |
558 | * Each device address list is sorted in order of scope - | 572 | * Each device address list is sorted in order of scope - |
559 | * global before linklocal. | 573 | * global before linklocal. |
560 | */ | 574 | */ |
561 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | 575 | list_for_each(p, &idev->addr_list) { |
562 | ifap = &ifa->if_next) { | 576 | struct inet6_ifaddr *ifa |
577 | = list_entry(p, struct inet6_ifaddr, if_list); | ||
563 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) | 578 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) |
564 | break; | 579 | break; |
565 | } | 580 | } |
566 | 581 | ||
567 | ifp->if_next = *ifap; | 582 | list_add_tail(&ifp->if_list, p); |
568 | *ifap = ifp; | ||
569 | } | 583 | } |
570 | 584 | ||
571 | /* | 585 | static u32 ipv6_addr_hash(const struct in6_addr *addr) |
572 | * Hash function taken from net_alias.c | ||
573 | */ | ||
574 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
575 | { | 586 | { |
576 | __u32 word; | ||
577 | |||
578 | /* | 587 | /* |
579 | * We perform the hash function over the last 64 bits of the address | 588 | * We perform the hash function over the last 64 bits of the address |
580 | * This will include the IEEE address token on links that support it. | 589 | * This will include the IEEE address token on links that support it. |
581 | */ | 590 | */ |
582 | 591 | return jhash_2words((__force u32)addr->s6_addr32[2], | |
583 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | 592 | (__force u32)addr->s6_addr32[3], 0) |
584 | word ^= (word >> 16); | 593 | & (IN6_ADDR_HSIZE - 1); |
585 | word ^= (word >> 8); | ||
586 | |||
587 | return ((word ^ (word >> 4)) & 0x0f); | ||
588 | } | 594 | } |
589 | 595 | ||
590 | /* On success it returns ifp with increased reference count */ | 596 | /* On success it returns ifp with increased reference count */ |
@@ -595,7 +601,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
595 | { | 601 | { |
596 | struct inet6_ifaddr *ifa = NULL; | 602 | struct inet6_ifaddr *ifa = NULL; |
597 | struct rt6_info *rt; | 603 | struct rt6_info *rt; |
598 | int hash; | 604 | unsigned int hash; |
599 | int err = 0; | 605 | int err = 0; |
600 | int addr_type = ipv6_addr_type(addr); | 606 | int addr_type = ipv6_addr_type(addr); |
601 | 607 | ||
@@ -616,7 +622,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
616 | goto out2; | 622 | goto out2; |
617 | } | 623 | } |
618 | 624 | ||
619 | write_lock(&addrconf_hash_lock); | 625 | spin_lock(&addrconf_hash_lock); |
620 | 626 | ||
621 | /* Ignore adding duplicate addresses on an interface */ | 627 | /* Ignore adding duplicate addresses on an interface */ |
622 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | 628 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
@@ -642,7 +648,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
642 | ipv6_addr_copy(&ifa->addr, addr); | 648 | ipv6_addr_copy(&ifa->addr, addr); |
643 | 649 | ||
644 | spin_lock_init(&ifa->lock); | 650 | spin_lock_init(&ifa->lock); |
651 | spin_lock_init(&ifa->state_lock); | ||
645 | init_timer(&ifa->timer); | 652 | init_timer(&ifa->timer); |
653 | INIT_HLIST_NODE(&ifa->addr_lst); | ||
646 | ifa->timer.data = (unsigned long) ifa; | 654 | ifa->timer.data = (unsigned long) ifa; |
647 | ifa->scope = scope; | 655 | ifa->scope = scope; |
648 | ifa->prefix_len = pfxlen; | 656 | ifa->prefix_len = pfxlen; |
@@ -669,10 +677,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
669 | /* Add to big hash table */ | 677 | /* Add to big hash table */ |
670 | hash = ipv6_addr_hash(addr); | 678 | hash = ipv6_addr_hash(addr); |
671 | 679 | ||
672 | ifa->lst_next = inet6_addr_lst[hash]; | 680 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
673 | inet6_addr_lst[hash] = ifa; | 681 | spin_unlock(&addrconf_hash_lock); |
674 | in6_ifa_hold(ifa); | ||
675 | write_unlock(&addrconf_hash_lock); | ||
676 | 682 | ||
677 | write_lock(&idev->lock); | 683 | write_lock(&idev->lock); |
678 | /* Add to inet6_dev unicast addr list. */ | 684 | /* Add to inet6_dev unicast addr list. */ |
@@ -680,8 +686,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
680 | 686 | ||
681 | #ifdef CONFIG_IPV6_PRIVACY | 687 | #ifdef CONFIG_IPV6_PRIVACY |
682 | if (ifa->flags&IFA_F_TEMPORARY) { | 688 | if (ifa->flags&IFA_F_TEMPORARY) { |
683 | ifa->tmp_next = idev->tempaddr_list; | 689 | list_add(&ifa->tmp_list, &idev->tempaddr_list); |
684 | idev->tempaddr_list = ifa; | ||
685 | in6_ifa_hold(ifa); | 690 | in6_ifa_hold(ifa); |
686 | } | 691 | } |
687 | #endif | 692 | #endif |
@@ -700,7 +705,7 @@ out2: | |||
700 | 705 | ||
701 | return ifa; | 706 | return ifa; |
702 | out: | 707 | out: |
703 | write_unlock(&addrconf_hash_lock); | 708 | spin_unlock(&addrconf_hash_lock); |
704 | goto out2; | 709 | goto out2; |
705 | } | 710 | } |
706 | 711 | ||
@@ -708,52 +713,44 @@ out: | |||
708 | 713 | ||
709 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) | 714 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) |
710 | { | 715 | { |
711 | struct inet6_ifaddr *ifa, **ifap; | 716 | struct inet6_ifaddr *ifa, *ifn; |
712 | struct inet6_dev *idev = ifp->idev; | 717 | struct inet6_dev *idev = ifp->idev; |
718 | int state; | ||
713 | int hash; | 719 | int hash; |
714 | int deleted = 0, onlink = 0; | 720 | int deleted = 0, onlink = 0; |
715 | unsigned long expires = jiffies; | 721 | unsigned long expires = jiffies; |
716 | 722 | ||
717 | hash = ipv6_addr_hash(&ifp->addr); | 723 | hash = ipv6_addr_hash(&ifp->addr); |
718 | 724 | ||
719 | ifp->dead = 1; | 725 | spin_lock_bh(&ifp->state_lock); |
726 | state = ifp->state; | ||
727 | ifp->state = INET6_IFADDR_STATE_DEAD; | ||
728 | spin_unlock_bh(&ifp->state_lock); | ||
720 | 729 | ||
721 | write_lock_bh(&addrconf_hash_lock); | 730 | if (state == INET6_IFADDR_STATE_DEAD) |
722 | for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL; | 731 | goto out; |
723 | ifap = &ifa->lst_next) { | 732 | |
724 | if (ifa == ifp) { | 733 | spin_lock_bh(&addrconf_hash_lock); |
725 | *ifap = ifa->lst_next; | 734 | hlist_del_init_rcu(&ifp->addr_lst); |
726 | __in6_ifa_put(ifp); | 735 | spin_unlock_bh(&addrconf_hash_lock); |
727 | ifa->lst_next = NULL; | ||
728 | break; | ||
729 | } | ||
730 | } | ||
731 | write_unlock_bh(&addrconf_hash_lock); | ||
732 | 736 | ||
733 | write_lock_bh(&idev->lock); | 737 | write_lock_bh(&idev->lock); |
734 | #ifdef CONFIG_IPV6_PRIVACY | 738 | #ifdef CONFIG_IPV6_PRIVACY |
735 | if (ifp->flags&IFA_F_TEMPORARY) { | 739 | if (ifp->flags&IFA_F_TEMPORARY) { |
736 | for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL; | 740 | list_del(&ifp->tmp_list); |
737 | ifap = &ifa->tmp_next) { | 741 | if (ifp->ifpub) { |
738 | if (ifa == ifp) { | 742 | in6_ifa_put(ifp->ifpub); |
739 | *ifap = ifa->tmp_next; | 743 | ifp->ifpub = NULL; |
740 | if (ifp->ifpub) { | ||
741 | in6_ifa_put(ifp->ifpub); | ||
742 | ifp->ifpub = NULL; | ||
743 | } | ||
744 | __in6_ifa_put(ifp); | ||
745 | ifa->tmp_next = NULL; | ||
746 | break; | ||
747 | } | ||
748 | } | 744 | } |
745 | __in6_ifa_put(ifp); | ||
749 | } | 746 | } |
750 | #endif | 747 | #endif |
751 | 748 | ||
752 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { | 749 | list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) { |
753 | if (ifa == ifp) { | 750 | if (ifa == ifp) { |
754 | *ifap = ifa->if_next; | 751 | list_del_init(&ifp->if_list); |
755 | __in6_ifa_put(ifp); | 752 | __in6_ifa_put(ifp); |
756 | ifa->if_next = NULL; | 753 | |
757 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 754 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
758 | break; | 755 | break; |
759 | deleted = 1; | 756 | deleted = 1; |
@@ -786,7 +783,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
786 | } | 783 | } |
787 | } | 784 | } |
788 | } | 785 | } |
789 | ifap = &ifa->if_next; | ||
790 | } | 786 | } |
791 | write_unlock_bh(&idev->lock); | 787 | write_unlock_bh(&idev->lock); |
792 | 788 | ||
@@ -830,6 +826,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
830 | dst_release(&rt->u.dst); | 826 | dst_release(&rt->u.dst); |
831 | } | 827 | } |
832 | 828 | ||
829 | out: | ||
833 | in6_ifa_put(ifp); | 830 | in6_ifa_put(ifp); |
834 | } | 831 | } |
835 | 832 | ||
@@ -1165,7 +1162,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1165 | continue; | 1162 | continue; |
1166 | 1163 | ||
1167 | read_lock_bh(&idev->lock); | 1164 | read_lock_bh(&idev->lock); |
1168 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { | 1165 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { |
1169 | int i; | 1166 | int i; |
1170 | 1167 | ||
1171 | /* | 1168 | /* |
@@ -1243,7 +1240,6 @@ try_nextdev: | |||
1243 | in6_ifa_put(hiscore->ifa); | 1240 | in6_ifa_put(hiscore->ifa); |
1244 | return 0; | 1241 | return 0; |
1245 | } | 1242 | } |
1246 | |||
1247 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1243 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
1248 | 1244 | ||
1249 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1245 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
@@ -1253,12 +1249,14 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1253 | int err = -EADDRNOTAVAIL; | 1249 | int err = -EADDRNOTAVAIL; |
1254 | 1250 | ||
1255 | rcu_read_lock(); | 1251 | rcu_read_lock(); |
1256 | if ((idev = __in6_dev_get(dev)) != NULL) { | 1252 | idev = __in6_dev_get(dev); |
1253 | if (idev) { | ||
1257 | struct inet6_ifaddr *ifp; | 1254 | struct inet6_ifaddr *ifp; |
1258 | 1255 | ||
1259 | read_lock_bh(&idev->lock); | 1256 | read_lock_bh(&idev->lock); |
1260 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1257 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1261 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { | 1258 | if (ifp->scope == IFA_LINK && |
1259 | !(ifp->flags & banned_flags)) { | ||
1262 | ipv6_addr_copy(addr, &ifp->addr); | 1260 | ipv6_addr_copy(addr, &ifp->addr); |
1263 | err = 0; | 1261 | err = 0; |
1264 | break; | 1262 | break; |
@@ -1276,7 +1274,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1276 | struct inet6_ifaddr *ifp; | 1274 | struct inet6_ifaddr *ifp; |
1277 | 1275 | ||
1278 | read_lock_bh(&idev->lock); | 1276 | read_lock_bh(&idev->lock); |
1279 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) | 1277 | list_for_each_entry(ifp, &idev->addr_list, if_list) |
1280 | cnt++; | 1278 | cnt++; |
1281 | read_unlock_bh(&idev->lock); | 1279 | read_unlock_bh(&idev->lock); |
1282 | return cnt; | 1280 | return cnt; |
@@ -1285,41 +1283,44 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1285 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1283 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, |
1286 | struct net_device *dev, int strict) | 1284 | struct net_device *dev, int strict) |
1287 | { | 1285 | { |
1288 | struct inet6_ifaddr * ifp; | 1286 | struct inet6_ifaddr *ifp; |
1289 | u8 hash = ipv6_addr_hash(addr); | 1287 | struct hlist_node *node; |
1288 | unsigned int hash = ipv6_addr_hash(addr); | ||
1290 | 1289 | ||
1291 | read_lock_bh(&addrconf_hash_lock); | 1290 | rcu_read_lock_bh(); |
1292 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1291 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1293 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1292 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1294 | continue; | 1293 | continue; |
1295 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1294 | if (ipv6_addr_equal(&ifp->addr, addr) && |
1296 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1295 | !(ifp->flags&IFA_F_TENTATIVE) && |
1297 | if (dev == NULL || ifp->idev->dev == dev || | 1296 | (dev == NULL || ifp->idev->dev == dev || |
1298 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) | 1297 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) { |
1299 | break; | 1298 | rcu_read_unlock_bh(); |
1299 | return 1; | ||
1300 | } | 1300 | } |
1301 | } | 1301 | } |
1302 | read_unlock_bh(&addrconf_hash_lock); | 1302 | |
1303 | return ifp != NULL; | 1303 | rcu_read_unlock_bh(); |
1304 | return 0; | ||
1304 | } | 1305 | } |
1305 | EXPORT_SYMBOL(ipv6_chk_addr); | 1306 | EXPORT_SYMBOL(ipv6_chk_addr); |
1306 | 1307 | ||
1307 | static | 1308 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
1308 | int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1309 | struct net_device *dev) |
1309 | struct net_device *dev) | ||
1310 | { | 1310 | { |
1311 | struct inet6_ifaddr * ifp; | 1311 | unsigned int hash = ipv6_addr_hash(addr); |
1312 | u8 hash = ipv6_addr_hash(addr); | 1312 | struct inet6_ifaddr *ifp; |
1313 | struct hlist_node *node; | ||
1313 | 1314 | ||
1314 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1315 | hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1315 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1316 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1316 | continue; | 1317 | continue; |
1317 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1318 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1318 | if (dev == NULL || ifp->idev->dev == dev) | 1319 | if (dev == NULL || ifp->idev->dev == dev) |
1319 | break; | 1320 | return true; |
1320 | } | 1321 | } |
1321 | } | 1322 | } |
1322 | return ifp != NULL; | 1323 | return false; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1326 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
@@ -1333,7 +1334,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
1333 | idev = __in6_dev_get(dev); | 1334 | idev = __in6_dev_get(dev); |
1334 | if (idev) { | 1335 | if (idev) { |
1335 | read_lock_bh(&idev->lock); | 1336 | read_lock_bh(&idev->lock); |
1336 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1337 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
1337 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | 1338 | onlink = ipv6_prefix_equal(addr, &ifa->addr, |
1338 | ifa->prefix_len); | 1339 | ifa->prefix_len); |
1339 | if (onlink) | 1340 | if (onlink) |
@@ -1350,24 +1351,26 @@ EXPORT_SYMBOL(ipv6_chk_prefix); | |||
1350 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | 1351 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
1351 | struct net_device *dev, int strict) | 1352 | struct net_device *dev, int strict) |
1352 | { | 1353 | { |
1353 | struct inet6_ifaddr * ifp; | 1354 | struct inet6_ifaddr *ifp, *result = NULL; |
1354 | u8 hash = ipv6_addr_hash(addr); | 1355 | unsigned int hash = ipv6_addr_hash(addr); |
1356 | struct hlist_node *node; | ||
1355 | 1357 | ||
1356 | read_lock_bh(&addrconf_hash_lock); | 1358 | rcu_read_lock_bh(); |
1357 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1359 | hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1358 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1360 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1359 | continue; | 1361 | continue; |
1360 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1362 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1361 | if (dev == NULL || ifp->idev->dev == dev || | 1363 | if (dev == NULL || ifp->idev->dev == dev || |
1362 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { | 1364 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { |
1365 | result = ifp; | ||
1363 | in6_ifa_hold(ifp); | 1366 | in6_ifa_hold(ifp); |
1364 | break; | 1367 | break; |
1365 | } | 1368 | } |
1366 | } | 1369 | } |
1367 | } | 1370 | } |
1368 | read_unlock_bh(&addrconf_hash_lock); | 1371 | rcu_read_unlock_bh(); |
1369 | 1372 | ||
1370 | return ifp; | 1373 | return result; |
1371 | } | 1374 | } |
1372 | 1375 | ||
1373 | /* Gets referenced address, destroys ifaddr */ | 1376 | /* Gets referenced address, destroys ifaddr */ |
@@ -1403,10 +1406,27 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1403 | ipv6_del_addr(ifp); | 1406 | ipv6_del_addr(ifp); |
1404 | } | 1407 | } |
1405 | 1408 | ||
1409 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | ||
1410 | { | ||
1411 | int err = -ENOENT; | ||
1412 | |||
1413 | spin_lock(&ifp->state_lock); | ||
1414 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | ||
1415 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
1416 | err = 0; | ||
1417 | } | ||
1418 | spin_unlock(&ifp->state_lock); | ||
1419 | |||
1420 | return err; | ||
1421 | } | ||
1422 | |||
1406 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1423 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
1407 | { | 1424 | { |
1408 | struct inet6_dev *idev = ifp->idev; | 1425 | struct inet6_dev *idev = ifp->idev; |
1409 | 1426 | ||
1427 | if (addrconf_dad_end(ifp)) | ||
1428 | return; | ||
1429 | |||
1410 | if (net_ratelimit()) | 1430 | if (net_ratelimit()) |
1411 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1431 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
1412 | ifp->idev->dev->name, &ifp->addr); | 1432 | ifp->idev->dev->name, &ifp->addr); |
@@ -1570,7 +1590,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
1570 | struct inet6_ifaddr *ifp; | 1590 | struct inet6_ifaddr *ifp; |
1571 | 1591 | ||
1572 | read_lock_bh(&idev->lock); | 1592 | read_lock_bh(&idev->lock); |
1573 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1593 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1574 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1594 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { |
1575 | memcpy(eui, ifp->addr.s6_addr+8, 8); | 1595 | memcpy(eui, ifp->addr.s6_addr+8, 8); |
1576 | err = 0; | 1596 | err = 0; |
@@ -1738,7 +1758,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
1738 | 1758 | ||
1739 | ASSERT_RTNL(); | 1759 | ASSERT_RTNL(); |
1740 | 1760 | ||
1741 | if ((idev = ipv6_find_idev(dev)) == NULL) | 1761 | idev = ipv6_find_idev(dev); |
1762 | if (!idev) | ||
1742 | return NULL; | 1763 | return NULL; |
1743 | 1764 | ||
1744 | /* Add default multicast route */ | 1765 | /* Add default multicast route */ |
@@ -1971,7 +1992,7 @@ ok: | |||
1971 | #ifdef CONFIG_IPV6_PRIVACY | 1992 | #ifdef CONFIG_IPV6_PRIVACY |
1972 | read_lock_bh(&in6_dev->lock); | 1993 | read_lock_bh(&in6_dev->lock); |
1973 | /* update all temporary addresses in the list */ | 1994 | /* update all temporary addresses in the list */ |
1974 | for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) { | 1995 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { |
1975 | /* | 1996 | /* |
1976 | * When adjusting the lifetimes of an existing | 1997 | * When adjusting the lifetimes of an existing |
1977 | * temporary address, only lower the lifetimes. | 1998 | * temporary address, only lower the lifetimes. |
@@ -2174,7 +2195,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2174 | return -ENXIO; | 2195 | return -ENXIO; |
2175 | 2196 | ||
2176 | read_lock_bh(&idev->lock); | 2197 | read_lock_bh(&idev->lock); |
2177 | for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { | 2198 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2178 | if (ifp->prefix_len == plen && | 2199 | if (ifp->prefix_len == plen && |
2179 | ipv6_addr_equal(pfx, &ifp->addr)) { | 2200 | ipv6_addr_equal(pfx, &ifp->addr)) { |
2180 | in6_ifa_hold(ifp); | 2201 | in6_ifa_hold(ifp); |
@@ -2185,7 +2206,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2185 | /* If the last address is deleted administratively, | 2206 | /* If the last address is deleted administratively, |
2186 | disable IPv6 on this interface. | 2207 | disable IPv6 on this interface. |
2187 | */ | 2208 | */ |
2188 | if (idev->addr_list == NULL) | 2209 | if (list_empty(&idev->addr_list)) |
2189 | addrconf_ifdown(idev->dev, 1); | 2210 | addrconf_ifdown(idev->dev, 1); |
2190 | return 0; | 2211 | return 0; |
2191 | } | 2212 | } |
@@ -2446,7 +2467,8 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2446 | 2467 | ||
2447 | ASSERT_RTNL(); | 2468 | ASSERT_RTNL(); |
2448 | 2469 | ||
2449 | if ((idev = addrconf_add_dev(dev)) == NULL) { | 2470 | idev = addrconf_add_dev(dev); |
2471 | if (!idev) { | ||
2450 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2472 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
2451 | return; | 2473 | return; |
2452 | } | 2474 | } |
@@ -2461,7 +2483,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2461 | int run_pending = 0; | 2483 | int run_pending = 0; |
2462 | int err; | 2484 | int err; |
2463 | 2485 | ||
2464 | switch(event) { | 2486 | switch (event) { |
2465 | case NETDEV_REGISTER: | 2487 | case NETDEV_REGISTER: |
2466 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2488 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2467 | idev = ipv6_add_dev(dev); | 2489 | idev = ipv6_add_dev(dev); |
@@ -2469,6 +2491,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2469 | return notifier_from_errno(-ENOMEM); | 2491 | return notifier_from_errno(-ENOMEM); |
2470 | } | 2492 | } |
2471 | break; | 2493 | break; |
2494 | |||
2472 | case NETDEV_UP: | 2495 | case NETDEV_UP: |
2473 | case NETDEV_CHANGE: | 2496 | case NETDEV_CHANGE: |
2474 | if (dev->flags & IFF_SLAVE) | 2497 | if (dev->flags & IFF_SLAVE) |
@@ -2498,10 +2521,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2498 | } | 2521 | } |
2499 | 2522 | ||
2500 | if (idev) { | 2523 | if (idev) { |
2501 | if (idev->if_flags & IF_READY) { | 2524 | if (idev->if_flags & IF_READY) |
2502 | /* device is already configured. */ | 2525 | /* device is already configured. */ |
2503 | break; | 2526 | break; |
2504 | } | ||
2505 | idev->if_flags |= IF_READY; | 2527 | idev->if_flags |= IF_READY; |
2506 | } | 2528 | } |
2507 | 2529 | ||
@@ -2513,7 +2535,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2513 | run_pending = 1; | 2535 | run_pending = 1; |
2514 | } | 2536 | } |
2515 | 2537 | ||
2516 | switch(dev->type) { | 2538 | switch (dev->type) { |
2517 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2539 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2518 | case ARPHRD_SIT: | 2540 | case ARPHRD_SIT: |
2519 | addrconf_sit_config(dev); | 2541 | addrconf_sit_config(dev); |
@@ -2530,25 +2552,30 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2530 | addrconf_dev_config(dev); | 2552 | addrconf_dev_config(dev); |
2531 | break; | 2553 | break; |
2532 | } | 2554 | } |
2555 | |||
2533 | if (idev) { | 2556 | if (idev) { |
2534 | if (run_pending) | 2557 | if (run_pending) |
2535 | addrconf_dad_run(idev); | 2558 | addrconf_dad_run(idev); |
2536 | 2559 | ||
2537 | /* If the MTU changed during the interface down, when the | 2560 | /* |
2538 | interface up, the changed MTU must be reflected in the | 2561 | * If the MTU changed during the interface down, |
2539 | idev as well as routers. | 2562 | * when the interface up, the changed MTU must be |
2563 | * reflected in the idev as well as routers. | ||
2540 | */ | 2564 | */ |
2541 | if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) { | 2565 | if (idev->cnf.mtu6 != dev->mtu && |
2566 | dev->mtu >= IPV6_MIN_MTU) { | ||
2542 | rt6_mtu_change(dev, dev->mtu); | 2567 | rt6_mtu_change(dev, dev->mtu); |
2543 | idev->cnf.mtu6 = dev->mtu; | 2568 | idev->cnf.mtu6 = dev->mtu; |
2544 | } | 2569 | } |
2545 | idev->tstamp = jiffies; | 2570 | idev->tstamp = jiffies; |
2546 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2571 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
2547 | /* If the changed mtu during down is lower than IPV6_MIN_MTU | 2572 | |
2548 | stop IPv6 on this interface. | 2573 | /* |
2574 | * If the changed mtu during down is lower than | ||
2575 | * IPV6_MIN_MTU stop IPv6 on this interface. | ||
2549 | */ | 2576 | */ |
2550 | if (dev->mtu < IPV6_MIN_MTU) | 2577 | if (dev->mtu < IPV6_MIN_MTU) |
2551 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2578 | addrconf_ifdown(dev, 1); |
2552 | } | 2579 | } |
2553 | break; | 2580 | break; |
2554 | 2581 | ||
@@ -2565,7 +2592,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2565 | break; | 2592 | break; |
2566 | } | 2593 | } |
2567 | 2594 | ||
2568 | /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ | 2595 | /* |
2596 | * MTU falled under IPV6_MIN_MTU. | ||
2597 | * Stop IPv6 on this interface. | ||
2598 | */ | ||
2569 | 2599 | ||
2570 | case NETDEV_DOWN: | 2600 | case NETDEV_DOWN: |
2571 | case NETDEV_UNREGISTER: | 2601 | case NETDEV_UNREGISTER: |
@@ -2585,9 +2615,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2585 | return notifier_from_errno(err); | 2615 | return notifier_from_errno(err); |
2586 | } | 2616 | } |
2587 | break; | 2617 | break; |
2588 | case NETDEV_BONDING_OLDTYPE: | 2618 | |
2589 | case NETDEV_BONDING_NEWTYPE: | 2619 | case NETDEV_PRE_TYPE_CHANGE: |
2590 | addrconf_bonding_change(dev, event); | 2620 | case NETDEV_POST_TYPE_CHANGE: |
2621 | addrconf_type_change(dev, event); | ||
2591 | break; | 2622 | break; |
2592 | } | 2623 | } |
2593 | 2624 | ||
@@ -2599,28 +2630,28 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2599 | */ | 2630 | */ |
2600 | static struct notifier_block ipv6_dev_notf = { | 2631 | static struct notifier_block ipv6_dev_notf = { |
2601 | .notifier_call = addrconf_notify, | 2632 | .notifier_call = addrconf_notify, |
2602 | .priority = 0 | ||
2603 | }; | 2633 | }; |
2604 | 2634 | ||
2605 | static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | 2635 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
2606 | { | 2636 | { |
2607 | struct inet6_dev *idev; | 2637 | struct inet6_dev *idev; |
2608 | ASSERT_RTNL(); | 2638 | ASSERT_RTNL(); |
2609 | 2639 | ||
2610 | idev = __in6_dev_get(dev); | 2640 | idev = __in6_dev_get(dev); |
2611 | 2641 | ||
2612 | if (event == NETDEV_BONDING_NEWTYPE) | 2642 | if (event == NETDEV_POST_TYPE_CHANGE) |
2613 | ipv6_mc_remap(idev); | 2643 | ipv6_mc_remap(idev); |
2614 | else if (event == NETDEV_BONDING_OLDTYPE) | 2644 | else if (event == NETDEV_PRE_TYPE_CHANGE) |
2615 | ipv6_mc_unmap(idev); | 2645 | ipv6_mc_unmap(idev); |
2616 | } | 2646 | } |
2617 | 2647 | ||
2618 | static int addrconf_ifdown(struct net_device *dev, int how) | 2648 | static int addrconf_ifdown(struct net_device *dev, int how) |
2619 | { | 2649 | { |
2620 | struct inet6_dev *idev; | ||
2621 | struct inet6_ifaddr *ifa, *keep_list, **bifa; | ||
2622 | struct net *net = dev_net(dev); | 2650 | struct net *net = dev_net(dev); |
2623 | int i; | 2651 | struct inet6_dev *idev; |
2652 | struct inet6_ifaddr *ifa; | ||
2653 | LIST_HEAD(keep_list); | ||
2654 | int state; | ||
2624 | 2655 | ||
2625 | ASSERT_RTNL(); | 2656 | ASSERT_RTNL(); |
2626 | 2657 | ||
@@ -2631,8 +2662,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2631 | if (idev == NULL) | 2662 | if (idev == NULL) |
2632 | return -ENODEV; | 2663 | return -ENODEV; |
2633 | 2664 | ||
2634 | /* Step 1: remove reference to ipv6 device from parent device. | 2665 | /* |
2635 | Do not dev_put! | 2666 | * Step 1: remove reference to ipv6 device from parent device. |
2667 | * Do not dev_put! | ||
2636 | */ | 2668 | */ |
2637 | if (how) { | 2669 | if (how) { |
2638 | idev->dead = 1; | 2670 | idev->dead = 1; |
@@ -2645,41 +2677,21 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2645 | 2677 | ||
2646 | } | 2678 | } |
2647 | 2679 | ||
2648 | /* Step 2: clear hash table */ | ||
2649 | for (i=0; i<IN6_ADDR_HSIZE; i++) { | ||
2650 | bifa = &inet6_addr_lst[i]; | ||
2651 | |||
2652 | write_lock_bh(&addrconf_hash_lock); | ||
2653 | while ((ifa = *bifa) != NULL) { | ||
2654 | if (ifa->idev == idev && | ||
2655 | (how || !(ifa->flags&IFA_F_PERMANENT) || | ||
2656 | ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2657 | *bifa = ifa->lst_next; | ||
2658 | ifa->lst_next = NULL; | ||
2659 | __in6_ifa_put(ifa); | ||
2660 | continue; | ||
2661 | } | ||
2662 | bifa = &ifa->lst_next; | ||
2663 | } | ||
2664 | write_unlock_bh(&addrconf_hash_lock); | ||
2665 | } | ||
2666 | |||
2667 | write_lock_bh(&idev->lock); | 2680 | write_lock_bh(&idev->lock); |
2668 | 2681 | ||
2669 | /* Step 3: clear flags for stateless addrconf */ | 2682 | /* Step 2: clear flags for stateless addrconf */ |
2670 | if (!how) | 2683 | if (!how) |
2671 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2684 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
2672 | 2685 | ||
2673 | /* Step 4: clear address list */ | ||
2674 | #ifdef CONFIG_IPV6_PRIVACY | 2686 | #ifdef CONFIG_IPV6_PRIVACY |
2675 | if (how && del_timer(&idev->regen_timer)) | 2687 | if (how && del_timer(&idev->regen_timer)) |
2676 | in6_dev_put(idev); | 2688 | in6_dev_put(idev); |
2677 | 2689 | ||
2678 | /* clear tempaddr list */ | 2690 | /* Step 3: clear tempaddr list */ |
2679 | while ((ifa = idev->tempaddr_list) != NULL) { | 2691 | while (!list_empty(&idev->tempaddr_list)) { |
2680 | idev->tempaddr_list = ifa->tmp_next; | 2692 | ifa = list_first_entry(&idev->tempaddr_list, |
2681 | ifa->tmp_next = NULL; | 2693 | struct inet6_ifaddr, tmp_list); |
2682 | ifa->dead = 1; | 2694 | list_del(&ifa->tmp_list); |
2683 | write_unlock_bh(&idev->lock); | 2695 | write_unlock_bh(&idev->lock); |
2684 | spin_lock_bh(&ifa->lock); | 2696 | spin_lock_bh(&ifa->lock); |
2685 | 2697 | ||
@@ -2692,23 +2704,18 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2692 | write_lock_bh(&idev->lock); | 2704 | write_lock_bh(&idev->lock); |
2693 | } | 2705 | } |
2694 | #endif | 2706 | #endif |
2695 | keep_list = NULL; | ||
2696 | bifa = &keep_list; | ||
2697 | while ((ifa = idev->addr_list) != NULL) { | ||
2698 | idev->addr_list = ifa->if_next; | ||
2699 | ifa->if_next = NULL; | ||
2700 | 2707 | ||
2708 | while (!list_empty(&idev->addr_list)) { | ||
2709 | ifa = list_first_entry(&idev->addr_list, | ||
2710 | struct inet6_ifaddr, if_list); | ||
2701 | addrconf_del_timer(ifa); | 2711 | addrconf_del_timer(ifa); |
2702 | 2712 | ||
2703 | /* If just doing link down, and address is permanent | 2713 | /* If just doing link down, and address is permanent |
2704 | and not link-local, then retain it. */ | 2714 | and not link-local, then retain it. */ |
2705 | if (how == 0 && | 2715 | if (!how && |
2706 | (ifa->flags&IFA_F_PERMANENT) && | 2716 | (ifa->flags&IFA_F_PERMANENT) && |
2707 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | 2717 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { |
2708 | 2718 | list_move_tail(&ifa->if_list, &keep_list); | |
2709 | /* Move to holding list */ | ||
2710 | *bifa = ifa; | ||
2711 | bifa = &ifa->if_next; | ||
2712 | 2719 | ||
2713 | /* If not doing DAD on this address, just keep it. */ | 2720 | /* If not doing DAD on this address, just keep it. */ |
2714 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | 2721 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || |
@@ -2722,25 +2729,45 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2722 | 2729 | ||
2723 | /* Flag it for later restoration when link comes up */ | 2730 | /* Flag it for later restoration when link comes up */ |
2724 | ifa->flags |= IFA_F_TENTATIVE; | 2731 | ifa->flags |= IFA_F_TENTATIVE; |
2732 | ifa->state = INET6_IFADDR_STATE_DAD; | ||
2733 | |||
2734 | write_unlock_bh(&idev->lock); | ||
2735 | |||
2725 | in6_ifa_hold(ifa); | 2736 | in6_ifa_hold(ifa); |
2726 | } else { | 2737 | } else { |
2727 | ifa->dead = 1; | 2738 | list_del(&ifa->if_list); |
2739 | |||
2740 | /* clear hash table */ | ||
2741 | spin_lock_bh(&addrconf_hash_lock); | ||
2742 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2743 | spin_unlock_bh(&addrconf_hash_lock); | ||
2744 | |||
2745 | write_unlock_bh(&idev->lock); | ||
2746 | spin_lock_bh(&ifa->state_lock); | ||
2747 | state = ifa->state; | ||
2748 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
2749 | spin_unlock_bh(&ifa->state_lock); | ||
2750 | |||
2751 | if (state == INET6_IFADDR_STATE_DEAD) | ||
2752 | goto put_ifa; | ||
2728 | } | 2753 | } |
2729 | write_unlock_bh(&idev->lock); | ||
2730 | 2754 | ||
2731 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2755 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2732 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2756 | if (ifa->state == INET6_IFADDR_STATE_DEAD) |
2757 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2758 | NETDEV_DOWN, ifa); | ||
2759 | |||
2760 | put_ifa: | ||
2733 | in6_ifa_put(ifa); | 2761 | in6_ifa_put(ifa); |
2734 | 2762 | ||
2735 | write_lock_bh(&idev->lock); | 2763 | write_lock_bh(&idev->lock); |
2736 | } | 2764 | } |
2737 | 2765 | ||
2738 | idev->addr_list = keep_list; | 2766 | list_splice(&keep_list, &idev->addr_list); |
2739 | 2767 | ||
2740 | write_unlock_bh(&idev->lock); | 2768 | write_unlock_bh(&idev->lock); |
2741 | 2769 | ||
2742 | /* Step 5: Discard multicast list */ | 2770 | /* Step 5: Discard multicast list */ |
2743 | |||
2744 | if (how) | 2771 | if (how) |
2745 | ipv6_mc_destroy_dev(idev); | 2772 | ipv6_mc_destroy_dev(idev); |
2746 | else | 2773 | else |
@@ -2748,8 +2775,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2748 | 2775 | ||
2749 | idev->tstamp = jiffies; | 2776 | idev->tstamp = jiffies; |
2750 | 2777 | ||
2751 | /* Shot the device (if unregistered) */ | 2778 | /* Last: Shot the device (if unregistered) */ |
2752 | |||
2753 | if (how) { | 2779 | if (how) { |
2754 | addrconf_sysctl_unregister(idev); | 2780 | addrconf_sysctl_unregister(idev); |
2755 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2781 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
@@ -2827,10 +2853,10 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2827 | net_srandom(ifp->addr.s6_addr32[3]); | 2853 | net_srandom(ifp->addr.s6_addr32[3]); |
2828 | 2854 | ||
2829 | read_lock_bh(&idev->lock); | 2855 | read_lock_bh(&idev->lock); |
2830 | if (ifp->dead) | 2856 | spin_lock(&ifp->lock); |
2857 | if (ifp->state == INET6_IFADDR_STATE_DEAD) | ||
2831 | goto out; | 2858 | goto out; |
2832 | 2859 | ||
2833 | spin_lock(&ifp->lock); | ||
2834 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2860 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2835 | idev->cnf.accept_dad < 1 || | 2861 | idev->cnf.accept_dad < 1 || |
2836 | !(ifp->flags&IFA_F_TENTATIVE) || | 2862 | !(ifp->flags&IFA_F_TENTATIVE) || |
@@ -2860,12 +2886,12 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2860 | * Optimistic nodes can start receiving | 2886 | * Optimistic nodes can start receiving |
2861 | * Frames right away | 2887 | * Frames right away |
2862 | */ | 2888 | */ |
2863 | if(ifp->flags & IFA_F_OPTIMISTIC) | 2889 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2864 | ip6_ins_rt(ifp->rt); | 2890 | ip6_ins_rt(ifp->rt); |
2865 | 2891 | ||
2866 | addrconf_dad_kick(ifp); | 2892 | addrconf_dad_kick(ifp); |
2867 | spin_unlock(&ifp->lock); | ||
2868 | out: | 2893 | out: |
2894 | spin_unlock(&ifp->lock); | ||
2869 | read_unlock_bh(&idev->lock); | 2895 | read_unlock_bh(&idev->lock); |
2870 | } | 2896 | } |
2871 | 2897 | ||
@@ -2875,6 +2901,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
2875 | struct inet6_dev *idev = ifp->idev; | 2901 | struct inet6_dev *idev = ifp->idev; |
2876 | struct in6_addr mcaddr; | 2902 | struct in6_addr mcaddr; |
2877 | 2903 | ||
2904 | if (!ifp->probes && addrconf_dad_end(ifp)) | ||
2905 | goto out; | ||
2906 | |||
2878 | read_lock(&idev->lock); | 2907 | read_lock(&idev->lock); |
2879 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 2908 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
2880 | read_unlock(&idev->lock); | 2909 | read_unlock(&idev->lock); |
@@ -2882,6 +2911,12 @@ static void addrconf_dad_timer(unsigned long data) | |||
2882 | } | 2911 | } |
2883 | 2912 | ||
2884 | spin_lock(&ifp->lock); | 2913 | spin_lock(&ifp->lock); |
2914 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | ||
2915 | spin_unlock(&ifp->lock); | ||
2916 | read_unlock(&idev->lock); | ||
2917 | goto out; | ||
2918 | } | ||
2919 | |||
2885 | if (ifp->probes == 0) { | 2920 | if (ifp->probes == 0) { |
2886 | /* | 2921 | /* |
2887 | * DAD was successful | 2922 | * DAD was successful |
@@ -2910,7 +2945,7 @@ out: | |||
2910 | 2945 | ||
2911 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 2946 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
2912 | { | 2947 | { |
2913 | struct net_device * dev = ifp->idev->dev; | 2948 | struct net_device *dev = ifp->idev->dev; |
2914 | 2949 | ||
2915 | /* | 2950 | /* |
2916 | * Configure the address for reception. Now it is valid. | 2951 | * Configure the address for reception. Now it is valid. |
@@ -2941,18 +2976,17 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2941 | } | 2976 | } |
2942 | } | 2977 | } |
2943 | 2978 | ||
2944 | static void addrconf_dad_run(struct inet6_dev *idev) { | 2979 | static void addrconf_dad_run(struct inet6_dev *idev) |
2980 | { | ||
2945 | struct inet6_ifaddr *ifp; | 2981 | struct inet6_ifaddr *ifp; |
2946 | 2982 | ||
2947 | read_lock_bh(&idev->lock); | 2983 | read_lock_bh(&idev->lock); |
2948 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2984 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2949 | spin_lock(&ifp->lock); | 2985 | spin_lock(&ifp->lock); |
2950 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2986 | if (ifp->flags & IFA_F_TENTATIVE && |
2951 | spin_unlock(&ifp->lock); | 2987 | ifp->state == INET6_IFADDR_STATE_DAD) |
2952 | continue; | 2988 | addrconf_dad_kick(ifp); |
2953 | } | ||
2954 | spin_unlock(&ifp->lock); | 2989 | spin_unlock(&ifp->lock); |
2955 | addrconf_dad_kick(ifp); | ||
2956 | } | 2990 | } |
2957 | read_unlock_bh(&idev->lock); | 2991 | read_unlock_bh(&idev->lock); |
2958 | } | 2992 | } |
@@ -2970,36 +3004,35 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2970 | struct net *net = seq_file_net(seq); | 3004 | struct net *net = seq_file_net(seq); |
2971 | 3005 | ||
2972 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 3006 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2973 | ifa = inet6_addr_lst[state->bucket]; | 3007 | struct hlist_node *n; |
2974 | 3008 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], | |
2975 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) | 3009 | addr_lst) |
2976 | ifa = ifa->lst_next; | 3010 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2977 | if (ifa) | 3011 | return ifa; |
2978 | break; | ||
2979 | } | 3012 | } |
2980 | return ifa; | 3013 | return NULL; |
2981 | } | 3014 | } |
2982 | 3015 | ||
2983 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 3016 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, |
3017 | struct inet6_ifaddr *ifa) | ||
2984 | { | 3018 | { |
2985 | struct if6_iter_state *state = seq->private; | 3019 | struct if6_iter_state *state = seq->private; |
2986 | struct net *net = seq_file_net(seq); | 3020 | struct net *net = seq_file_net(seq); |
3021 | struct hlist_node *n = &ifa->addr_lst; | ||
2987 | 3022 | ||
2988 | ifa = ifa->lst_next; | 3023 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) |
2989 | try_again: | 3024 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2990 | if (ifa) { | 3025 | return ifa; |
2991 | if (!net_eq(dev_net(ifa->idev->dev), net)) { | ||
2992 | ifa = ifa->lst_next; | ||
2993 | goto try_again; | ||
2994 | } | ||
2995 | } | ||
2996 | 3026 | ||
2997 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 3027 | while (++state->bucket < IN6_ADDR_HSIZE) { |
2998 | ifa = inet6_addr_lst[state->bucket]; | 3028 | hlist_for_each_entry_rcu_bh(ifa, n, |
2999 | goto try_again; | 3029 | &inet6_addr_lst[state->bucket], addr_lst) { |
3030 | if (net_eq(dev_net(ifa->idev->dev), net)) | ||
3031 | return ifa; | ||
3032 | } | ||
3000 | } | 3033 | } |
3001 | 3034 | ||
3002 | return ifa; | 3035 | return NULL; |
3003 | } | 3036 | } |
3004 | 3037 | ||
3005 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | 3038 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) |
@@ -3007,15 +3040,15 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
3007 | struct inet6_ifaddr *ifa = if6_get_first(seq); | 3040 | struct inet6_ifaddr *ifa = if6_get_first(seq); |
3008 | 3041 | ||
3009 | if (ifa) | 3042 | if (ifa) |
3010 | while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) | 3043 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) |
3011 | --pos; | 3044 | --pos; |
3012 | return pos ? NULL : ifa; | 3045 | return pos ? NULL : ifa; |
3013 | } | 3046 | } |
3014 | 3047 | ||
3015 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3048 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
3016 | __acquires(addrconf_hash_lock) | 3049 | __acquires(rcu_bh) |
3017 | { | 3050 | { |
3018 | read_lock_bh(&addrconf_hash_lock); | 3051 | rcu_read_lock_bh(); |
3019 | return if6_get_idx(seq, *pos); | 3052 | return if6_get_idx(seq, *pos); |
3020 | } | 3053 | } |
3021 | 3054 | ||
@@ -3029,9 +3062,9 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3029 | } | 3062 | } |
3030 | 3063 | ||
3031 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3064 | static void if6_seq_stop(struct seq_file *seq, void *v) |
3032 | __releases(addrconf_hash_lock) | 3065 | __releases(rcu_bh) |
3033 | { | 3066 | { |
3034 | read_unlock_bh(&addrconf_hash_lock); | 3067 | rcu_read_unlock_bh(); |
3035 | } | 3068 | } |
3036 | 3069 | ||
3037 | static int if6_seq_show(struct seq_file *seq, void *v) | 3070 | static int if6_seq_show(struct seq_file *seq, void *v) |
@@ -3101,10 +3134,12 @@ void if6_proc_exit(void) | |||
3101 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3134 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) |
3102 | { | 3135 | { |
3103 | int ret = 0; | 3136 | int ret = 0; |
3104 | struct inet6_ifaddr * ifp; | 3137 | struct inet6_ifaddr *ifp = NULL; |
3105 | u8 hash = ipv6_addr_hash(addr); | 3138 | struct hlist_node *n; |
3106 | read_lock_bh(&addrconf_hash_lock); | 3139 | unsigned int hash = ipv6_addr_hash(addr); |
3107 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 3140 | |
3141 | rcu_read_lock_bh(); | ||
3142 | hlist_for_each_entry_rcu_bh(ifp, n, &inet6_addr_lst[hash], addr_lst) { | ||
3108 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3143 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
3109 | continue; | 3144 | continue; |
3110 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3145 | if (ipv6_addr_equal(&ifp->addr, addr) && |
@@ -3113,7 +3148,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3113 | break; | 3148 | break; |
3114 | } | 3149 | } |
3115 | } | 3150 | } |
3116 | read_unlock_bh(&addrconf_hash_lock); | 3151 | rcu_read_unlock_bh(); |
3117 | return ret; | 3152 | return ret; |
3118 | } | 3153 | } |
3119 | #endif | 3154 | #endif |
@@ -3124,43 +3159,35 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3124 | 3159 | ||
3125 | static void addrconf_verify(unsigned long foo) | 3160 | static void addrconf_verify(unsigned long foo) |
3126 | { | 3161 | { |
3162 | unsigned long now, next, next_sec, next_sched; | ||
3127 | struct inet6_ifaddr *ifp; | 3163 | struct inet6_ifaddr *ifp; |
3128 | unsigned long now, next; | 3164 | struct hlist_node *node; |
3129 | int i; | 3165 | int i; |
3130 | 3166 | ||
3131 | spin_lock_bh(&addrconf_verify_lock); | 3167 | rcu_read_lock_bh(); |
3168 | spin_lock(&addrconf_verify_lock); | ||
3132 | now = jiffies; | 3169 | now = jiffies; |
3133 | next = now + ADDR_CHECK_FREQUENCY; | 3170 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
3134 | 3171 | ||
3135 | del_timer(&addr_chk_timer); | 3172 | del_timer(&addr_chk_timer); |
3136 | 3173 | ||
3137 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 3174 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
3138 | |||
3139 | restart: | 3175 | restart: |
3140 | read_lock(&addrconf_hash_lock); | 3176 | hlist_for_each_entry_rcu_bh(ifp, node, |
3141 | for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { | 3177 | &inet6_addr_lst[i], addr_lst) { |
3142 | unsigned long age; | 3178 | unsigned long age; |
3143 | #ifdef CONFIG_IPV6_PRIVACY | ||
3144 | unsigned long regen_advance; | ||
3145 | #endif | ||
3146 | 3179 | ||
3147 | if (ifp->flags & IFA_F_PERMANENT) | 3180 | if (ifp->flags & IFA_F_PERMANENT) |
3148 | continue; | 3181 | continue; |
3149 | 3182 | ||
3150 | spin_lock(&ifp->lock); | 3183 | spin_lock(&ifp->lock); |
3151 | age = (now - ifp->tstamp) / HZ; | 3184 | /* We try to batch several events at once. */ |
3152 | 3185 | age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | |
3153 | #ifdef CONFIG_IPV6_PRIVACY | ||
3154 | regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3155 | ifp->idev->cnf.dad_transmits * | ||
3156 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3157 | #endif | ||
3158 | 3186 | ||
3159 | if (ifp->valid_lft != INFINITY_LIFE_TIME && | 3187 | if (ifp->valid_lft != INFINITY_LIFE_TIME && |
3160 | age >= ifp->valid_lft) { | 3188 | age >= ifp->valid_lft) { |
3161 | spin_unlock(&ifp->lock); | 3189 | spin_unlock(&ifp->lock); |
3162 | in6_ifa_hold(ifp); | 3190 | in6_ifa_hold(ifp); |
3163 | read_unlock(&addrconf_hash_lock); | ||
3164 | ipv6_del_addr(ifp); | 3191 | ipv6_del_addr(ifp); |
3165 | goto restart; | 3192 | goto restart; |
3166 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { | 3193 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { |
@@ -3182,7 +3209,6 @@ restart: | |||
3182 | 3209 | ||
3183 | if (deprecate) { | 3210 | if (deprecate) { |
3184 | in6_ifa_hold(ifp); | 3211 | in6_ifa_hold(ifp); |
3185 | read_unlock(&addrconf_hash_lock); | ||
3186 | 3212 | ||
3187 | ipv6_ifa_notify(0, ifp); | 3213 | ipv6_ifa_notify(0, ifp); |
3188 | in6_ifa_put(ifp); | 3214 | in6_ifa_put(ifp); |
@@ -3191,6 +3217,10 @@ restart: | |||
3191 | #ifdef CONFIG_IPV6_PRIVACY | 3217 | #ifdef CONFIG_IPV6_PRIVACY |
3192 | } else if ((ifp->flags&IFA_F_TEMPORARY) && | 3218 | } else if ((ifp->flags&IFA_F_TEMPORARY) && |
3193 | !(ifp->flags&IFA_F_TENTATIVE)) { | 3219 | !(ifp->flags&IFA_F_TENTATIVE)) { |
3220 | unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3221 | ifp->idev->cnf.dad_transmits * | ||
3222 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3223 | |||
3194 | if (age >= ifp->prefered_lft - regen_advance) { | 3224 | if (age >= ifp->prefered_lft - regen_advance) { |
3195 | struct inet6_ifaddr *ifpub = ifp->ifpub; | 3225 | struct inet6_ifaddr *ifpub = ifp->ifpub; |
3196 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) | 3226 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) |
@@ -3200,7 +3230,7 @@ restart: | |||
3200 | in6_ifa_hold(ifp); | 3230 | in6_ifa_hold(ifp); |
3201 | in6_ifa_hold(ifpub); | 3231 | in6_ifa_hold(ifpub); |
3202 | spin_unlock(&ifp->lock); | 3232 | spin_unlock(&ifp->lock); |
3203 | read_unlock(&addrconf_hash_lock); | 3233 | |
3204 | spin_lock(&ifpub->lock); | 3234 | spin_lock(&ifpub->lock); |
3205 | ifpub->regen_count = 0; | 3235 | ifpub->regen_count = 0; |
3206 | spin_unlock(&ifpub->lock); | 3236 | spin_unlock(&ifpub->lock); |
@@ -3220,12 +3250,26 @@ restart: | |||
3220 | spin_unlock(&ifp->lock); | 3250 | spin_unlock(&ifp->lock); |
3221 | } | 3251 | } |
3222 | } | 3252 | } |
3223 | read_unlock(&addrconf_hash_lock); | ||
3224 | } | 3253 | } |
3225 | 3254 | ||
3226 | addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; | 3255 | next_sec = round_jiffies_up(next); |
3256 | next_sched = next; | ||
3257 | |||
3258 | /* If rounded timeout is accurate enough, accept it. */ | ||
3259 | if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) | ||
3260 | next_sched = next_sec; | ||
3261 | |||
3262 | /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ | ||
3263 | if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX)) | ||
3264 | next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX; | ||
3265 | |||
3266 | ADBG((KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | ||
3267 | now, next, next_sec, next_sched)); | ||
3268 | |||
3269 | addr_chk_timer.expires = next_sched; | ||
3227 | add_timer(&addr_chk_timer); | 3270 | add_timer(&addr_chk_timer); |
3228 | spin_unlock_bh(&addrconf_verify_lock); | 3271 | spin_unlock(&addrconf_verify_lock); |
3272 | rcu_read_unlock_bh(); | ||
3229 | } | 3273 | } |
3230 | 3274 | ||
3231 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3275 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) |
@@ -3515,8 +3559,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
3515 | return nlmsg_end(skb, nlh); | 3559 | return nlmsg_end(skb, nlh); |
3516 | } | 3560 | } |
3517 | 3561 | ||
3518 | enum addr_type_t | 3562 | enum addr_type_t { |
3519 | { | ||
3520 | UNICAST_ADDR, | 3563 | UNICAST_ADDR, |
3521 | MULTICAST_ADDR, | 3564 | MULTICAST_ADDR, |
3522 | ANYCAST_ADDR, | 3565 | ANYCAST_ADDR, |
@@ -3527,7 +3570,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3527 | struct netlink_callback *cb, enum addr_type_t type, | 3570 | struct netlink_callback *cb, enum addr_type_t type, |
3528 | int s_ip_idx, int *p_ip_idx) | 3571 | int s_ip_idx, int *p_ip_idx) |
3529 | { | 3572 | { |
3530 | struct inet6_ifaddr *ifa; | ||
3531 | struct ifmcaddr6 *ifmca; | 3573 | struct ifmcaddr6 *ifmca; |
3532 | struct ifacaddr6 *ifaca; | 3574 | struct ifacaddr6 *ifaca; |
3533 | int err = 1; | 3575 | int err = 1; |
@@ -3535,11 +3577,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3535 | 3577 | ||
3536 | read_lock_bh(&idev->lock); | 3578 | read_lock_bh(&idev->lock); |
3537 | switch (type) { | 3579 | switch (type) { |
3538 | case UNICAST_ADDR: | 3580 | case UNICAST_ADDR: { |
3581 | struct inet6_ifaddr *ifa; | ||
3582 | |||
3539 | /* unicast address incl. temp addr */ | 3583 | /* unicast address incl. temp addr */ |
3540 | for (ifa = idev->addr_list; ifa; | 3584 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
3541 | ifa = ifa->if_next, ip_idx++) { | 3585 | if (++ip_idx < s_ip_idx) |
3542 | if (ip_idx < s_ip_idx) | ||
3543 | continue; | 3586 | continue; |
3544 | err = inet6_fill_ifaddr(skb, ifa, | 3587 | err = inet6_fill_ifaddr(skb, ifa, |
3545 | NETLINK_CB(cb->skb).pid, | 3588 | NETLINK_CB(cb->skb).pid, |
@@ -3550,6 +3593,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3550 | break; | 3593 | break; |
3551 | } | 3594 | } |
3552 | break; | 3595 | break; |
3596 | } | ||
3553 | case MULTICAST_ADDR: | 3597 | case MULTICAST_ADDR: |
3554 | /* multicast address */ | 3598 | /* multicast address */ |
3555 | for (ifmca = idev->mc_list; ifmca; | 3599 | for (ifmca = idev->mc_list; ifmca; |
@@ -3614,7 +3658,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3614 | if (h > s_h || idx > s_idx) | 3658 | if (h > s_h || idx > s_idx) |
3615 | s_ip_idx = 0; | 3659 | s_ip_idx = 0; |
3616 | ip_idx = 0; | 3660 | ip_idx = 0; |
3617 | if ((idev = __in6_dev_get(dev)) == NULL) | 3661 | idev = __in6_dev_get(dev); |
3662 | if (!idev) | ||
3618 | goto cont; | 3663 | goto cont; |
3619 | 3664 | ||
3620 | if (in6_dump_addrs(idev, skb, cb, type, | 3665 | if (in6_dump_addrs(idev, skb, cb, type, |
@@ -3681,12 +3726,14 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3681 | if (ifm->ifa_index) | 3726 | if (ifm->ifa_index) |
3682 | dev = __dev_get_by_index(net, ifm->ifa_index); | 3727 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3683 | 3728 | ||
3684 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3729 | ifa = ipv6_get_ifaddr(net, addr, dev, 1); |
3730 | if (!ifa) { | ||
3685 | err = -EADDRNOTAVAIL; | 3731 | err = -EADDRNOTAVAIL; |
3686 | goto errout; | 3732 | goto errout; |
3687 | } | 3733 | } |
3688 | 3734 | ||
3689 | if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { | 3735 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); |
3736 | if (!skb) { | ||
3690 | err = -ENOBUFS; | 3737 | err = -ENOBUFS; |
3691 | goto errout_ifa; | 3738 | goto errout_ifa; |
3692 | } | 3739 | } |
@@ -3811,7 +3858,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3811 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
3812 | int bytes) | 3859 | int bytes) |
3813 | { | 3860 | { |
3814 | switch(attrtype) { | 3861 | switch (attrtype) { |
3815 | case IFLA_INET6_STATS: | 3862 | case IFLA_INET6_STATS: |
3816 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
3817 | break; | 3864 | break; |
@@ -4047,7 +4094,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4047 | addrconf_leave_anycast(ifp); | 4094 | addrconf_leave_anycast(ifp); |
4048 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4049 | dst_hold(&ifp->rt->u.dst); | 4096 | dst_hold(&ifp->rt->u.dst); |
4050 | if (ip6_del_rt(ifp->rt)) | 4097 | |
4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | ||
4099 | ip6_del_rt(ifp->rt)) | ||
4051 | dst_free(&ifp->rt->u.dst); | 4100 | dst_free(&ifp->rt->u.dst); |
4052 | break; | 4101 | break; |
4053 | } | 4102 | } |
@@ -4163,211 +4212,211 @@ static struct addrconf_sysctl_table | |||
4163 | .sysctl_header = NULL, | 4212 | .sysctl_header = NULL, |
4164 | .addrconf_vars = { | 4213 | .addrconf_vars = { |
4165 | { | 4214 | { |
4166 | .procname = "forwarding", | 4215 | .procname = "forwarding", |
4167 | .data = &ipv6_devconf.forwarding, | 4216 | .data = &ipv6_devconf.forwarding, |
4168 | .maxlen = sizeof(int), | 4217 | .maxlen = sizeof(int), |
4169 | .mode = 0644, | 4218 | .mode = 0644, |
4170 | .proc_handler = addrconf_sysctl_forward, | 4219 | .proc_handler = addrconf_sysctl_forward, |
4171 | }, | 4220 | }, |
4172 | { | 4221 | { |
4173 | .procname = "hop_limit", | 4222 | .procname = "hop_limit", |
4174 | .data = &ipv6_devconf.hop_limit, | 4223 | .data = &ipv6_devconf.hop_limit, |
4175 | .maxlen = sizeof(int), | 4224 | .maxlen = sizeof(int), |
4176 | .mode = 0644, | 4225 | .mode = 0644, |
4177 | .proc_handler = proc_dointvec, | 4226 | .proc_handler = proc_dointvec, |
4178 | }, | 4227 | }, |
4179 | { | 4228 | { |
4180 | .procname = "mtu", | 4229 | .procname = "mtu", |
4181 | .data = &ipv6_devconf.mtu6, | 4230 | .data = &ipv6_devconf.mtu6, |
4182 | .maxlen = sizeof(int), | 4231 | .maxlen = sizeof(int), |
4183 | .mode = 0644, | 4232 | .mode = 0644, |
4184 | .proc_handler = proc_dointvec, | 4233 | .proc_handler = proc_dointvec, |
4185 | }, | 4234 | }, |
4186 | { | 4235 | { |
4187 | .procname = "accept_ra", | 4236 | .procname = "accept_ra", |
4188 | .data = &ipv6_devconf.accept_ra, | 4237 | .data = &ipv6_devconf.accept_ra, |
4189 | .maxlen = sizeof(int), | 4238 | .maxlen = sizeof(int), |
4190 | .mode = 0644, | 4239 | .mode = 0644, |
4191 | .proc_handler = proc_dointvec, | 4240 | .proc_handler = proc_dointvec, |
4192 | }, | 4241 | }, |
4193 | { | 4242 | { |
4194 | .procname = "accept_redirects", | 4243 | .procname = "accept_redirects", |
4195 | .data = &ipv6_devconf.accept_redirects, | 4244 | .data = &ipv6_devconf.accept_redirects, |
4196 | .maxlen = sizeof(int), | 4245 | .maxlen = sizeof(int), |
4197 | .mode = 0644, | 4246 | .mode = 0644, |
4198 | .proc_handler = proc_dointvec, | 4247 | .proc_handler = proc_dointvec, |
4199 | }, | 4248 | }, |
4200 | { | 4249 | { |
4201 | .procname = "autoconf", | 4250 | .procname = "autoconf", |
4202 | .data = &ipv6_devconf.autoconf, | 4251 | .data = &ipv6_devconf.autoconf, |
4203 | .maxlen = sizeof(int), | 4252 | .maxlen = sizeof(int), |
4204 | .mode = 0644, | 4253 | .mode = 0644, |
4205 | .proc_handler = proc_dointvec, | 4254 | .proc_handler = proc_dointvec, |
4206 | }, | 4255 | }, |
4207 | { | 4256 | { |
4208 | .procname = "dad_transmits", | 4257 | .procname = "dad_transmits", |
4209 | .data = &ipv6_devconf.dad_transmits, | 4258 | .data = &ipv6_devconf.dad_transmits, |
4210 | .maxlen = sizeof(int), | 4259 | .maxlen = sizeof(int), |
4211 | .mode = 0644, | 4260 | .mode = 0644, |
4212 | .proc_handler = proc_dointvec, | 4261 | .proc_handler = proc_dointvec, |
4213 | }, | 4262 | }, |
4214 | { | 4263 | { |
4215 | .procname = "router_solicitations", | 4264 | .procname = "router_solicitations", |
4216 | .data = &ipv6_devconf.rtr_solicits, | 4265 | .data = &ipv6_devconf.rtr_solicits, |
4217 | .maxlen = sizeof(int), | 4266 | .maxlen = sizeof(int), |
4218 | .mode = 0644, | 4267 | .mode = 0644, |
4219 | .proc_handler = proc_dointvec, | 4268 | .proc_handler = proc_dointvec, |
4220 | }, | 4269 | }, |
4221 | { | 4270 | { |
4222 | .procname = "router_solicitation_interval", | 4271 | .procname = "router_solicitation_interval", |
4223 | .data = &ipv6_devconf.rtr_solicit_interval, | 4272 | .data = &ipv6_devconf.rtr_solicit_interval, |
4224 | .maxlen = sizeof(int), | 4273 | .maxlen = sizeof(int), |
4225 | .mode = 0644, | 4274 | .mode = 0644, |
4226 | .proc_handler = proc_dointvec_jiffies, | 4275 | .proc_handler = proc_dointvec_jiffies, |
4227 | }, | 4276 | }, |
4228 | { | 4277 | { |
4229 | .procname = "router_solicitation_delay", | 4278 | .procname = "router_solicitation_delay", |
4230 | .data = &ipv6_devconf.rtr_solicit_delay, | 4279 | .data = &ipv6_devconf.rtr_solicit_delay, |
4231 | .maxlen = sizeof(int), | 4280 | .maxlen = sizeof(int), |
4232 | .mode = 0644, | 4281 | .mode = 0644, |
4233 | .proc_handler = proc_dointvec_jiffies, | 4282 | .proc_handler = proc_dointvec_jiffies, |
4234 | }, | 4283 | }, |
4235 | { | 4284 | { |
4236 | .procname = "force_mld_version", | 4285 | .procname = "force_mld_version", |
4237 | .data = &ipv6_devconf.force_mld_version, | 4286 | .data = &ipv6_devconf.force_mld_version, |
4238 | .maxlen = sizeof(int), | 4287 | .maxlen = sizeof(int), |
4239 | .mode = 0644, | 4288 | .mode = 0644, |
4240 | .proc_handler = proc_dointvec, | 4289 | .proc_handler = proc_dointvec, |
4241 | }, | 4290 | }, |
4242 | #ifdef CONFIG_IPV6_PRIVACY | 4291 | #ifdef CONFIG_IPV6_PRIVACY |
4243 | { | 4292 | { |
4244 | .procname = "use_tempaddr", | 4293 | .procname = "use_tempaddr", |
4245 | .data = &ipv6_devconf.use_tempaddr, | 4294 | .data = &ipv6_devconf.use_tempaddr, |
4246 | .maxlen = sizeof(int), | 4295 | .maxlen = sizeof(int), |
4247 | .mode = 0644, | 4296 | .mode = 0644, |
4248 | .proc_handler = proc_dointvec, | 4297 | .proc_handler = proc_dointvec, |
4249 | }, | 4298 | }, |
4250 | { | 4299 | { |
4251 | .procname = "temp_valid_lft", | 4300 | .procname = "temp_valid_lft", |
4252 | .data = &ipv6_devconf.temp_valid_lft, | 4301 | .data = &ipv6_devconf.temp_valid_lft, |
4253 | .maxlen = sizeof(int), | 4302 | .maxlen = sizeof(int), |
4254 | .mode = 0644, | 4303 | .mode = 0644, |
4255 | .proc_handler = proc_dointvec, | 4304 | .proc_handler = proc_dointvec, |
4256 | }, | 4305 | }, |
4257 | { | 4306 | { |
4258 | .procname = "temp_prefered_lft", | 4307 | .procname = "temp_prefered_lft", |
4259 | .data = &ipv6_devconf.temp_prefered_lft, | 4308 | .data = &ipv6_devconf.temp_prefered_lft, |
4260 | .maxlen = sizeof(int), | 4309 | .maxlen = sizeof(int), |
4261 | .mode = 0644, | 4310 | .mode = 0644, |
4262 | .proc_handler = proc_dointvec, | 4311 | .proc_handler = proc_dointvec, |
4263 | }, | 4312 | }, |
4264 | { | 4313 | { |
4265 | .procname = "regen_max_retry", | 4314 | .procname = "regen_max_retry", |
4266 | .data = &ipv6_devconf.regen_max_retry, | 4315 | .data = &ipv6_devconf.regen_max_retry, |
4267 | .maxlen = sizeof(int), | 4316 | .maxlen = sizeof(int), |
4268 | .mode = 0644, | 4317 | .mode = 0644, |
4269 | .proc_handler = proc_dointvec, | 4318 | .proc_handler = proc_dointvec, |
4270 | }, | 4319 | }, |
4271 | { | 4320 | { |
4272 | .procname = "max_desync_factor", | 4321 | .procname = "max_desync_factor", |
4273 | .data = &ipv6_devconf.max_desync_factor, | 4322 | .data = &ipv6_devconf.max_desync_factor, |
4274 | .maxlen = sizeof(int), | 4323 | .maxlen = sizeof(int), |
4275 | .mode = 0644, | 4324 | .mode = 0644, |
4276 | .proc_handler = proc_dointvec, | 4325 | .proc_handler = proc_dointvec, |
4277 | }, | 4326 | }, |
4278 | #endif | 4327 | #endif |
4279 | { | 4328 | { |
4280 | .procname = "max_addresses", | 4329 | .procname = "max_addresses", |
4281 | .data = &ipv6_devconf.max_addresses, | 4330 | .data = &ipv6_devconf.max_addresses, |
4282 | .maxlen = sizeof(int), | 4331 | .maxlen = sizeof(int), |
4283 | .mode = 0644, | 4332 | .mode = 0644, |
4284 | .proc_handler = proc_dointvec, | 4333 | .proc_handler = proc_dointvec, |
4285 | }, | 4334 | }, |
4286 | { | 4335 | { |
4287 | .procname = "accept_ra_defrtr", | 4336 | .procname = "accept_ra_defrtr", |
4288 | .data = &ipv6_devconf.accept_ra_defrtr, | 4337 | .data = &ipv6_devconf.accept_ra_defrtr, |
4289 | .maxlen = sizeof(int), | 4338 | .maxlen = sizeof(int), |
4290 | .mode = 0644, | 4339 | .mode = 0644, |
4291 | .proc_handler = proc_dointvec, | 4340 | .proc_handler = proc_dointvec, |
4292 | }, | 4341 | }, |
4293 | { | 4342 | { |
4294 | .procname = "accept_ra_pinfo", | 4343 | .procname = "accept_ra_pinfo", |
4295 | .data = &ipv6_devconf.accept_ra_pinfo, | 4344 | .data = &ipv6_devconf.accept_ra_pinfo, |
4296 | .maxlen = sizeof(int), | 4345 | .maxlen = sizeof(int), |
4297 | .mode = 0644, | 4346 | .mode = 0644, |
4298 | .proc_handler = proc_dointvec, | 4347 | .proc_handler = proc_dointvec, |
4299 | }, | 4348 | }, |
4300 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4349 | #ifdef CONFIG_IPV6_ROUTER_PREF |
4301 | { | 4350 | { |
4302 | .procname = "accept_ra_rtr_pref", | 4351 | .procname = "accept_ra_rtr_pref", |
4303 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4352 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
4304 | .maxlen = sizeof(int), | 4353 | .maxlen = sizeof(int), |
4305 | .mode = 0644, | 4354 | .mode = 0644, |
4306 | .proc_handler = proc_dointvec, | 4355 | .proc_handler = proc_dointvec, |
4307 | }, | 4356 | }, |
4308 | { | 4357 | { |
4309 | .procname = "router_probe_interval", | 4358 | .procname = "router_probe_interval", |
4310 | .data = &ipv6_devconf.rtr_probe_interval, | 4359 | .data = &ipv6_devconf.rtr_probe_interval, |
4311 | .maxlen = sizeof(int), | 4360 | .maxlen = sizeof(int), |
4312 | .mode = 0644, | 4361 | .mode = 0644, |
4313 | .proc_handler = proc_dointvec_jiffies, | 4362 | .proc_handler = proc_dointvec_jiffies, |
4314 | }, | 4363 | }, |
4315 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4364 | #ifdef CONFIG_IPV6_ROUTE_INFO |
4316 | { | 4365 | { |
4317 | .procname = "accept_ra_rt_info_max_plen", | 4366 | .procname = "accept_ra_rt_info_max_plen", |
4318 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4367 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
4319 | .maxlen = sizeof(int), | 4368 | .maxlen = sizeof(int), |
4320 | .mode = 0644, | 4369 | .mode = 0644, |
4321 | .proc_handler = proc_dointvec, | 4370 | .proc_handler = proc_dointvec, |
4322 | }, | 4371 | }, |
4323 | #endif | 4372 | #endif |
4324 | #endif | 4373 | #endif |
4325 | { | 4374 | { |
4326 | .procname = "proxy_ndp", | 4375 | .procname = "proxy_ndp", |
4327 | .data = &ipv6_devconf.proxy_ndp, | 4376 | .data = &ipv6_devconf.proxy_ndp, |
4328 | .maxlen = sizeof(int), | 4377 | .maxlen = sizeof(int), |
4329 | .mode = 0644, | 4378 | .mode = 0644, |
4330 | .proc_handler = proc_dointvec, | 4379 | .proc_handler = proc_dointvec, |
4331 | }, | 4380 | }, |
4332 | { | 4381 | { |
4333 | .procname = "accept_source_route", | 4382 | .procname = "accept_source_route", |
4334 | .data = &ipv6_devconf.accept_source_route, | 4383 | .data = &ipv6_devconf.accept_source_route, |
4335 | .maxlen = sizeof(int), | 4384 | .maxlen = sizeof(int), |
4336 | .mode = 0644, | 4385 | .mode = 0644, |
4337 | .proc_handler = proc_dointvec, | 4386 | .proc_handler = proc_dointvec, |
4338 | }, | 4387 | }, |
4339 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4388 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
4340 | { | 4389 | { |
4341 | .procname = "optimistic_dad", | 4390 | .procname = "optimistic_dad", |
4342 | .data = &ipv6_devconf.optimistic_dad, | 4391 | .data = &ipv6_devconf.optimistic_dad, |
4343 | .maxlen = sizeof(int), | 4392 | .maxlen = sizeof(int), |
4344 | .mode = 0644, | 4393 | .mode = 0644, |
4345 | .proc_handler = proc_dointvec, | 4394 | .proc_handler = proc_dointvec, |
4346 | 4395 | ||
4347 | }, | 4396 | }, |
4348 | #endif | 4397 | #endif |
4349 | #ifdef CONFIG_IPV6_MROUTE | 4398 | #ifdef CONFIG_IPV6_MROUTE |
4350 | { | 4399 | { |
4351 | .procname = "mc_forwarding", | 4400 | .procname = "mc_forwarding", |
4352 | .data = &ipv6_devconf.mc_forwarding, | 4401 | .data = &ipv6_devconf.mc_forwarding, |
4353 | .maxlen = sizeof(int), | 4402 | .maxlen = sizeof(int), |
4354 | .mode = 0444, | 4403 | .mode = 0444, |
4355 | .proc_handler = proc_dointvec, | 4404 | .proc_handler = proc_dointvec, |
4356 | }, | 4405 | }, |
4357 | #endif | 4406 | #endif |
4358 | { | 4407 | { |
4359 | .procname = "disable_ipv6", | 4408 | .procname = "disable_ipv6", |
4360 | .data = &ipv6_devconf.disable_ipv6, | 4409 | .data = &ipv6_devconf.disable_ipv6, |
4361 | .maxlen = sizeof(int), | 4410 | .maxlen = sizeof(int), |
4362 | .mode = 0644, | 4411 | .mode = 0644, |
4363 | .proc_handler = addrconf_sysctl_disable, | 4412 | .proc_handler = addrconf_sysctl_disable, |
4364 | }, | 4413 | }, |
4365 | { | 4414 | { |
4366 | .procname = "accept_dad", | 4415 | .procname = "accept_dad", |
4367 | .data = &ipv6_devconf.accept_dad, | 4416 | .data = &ipv6_devconf.accept_dad, |
4368 | .maxlen = sizeof(int), | 4417 | .maxlen = sizeof(int), |
4369 | .mode = 0644, | 4418 | .mode = 0644, |
4370 | .proc_handler = proc_dointvec, | 4419 | .proc_handler = proc_dointvec, |
4371 | }, | 4420 | }, |
4372 | { | 4421 | { |
4373 | .procname = "force_tllao", | 4422 | .procname = "force_tllao", |
@@ -4403,8 +4452,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
4403 | if (t == NULL) | 4452 | if (t == NULL) |
4404 | goto out; | 4453 | goto out; |
4405 | 4454 | ||
4406 | for (i=0; t->addrconf_vars[i].data; i++) { | 4455 | for (i = 0; t->addrconf_vars[i].data; i++) { |
4407 | t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; | 4456 | t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; |
4408 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ | 4457 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ |
4409 | t->addrconf_vars[i].extra2 = net; | 4458 | t->addrconf_vars[i].extra2 = net; |
4410 | } | 4459 | } |
@@ -4541,14 +4590,12 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
4541 | { | 4590 | { |
4542 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4591 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
4543 | } | 4592 | } |
4544 | |||
4545 | EXPORT_SYMBOL(register_inet6addr_notifier); | 4593 | EXPORT_SYMBOL(register_inet6addr_notifier); |
4546 | 4594 | ||
4547 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4595 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
4548 | { | 4596 | { |
4549 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4597 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); |
4550 | } | 4598 | } |
4551 | |||
4552 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4599 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4553 | 4600 | ||
4554 | /* | 4601 | /* |
@@ -4557,11 +4604,12 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier); | |||
4557 | 4604 | ||
4558 | int __init addrconf_init(void) | 4605 | int __init addrconf_init(void) |
4559 | { | 4606 | { |
4560 | int err; | 4607 | int i, err; |
4561 | 4608 | ||
4562 | if ((err = ipv6_addr_label_init()) < 0) { | 4609 | err = ipv6_addr_label_init(); |
4563 | printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n", | 4610 | if (err < 0) { |
4564 | err); | 4611 | printk(KERN_CRIT "IPv6 Addrconf:" |
4612 | " cannot initialize default policy table: %d.\n", err); | ||
4565 | return err; | 4613 | return err; |
4566 | } | 4614 | } |
4567 | 4615 | ||
@@ -4592,6 +4640,9 @@ int __init addrconf_init(void) | |||
4592 | if (err) | 4640 | if (err) |
4593 | goto errlo; | 4641 | goto errlo; |
4594 | 4642 | ||
4643 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
4644 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | ||
4645 | |||
4595 | register_netdevice_notifier(&ipv6_dev_notf); | 4646 | register_netdevice_notifier(&ipv6_dev_notf); |
4596 | 4647 | ||
4597 | addrconf_verify(0); | 4648 | addrconf_verify(0); |
@@ -4620,7 +4671,6 @@ errlo: | |||
4620 | 4671 | ||
4621 | void addrconf_cleanup(void) | 4672 | void addrconf_cleanup(void) |
4622 | { | 4673 | { |
4623 | struct inet6_ifaddr *ifa; | ||
4624 | struct net_device *dev; | 4674 | struct net_device *dev; |
4625 | int i; | 4675 | int i; |
4626 | 4676 | ||
@@ -4640,20 +4690,10 @@ void addrconf_cleanup(void) | |||
4640 | /* | 4690 | /* |
4641 | * Check hash table. | 4691 | * Check hash table. |
4642 | */ | 4692 | */ |
4643 | write_lock_bh(&addrconf_hash_lock); | 4693 | spin_lock_bh(&addrconf_hash_lock); |
4644 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4694 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
4645 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4695 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
4646 | struct inet6_ifaddr *bifa; | 4696 | spin_unlock_bh(&addrconf_hash_lock); |
4647 | |||
4648 | bifa = ifa; | ||
4649 | ifa = ifa->lst_next; | ||
4650 | printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa); | ||
4651 | /* Do not free it; something is wrong. | ||
4652 | Now we can investigate it with debugger. | ||
4653 | */ | ||
4654 | } | ||
4655 | } | ||
4656 | write_unlock_bh(&addrconf_hash_lock); | ||
4657 | 4697 | ||
4658 | del_timer(&addr_chk_timer); | 4698 | del_timer(&addr_chk_timer); |
4659 | rtnl_unlock(); | 4699 | rtnl_unlock(); |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index ae404c9a746c..8c4348cb1950 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -422,10 +422,6 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
422 | ifal->ifal_prefixlen > 128) | 422 | ifal->ifal_prefixlen > 128) |
423 | return -EINVAL; | 423 | return -EINVAL; |
424 | 424 | ||
425 | if (ifal->ifal_index && | ||
426 | !__dev_get_by_index(net, ifal->ifal_index)) | ||
427 | return -EINVAL; | ||
428 | |||
429 | if (!tb[IFAL_ADDRESS]) | 425 | if (!tb[IFAL_ADDRESS]) |
430 | return -EINVAL; | 426 | return -EINVAL; |
431 | 427 | ||
@@ -441,6 +437,10 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
441 | 437 | ||
442 | switch(nlh->nlmsg_type) { | 438 | switch(nlh->nlmsg_type) { |
443 | case RTM_NEWADDRLABEL: | 439 | case RTM_NEWADDRLABEL: |
440 | if (ifal->ifal_index && | ||
441 | !__dev_get_by_index(net, ifal->ifal_index)) | ||
442 | return -EINVAL; | ||
443 | |||
444 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, | 444 | err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, |
445 | ifal->ifal_index, label, | 445 | ifal->ifal_index, label, |
446 | nlh->nlmsg_flags & NLM_F_REPLACE); | 446 | nlh->nlmsg_flags & NLM_F_REPLACE); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3192aa02ba5d..e733942dafe1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -200,7 +200,7 @@ lookup_protocol: | |||
200 | 200 | ||
201 | inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk); | 201 | inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk); |
202 | np->hop_limit = -1; | 202 | np->hop_limit = -1; |
203 | np->mcast_hops = -1; | 203 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; |
204 | np->mc_loop = 1; | 204 | np->mc_loop = 1; |
205 | np->pmtudisc = IPV6_PMTUDISC_WANT; | 205 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
206 | np->ipv6only = net->ipv6.sysctl.bindv6only; | 206 | np->ipv6only = net->ipv6.sysctl.bindv6only; |
@@ -417,6 +417,9 @@ void inet6_destroy_sock(struct sock *sk) | |||
417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) | 417 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) |
418 | kfree_skb(skb); | 418 | kfree_skb(skb); |
419 | 419 | ||
420 | if ((skb = xchg(&np->rxpmtu, NULL)) != NULL) | ||
421 | kfree_skb(skb); | ||
422 | |||
420 | /* Free flowlabels */ | 423 | /* Free flowlabels */ |
421 | fl6_free_socklist(sk); | 424 | fl6_free_socklist(sk); |
422 | 425 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 622dc7939a1b..712684687c9a 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -222,6 +222,8 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | |||
222 | if (!skb) | 222 | if (!skb) |
223 | return; | 223 | return; |
224 | 224 | ||
225 | skb->protocol = htons(ETH_P_IPV6); | ||
226 | |||
225 | serr = SKB_EXT_ERR(skb); | 227 | serr = SKB_EXT_ERR(skb); |
226 | serr->ee.ee_errno = err; | 228 | serr->ee.ee_errno = err; |
227 | serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6; | 229 | serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6; |
@@ -255,6 +257,8 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
255 | if (!skb) | 257 | if (!skb) |
256 | return; | 258 | return; |
257 | 259 | ||
260 | skb->protocol = htons(ETH_P_IPV6); | ||
261 | |||
258 | skb_put(skb, sizeof(struct ipv6hdr)); | 262 | skb_put(skb, sizeof(struct ipv6hdr)); |
259 | skb_reset_network_header(skb); | 263 | skb_reset_network_header(skb); |
260 | iph = ipv6_hdr(skb); | 264 | iph = ipv6_hdr(skb); |
@@ -278,6 +282,45 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) | |||
278 | kfree_skb(skb); | 282 | kfree_skb(skb); |
279 | } | 283 | } |
280 | 284 | ||
285 | void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu) | ||
286 | { | ||
287 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
288 | struct ipv6hdr *iph; | ||
289 | struct sk_buff *skb; | ||
290 | struct ip6_mtuinfo *mtu_info; | ||
291 | |||
292 | if (!np->rxopt.bits.rxpmtu) | ||
293 | return; | ||
294 | |||
295 | skb = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC); | ||
296 | if (!skb) | ||
297 | return; | ||
298 | |||
299 | skb_put(skb, sizeof(struct ipv6hdr)); | ||
300 | skb_reset_network_header(skb); | ||
301 | iph = ipv6_hdr(skb); | ||
302 | ipv6_addr_copy(&iph->daddr, &fl->fl6_dst); | ||
303 | |||
304 | mtu_info = IP6CBMTU(skb); | ||
305 | if (!mtu_info) { | ||
306 | kfree_skb(skb); | ||
307 | return; | ||
308 | } | ||
309 | |||
310 | mtu_info->ip6m_mtu = mtu; | ||
311 | mtu_info->ip6m_addr.sin6_family = AF_INET6; | ||
312 | mtu_info->ip6m_addr.sin6_port = 0; | ||
313 | mtu_info->ip6m_addr.sin6_flowinfo = 0; | ||
314 | mtu_info->ip6m_addr.sin6_scope_id = fl->oif; | ||
315 | ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr); | ||
316 | |||
317 | __skb_pull(skb, skb_tail_pointer(skb) - skb->data); | ||
318 | skb_reset_transport_header(skb); | ||
319 | |||
320 | skb = xchg(&np->rxpmtu, skb); | ||
321 | kfree_skb(skb); | ||
322 | } | ||
323 | |||
281 | /* | 324 | /* |
282 | * Handle MSG_ERRQUEUE | 325 | * Handle MSG_ERRQUEUE |
283 | */ | 326 | */ |
@@ -319,7 +362,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
319 | sin->sin6_flowinfo = 0; | 362 | sin->sin6_flowinfo = 0; |
320 | sin->sin6_port = serr->port; | 363 | sin->sin6_port = serr->port; |
321 | sin->sin6_scope_id = 0; | 364 | sin->sin6_scope_id = 0; |
322 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { | 365 | if (skb->protocol == htons(ETH_P_IPV6)) { |
323 | ipv6_addr_copy(&sin->sin6_addr, | 366 | ipv6_addr_copy(&sin->sin6_addr, |
324 | (struct in6_addr *)(nh + serr->addr_offset)); | 367 | (struct in6_addr *)(nh + serr->addr_offset)); |
325 | if (np->sndflow) | 368 | if (np->sndflow) |
@@ -341,7 +384,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
341 | sin->sin6_family = AF_INET6; | 384 | sin->sin6_family = AF_INET6; |
342 | sin->sin6_flowinfo = 0; | 385 | sin->sin6_flowinfo = 0; |
343 | sin->sin6_scope_id = 0; | 386 | sin->sin6_scope_id = 0; |
344 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { | 387 | if (skb->protocol == htons(ETH_P_IPV6)) { |
345 | ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr); | 388 | ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr); |
346 | if (np->rxopt.all) | 389 | if (np->rxopt.all) |
347 | datagram_recv_ctl(sk, msg, skb); | 390 | datagram_recv_ctl(sk, msg, skb); |
@@ -381,6 +424,54 @@ out: | |||
381 | return err; | 424 | return err; |
382 | } | 425 | } |
383 | 426 | ||
427 | /* | ||
428 | * Handle IPV6_RECVPATHMTU | ||
429 | */ | ||
430 | int ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len) | ||
431 | { | ||
432 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
433 | struct sk_buff *skb; | ||
434 | struct sockaddr_in6 *sin; | ||
435 | struct ip6_mtuinfo mtu_info; | ||
436 | int err; | ||
437 | int copied; | ||
438 | |||
439 | err = -EAGAIN; | ||
440 | skb = xchg(&np->rxpmtu, NULL); | ||
441 | if (skb == NULL) | ||
442 | goto out; | ||
443 | |||
444 | copied = skb->len; | ||
445 | if (copied > len) { | ||
446 | msg->msg_flags |= MSG_TRUNC; | ||
447 | copied = len; | ||
448 | } | ||
449 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
450 | if (err) | ||
451 | goto out_free_skb; | ||
452 | |||
453 | sock_recv_timestamp(msg, sk, skb); | ||
454 | |||
455 | memcpy(&mtu_info, IP6CBMTU(skb), sizeof(mtu_info)); | ||
456 | |||
457 | sin = (struct sockaddr_in6 *)msg->msg_name; | ||
458 | if (sin) { | ||
459 | sin->sin6_family = AF_INET6; | ||
460 | sin->sin6_flowinfo = 0; | ||
461 | sin->sin6_port = 0; | ||
462 | sin->sin6_scope_id = mtu_info.ip6m_addr.sin6_scope_id; | ||
463 | ipv6_addr_copy(&sin->sin6_addr, &mtu_info.ip6m_addr.sin6_addr); | ||
464 | } | ||
465 | |||
466 | put_cmsg(msg, SOL_IPV6, IPV6_PATHMTU, sizeof(mtu_info), &mtu_info); | ||
467 | |||
468 | err = copied; | ||
469 | |||
470 | out_free_skb: | ||
471 | kfree_skb(skb); | ||
472 | out: | ||
473 | return err; | ||
474 | } | ||
384 | 475 | ||
385 | 476 | ||
386 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | 477 | int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) |
@@ -497,7 +588,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
497 | int datagram_send_ctl(struct net *net, | 588 | int datagram_send_ctl(struct net *net, |
498 | struct msghdr *msg, struct flowi *fl, | 589 | struct msghdr *msg, struct flowi *fl, |
499 | struct ipv6_txoptions *opt, | 590 | struct ipv6_txoptions *opt, |
500 | int *hlimit, int *tclass) | 591 | int *hlimit, int *tclass, int *dontfrag) |
501 | { | 592 | { |
502 | struct in6_pktinfo *src_info; | 593 | struct in6_pktinfo *src_info; |
503 | struct cmsghdr *cmsg; | 594 | struct cmsghdr *cmsg; |
@@ -737,6 +828,25 @@ int datagram_send_ctl(struct net *net, | |||
737 | 828 | ||
738 | break; | 829 | break; |
739 | } | 830 | } |
831 | |||
832 | case IPV6_DONTFRAG: | ||
833 | { | ||
834 | int df; | ||
835 | |||
836 | err = -EINVAL; | ||
837 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { | ||
838 | goto exit_f; | ||
839 | } | ||
840 | |||
841 | df = *(int *)CMSG_DATA(cmsg); | ||
842 | if (df < 0 || df > 1) | ||
843 | goto exit_f; | ||
844 | |||
845 | err = 0; | ||
846 | *dontfrag = df; | ||
847 | |||
848 | break; | ||
849 | } | ||
740 | default: | 850 | default: |
741 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", | 851 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
742 | cmsg->cmsg_type); | 852 | cmsg->cmsg_type); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 5e463c43fcc2..8e44f8f9c188 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -208,7 +208,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
208 | { | 208 | { |
209 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 209 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
210 | 210 | ||
211 | frh->family = AF_INET6; | ||
212 | frh->dst_len = rule6->dst.plen; | 211 | frh->dst_len = rule6->dst.plen; |
213 | frh->src_len = rule6->src.plen; | 212 | frh->src_len = rule6->src.plen; |
214 | frh->tos = rule6->tclass; | 213 | frh->tos = rule6->tclass; |
@@ -238,7 +237,7 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | |||
238 | + nla_total_size(16); /* src */ | 237 | + nla_total_size(16); /* src */ |
239 | } | 238 | } |
240 | 239 | ||
241 | static struct fib_rules_ops fib6_rules_ops_template = { | 240 | static const struct fib_rules_ops __net_initdata fib6_rules_ops_template = { |
242 | .family = AF_INET6, | 241 | .family = AF_INET6, |
243 | .rule_size = sizeof(struct fib6_rule), | 242 | .rule_size = sizeof(struct fib6_rule), |
244 | .addr_size = sizeof(struct in6_addr), | 243 | .addr_size = sizeof(struct in6_addr), |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 3330a4bd6157..ce7992982557 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -481,8 +481,9 @@ route_done: | |||
481 | len + sizeof(struct icmp6hdr), | 481 | len + sizeof(struct icmp6hdr), |
482 | sizeof(struct icmp6hdr), hlimit, | 482 | sizeof(struct icmp6hdr), hlimit, |
483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, | 483 | np->tclass, NULL, &fl, (struct rt6_info*)dst, |
484 | MSG_DONTWAIT); | 484 | MSG_DONTWAIT, np->dontfrag); |
485 | if (err) { | 485 | if (err) { |
486 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | ||
486 | ip6_flush_pending_frames(sk); | 487 | ip6_flush_pending_frames(sk); |
487 | goto out_put; | 488 | goto out_put; |
488 | } | 489 | } |
@@ -560,9 +561,11 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
560 | 561 | ||
561 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 562 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
562 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, | 563 | sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl, |
563 | (struct rt6_info*)dst, MSG_DONTWAIT); | 564 | (struct rt6_info*)dst, MSG_DONTWAIT, |
565 | np->dontfrag); | ||
564 | 566 | ||
565 | if (err) { | 567 | if (err) { |
568 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | ||
566 | ip6_flush_pending_frames(sk); | 569 | ip6_flush_pending_frames(sk); |
567 | goto out_put; | 570 | goto out_put; |
568 | } | 571 | } |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 628db24bcf22..0c5e3c3b7fd5 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -178,7 +178,7 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
178 | return dst; | 178 | return dst; |
179 | } | 179 | } |
180 | 180 | ||
181 | int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | 181 | int inet6_csk_xmit(struct sk_buff *skb) |
182 | { | 182 | { |
183 | struct sock *sk = skb->sk; | 183 | struct sock *sk = skb->sk; |
184 | struct inet_sock *inet = inet_sk(sk); | 184 | struct inet_sock *inet = inet_sk(sk); |
@@ -234,7 +234,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | |||
234 | /* Restore final destination back after routing done */ | 234 | /* Restore final destination back after routing done */ |
235 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); | 235 | ipv6_addr_copy(&fl.fl6_dst, &np->daddr); |
236 | 236 | ||
237 | return ip6_xmit(sk, skb, &fl, np->opt, 0); | 237 | return ip6_xmit(sk, skb, &fl, np->opt); |
238 | } | 238 | } |
239 | 239 | ||
240 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 240 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 6b82e02158c6..92a122b7795d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -128,12 +128,24 @@ static __inline__ u32 fib6_new_sernum(void) | |||
128 | /* | 128 | /* |
129 | * test bit | 129 | * test bit |
130 | */ | 130 | */ |
131 | #if defined(__LITTLE_ENDIAN) | ||
132 | # define BITOP_BE32_SWIZZLE (0x1F & ~7) | ||
133 | #else | ||
134 | # define BITOP_BE32_SWIZZLE 0 | ||
135 | #endif | ||
131 | 136 | ||
132 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) | 137 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) |
133 | { | 138 | { |
134 | __be32 *addr = token; | 139 | __be32 *addr = token; |
135 | 140 | /* | |
136 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; | 141 | * Here, |
142 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) | ||
143 | * is optimized version of | ||
144 | * htonl(1 << ((~fn_bit)&0x1F)) | ||
145 | * See include/asm-generic/bitops/le.h. | ||
146 | */ | ||
147 | return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & | ||
148 | addr[fn_bit >> 5]; | ||
137 | } | 149 | } |
138 | 150 | ||
139 | static __inline__ struct fib6_node * node_alloc(void) | 151 | static __inline__ struct fib6_node * node_alloc(void) |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 14e23216eb28..13654686aeab 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -360,7 +360,8 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
360 | msg.msg_control = (void*)(fl->opt+1); | 360 | msg.msg_control = (void*)(fl->opt+1); |
361 | flowi.oif = 0; | 361 | flowi.oif = 0; |
362 | 362 | ||
363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, &junk); | 363 | err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk, |
364 | &junk, &junk); | ||
364 | if (err) | 365 | if (err) |
365 | goto done; | 366 | goto done; |
366 | err = -EINVAL; | 367 | err = -EINVAL; |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 6aa7ee1295c2..a83e9209cecc 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -143,7 +143,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
143 | /* Must drop socket now because of tproxy. */ | 143 | /* Must drop socket now because of tproxy. */ |
144 | skb_orphan(skb); | 144 | skb_orphan(skb); |
145 | 145 | ||
146 | return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, | 146 | return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, dev, NULL, |
147 | ip6_rcv_finish); | 147 | ip6_rcv_finish); |
148 | err: | 148 | err: |
149 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); | 149 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS); |
@@ -236,7 +236,7 @@ discard: | |||
236 | 236 | ||
237 | int ip6_input(struct sk_buff *skb) | 237 | int ip6_input(struct sk_buff *skb) |
238 | { | 238 | { |
239 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, | 239 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, skb, skb->dev, NULL, |
240 | ip6_input_finish); | 240 | ip6_input_finish); |
241 | } | 241 | } |
242 | 242 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 65f9c379df38..cd963f64e27c 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -67,8 +67,8 @@ int __ip6_local_out(struct sk_buff *skb) | |||
67 | len = 0; | 67 | len = 0; |
68 | ipv6_hdr(skb)->payload_len = htons(len); | 68 | ipv6_hdr(skb)->payload_len = htons(len); |
69 | 69 | ||
70 | return nf_hook(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb_dst(skb)->dev, | 70 | return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
71 | dst_output); | 71 | skb_dst(skb)->dev, dst_output); |
72 | } | 72 | } |
73 | 73 | ||
74 | int ip6_local_out(struct sk_buff *skb) | 74 | int ip6_local_out(struct sk_buff *skb) |
@@ -83,22 +83,6 @@ int ip6_local_out(struct sk_buff *skb) | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL_GPL(ip6_local_out); | 84 | EXPORT_SYMBOL_GPL(ip6_local_out); |
85 | 85 | ||
86 | static int ip6_output_finish(struct sk_buff *skb) | ||
87 | { | ||
88 | struct dst_entry *dst = skb_dst(skb); | ||
89 | |||
90 | if (dst->hh) | ||
91 | return neigh_hh_output(dst->hh, skb); | ||
92 | else if (dst->neighbour) | ||
93 | return dst->neighbour->output(skb); | ||
94 | |||
95 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
96 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
97 | kfree_skb(skb); | ||
98 | return -EINVAL; | ||
99 | |||
100 | } | ||
101 | |||
102 | /* dev_loopback_xmit for use with netfilter. */ | 86 | /* dev_loopback_xmit for use with netfilter. */ |
103 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | 87 | static int ip6_dev_loopback_xmit(struct sk_buff *newskb) |
104 | { | 88 | { |
@@ -112,8 +96,7 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb) | |||
112 | return 0; | 96 | return 0; |
113 | } | 97 | } |
114 | 98 | ||
115 | 99 | static int ip6_finish_output2(struct sk_buff *skb) | |
116 | static int ip6_output2(struct sk_buff *skb) | ||
117 | { | 100 | { |
118 | struct dst_entry *dst = skb_dst(skb); | 101 | struct dst_entry *dst = skb_dst(skb); |
119 | struct net_device *dev = dst->dev; | 102 | struct net_device *dev = dst->dev; |
@@ -125,7 +108,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
125 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 108 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
126 | 109 | ||
127 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && | 110 | if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(skb->sk) && |
128 | ((mroute6_socket(dev_net(dev)) && | 111 | ((mroute6_socket(dev_net(dev), skb) && |
129 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || | 112 | !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || |
130 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, | 113 | ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, |
131 | &ipv6_hdr(skb)->saddr))) { | 114 | &ipv6_hdr(skb)->saddr))) { |
@@ -135,8 +118,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
135 | is not supported in any case. | 118 | is not supported in any case. |
136 | */ | 119 | */ |
137 | if (newskb) | 120 | if (newskb) |
138 | NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, newskb, | 121 | NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, |
139 | NULL, newskb->dev, | 122 | newskb, NULL, newskb->dev, |
140 | ip6_dev_loopback_xmit); | 123 | ip6_dev_loopback_xmit); |
141 | 124 | ||
142 | if (ipv6_hdr(skb)->hop_limit == 0) { | 125 | if (ipv6_hdr(skb)->hop_limit == 0) { |
@@ -151,8 +134,15 @@ static int ip6_output2(struct sk_buff *skb) | |||
151 | skb->len); | 134 | skb->len); |
152 | } | 135 | } |
153 | 136 | ||
154 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev, | 137 | if (dst->hh) |
155 | ip6_output_finish); | 138 | return neigh_hh_output(dst->hh, skb); |
139 | else if (dst->neighbour) | ||
140 | return dst->neighbour->output(skb); | ||
141 | |||
142 | IP6_INC_STATS_BH(dev_net(dst->dev), | ||
143 | ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | ||
144 | kfree_skb(skb); | ||
145 | return -EINVAL; | ||
156 | } | 146 | } |
157 | 147 | ||
158 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | 148 | static inline int ip6_skb_dst_mtu(struct sk_buff *skb) |
@@ -163,29 +153,37 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) | |||
163 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); | 153 | skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); |
164 | } | 154 | } |
165 | 155 | ||
156 | static int ip6_finish_output(struct sk_buff *skb) | ||
157 | { | ||
158 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | ||
159 | dst_allfrag(skb_dst(skb))) | ||
160 | return ip6_fragment(skb, ip6_finish_output2); | ||
161 | else | ||
162 | return ip6_finish_output2(skb); | ||
163 | } | ||
164 | |||
166 | int ip6_output(struct sk_buff *skb) | 165 | int ip6_output(struct sk_buff *skb) |
167 | { | 166 | { |
167 | struct net_device *dev = skb_dst(skb)->dev; | ||
168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 168 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
169 | if (unlikely(idev->cnf.disable_ipv6)) { | 169 | if (unlikely(idev->cnf.disable_ipv6)) { |
170 | IP6_INC_STATS(dev_net(skb_dst(skb)->dev), idev, | 170 | IP6_INC_STATS(dev_net(dev), idev, |
171 | IPSTATS_MIB_OUTDISCARDS); | 171 | IPSTATS_MIB_OUTDISCARDS); |
172 | kfree_skb(skb); | 172 | kfree_skb(skb); |
173 | return 0; | 173 | return 0; |
174 | } | 174 | } |
175 | 175 | ||
176 | if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 176 | return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, dev, |
177 | dst_allfrag(skb_dst(skb))) | 177 | ip6_finish_output, |
178 | return ip6_fragment(skb, ip6_output2); | 178 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); |
179 | else | ||
180 | return ip6_output2(skb); | ||
181 | } | 179 | } |
182 | 180 | ||
183 | /* | 181 | /* |
184 | * xmit an sk_buff (used by TCP) | 182 | * xmit an sk_buff (used by TCP, SCTP and DCCP) |
185 | */ | 183 | */ |
186 | 184 | ||
187 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | 185 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, |
188 | struct ipv6_txoptions *opt, int ipfragok) | 186 | struct ipv6_txoptions *opt) |
189 | { | 187 | { |
190 | struct net *net = sock_net(sk); | 188 | struct net *net = sock_net(sk); |
191 | struct ipv6_pinfo *np = inet6_sk(sk); | 189 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -218,8 +216,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
218 | } | 216 | } |
219 | kfree_skb(skb); | 217 | kfree_skb(skb); |
220 | skb = skb2; | 218 | skb = skb2; |
221 | if (sk) | 219 | skb_set_owner_w(skb, sk); |
222 | skb_set_owner_w(skb, sk); | ||
223 | } | 220 | } |
224 | if (opt->opt_flen) | 221 | if (opt->opt_flen) |
225 | ipv6_push_frag_opts(skb, opt, &proto); | 222 | ipv6_push_frag_opts(skb, opt, &proto); |
@@ -231,10 +228,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
231 | skb_reset_network_header(skb); | 228 | skb_reset_network_header(skb); |
232 | hdr = ipv6_hdr(skb); | 229 | hdr = ipv6_hdr(skb); |
233 | 230 | ||
234 | /* Allow local fragmentation. */ | ||
235 | if (ipfragok) | ||
236 | skb->local_df = 1; | ||
237 | |||
238 | /* | 231 | /* |
239 | * Fill in the IPv6 header | 232 | * Fill in the IPv6 header |
240 | */ | 233 | */ |
@@ -261,8 +254,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
261 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { | 254 | if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { |
262 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), | 255 | IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)), |
263 | IPSTATS_MIB_OUT, skb->len); | 256 | IPSTATS_MIB_OUT, skb->len); |
264 | return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 257 | return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
265 | dst_output); | 258 | dst->dev, dst_output); |
266 | } | 259 | } |
267 | 260 | ||
268 | if (net_ratelimit()) | 261 | if (net_ratelimit()) |
@@ -538,7 +531,7 @@ int ip6_forward(struct sk_buff *skb) | |||
538 | hdr->hop_limit--; | 531 | hdr->hop_limit--; |
539 | 532 | ||
540 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); | 533 | IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
541 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dst->dev, | 534 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, |
542 | ip6_forward_finish); | 535 | ip6_forward_finish); |
543 | 536 | ||
544 | error: | 537 | error: |
@@ -629,7 +622,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
629 | /* We must not fragment if the socket is set to force MTU discovery | 622 | /* We must not fragment if the socket is set to force MTU discovery |
630 | * or if the skb it not generated by a local socket. | 623 | * or if the skb it not generated by a local socket. |
631 | */ | 624 | */ |
632 | if (!skb->local_df) { | 625 | if (!skb->local_df && skb->len > mtu) { |
633 | skb->dev = skb_dst(skb)->dev; | 626 | skb->dev = skb_dst(skb)->dev; |
634 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 627 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
635 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 628 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
@@ -1109,7 +1102,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1109 | int offset, int len, int odd, struct sk_buff *skb), | 1102 | int offset, int len, int odd, struct sk_buff *skb), |
1110 | void *from, int length, int transhdrlen, | 1103 | void *from, int length, int transhdrlen, |
1111 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, | 1104 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
1112 | struct rt6_info *rt, unsigned int flags) | 1105 | struct rt6_info *rt, unsigned int flags, int dontfrag) |
1113 | { | 1106 | { |
1114 | struct inet_sock *inet = inet_sk(sk); | 1107 | struct inet_sock *inet = inet_sk(sk); |
1115 | struct ipv6_pinfo *np = inet6_sk(sk); | 1108 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -1223,15 +1216,23 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1223 | */ | 1216 | */ |
1224 | 1217 | ||
1225 | inet->cork.length += length; | 1218 | inet->cork.length += length; |
1226 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | 1219 | if (length > mtu) { |
1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | 1220 | int proto = sk->sk_protocol; |
1221 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | ||
1222 | ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen); | ||
1223 | return -EMSGSIZE; | ||
1224 | } | ||
1228 | 1225 | ||
1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | 1226 | if (proto == IPPROTO_UDP && |
1230 | fragheaderlen, transhdrlen, mtu, | 1227 | (rt->u.dst.dev->features & NETIF_F_UFO)) { |
1231 | flags); | 1228 | |
1232 | if (err) | 1229 | err = ip6_ufo_append_data(sk, getfrag, from, length, |
1233 | goto error; | 1230 | hh_len, fragheaderlen, |
1234 | return 0; | 1231 | transhdrlen, mtu, flags); |
1232 | if (err) | ||
1233 | goto error; | ||
1234 | return 0; | ||
1235 | } | ||
1235 | } | 1236 | } |
1236 | 1237 | ||
1237 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1238 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 2599870747ec..8f39893d8081 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -723,14 +723,10 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | |||
723 | skb->protocol = htons(protocol); | 723 | skb->protocol = htons(protocol); |
724 | skb->pkt_type = PACKET_HOST; | 724 | skb->pkt_type = PACKET_HOST; |
725 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | 725 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); |
726 | skb->dev = t->dev; | ||
727 | skb_dst_drop(skb); | ||
728 | nf_reset(skb); | ||
729 | 726 | ||
730 | dscp_ecn_decapsulate(t, ipv6h, skb); | 727 | skb_tunnel_rx(skb, t->dev); |
731 | 728 | ||
732 | t->dev->stats.rx_packets++; | 729 | dscp_ecn_decapsulate(t, ipv6h, skb); |
733 | t->dev->stats.rx_bytes += skb->len; | ||
734 | netif_rx(skb); | 730 | netif_rx(skb); |
735 | rcu_read_unlock(); | 731 | rcu_read_unlock(); |
736 | return 0; | 732 | return 0; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 3e333268db89..bd9e7d3e9c8e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/if_arp.h> | 42 | #include <linux/if_arp.h> |
43 | #include <net/checksum.h> | 43 | #include <net/checksum.h> |
44 | #include <net/netlink.h> | 44 | #include <net/netlink.h> |
45 | #include <net/fib_rules.h> | ||
45 | 46 | ||
46 | #include <net/ipv6.h> | 47 | #include <net/ipv6.h> |
47 | #include <net/ip6_route.h> | 48 | #include <net/ip6_route.h> |
@@ -51,6 +52,34 @@ | |||
51 | #include <linux/netfilter_ipv6.h> | 52 | #include <linux/netfilter_ipv6.h> |
52 | #include <net/ip6_checksum.h> | 53 | #include <net/ip6_checksum.h> |
53 | 54 | ||
55 | struct mr6_table { | ||
56 | struct list_head list; | ||
57 | #ifdef CONFIG_NET_NS | ||
58 | struct net *net; | ||
59 | #endif | ||
60 | u32 id; | ||
61 | struct sock *mroute6_sk; | ||
62 | struct timer_list ipmr_expire_timer; | ||
63 | struct list_head mfc6_unres_queue; | ||
64 | struct list_head mfc6_cache_array[MFC6_LINES]; | ||
65 | struct mif_device vif6_table[MAXMIFS]; | ||
66 | int maxvif; | ||
67 | atomic_t cache_resolve_queue_len; | ||
68 | int mroute_do_assert; | ||
69 | int mroute_do_pim; | ||
70 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
71 | int mroute_reg_vif_num; | ||
72 | #endif | ||
73 | }; | ||
74 | |||
75 | struct ip6mr_rule { | ||
76 | struct fib_rule common; | ||
77 | }; | ||
78 | |||
79 | struct ip6mr_result { | ||
80 | struct mr6_table *mrt; | ||
81 | }; | ||
82 | |||
54 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 83 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
55 | Note that the changes are semaphored via rtnl_lock. | 84 | Note that the changes are semaphored via rtnl_lock. |
56 | */ | 85 | */ |
@@ -61,9 +90,7 @@ static DEFINE_RWLOCK(mrt_lock); | |||
61 | * Multicast router control variables | 90 | * Multicast router control variables |
62 | */ | 91 | */ |
63 | 92 | ||
64 | #define MIF_EXISTS(_net, _idx) ((_net)->ipv6.vif6_table[_idx].dev != NULL) | 93 | #define MIF_EXISTS(_mrt, _idx) ((_mrt)->vif6_table[_idx].dev != NULL) |
65 | |||
66 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ | ||
67 | 94 | ||
68 | /* Special spinlock for queue of unresolved entries */ | 95 | /* Special spinlock for queue of unresolved entries */ |
69 | static DEFINE_SPINLOCK(mfc_unres_lock); | 96 | static DEFINE_SPINLOCK(mfc_unres_lock); |
@@ -78,20 +105,233 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
78 | 105 | ||
79 | static struct kmem_cache *mrt_cachep __read_mostly; | 106 | static struct kmem_cache *mrt_cachep __read_mostly; |
80 | 107 | ||
81 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); | 108 | static struct mr6_table *ip6mr_new_table(struct net *net, u32 id); |
82 | static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, | 109 | static void ip6mr_free_table(struct mr6_table *mrt); |
110 | |||
111 | static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, | ||
112 | struct sk_buff *skb, struct mfc6_cache *cache); | ||
113 | static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, | ||
83 | mifi_t mifi, int assert); | 114 | mifi_t mifi, int assert); |
84 | static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); | 115 | static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
85 | static void mroute_clean_tables(struct net *net); | 116 | struct mfc6_cache *c, struct rtmsg *rtm); |
117 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, | ||
118 | struct netlink_callback *cb); | ||
119 | static void mroute_clean_tables(struct mr6_table *mrt); | ||
120 | static void ipmr_expire_process(unsigned long arg); | ||
121 | |||
122 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
123 | #define ip6mr_for_each_table(mrt, met) \ | ||
124 | list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) | ||
125 | |||
126 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | ||
127 | { | ||
128 | struct mr6_table *mrt; | ||
129 | |||
130 | ip6mr_for_each_table(mrt, net) { | ||
131 | if (mrt->id == id) | ||
132 | return mrt; | ||
133 | } | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | ||
138 | struct mr6_table **mrt) | ||
139 | { | ||
140 | struct ip6mr_result res; | ||
141 | struct fib_lookup_arg arg = { .result = &res, }; | ||
142 | int err; | ||
143 | |||
144 | err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flp, 0, &arg); | ||
145 | if (err < 0) | ||
146 | return err; | ||
147 | *mrt = res.mrt; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp, | ||
152 | int flags, struct fib_lookup_arg *arg) | ||
153 | { | ||
154 | struct ip6mr_result *res = arg->result; | ||
155 | struct mr6_table *mrt; | ||
156 | |||
157 | switch (rule->action) { | ||
158 | case FR_ACT_TO_TBL: | ||
159 | break; | ||
160 | case FR_ACT_UNREACHABLE: | ||
161 | return -ENETUNREACH; | ||
162 | case FR_ACT_PROHIBIT: | ||
163 | return -EACCES; | ||
164 | case FR_ACT_BLACKHOLE: | ||
165 | default: | ||
166 | return -EINVAL; | ||
167 | } | ||
168 | |||
169 | mrt = ip6mr_get_table(rule->fr_net, rule->table); | ||
170 | if (mrt == NULL) | ||
171 | return -EAGAIN; | ||
172 | res->mrt = mrt; | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int ip6mr_rule_match(struct fib_rule *rule, struct flowi *flp, int flags) | ||
177 | { | ||
178 | return 1; | ||
179 | } | ||
180 | |||
181 | static const struct nla_policy ip6mr_rule_policy[FRA_MAX + 1] = { | ||
182 | FRA_GENERIC_POLICY, | ||
183 | }; | ||
184 | |||
185 | static int ip6mr_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | ||
186 | struct fib_rule_hdr *frh, struct nlattr **tb) | ||
187 | { | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int ip6mr_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | ||
192 | struct nlattr **tb) | ||
193 | { | ||
194 | return 1; | ||
195 | } | ||
196 | |||
197 | static int ip6mr_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | ||
198 | struct fib_rule_hdr *frh) | ||
199 | { | ||
200 | frh->dst_len = 0; | ||
201 | frh->src_len = 0; | ||
202 | frh->tos = 0; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static const struct fib_rules_ops __net_initdata ip6mr_rules_ops_template = { | ||
207 | .family = RTNL_FAMILY_IP6MR, | ||
208 | .rule_size = sizeof(struct ip6mr_rule), | ||
209 | .addr_size = sizeof(struct in6_addr), | ||
210 | .action = ip6mr_rule_action, | ||
211 | .match = ip6mr_rule_match, | ||
212 | .configure = ip6mr_rule_configure, | ||
213 | .compare = ip6mr_rule_compare, | ||
214 | .default_pref = fib_default_rule_pref, | ||
215 | .fill = ip6mr_rule_fill, | ||
216 | .nlgroup = RTNLGRP_IPV6_RULE, | ||
217 | .policy = ip6mr_rule_policy, | ||
218 | .owner = THIS_MODULE, | ||
219 | }; | ||
220 | |||
221 | static int __net_init ip6mr_rules_init(struct net *net) | ||
222 | { | ||
223 | struct fib_rules_ops *ops; | ||
224 | struct mr6_table *mrt; | ||
225 | int err; | ||
226 | |||
227 | ops = fib_rules_register(&ip6mr_rules_ops_template, net); | ||
228 | if (IS_ERR(ops)) | ||
229 | return PTR_ERR(ops); | ||
230 | |||
231 | INIT_LIST_HEAD(&net->ipv6.mr6_tables); | ||
232 | |||
233 | mrt = ip6mr_new_table(net, RT6_TABLE_DFLT); | ||
234 | if (mrt == NULL) { | ||
235 | err = -ENOMEM; | ||
236 | goto err1; | ||
237 | } | ||
238 | |||
239 | err = fib_default_rule_add(ops, 0x7fff, RT6_TABLE_DFLT, 0); | ||
240 | if (err < 0) | ||
241 | goto err2; | ||
242 | |||
243 | net->ipv6.mr6_rules_ops = ops; | ||
244 | return 0; | ||
245 | |||
246 | err2: | ||
247 | kfree(mrt); | ||
248 | err1: | ||
249 | fib_rules_unregister(ops); | ||
250 | return err; | ||
251 | } | ||
252 | |||
253 | static void __net_exit ip6mr_rules_exit(struct net *net) | ||
254 | { | ||
255 | struct mr6_table *mrt, *next; | ||
256 | |||
257 | list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) | ||
258 | ip6mr_free_table(mrt); | ||
259 | fib_rules_unregister(net->ipv6.mr6_rules_ops); | ||
260 | } | ||
261 | #else | ||
262 | #define ip6mr_for_each_table(mrt, net) \ | ||
263 | for (mrt = net->ipv6.mrt6; mrt; mrt = NULL) | ||
264 | |||
265 | static struct mr6_table *ip6mr_get_table(struct net *net, u32 id) | ||
266 | { | ||
267 | return net->ipv6.mrt6; | ||
268 | } | ||
269 | |||
270 | static int ip6mr_fib_lookup(struct net *net, struct flowi *flp, | ||
271 | struct mr6_table **mrt) | ||
272 | { | ||
273 | *mrt = net->ipv6.mrt6; | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int __net_init ip6mr_rules_init(struct net *net) | ||
278 | { | ||
279 | net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT); | ||
280 | return net->ipv6.mrt6 ? 0 : -ENOMEM; | ||
281 | } | ||
86 | 282 | ||
87 | static struct timer_list ipmr_expire_timer; | 283 | static void __net_exit ip6mr_rules_exit(struct net *net) |
284 | { | ||
285 | ip6mr_free_table(net->ipv6.mrt6); | ||
286 | } | ||
287 | #endif | ||
288 | |||
289 | static struct mr6_table *ip6mr_new_table(struct net *net, u32 id) | ||
290 | { | ||
291 | struct mr6_table *mrt; | ||
292 | unsigned int i; | ||
293 | |||
294 | mrt = ip6mr_get_table(net, id); | ||
295 | if (mrt != NULL) | ||
296 | return mrt; | ||
297 | |||
298 | mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); | ||
299 | if (mrt == NULL) | ||
300 | return NULL; | ||
301 | mrt->id = id; | ||
302 | write_pnet(&mrt->net, net); | ||
303 | |||
304 | /* Forwarding cache */ | ||
305 | for (i = 0; i < MFC6_LINES; i++) | ||
306 | INIT_LIST_HEAD(&mrt->mfc6_cache_array[i]); | ||
307 | |||
308 | INIT_LIST_HEAD(&mrt->mfc6_unres_queue); | ||
88 | 309 | ||
310 | setup_timer(&mrt->ipmr_expire_timer, ipmr_expire_process, | ||
311 | (unsigned long)mrt); | ||
312 | |||
313 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
314 | mrt->mroute_reg_vif_num = -1; | ||
315 | #endif | ||
316 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
317 | list_add_tail_rcu(&mrt->list, &net->ipv6.mr6_tables); | ||
318 | #endif | ||
319 | return mrt; | ||
320 | } | ||
321 | |||
322 | static void ip6mr_free_table(struct mr6_table *mrt) | ||
323 | { | ||
324 | del_timer(&mrt->ipmr_expire_timer); | ||
325 | mroute_clean_tables(mrt); | ||
326 | kfree(mrt); | ||
327 | } | ||
89 | 328 | ||
90 | #ifdef CONFIG_PROC_FS | 329 | #ifdef CONFIG_PROC_FS |
91 | 330 | ||
92 | struct ipmr_mfc_iter { | 331 | struct ipmr_mfc_iter { |
93 | struct seq_net_private p; | 332 | struct seq_net_private p; |
94 | struct mfc6_cache **cache; | 333 | struct mr6_table *mrt; |
334 | struct list_head *cache; | ||
95 | int ct; | 335 | int ct; |
96 | }; | 336 | }; |
97 | 337 | ||
@@ -99,22 +339,22 @@ struct ipmr_mfc_iter { | |||
99 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, | 339 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, |
100 | struct ipmr_mfc_iter *it, loff_t pos) | 340 | struct ipmr_mfc_iter *it, loff_t pos) |
101 | { | 341 | { |
342 | struct mr6_table *mrt = it->mrt; | ||
102 | struct mfc6_cache *mfc; | 343 | struct mfc6_cache *mfc; |
103 | 344 | ||
104 | it->cache = net->ipv6.mfc6_cache_array; | ||
105 | read_lock(&mrt_lock); | 345 | read_lock(&mrt_lock); |
106 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) | 346 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) { |
107 | for (mfc = net->ipv6.mfc6_cache_array[it->ct]; | 347 | it->cache = &mrt->mfc6_cache_array[it->ct]; |
108 | mfc; mfc = mfc->next) | 348 | list_for_each_entry(mfc, it->cache, list) |
109 | if (pos-- == 0) | 349 | if (pos-- == 0) |
110 | return mfc; | 350 | return mfc; |
351 | } | ||
111 | read_unlock(&mrt_lock); | 352 | read_unlock(&mrt_lock); |
112 | 353 | ||
113 | it->cache = &mfc_unres_queue; | ||
114 | spin_lock_bh(&mfc_unres_lock); | 354 | spin_lock_bh(&mfc_unres_lock); |
115 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 355 | it->cache = &mrt->mfc6_unres_queue; |
116 | if (net_eq(mfc6_net(mfc), net) && | 356 | list_for_each_entry(mfc, it->cache, list) |
117 | pos-- == 0) | 357 | if (pos-- == 0) |
118 | return mfc; | 358 | return mfc; |
119 | spin_unlock_bh(&mfc_unres_lock); | 359 | spin_unlock_bh(&mfc_unres_lock); |
120 | 360 | ||
@@ -122,15 +362,13 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, | |||
122 | return NULL; | 362 | return NULL; |
123 | } | 363 | } |
124 | 364 | ||
125 | |||
126 | |||
127 | |||
128 | /* | 365 | /* |
129 | * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif | 366 | * The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif |
130 | */ | 367 | */ |
131 | 368 | ||
132 | struct ipmr_vif_iter { | 369 | struct ipmr_vif_iter { |
133 | struct seq_net_private p; | 370 | struct seq_net_private p; |
371 | struct mr6_table *mrt; | ||
134 | int ct; | 372 | int ct; |
135 | }; | 373 | }; |
136 | 374 | ||
@@ -138,11 +376,13 @@ static struct mif_device *ip6mr_vif_seq_idx(struct net *net, | |||
138 | struct ipmr_vif_iter *iter, | 376 | struct ipmr_vif_iter *iter, |
139 | loff_t pos) | 377 | loff_t pos) |
140 | { | 378 | { |
141 | for (iter->ct = 0; iter->ct < net->ipv6.maxvif; ++iter->ct) { | 379 | struct mr6_table *mrt = iter->mrt; |
142 | if (!MIF_EXISTS(net, iter->ct)) | 380 | |
381 | for (iter->ct = 0; iter->ct < mrt->maxvif; ++iter->ct) { | ||
382 | if (!MIF_EXISTS(mrt, iter->ct)) | ||
143 | continue; | 383 | continue; |
144 | if (pos-- == 0) | 384 | if (pos-- == 0) |
145 | return &net->ipv6.vif6_table[iter->ct]; | 385 | return &mrt->vif6_table[iter->ct]; |
146 | } | 386 | } |
147 | return NULL; | 387 | return NULL; |
148 | } | 388 | } |
@@ -150,7 +390,15 @@ static struct mif_device *ip6mr_vif_seq_idx(struct net *net, | |||
150 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) | 390 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) |
151 | __acquires(mrt_lock) | 391 | __acquires(mrt_lock) |
152 | { | 392 | { |
393 | struct ipmr_vif_iter *iter = seq->private; | ||
153 | struct net *net = seq_file_net(seq); | 394 | struct net *net = seq_file_net(seq); |
395 | struct mr6_table *mrt; | ||
396 | |||
397 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
398 | if (mrt == NULL) | ||
399 | return ERR_PTR(-ENOENT); | ||
400 | |||
401 | iter->mrt = mrt; | ||
154 | 402 | ||
155 | read_lock(&mrt_lock); | 403 | read_lock(&mrt_lock); |
156 | return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1) | 404 | return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1) |
@@ -161,15 +409,16 @@ static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
161 | { | 409 | { |
162 | struct ipmr_vif_iter *iter = seq->private; | 410 | struct ipmr_vif_iter *iter = seq->private; |
163 | struct net *net = seq_file_net(seq); | 411 | struct net *net = seq_file_net(seq); |
412 | struct mr6_table *mrt = iter->mrt; | ||
164 | 413 | ||
165 | ++*pos; | 414 | ++*pos; |
166 | if (v == SEQ_START_TOKEN) | 415 | if (v == SEQ_START_TOKEN) |
167 | return ip6mr_vif_seq_idx(net, iter, 0); | 416 | return ip6mr_vif_seq_idx(net, iter, 0); |
168 | 417 | ||
169 | while (++iter->ct < net->ipv6.maxvif) { | 418 | while (++iter->ct < mrt->maxvif) { |
170 | if (!MIF_EXISTS(net, iter->ct)) | 419 | if (!MIF_EXISTS(mrt, iter->ct)) |
171 | continue; | 420 | continue; |
172 | return &net->ipv6.vif6_table[iter->ct]; | 421 | return &mrt->vif6_table[iter->ct]; |
173 | } | 422 | } |
174 | return NULL; | 423 | return NULL; |
175 | } | 424 | } |
@@ -182,7 +431,8 @@ static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v) | |||
182 | 431 | ||
183 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | 432 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) |
184 | { | 433 | { |
185 | struct net *net = seq_file_net(seq); | 434 | struct ipmr_vif_iter *iter = seq->private; |
435 | struct mr6_table *mrt = iter->mrt; | ||
186 | 436 | ||
187 | if (v == SEQ_START_TOKEN) { | 437 | if (v == SEQ_START_TOKEN) { |
188 | seq_puts(seq, | 438 | seq_puts(seq, |
@@ -193,7 +443,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | |||
193 | 443 | ||
194 | seq_printf(seq, | 444 | seq_printf(seq, |
195 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", | 445 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", |
196 | vif - net->ipv6.vif6_table, | 446 | vif - mrt->vif6_table, |
197 | name, vif->bytes_in, vif->pkt_in, | 447 | name, vif->bytes_in, vif->pkt_in, |
198 | vif->bytes_out, vif->pkt_out, | 448 | vif->bytes_out, vif->pkt_out, |
199 | vif->flags); | 449 | vif->flags); |
@@ -224,8 +474,15 @@ static const struct file_operations ip6mr_vif_fops = { | |||
224 | 474 | ||
225 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | 475 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) |
226 | { | 476 | { |
477 | struct ipmr_mfc_iter *it = seq->private; | ||
227 | struct net *net = seq_file_net(seq); | 478 | struct net *net = seq_file_net(seq); |
479 | struct mr6_table *mrt; | ||
228 | 480 | ||
481 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
482 | if (mrt == NULL) | ||
483 | return ERR_PTR(-ENOENT); | ||
484 | |||
485 | it->mrt = mrt; | ||
229 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) | 486 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) |
230 | : SEQ_START_TOKEN; | 487 | : SEQ_START_TOKEN; |
231 | } | 488 | } |
@@ -235,35 +492,36 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
235 | struct mfc6_cache *mfc = v; | 492 | struct mfc6_cache *mfc = v; |
236 | struct ipmr_mfc_iter *it = seq->private; | 493 | struct ipmr_mfc_iter *it = seq->private; |
237 | struct net *net = seq_file_net(seq); | 494 | struct net *net = seq_file_net(seq); |
495 | struct mr6_table *mrt = it->mrt; | ||
238 | 496 | ||
239 | ++*pos; | 497 | ++*pos; |
240 | 498 | ||
241 | if (v == SEQ_START_TOKEN) | 499 | if (v == SEQ_START_TOKEN) |
242 | return ipmr_mfc_seq_idx(net, seq->private, 0); | 500 | return ipmr_mfc_seq_idx(net, seq->private, 0); |
243 | 501 | ||
244 | if (mfc->next) | 502 | if (mfc->list.next != it->cache) |
245 | return mfc->next; | 503 | return list_entry(mfc->list.next, struct mfc6_cache, list); |
246 | 504 | ||
247 | if (it->cache == &mfc_unres_queue) | 505 | if (it->cache == &mrt->mfc6_unres_queue) |
248 | goto end_of_list; | 506 | goto end_of_list; |
249 | 507 | ||
250 | BUG_ON(it->cache != net->ipv6.mfc6_cache_array); | 508 | BUG_ON(it->cache != &mrt->mfc6_cache_array[it->ct]); |
251 | 509 | ||
252 | while (++it->ct < MFC6_LINES) { | 510 | while (++it->ct < MFC6_LINES) { |
253 | mfc = net->ipv6.mfc6_cache_array[it->ct]; | 511 | it->cache = &mrt->mfc6_cache_array[it->ct]; |
254 | if (mfc) | 512 | if (list_empty(it->cache)) |
255 | return mfc; | 513 | continue; |
514 | return list_first_entry(it->cache, struct mfc6_cache, list); | ||
256 | } | 515 | } |
257 | 516 | ||
258 | /* exhausted cache_array, show unresolved */ | 517 | /* exhausted cache_array, show unresolved */ |
259 | read_unlock(&mrt_lock); | 518 | read_unlock(&mrt_lock); |
260 | it->cache = &mfc_unres_queue; | 519 | it->cache = &mrt->mfc6_unres_queue; |
261 | it->ct = 0; | 520 | it->ct = 0; |
262 | 521 | ||
263 | spin_lock_bh(&mfc_unres_lock); | 522 | spin_lock_bh(&mfc_unres_lock); |
264 | mfc = mfc_unres_queue; | 523 | if (!list_empty(it->cache)) |
265 | if (mfc) | 524 | return list_first_entry(it->cache, struct mfc6_cache, list); |
266 | return mfc; | ||
267 | 525 | ||
268 | end_of_list: | 526 | end_of_list: |
269 | spin_unlock_bh(&mfc_unres_lock); | 527 | spin_unlock_bh(&mfc_unres_lock); |
@@ -275,18 +533,17 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
275 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | 533 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
276 | { | 534 | { |
277 | struct ipmr_mfc_iter *it = seq->private; | 535 | struct ipmr_mfc_iter *it = seq->private; |
278 | struct net *net = seq_file_net(seq); | 536 | struct mr6_table *mrt = it->mrt; |
279 | 537 | ||
280 | if (it->cache == &mfc_unres_queue) | 538 | if (it->cache == &mrt->mfc6_unres_queue) |
281 | spin_unlock_bh(&mfc_unres_lock); | 539 | spin_unlock_bh(&mfc_unres_lock); |
282 | else if (it->cache == net->ipv6.mfc6_cache_array) | 540 | else if (it->cache == mrt->mfc6_cache_array) |
283 | read_unlock(&mrt_lock); | 541 | read_unlock(&mrt_lock); |
284 | } | 542 | } |
285 | 543 | ||
286 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | 544 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) |
287 | { | 545 | { |
288 | int n; | 546 | int n; |
289 | struct net *net = seq_file_net(seq); | ||
290 | 547 | ||
291 | if (v == SEQ_START_TOKEN) { | 548 | if (v == SEQ_START_TOKEN) { |
292 | seq_puts(seq, | 549 | seq_puts(seq, |
@@ -296,19 +553,20 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
296 | } else { | 553 | } else { |
297 | const struct mfc6_cache *mfc = v; | 554 | const struct mfc6_cache *mfc = v; |
298 | const struct ipmr_mfc_iter *it = seq->private; | 555 | const struct ipmr_mfc_iter *it = seq->private; |
556 | struct mr6_table *mrt = it->mrt; | ||
299 | 557 | ||
300 | seq_printf(seq, "%pI6 %pI6 %-3hd", | 558 | seq_printf(seq, "%pI6 %pI6 %-3hd", |
301 | &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, | 559 | &mfc->mf6c_mcastgrp, &mfc->mf6c_origin, |
302 | mfc->mf6c_parent); | 560 | mfc->mf6c_parent); |
303 | 561 | ||
304 | if (it->cache != &mfc_unres_queue) { | 562 | if (it->cache != &mrt->mfc6_unres_queue) { |
305 | seq_printf(seq, " %8lu %8lu %8lu", | 563 | seq_printf(seq, " %8lu %8lu %8lu", |
306 | mfc->mfc_un.res.pkt, | 564 | mfc->mfc_un.res.pkt, |
307 | mfc->mfc_un.res.bytes, | 565 | mfc->mfc_un.res.bytes, |
308 | mfc->mfc_un.res.wrong_if); | 566 | mfc->mfc_un.res.wrong_if); |
309 | for (n = mfc->mfc_un.res.minvif; | 567 | for (n = mfc->mfc_un.res.minvif; |
310 | n < mfc->mfc_un.res.maxvif; n++) { | 568 | n < mfc->mfc_un.res.maxvif; n++) { |
311 | if (MIF_EXISTS(net, n) && | 569 | if (MIF_EXISTS(mrt, n) && |
312 | mfc->mfc_un.res.ttls[n] < 255) | 570 | mfc->mfc_un.res.ttls[n] < 255) |
313 | seq_printf(seq, | 571 | seq_printf(seq, |
314 | " %2d:%-3d", | 572 | " %2d:%-3d", |
@@ -355,7 +613,12 @@ static int pim6_rcv(struct sk_buff *skb) | |||
355 | struct ipv6hdr *encap; | 613 | struct ipv6hdr *encap; |
356 | struct net_device *reg_dev = NULL; | 614 | struct net_device *reg_dev = NULL; |
357 | struct net *net = dev_net(skb->dev); | 615 | struct net *net = dev_net(skb->dev); |
358 | int reg_vif_num = net->ipv6.mroute_reg_vif_num; | 616 | struct mr6_table *mrt; |
617 | struct flowi fl = { | ||
618 | .iif = skb->dev->ifindex, | ||
619 | .mark = skb->mark, | ||
620 | }; | ||
621 | int reg_vif_num; | ||
359 | 622 | ||
360 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) | 623 | if (!pskb_may_pull(skb, sizeof(*pim) + sizeof(*encap))) |
361 | goto drop; | 624 | goto drop; |
@@ -378,9 +641,13 @@ static int pim6_rcv(struct sk_buff *skb) | |||
378 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) | 641 | ntohs(encap->payload_len) + sizeof(*pim) > skb->len) |
379 | goto drop; | 642 | goto drop; |
380 | 643 | ||
644 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | ||
645 | goto drop; | ||
646 | reg_vif_num = mrt->mroute_reg_vif_num; | ||
647 | |||
381 | read_lock(&mrt_lock); | 648 | read_lock(&mrt_lock); |
382 | if (reg_vif_num >= 0) | 649 | if (reg_vif_num >= 0) |
383 | reg_dev = net->ipv6.vif6_table[reg_vif_num].dev; | 650 | reg_dev = mrt->vif6_table[reg_vif_num].dev; |
384 | if (reg_dev) | 651 | if (reg_dev) |
385 | dev_hold(reg_dev); | 652 | dev_hold(reg_dev); |
386 | read_unlock(&mrt_lock); | 653 | read_unlock(&mrt_lock); |
@@ -391,14 +658,12 @@ static int pim6_rcv(struct sk_buff *skb) | |||
391 | skb->mac_header = skb->network_header; | 658 | skb->mac_header = skb->network_header; |
392 | skb_pull(skb, (u8 *)encap - skb->data); | 659 | skb_pull(skb, (u8 *)encap - skb->data); |
393 | skb_reset_network_header(skb); | 660 | skb_reset_network_header(skb); |
394 | skb->dev = reg_dev; | ||
395 | skb->protocol = htons(ETH_P_IPV6); | 661 | skb->protocol = htons(ETH_P_IPV6); |
396 | skb->ip_summed = 0; | 662 | skb->ip_summed = 0; |
397 | skb->pkt_type = PACKET_HOST; | 663 | skb->pkt_type = PACKET_HOST; |
398 | skb_dst_drop(skb); | 664 | |
399 | reg_dev->stats.rx_bytes += skb->len; | 665 | skb_tunnel_rx(skb, reg_dev); |
400 | reg_dev->stats.rx_packets++; | 666 | |
401 | nf_reset(skb); | ||
402 | netif_rx(skb); | 667 | netif_rx(skb); |
403 | dev_put(reg_dev); | 668 | dev_put(reg_dev); |
404 | return 0; | 669 | return 0; |
@@ -417,12 +682,22 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
417 | struct net_device *dev) | 682 | struct net_device *dev) |
418 | { | 683 | { |
419 | struct net *net = dev_net(dev); | 684 | struct net *net = dev_net(dev); |
685 | struct mr6_table *mrt; | ||
686 | struct flowi fl = { | ||
687 | .oif = dev->ifindex, | ||
688 | .iif = skb->skb_iif, | ||
689 | .mark = skb->mark, | ||
690 | }; | ||
691 | int err; | ||
692 | |||
693 | err = ip6mr_fib_lookup(net, &fl, &mrt); | ||
694 | if (err < 0) | ||
695 | return err; | ||
420 | 696 | ||
421 | read_lock(&mrt_lock); | 697 | read_lock(&mrt_lock); |
422 | dev->stats.tx_bytes += skb->len; | 698 | dev->stats.tx_bytes += skb->len; |
423 | dev->stats.tx_packets++; | 699 | dev->stats.tx_packets++; |
424 | ip6mr_cache_report(net, skb, net->ipv6.mroute_reg_vif_num, | 700 | ip6mr_cache_report(mrt, skb, mrt->mroute_reg_vif_num, MRT6MSG_WHOLEPKT); |
425 | MRT6MSG_WHOLEPKT); | ||
426 | read_unlock(&mrt_lock); | 701 | read_unlock(&mrt_lock); |
427 | kfree_skb(skb); | 702 | kfree_skb(skb); |
428 | return NETDEV_TX_OK; | 703 | return NETDEV_TX_OK; |
@@ -442,11 +717,17 @@ static void reg_vif_setup(struct net_device *dev) | |||
442 | dev->features |= NETIF_F_NETNS_LOCAL; | 717 | dev->features |= NETIF_F_NETNS_LOCAL; |
443 | } | 718 | } |
444 | 719 | ||
445 | static struct net_device *ip6mr_reg_vif(struct net *net) | 720 | static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) |
446 | { | 721 | { |
447 | struct net_device *dev; | 722 | struct net_device *dev; |
723 | char name[IFNAMSIZ]; | ||
724 | |||
725 | if (mrt->id == RT6_TABLE_DFLT) | ||
726 | sprintf(name, "pim6reg"); | ||
727 | else | ||
728 | sprintf(name, "pim6reg%u", mrt->id); | ||
448 | 729 | ||
449 | dev = alloc_netdev(0, "pim6reg", reg_vif_setup); | 730 | dev = alloc_netdev(0, name, reg_vif_setup); |
450 | if (dev == NULL) | 731 | if (dev == NULL) |
451 | return NULL; | 732 | return NULL; |
452 | 733 | ||
@@ -478,15 +759,16 @@ failure: | |||
478 | * Delete a VIF entry | 759 | * Delete a VIF entry |
479 | */ | 760 | */ |
480 | 761 | ||
481 | static int mif6_delete(struct net *net, int vifi, struct list_head *head) | 762 | static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head) |
482 | { | 763 | { |
483 | struct mif_device *v; | 764 | struct mif_device *v; |
484 | struct net_device *dev; | 765 | struct net_device *dev; |
485 | struct inet6_dev *in6_dev; | 766 | struct inet6_dev *in6_dev; |
486 | if (vifi < 0 || vifi >= net->ipv6.maxvif) | 767 | |
768 | if (vifi < 0 || vifi >= mrt->maxvif) | ||
487 | return -EADDRNOTAVAIL; | 769 | return -EADDRNOTAVAIL; |
488 | 770 | ||
489 | v = &net->ipv6.vif6_table[vifi]; | 771 | v = &mrt->vif6_table[vifi]; |
490 | 772 | ||
491 | write_lock_bh(&mrt_lock); | 773 | write_lock_bh(&mrt_lock); |
492 | dev = v->dev; | 774 | dev = v->dev; |
@@ -498,17 +780,17 @@ static int mif6_delete(struct net *net, int vifi, struct list_head *head) | |||
498 | } | 780 | } |
499 | 781 | ||
500 | #ifdef CONFIG_IPV6_PIMSM_V2 | 782 | #ifdef CONFIG_IPV6_PIMSM_V2 |
501 | if (vifi == net->ipv6.mroute_reg_vif_num) | 783 | if (vifi == mrt->mroute_reg_vif_num) |
502 | net->ipv6.mroute_reg_vif_num = -1; | 784 | mrt->mroute_reg_vif_num = -1; |
503 | #endif | 785 | #endif |
504 | 786 | ||
505 | if (vifi + 1 == net->ipv6.maxvif) { | 787 | if (vifi + 1 == mrt->maxvif) { |
506 | int tmp; | 788 | int tmp; |
507 | for (tmp = vifi - 1; tmp >= 0; tmp--) { | 789 | for (tmp = vifi - 1; tmp >= 0; tmp--) { |
508 | if (MIF_EXISTS(net, tmp)) | 790 | if (MIF_EXISTS(mrt, tmp)) |
509 | break; | 791 | break; |
510 | } | 792 | } |
511 | net->ipv6.maxvif = tmp + 1; | 793 | mrt->maxvif = tmp + 1; |
512 | } | 794 | } |
513 | 795 | ||
514 | write_unlock_bh(&mrt_lock); | 796 | write_unlock_bh(&mrt_lock); |
@@ -528,7 +810,6 @@ static int mif6_delete(struct net *net, int vifi, struct list_head *head) | |||
528 | 810 | ||
529 | static inline void ip6mr_cache_free(struct mfc6_cache *c) | 811 | static inline void ip6mr_cache_free(struct mfc6_cache *c) |
530 | { | 812 | { |
531 | release_net(mfc6_net(c)); | ||
532 | kmem_cache_free(mrt_cachep, c); | 813 | kmem_cache_free(mrt_cachep, c); |
533 | } | 814 | } |
534 | 815 | ||
@@ -536,12 +817,12 @@ static inline void ip6mr_cache_free(struct mfc6_cache *c) | |||
536 | and reporting error to netlink readers. | 817 | and reporting error to netlink readers. |
537 | */ | 818 | */ |
538 | 819 | ||
539 | static void ip6mr_destroy_unres(struct mfc6_cache *c) | 820 | static void ip6mr_destroy_unres(struct mr6_table *mrt, struct mfc6_cache *c) |
540 | { | 821 | { |
822 | struct net *net = read_pnet(&mrt->net); | ||
541 | struct sk_buff *skb; | 823 | struct sk_buff *skb; |
542 | struct net *net = mfc6_net(c); | ||
543 | 824 | ||
544 | atomic_dec(&net->ipv6.cache_resolve_queue_len); | 825 | atomic_dec(&mrt->cache_resolve_queue_len); |
545 | 826 | ||
546 | while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { | 827 | while((skb = skb_dequeue(&c->mfc_un.unres.unresolved)) != NULL) { |
547 | if (ipv6_hdr(skb)->version == 0) { | 828 | if (ipv6_hdr(skb)->version == 0) { |
@@ -559,60 +840,59 @@ static void ip6mr_destroy_unres(struct mfc6_cache *c) | |||
559 | } | 840 | } |
560 | 841 | ||
561 | 842 | ||
562 | /* Single timer process for all the unresolved queue. */ | 843 | /* Timer process for all the unresolved queue. */ |
563 | 844 | ||
564 | static void ipmr_do_expire_process(unsigned long dummy) | 845 | static void ipmr_do_expire_process(struct mr6_table *mrt) |
565 | { | 846 | { |
566 | unsigned long now = jiffies; | 847 | unsigned long now = jiffies; |
567 | unsigned long expires = 10 * HZ; | 848 | unsigned long expires = 10 * HZ; |
568 | struct mfc6_cache *c, **cp; | 849 | struct mfc6_cache *c, *next; |
569 | |||
570 | cp = &mfc_unres_queue; | ||
571 | 850 | ||
572 | while ((c = *cp) != NULL) { | 851 | list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) { |
573 | if (time_after(c->mfc_un.unres.expires, now)) { | 852 | if (time_after(c->mfc_un.unres.expires, now)) { |
574 | /* not yet... */ | 853 | /* not yet... */ |
575 | unsigned long interval = c->mfc_un.unres.expires - now; | 854 | unsigned long interval = c->mfc_un.unres.expires - now; |
576 | if (interval < expires) | 855 | if (interval < expires) |
577 | expires = interval; | 856 | expires = interval; |
578 | cp = &c->next; | ||
579 | continue; | 857 | continue; |
580 | } | 858 | } |
581 | 859 | ||
582 | *cp = c->next; | 860 | list_del(&c->list); |
583 | ip6mr_destroy_unres(c); | 861 | ip6mr_destroy_unres(mrt, c); |
584 | } | 862 | } |
585 | 863 | ||
586 | if (mfc_unres_queue != NULL) | 864 | if (!list_empty(&mrt->mfc6_unres_queue)) |
587 | mod_timer(&ipmr_expire_timer, jiffies + expires); | 865 | mod_timer(&mrt->ipmr_expire_timer, jiffies + expires); |
588 | } | 866 | } |
589 | 867 | ||
590 | static void ipmr_expire_process(unsigned long dummy) | 868 | static void ipmr_expire_process(unsigned long arg) |
591 | { | 869 | { |
870 | struct mr6_table *mrt = (struct mr6_table *)arg; | ||
871 | |||
592 | if (!spin_trylock(&mfc_unres_lock)) { | 872 | if (!spin_trylock(&mfc_unres_lock)) { |
593 | mod_timer(&ipmr_expire_timer, jiffies + 1); | 873 | mod_timer(&mrt->ipmr_expire_timer, jiffies + 1); |
594 | return; | 874 | return; |
595 | } | 875 | } |
596 | 876 | ||
597 | if (mfc_unres_queue != NULL) | 877 | if (!list_empty(&mrt->mfc6_unres_queue)) |
598 | ipmr_do_expire_process(dummy); | 878 | ipmr_do_expire_process(mrt); |
599 | 879 | ||
600 | spin_unlock(&mfc_unres_lock); | 880 | spin_unlock(&mfc_unres_lock); |
601 | } | 881 | } |
602 | 882 | ||
603 | /* Fill oifs list. It is called under write locked mrt_lock. */ | 883 | /* Fill oifs list. It is called under write locked mrt_lock. */ |
604 | 884 | ||
605 | static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttls) | 885 | static void ip6mr_update_thresholds(struct mr6_table *mrt, struct mfc6_cache *cache, |
886 | unsigned char *ttls) | ||
606 | { | 887 | { |
607 | int vifi; | 888 | int vifi; |
608 | struct net *net = mfc6_net(cache); | ||
609 | 889 | ||
610 | cache->mfc_un.res.minvif = MAXMIFS; | 890 | cache->mfc_un.res.minvif = MAXMIFS; |
611 | cache->mfc_un.res.maxvif = 0; | 891 | cache->mfc_un.res.maxvif = 0; |
612 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); | 892 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); |
613 | 893 | ||
614 | for (vifi = 0; vifi < net->ipv6.maxvif; vifi++) { | 894 | for (vifi = 0; vifi < mrt->maxvif; vifi++) { |
615 | if (MIF_EXISTS(net, vifi) && | 895 | if (MIF_EXISTS(mrt, vifi) && |
616 | ttls[vifi] && ttls[vifi] < 255) { | 896 | ttls[vifi] && ttls[vifi] < 255) { |
617 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; | 897 | cache->mfc_un.res.ttls[vifi] = ttls[vifi]; |
618 | if (cache->mfc_un.res.minvif > vifi) | 898 | if (cache->mfc_un.res.minvif > vifi) |
@@ -623,16 +903,17 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl | |||
623 | } | 903 | } |
624 | } | 904 | } |
625 | 905 | ||
626 | static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | 906 | static int mif6_add(struct net *net, struct mr6_table *mrt, |
907 | struct mif6ctl *vifc, int mrtsock) | ||
627 | { | 908 | { |
628 | int vifi = vifc->mif6c_mifi; | 909 | int vifi = vifc->mif6c_mifi; |
629 | struct mif_device *v = &net->ipv6.vif6_table[vifi]; | 910 | struct mif_device *v = &mrt->vif6_table[vifi]; |
630 | struct net_device *dev; | 911 | struct net_device *dev; |
631 | struct inet6_dev *in6_dev; | 912 | struct inet6_dev *in6_dev; |
632 | int err; | 913 | int err; |
633 | 914 | ||
634 | /* Is vif busy ? */ | 915 | /* Is vif busy ? */ |
635 | if (MIF_EXISTS(net, vifi)) | 916 | if (MIF_EXISTS(mrt, vifi)) |
636 | return -EADDRINUSE; | 917 | return -EADDRINUSE; |
637 | 918 | ||
638 | switch (vifc->mif6c_flags) { | 919 | switch (vifc->mif6c_flags) { |
@@ -642,9 +923,9 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
642 | * Special Purpose VIF in PIM | 923 | * Special Purpose VIF in PIM |
643 | * All the packets will be sent to the daemon | 924 | * All the packets will be sent to the daemon |
644 | */ | 925 | */ |
645 | if (net->ipv6.mroute_reg_vif_num >= 0) | 926 | if (mrt->mroute_reg_vif_num >= 0) |
646 | return -EADDRINUSE; | 927 | return -EADDRINUSE; |
647 | dev = ip6mr_reg_vif(net); | 928 | dev = ip6mr_reg_vif(net, mrt); |
648 | if (!dev) | 929 | if (!dev) |
649 | return -ENOBUFS; | 930 | return -ENOBUFS; |
650 | err = dev_set_allmulti(dev, 1); | 931 | err = dev_set_allmulti(dev, 1); |
@@ -694,50 +975,48 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
694 | v->dev = dev; | 975 | v->dev = dev; |
695 | #ifdef CONFIG_IPV6_PIMSM_V2 | 976 | #ifdef CONFIG_IPV6_PIMSM_V2 |
696 | if (v->flags & MIFF_REGISTER) | 977 | if (v->flags & MIFF_REGISTER) |
697 | net->ipv6.mroute_reg_vif_num = vifi; | 978 | mrt->mroute_reg_vif_num = vifi; |
698 | #endif | 979 | #endif |
699 | if (vifi + 1 > net->ipv6.maxvif) | 980 | if (vifi + 1 > mrt->maxvif) |
700 | net->ipv6.maxvif = vifi + 1; | 981 | mrt->maxvif = vifi + 1; |
701 | write_unlock_bh(&mrt_lock); | 982 | write_unlock_bh(&mrt_lock); |
702 | return 0; | 983 | return 0; |
703 | } | 984 | } |
704 | 985 | ||
705 | static struct mfc6_cache *ip6mr_cache_find(struct net *net, | 986 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, |
706 | struct in6_addr *origin, | 987 | struct in6_addr *origin, |
707 | struct in6_addr *mcastgrp) | 988 | struct in6_addr *mcastgrp) |
708 | { | 989 | { |
709 | int line = MFC6_HASH(mcastgrp, origin); | 990 | int line = MFC6_HASH(mcastgrp, origin); |
710 | struct mfc6_cache *c; | 991 | struct mfc6_cache *c; |
711 | 992 | ||
712 | for (c = net->ipv6.mfc6_cache_array[line]; c; c = c->next) { | 993 | list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { |
713 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && | 994 | if (ipv6_addr_equal(&c->mf6c_origin, origin) && |
714 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) | 995 | ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) |
715 | break; | 996 | return c; |
716 | } | 997 | } |
717 | return c; | 998 | return NULL; |
718 | } | 999 | } |
719 | 1000 | ||
720 | /* | 1001 | /* |
721 | * Allocate a multicast cache entry | 1002 | * Allocate a multicast cache entry |
722 | */ | 1003 | */ |
723 | static struct mfc6_cache *ip6mr_cache_alloc(struct net *net) | 1004 | static struct mfc6_cache *ip6mr_cache_alloc(void) |
724 | { | 1005 | { |
725 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); | 1006 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL); |
726 | if (c == NULL) | 1007 | if (c == NULL) |
727 | return NULL; | 1008 | return NULL; |
728 | c->mfc_un.res.minvif = MAXMIFS; | 1009 | c->mfc_un.res.minvif = MAXMIFS; |
729 | mfc6_net_set(c, net); | ||
730 | return c; | 1010 | return c; |
731 | } | 1011 | } |
732 | 1012 | ||
733 | static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net) | 1013 | static struct mfc6_cache *ip6mr_cache_alloc_unres(void) |
734 | { | 1014 | { |
735 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); | 1015 | struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_ATOMIC); |
736 | if (c == NULL) | 1016 | if (c == NULL) |
737 | return NULL; | 1017 | return NULL; |
738 | skb_queue_head_init(&c->mfc_un.unres.unresolved); | 1018 | skb_queue_head_init(&c->mfc_un.unres.unresolved); |
739 | c->mfc_un.unres.expires = jiffies + 10 * HZ; | 1019 | c->mfc_un.unres.expires = jiffies + 10 * HZ; |
740 | mfc6_net_set(c, net); | ||
741 | return c; | 1020 | return c; |
742 | } | 1021 | } |
743 | 1022 | ||
@@ -745,7 +1024,8 @@ static struct mfc6_cache *ip6mr_cache_alloc_unres(struct net *net) | |||
745 | * A cache entry has gone into a resolved state from queued | 1024 | * A cache entry has gone into a resolved state from queued |
746 | */ | 1025 | */ |
747 | 1026 | ||
748 | static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | 1027 | static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt, |
1028 | struct mfc6_cache *uc, struct mfc6_cache *c) | ||
749 | { | 1029 | { |
750 | struct sk_buff *skb; | 1030 | struct sk_buff *skb; |
751 | 1031 | ||
@@ -758,7 +1038,7 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
758 | int err; | 1038 | int err; |
759 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); | 1039 | struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr)); |
760 | 1040 | ||
761 | if (ip6mr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) { | 1041 | if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) { |
762 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; | 1042 | nlh->nlmsg_len = skb_tail_pointer(skb) - (u8 *)nlh; |
763 | } else { | 1043 | } else { |
764 | nlh->nlmsg_type = NLMSG_ERROR; | 1044 | nlh->nlmsg_type = NLMSG_ERROR; |
@@ -766,9 +1046,9 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
766 | skb_trim(skb, nlh->nlmsg_len); | 1046 | skb_trim(skb, nlh->nlmsg_len); |
767 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; | 1047 | ((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE; |
768 | } | 1048 | } |
769 | err = rtnl_unicast(skb, mfc6_net(uc), NETLINK_CB(skb).pid); | 1049 | err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid); |
770 | } else | 1050 | } else |
771 | ip6_mr_forward(skb, c); | 1051 | ip6_mr_forward(net, mrt, skb, c); |
772 | } | 1052 | } |
773 | } | 1053 | } |
774 | 1054 | ||
@@ -779,8 +1059,8 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
779 | * Called under mrt_lock. | 1059 | * Called under mrt_lock. |
780 | */ | 1060 | */ |
781 | 1061 | ||
782 | static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | 1062 | static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt, |
783 | int assert) | 1063 | mifi_t mifi, int assert) |
784 | { | 1064 | { |
785 | struct sk_buff *skb; | 1065 | struct sk_buff *skb; |
786 | struct mrt6msg *msg; | 1066 | struct mrt6msg *msg; |
@@ -816,7 +1096,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
816 | msg = (struct mrt6msg *)skb_transport_header(skb); | 1096 | msg = (struct mrt6msg *)skb_transport_header(skb); |
817 | msg->im6_mbz = 0; | 1097 | msg->im6_mbz = 0; |
818 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; | 1098 | msg->im6_msgtype = MRT6MSG_WHOLEPKT; |
819 | msg->im6_mif = net->ipv6.mroute_reg_vif_num; | 1099 | msg->im6_mif = mrt->mroute_reg_vif_num; |
820 | msg->im6_pad = 0; | 1100 | msg->im6_pad = 0; |
821 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | 1101 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); |
822 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | 1102 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); |
@@ -851,7 +1131,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
851 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1131 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
852 | } | 1132 | } |
853 | 1133 | ||
854 | if (net->ipv6.mroute6_sk == NULL) { | 1134 | if (mrt->mroute6_sk == NULL) { |
855 | kfree_skb(skb); | 1135 | kfree_skb(skb); |
856 | return -EINVAL; | 1136 | return -EINVAL; |
857 | } | 1137 | } |
@@ -859,7 +1139,7 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
859 | /* | 1139 | /* |
860 | * Deliver to user space multicast routing algorithms | 1140 | * Deliver to user space multicast routing algorithms |
861 | */ | 1141 | */ |
862 | ret = sock_queue_rcv_skb(net->ipv6.mroute6_sk, skb); | 1142 | ret = sock_queue_rcv_skb(mrt->mroute6_sk, skb); |
863 | if (ret < 0) { | 1143 | if (ret < 0) { |
864 | if (net_ratelimit()) | 1144 | if (net_ratelimit()) |
865 | printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); | 1145 | printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); |
@@ -874,26 +1154,28 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
874 | */ | 1154 | */ |
875 | 1155 | ||
876 | static int | 1156 | static int |
877 | ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | 1157 | ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb) |
878 | { | 1158 | { |
1159 | bool found = false; | ||
879 | int err; | 1160 | int err; |
880 | struct mfc6_cache *c; | 1161 | struct mfc6_cache *c; |
881 | 1162 | ||
882 | spin_lock_bh(&mfc_unres_lock); | 1163 | spin_lock_bh(&mfc_unres_lock); |
883 | for (c = mfc_unres_queue; c; c = c->next) { | 1164 | list_for_each_entry(c, &mrt->mfc6_unres_queue, list) { |
884 | if (net_eq(mfc6_net(c), net) && | 1165 | if (ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && |
885 | ipv6_addr_equal(&c->mf6c_mcastgrp, &ipv6_hdr(skb)->daddr) && | 1166 | ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) { |
886 | ipv6_addr_equal(&c->mf6c_origin, &ipv6_hdr(skb)->saddr)) | 1167 | found = true; |
887 | break; | 1168 | break; |
1169 | } | ||
888 | } | 1170 | } |
889 | 1171 | ||
890 | if (c == NULL) { | 1172 | if (!found) { |
891 | /* | 1173 | /* |
892 | * Create a new entry if allowable | 1174 | * Create a new entry if allowable |
893 | */ | 1175 | */ |
894 | 1176 | ||
895 | if (atomic_read(&net->ipv6.cache_resolve_queue_len) >= 10 || | 1177 | if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 || |
896 | (c = ip6mr_cache_alloc_unres(net)) == NULL) { | 1178 | (c = ip6mr_cache_alloc_unres()) == NULL) { |
897 | spin_unlock_bh(&mfc_unres_lock); | 1179 | spin_unlock_bh(&mfc_unres_lock); |
898 | 1180 | ||
899 | kfree_skb(skb); | 1181 | kfree_skb(skb); |
@@ -910,7 +1192,7 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
910 | /* | 1192 | /* |
911 | * Reflect first query at pim6sd | 1193 | * Reflect first query at pim6sd |
912 | */ | 1194 | */ |
913 | err = ip6mr_cache_report(net, skb, mifi, MRT6MSG_NOCACHE); | 1195 | err = ip6mr_cache_report(mrt, skb, mifi, MRT6MSG_NOCACHE); |
914 | if (err < 0) { | 1196 | if (err < 0) { |
915 | /* If the report failed throw the cache entry | 1197 | /* If the report failed throw the cache entry |
916 | out - Brad Parker | 1198 | out - Brad Parker |
@@ -922,11 +1204,10 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
922 | return err; | 1204 | return err; |
923 | } | 1205 | } |
924 | 1206 | ||
925 | atomic_inc(&net->ipv6.cache_resolve_queue_len); | 1207 | atomic_inc(&mrt->cache_resolve_queue_len); |
926 | c->next = mfc_unres_queue; | 1208 | list_add(&c->list, &mrt->mfc6_unres_queue); |
927 | mfc_unres_queue = c; | ||
928 | 1209 | ||
929 | ipmr_do_expire_process(1); | 1210 | ipmr_do_expire_process(mrt); |
930 | } | 1211 | } |
931 | 1212 | ||
932 | /* | 1213 | /* |
@@ -948,19 +1229,18 @@ ip6mr_cache_unresolved(struct net *net, mifi_t mifi, struct sk_buff *skb) | |||
948 | * MFC6 cache manipulation by user space | 1229 | * MFC6 cache manipulation by user space |
949 | */ | 1230 | */ |
950 | 1231 | ||
951 | static int ip6mr_mfc_delete(struct net *net, struct mf6cctl *mfc) | 1232 | static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc) |
952 | { | 1233 | { |
953 | int line; | 1234 | int line; |
954 | struct mfc6_cache *c, **cp; | 1235 | struct mfc6_cache *c, *next; |
955 | 1236 | ||
956 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 1237 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
957 | 1238 | ||
958 | for (cp = &net->ipv6.mfc6_cache_array[line]; | 1239 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) { |
959 | (c = *cp) != NULL; cp = &c->next) { | ||
960 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 1240 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
961 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { | 1241 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { |
962 | write_lock_bh(&mrt_lock); | 1242 | write_lock_bh(&mrt_lock); |
963 | *cp = c->next; | 1243 | list_del(&c->list); |
964 | write_unlock_bh(&mrt_lock); | 1244 | write_unlock_bh(&mrt_lock); |
965 | 1245 | ||
966 | ip6mr_cache_free(c); | 1246 | ip6mr_cache_free(c); |
@@ -975,6 +1255,7 @@ static int ip6mr_device_event(struct notifier_block *this, | |||
975 | { | 1255 | { |
976 | struct net_device *dev = ptr; | 1256 | struct net_device *dev = ptr; |
977 | struct net *net = dev_net(dev); | 1257 | struct net *net = dev_net(dev); |
1258 | struct mr6_table *mrt; | ||
978 | struct mif_device *v; | 1259 | struct mif_device *v; |
979 | int ct; | 1260 | int ct; |
980 | LIST_HEAD(list); | 1261 | LIST_HEAD(list); |
@@ -982,10 +1263,12 @@ static int ip6mr_device_event(struct notifier_block *this, | |||
982 | if (event != NETDEV_UNREGISTER) | 1263 | if (event != NETDEV_UNREGISTER) |
983 | return NOTIFY_DONE; | 1264 | return NOTIFY_DONE; |
984 | 1265 | ||
985 | v = &net->ipv6.vif6_table[0]; | 1266 | ip6mr_for_each_table(mrt, net) { |
986 | for (ct = 0; ct < net->ipv6.maxvif; ct++, v++) { | 1267 | v = &mrt->vif6_table[0]; |
987 | if (v->dev == dev) | 1268 | for (ct = 0; ct < mrt->maxvif; ct++, v++) { |
988 | mif6_delete(net, ct, &list); | 1269 | if (v->dev == dev) |
1270 | mif6_delete(mrt, ct, &list); | ||
1271 | } | ||
989 | } | 1272 | } |
990 | unregister_netdevice_many(&list); | 1273 | unregister_netdevice_many(&list); |
991 | 1274 | ||
@@ -1002,26 +1285,11 @@ static struct notifier_block ip6_mr_notifier = { | |||
1002 | 1285 | ||
1003 | static int __net_init ip6mr_net_init(struct net *net) | 1286 | static int __net_init ip6mr_net_init(struct net *net) |
1004 | { | 1287 | { |
1005 | int err = 0; | 1288 | int err; |
1006 | net->ipv6.vif6_table = kcalloc(MAXMIFS, sizeof(struct mif_device), | ||
1007 | GFP_KERNEL); | ||
1008 | if (!net->ipv6.vif6_table) { | ||
1009 | err = -ENOMEM; | ||
1010 | goto fail; | ||
1011 | } | ||
1012 | |||
1013 | /* Forwarding cache */ | ||
1014 | net->ipv6.mfc6_cache_array = kcalloc(MFC6_LINES, | ||
1015 | sizeof(struct mfc6_cache *), | ||
1016 | GFP_KERNEL); | ||
1017 | if (!net->ipv6.mfc6_cache_array) { | ||
1018 | err = -ENOMEM; | ||
1019 | goto fail_mfc6_cache; | ||
1020 | } | ||
1021 | 1289 | ||
1022 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1290 | err = ip6mr_rules_init(net); |
1023 | net->ipv6.mroute_reg_vif_num = -1; | 1291 | if (err < 0) |
1024 | #endif | 1292 | goto fail; |
1025 | 1293 | ||
1026 | #ifdef CONFIG_PROC_FS | 1294 | #ifdef CONFIG_PROC_FS |
1027 | err = -ENOMEM; | 1295 | err = -ENOMEM; |
@@ -1030,16 +1298,15 @@ static int __net_init ip6mr_net_init(struct net *net) | |||
1030 | if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops)) | 1298 | if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops)) |
1031 | goto proc_cache_fail; | 1299 | goto proc_cache_fail; |
1032 | #endif | 1300 | #endif |
1301 | |||
1033 | return 0; | 1302 | return 0; |
1034 | 1303 | ||
1035 | #ifdef CONFIG_PROC_FS | 1304 | #ifdef CONFIG_PROC_FS |
1036 | proc_cache_fail: | 1305 | proc_cache_fail: |
1037 | proc_net_remove(net, "ip6_mr_vif"); | 1306 | proc_net_remove(net, "ip6_mr_vif"); |
1038 | proc_vif_fail: | 1307 | proc_vif_fail: |
1039 | kfree(net->ipv6.mfc6_cache_array); | 1308 | ip6mr_rules_exit(net); |
1040 | #endif | 1309 | #endif |
1041 | fail_mfc6_cache: | ||
1042 | kfree(net->ipv6.vif6_table); | ||
1043 | fail: | 1310 | fail: |
1044 | return err; | 1311 | return err; |
1045 | } | 1312 | } |
@@ -1050,9 +1317,7 @@ static void __net_exit ip6mr_net_exit(struct net *net) | |||
1050 | proc_net_remove(net, "ip6_mr_cache"); | 1317 | proc_net_remove(net, "ip6_mr_cache"); |
1051 | proc_net_remove(net, "ip6_mr_vif"); | 1318 | proc_net_remove(net, "ip6_mr_vif"); |
1052 | #endif | 1319 | #endif |
1053 | mroute_clean_tables(net); | 1320 | ip6mr_rules_exit(net); |
1054 | kfree(net->ipv6.mfc6_cache_array); | ||
1055 | kfree(net->ipv6.vif6_table); | ||
1056 | } | 1321 | } |
1057 | 1322 | ||
1058 | static struct pernet_operations ip6mr_net_ops = { | 1323 | static struct pernet_operations ip6mr_net_ops = { |
@@ -1075,7 +1340,6 @@ int __init ip6_mr_init(void) | |||
1075 | if (err) | 1340 | if (err) |
1076 | goto reg_pernet_fail; | 1341 | goto reg_pernet_fail; |
1077 | 1342 | ||
1078 | setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); | ||
1079 | err = register_netdevice_notifier(&ip6_mr_notifier); | 1343 | err = register_netdevice_notifier(&ip6_mr_notifier); |
1080 | if (err) | 1344 | if (err) |
1081 | goto reg_notif_fail; | 1345 | goto reg_notif_fail; |
@@ -1086,13 +1350,13 @@ int __init ip6_mr_init(void) | |||
1086 | goto add_proto_fail; | 1350 | goto add_proto_fail; |
1087 | } | 1351 | } |
1088 | #endif | 1352 | #endif |
1353 | rtnl_register(RTNL_FAMILY_IP6MR, RTM_GETROUTE, NULL, ip6mr_rtm_dumproute); | ||
1089 | return 0; | 1354 | return 0; |
1090 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1355 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1091 | add_proto_fail: | 1356 | add_proto_fail: |
1092 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1357 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1093 | #endif | 1358 | #endif |
1094 | reg_notif_fail: | 1359 | reg_notif_fail: |
1095 | del_timer(&ipmr_expire_timer); | ||
1096 | unregister_pernet_subsys(&ip6mr_net_ops); | 1360 | unregister_pernet_subsys(&ip6mr_net_ops); |
1097 | reg_pernet_fail: | 1361 | reg_pernet_fail: |
1098 | kmem_cache_destroy(mrt_cachep); | 1362 | kmem_cache_destroy(mrt_cachep); |
@@ -1102,15 +1366,16 @@ reg_pernet_fail: | |||
1102 | void ip6_mr_cleanup(void) | 1366 | void ip6_mr_cleanup(void) |
1103 | { | 1367 | { |
1104 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1368 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1105 | del_timer(&ipmr_expire_timer); | ||
1106 | unregister_pernet_subsys(&ip6mr_net_ops); | 1369 | unregister_pernet_subsys(&ip6mr_net_ops); |
1107 | kmem_cache_destroy(mrt_cachep); | 1370 | kmem_cache_destroy(mrt_cachep); |
1108 | } | 1371 | } |
1109 | 1372 | ||
1110 | static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | 1373 | static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, |
1374 | struct mf6cctl *mfc, int mrtsock) | ||
1111 | { | 1375 | { |
1376 | bool found = false; | ||
1112 | int line; | 1377 | int line; |
1113 | struct mfc6_cache *uc, *c, **cp; | 1378 | struct mfc6_cache *uc, *c; |
1114 | unsigned char ttls[MAXMIFS]; | 1379 | unsigned char ttls[MAXMIFS]; |
1115 | int i; | 1380 | int i; |
1116 | 1381 | ||
@@ -1126,17 +1391,18 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1126 | 1391 | ||
1127 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); | 1392 | line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); |
1128 | 1393 | ||
1129 | for (cp = &net->ipv6.mfc6_cache_array[line]; | 1394 | list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { |
1130 | (c = *cp) != NULL; cp = &c->next) { | ||
1131 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && | 1395 | if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && |
1132 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) | 1396 | ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { |
1397 | found = true; | ||
1133 | break; | 1398 | break; |
1399 | } | ||
1134 | } | 1400 | } |
1135 | 1401 | ||
1136 | if (c != NULL) { | 1402 | if (found) { |
1137 | write_lock_bh(&mrt_lock); | 1403 | write_lock_bh(&mrt_lock); |
1138 | c->mf6c_parent = mfc->mf6cc_parent; | 1404 | c->mf6c_parent = mfc->mf6cc_parent; |
1139 | ip6mr_update_thresholds(c, ttls); | 1405 | ip6mr_update_thresholds(mrt, c, ttls); |
1140 | if (!mrtsock) | 1406 | if (!mrtsock) |
1141 | c->mfc_flags |= MFC_STATIC; | 1407 | c->mfc_flags |= MFC_STATIC; |
1142 | write_unlock_bh(&mrt_lock); | 1408 | write_unlock_bh(&mrt_lock); |
@@ -1146,43 +1412,42 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1146 | if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) | 1412 | if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) |
1147 | return -EINVAL; | 1413 | return -EINVAL; |
1148 | 1414 | ||
1149 | c = ip6mr_cache_alloc(net); | 1415 | c = ip6mr_cache_alloc(); |
1150 | if (c == NULL) | 1416 | if (c == NULL) |
1151 | return -ENOMEM; | 1417 | return -ENOMEM; |
1152 | 1418 | ||
1153 | c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; | 1419 | c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; |
1154 | c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; | 1420 | c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; |
1155 | c->mf6c_parent = mfc->mf6cc_parent; | 1421 | c->mf6c_parent = mfc->mf6cc_parent; |
1156 | ip6mr_update_thresholds(c, ttls); | 1422 | ip6mr_update_thresholds(mrt, c, ttls); |
1157 | if (!mrtsock) | 1423 | if (!mrtsock) |
1158 | c->mfc_flags |= MFC_STATIC; | 1424 | c->mfc_flags |= MFC_STATIC; |
1159 | 1425 | ||
1160 | write_lock_bh(&mrt_lock); | 1426 | write_lock_bh(&mrt_lock); |
1161 | c->next = net->ipv6.mfc6_cache_array[line]; | 1427 | list_add(&c->list, &mrt->mfc6_cache_array[line]); |
1162 | net->ipv6.mfc6_cache_array[line] = c; | ||
1163 | write_unlock_bh(&mrt_lock); | 1428 | write_unlock_bh(&mrt_lock); |
1164 | 1429 | ||
1165 | /* | 1430 | /* |
1166 | * Check to see if we resolved a queued list. If so we | 1431 | * Check to see if we resolved a queued list. If so we |
1167 | * need to send on the frames and tidy up. | 1432 | * need to send on the frames and tidy up. |
1168 | */ | 1433 | */ |
1434 | found = false; | ||
1169 | spin_lock_bh(&mfc_unres_lock); | 1435 | spin_lock_bh(&mfc_unres_lock); |
1170 | for (cp = &mfc_unres_queue; (uc = *cp) != NULL; | 1436 | list_for_each_entry(uc, &mrt->mfc6_unres_queue, list) { |
1171 | cp = &uc->next) { | 1437 | if (ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && |
1172 | if (net_eq(mfc6_net(uc), net) && | ||
1173 | ipv6_addr_equal(&uc->mf6c_origin, &c->mf6c_origin) && | ||
1174 | ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { | 1438 | ipv6_addr_equal(&uc->mf6c_mcastgrp, &c->mf6c_mcastgrp)) { |
1175 | *cp = uc->next; | 1439 | list_del(&uc->list); |
1176 | atomic_dec(&net->ipv6.cache_resolve_queue_len); | 1440 | atomic_dec(&mrt->cache_resolve_queue_len); |
1441 | found = true; | ||
1177 | break; | 1442 | break; |
1178 | } | 1443 | } |
1179 | } | 1444 | } |
1180 | if (mfc_unres_queue == NULL) | 1445 | if (list_empty(&mrt->mfc6_unres_queue)) |
1181 | del_timer(&ipmr_expire_timer); | 1446 | del_timer(&mrt->ipmr_expire_timer); |
1182 | spin_unlock_bh(&mfc_unres_lock); | 1447 | spin_unlock_bh(&mfc_unres_lock); |
1183 | 1448 | ||
1184 | if (uc) { | 1449 | if (found) { |
1185 | ip6mr_cache_resolve(uc, c); | 1450 | ip6mr_cache_resolve(net, mrt, uc, c); |
1186 | ip6mr_cache_free(uc); | 1451 | ip6mr_cache_free(uc); |
1187 | } | 1452 | } |
1188 | return 0; | 1453 | return 0; |
@@ -1192,17 +1457,18 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1192 | * Close the multicast socket, and clear the vif tables etc | 1457 | * Close the multicast socket, and clear the vif tables etc |
1193 | */ | 1458 | */ |
1194 | 1459 | ||
1195 | static void mroute_clean_tables(struct net *net) | 1460 | static void mroute_clean_tables(struct mr6_table *mrt) |
1196 | { | 1461 | { |
1197 | int i; | 1462 | int i; |
1198 | LIST_HEAD(list); | 1463 | LIST_HEAD(list); |
1464 | struct mfc6_cache *c, *next; | ||
1199 | 1465 | ||
1200 | /* | 1466 | /* |
1201 | * Shut down all active vif entries | 1467 | * Shut down all active vif entries |
1202 | */ | 1468 | */ |
1203 | for (i = 0; i < net->ipv6.maxvif; i++) { | 1469 | for (i = 0; i < mrt->maxvif; i++) { |
1204 | if (!(net->ipv6.vif6_table[i].flags & VIFF_STATIC)) | 1470 | if (!(mrt->vif6_table[i].flags & VIFF_STATIC)) |
1205 | mif6_delete(net, i, &list); | 1471 | mif6_delete(mrt, i, &list); |
1206 | } | 1472 | } |
1207 | unregister_netdevice_many(&list); | 1473 | unregister_netdevice_many(&list); |
1208 | 1474 | ||
@@ -1210,48 +1476,36 @@ static void mroute_clean_tables(struct net *net) | |||
1210 | * Wipe the cache | 1476 | * Wipe the cache |
1211 | */ | 1477 | */ |
1212 | for (i = 0; i < MFC6_LINES; i++) { | 1478 | for (i = 0; i < MFC6_LINES; i++) { |
1213 | struct mfc6_cache *c, **cp; | 1479 | list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[i], list) { |
1214 | 1480 | if (c->mfc_flags & MFC_STATIC) | |
1215 | cp = &net->ipv6.mfc6_cache_array[i]; | ||
1216 | while ((c = *cp) != NULL) { | ||
1217 | if (c->mfc_flags & MFC_STATIC) { | ||
1218 | cp = &c->next; | ||
1219 | continue; | 1481 | continue; |
1220 | } | ||
1221 | write_lock_bh(&mrt_lock); | 1482 | write_lock_bh(&mrt_lock); |
1222 | *cp = c->next; | 1483 | list_del(&c->list); |
1223 | write_unlock_bh(&mrt_lock); | 1484 | write_unlock_bh(&mrt_lock); |
1224 | 1485 | ||
1225 | ip6mr_cache_free(c); | 1486 | ip6mr_cache_free(c); |
1226 | } | 1487 | } |
1227 | } | 1488 | } |
1228 | 1489 | ||
1229 | if (atomic_read(&net->ipv6.cache_resolve_queue_len) != 0) { | 1490 | if (atomic_read(&mrt->cache_resolve_queue_len) != 0) { |
1230 | struct mfc6_cache *c, **cp; | ||
1231 | |||
1232 | spin_lock_bh(&mfc_unres_lock); | 1491 | spin_lock_bh(&mfc_unres_lock); |
1233 | cp = &mfc_unres_queue; | 1492 | list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) { |
1234 | while ((c = *cp) != NULL) { | 1493 | list_del(&c->list); |
1235 | if (!net_eq(mfc6_net(c), net)) { | 1494 | ip6mr_destroy_unres(mrt, c); |
1236 | cp = &c->next; | ||
1237 | continue; | ||
1238 | } | ||
1239 | *cp = c->next; | ||
1240 | ip6mr_destroy_unres(c); | ||
1241 | } | 1495 | } |
1242 | spin_unlock_bh(&mfc_unres_lock); | 1496 | spin_unlock_bh(&mfc_unres_lock); |
1243 | } | 1497 | } |
1244 | } | 1498 | } |
1245 | 1499 | ||
1246 | static int ip6mr_sk_init(struct sock *sk) | 1500 | static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk) |
1247 | { | 1501 | { |
1248 | int err = 0; | 1502 | int err = 0; |
1249 | struct net *net = sock_net(sk); | 1503 | struct net *net = sock_net(sk); |
1250 | 1504 | ||
1251 | rtnl_lock(); | 1505 | rtnl_lock(); |
1252 | write_lock_bh(&mrt_lock); | 1506 | write_lock_bh(&mrt_lock); |
1253 | if (likely(net->ipv6.mroute6_sk == NULL)) { | 1507 | if (likely(mrt->mroute6_sk == NULL)) { |
1254 | net->ipv6.mroute6_sk = sk; | 1508 | mrt->mroute6_sk = sk; |
1255 | net->ipv6.devconf_all->mc_forwarding++; | 1509 | net->ipv6.devconf_all->mc_forwarding++; |
1256 | } | 1510 | } |
1257 | else | 1511 | else |
@@ -1265,24 +1519,43 @@ static int ip6mr_sk_init(struct sock *sk) | |||
1265 | 1519 | ||
1266 | int ip6mr_sk_done(struct sock *sk) | 1520 | int ip6mr_sk_done(struct sock *sk) |
1267 | { | 1521 | { |
1268 | int err = 0; | 1522 | int err = -EACCES; |
1269 | struct net *net = sock_net(sk); | 1523 | struct net *net = sock_net(sk); |
1524 | struct mr6_table *mrt; | ||
1270 | 1525 | ||
1271 | rtnl_lock(); | 1526 | rtnl_lock(); |
1272 | if (sk == net->ipv6.mroute6_sk) { | 1527 | ip6mr_for_each_table(mrt, net) { |
1273 | write_lock_bh(&mrt_lock); | 1528 | if (sk == mrt->mroute6_sk) { |
1274 | net->ipv6.mroute6_sk = NULL; | 1529 | write_lock_bh(&mrt_lock); |
1275 | net->ipv6.devconf_all->mc_forwarding--; | 1530 | mrt->mroute6_sk = NULL; |
1276 | write_unlock_bh(&mrt_lock); | 1531 | net->ipv6.devconf_all->mc_forwarding--; |
1532 | write_unlock_bh(&mrt_lock); | ||
1277 | 1533 | ||
1278 | mroute_clean_tables(net); | 1534 | mroute_clean_tables(mrt); |
1279 | } else | 1535 | err = 0; |
1280 | err = -EACCES; | 1536 | break; |
1537 | } | ||
1538 | } | ||
1281 | rtnl_unlock(); | 1539 | rtnl_unlock(); |
1282 | 1540 | ||
1283 | return err; | 1541 | return err; |
1284 | } | 1542 | } |
1285 | 1543 | ||
1544 | struct sock *mroute6_socket(struct net *net, struct sk_buff *skb) | ||
1545 | { | ||
1546 | struct mr6_table *mrt; | ||
1547 | struct flowi fl = { | ||
1548 | .iif = skb->skb_iif, | ||
1549 | .oif = skb->dev->ifindex, | ||
1550 | .mark = skb->mark, | ||
1551 | }; | ||
1552 | |||
1553 | if (ip6mr_fib_lookup(net, &fl, &mrt) < 0) | ||
1554 | return NULL; | ||
1555 | |||
1556 | return mrt->mroute6_sk; | ||
1557 | } | ||
1558 | |||
1286 | /* | 1559 | /* |
1287 | * Socket options and virtual interface manipulation. The whole | 1560 | * Socket options and virtual interface manipulation. The whole |
1288 | * virtual interface system is a complete heap, but unfortunately | 1561 | * virtual interface system is a complete heap, but unfortunately |
@@ -1297,9 +1570,14 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1297 | struct mf6cctl mfc; | 1570 | struct mf6cctl mfc; |
1298 | mifi_t mifi; | 1571 | mifi_t mifi; |
1299 | struct net *net = sock_net(sk); | 1572 | struct net *net = sock_net(sk); |
1573 | struct mr6_table *mrt; | ||
1574 | |||
1575 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1576 | if (mrt == NULL) | ||
1577 | return -ENOENT; | ||
1300 | 1578 | ||
1301 | if (optname != MRT6_INIT) { | 1579 | if (optname != MRT6_INIT) { |
1302 | if (sk != net->ipv6.mroute6_sk && !capable(CAP_NET_ADMIN)) | 1580 | if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN)) |
1303 | return -EACCES; | 1581 | return -EACCES; |
1304 | } | 1582 | } |
1305 | 1583 | ||
@@ -1311,7 +1589,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1311 | if (optlen < sizeof(int)) | 1589 | if (optlen < sizeof(int)) |
1312 | return -EINVAL; | 1590 | return -EINVAL; |
1313 | 1591 | ||
1314 | return ip6mr_sk_init(sk); | 1592 | return ip6mr_sk_init(mrt, sk); |
1315 | 1593 | ||
1316 | case MRT6_DONE: | 1594 | case MRT6_DONE: |
1317 | return ip6mr_sk_done(sk); | 1595 | return ip6mr_sk_done(sk); |
@@ -1324,7 +1602,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1324 | if (vif.mif6c_mifi >= MAXMIFS) | 1602 | if (vif.mif6c_mifi >= MAXMIFS) |
1325 | return -ENFILE; | 1603 | return -ENFILE; |
1326 | rtnl_lock(); | 1604 | rtnl_lock(); |
1327 | ret = mif6_add(net, &vif, sk == net->ipv6.mroute6_sk); | 1605 | ret = mif6_add(net, mrt, &vif, sk == mrt->mroute6_sk); |
1328 | rtnl_unlock(); | 1606 | rtnl_unlock(); |
1329 | return ret; | 1607 | return ret; |
1330 | 1608 | ||
@@ -1334,7 +1612,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1334 | if (copy_from_user(&mifi, optval, sizeof(mifi_t))) | 1612 | if (copy_from_user(&mifi, optval, sizeof(mifi_t))) |
1335 | return -EFAULT; | 1613 | return -EFAULT; |
1336 | rtnl_lock(); | 1614 | rtnl_lock(); |
1337 | ret = mif6_delete(net, mifi, NULL); | 1615 | ret = mif6_delete(mrt, mifi, NULL); |
1338 | rtnl_unlock(); | 1616 | rtnl_unlock(); |
1339 | return ret; | 1617 | return ret; |
1340 | 1618 | ||
@@ -1350,10 +1628,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1350 | return -EFAULT; | 1628 | return -EFAULT; |
1351 | rtnl_lock(); | 1629 | rtnl_lock(); |
1352 | if (optname == MRT6_DEL_MFC) | 1630 | if (optname == MRT6_DEL_MFC) |
1353 | ret = ip6mr_mfc_delete(net, &mfc); | 1631 | ret = ip6mr_mfc_delete(mrt, &mfc); |
1354 | else | 1632 | else |
1355 | ret = ip6mr_mfc_add(net, &mfc, | 1633 | ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk); |
1356 | sk == net->ipv6.mroute6_sk); | ||
1357 | rtnl_unlock(); | 1634 | rtnl_unlock(); |
1358 | return ret; | 1635 | return ret; |
1359 | 1636 | ||
@@ -1365,7 +1642,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1365 | int v; | 1642 | int v; |
1366 | if (get_user(v, (int __user *)optval)) | 1643 | if (get_user(v, (int __user *)optval)) |
1367 | return -EFAULT; | 1644 | return -EFAULT; |
1368 | net->ipv6.mroute_do_assert = !!v; | 1645 | mrt->mroute_do_assert = !!v; |
1369 | return 0; | 1646 | return 0; |
1370 | } | 1647 | } |
1371 | 1648 | ||
@@ -1378,15 +1655,36 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns | |||
1378 | v = !!v; | 1655 | v = !!v; |
1379 | rtnl_lock(); | 1656 | rtnl_lock(); |
1380 | ret = 0; | 1657 | ret = 0; |
1381 | if (v != net->ipv6.mroute_do_pim) { | 1658 | if (v != mrt->mroute_do_pim) { |
1382 | net->ipv6.mroute_do_pim = v; | 1659 | mrt->mroute_do_pim = v; |
1383 | net->ipv6.mroute_do_assert = v; | 1660 | mrt->mroute_do_assert = v; |
1384 | } | 1661 | } |
1385 | rtnl_unlock(); | 1662 | rtnl_unlock(); |
1386 | return ret; | 1663 | return ret; |
1387 | } | 1664 | } |
1388 | 1665 | ||
1389 | #endif | 1666 | #endif |
1667 | #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES | ||
1668 | case MRT6_TABLE: | ||
1669 | { | ||
1670 | u32 v; | ||
1671 | |||
1672 | if (optlen != sizeof(u32)) | ||
1673 | return -EINVAL; | ||
1674 | if (get_user(v, (u32 __user *)optval)) | ||
1675 | return -EFAULT; | ||
1676 | if (sk == mrt->mroute6_sk) | ||
1677 | return -EBUSY; | ||
1678 | |||
1679 | rtnl_lock(); | ||
1680 | ret = 0; | ||
1681 | if (!ip6mr_new_table(net, v)) | ||
1682 | ret = -ENOMEM; | ||
1683 | raw6_sk(sk)->ip6mr_table = v; | ||
1684 | rtnl_unlock(); | ||
1685 | return ret; | ||
1686 | } | ||
1687 | #endif | ||
1390 | /* | 1688 | /* |
1391 | * Spurious command, or MRT6_VERSION which you cannot | 1689 | * Spurious command, or MRT6_VERSION which you cannot |
1392 | * set. | 1690 | * set. |
@@ -1406,6 +1704,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, | |||
1406 | int olr; | 1704 | int olr; |
1407 | int val; | 1705 | int val; |
1408 | struct net *net = sock_net(sk); | 1706 | struct net *net = sock_net(sk); |
1707 | struct mr6_table *mrt; | ||
1708 | |||
1709 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1710 | if (mrt == NULL) | ||
1711 | return -ENOENT; | ||
1409 | 1712 | ||
1410 | switch (optname) { | 1713 | switch (optname) { |
1411 | case MRT6_VERSION: | 1714 | case MRT6_VERSION: |
@@ -1413,11 +1716,11 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, | |||
1413 | break; | 1716 | break; |
1414 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1717 | #ifdef CONFIG_IPV6_PIMSM_V2 |
1415 | case MRT6_PIM: | 1718 | case MRT6_PIM: |
1416 | val = net->ipv6.mroute_do_pim; | 1719 | val = mrt->mroute_do_pim; |
1417 | break; | 1720 | break; |
1418 | #endif | 1721 | #endif |
1419 | case MRT6_ASSERT: | 1722 | case MRT6_ASSERT: |
1420 | val = net->ipv6.mroute_do_assert; | 1723 | val = mrt->mroute_do_assert; |
1421 | break; | 1724 | break; |
1422 | default: | 1725 | default: |
1423 | return -ENOPROTOOPT; | 1726 | return -ENOPROTOOPT; |
@@ -1448,16 +1751,21 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1448 | struct mif_device *vif; | 1751 | struct mif_device *vif; |
1449 | struct mfc6_cache *c; | 1752 | struct mfc6_cache *c; |
1450 | struct net *net = sock_net(sk); | 1753 | struct net *net = sock_net(sk); |
1754 | struct mr6_table *mrt; | ||
1755 | |||
1756 | mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT); | ||
1757 | if (mrt == NULL) | ||
1758 | return -ENOENT; | ||
1451 | 1759 | ||
1452 | switch (cmd) { | 1760 | switch (cmd) { |
1453 | case SIOCGETMIFCNT_IN6: | 1761 | case SIOCGETMIFCNT_IN6: |
1454 | if (copy_from_user(&vr, arg, sizeof(vr))) | 1762 | if (copy_from_user(&vr, arg, sizeof(vr))) |
1455 | return -EFAULT; | 1763 | return -EFAULT; |
1456 | if (vr.mifi >= net->ipv6.maxvif) | 1764 | if (vr.mifi >= mrt->maxvif) |
1457 | return -EINVAL; | 1765 | return -EINVAL; |
1458 | read_lock(&mrt_lock); | 1766 | read_lock(&mrt_lock); |
1459 | vif = &net->ipv6.vif6_table[vr.mifi]; | 1767 | vif = &mrt->vif6_table[vr.mifi]; |
1460 | if (MIF_EXISTS(net, vr.mifi)) { | 1768 | if (MIF_EXISTS(mrt, vr.mifi)) { |
1461 | vr.icount = vif->pkt_in; | 1769 | vr.icount = vif->pkt_in; |
1462 | vr.ocount = vif->pkt_out; | 1770 | vr.ocount = vif->pkt_out; |
1463 | vr.ibytes = vif->bytes_in; | 1771 | vr.ibytes = vif->bytes_in; |
@@ -1475,7 +1783,7 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) | |||
1475 | return -EFAULT; | 1783 | return -EFAULT; |
1476 | 1784 | ||
1477 | read_lock(&mrt_lock); | 1785 | read_lock(&mrt_lock); |
1478 | c = ip6mr_cache_find(net, &sr.src.sin6_addr, &sr.grp.sin6_addr); | 1786 | c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); |
1479 | if (c) { | 1787 | if (c) { |
1480 | sr.pktcnt = c->mfc_un.res.pkt; | 1788 | sr.pktcnt = c->mfc_un.res.pkt; |
1481 | sr.bytecnt = c->mfc_un.res.bytes; | 1789 | sr.bytecnt = c->mfc_un.res.bytes; |
@@ -1505,11 +1813,11 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb) | |||
1505 | * Processing handlers for ip6mr_forward | 1813 | * Processing handlers for ip6mr_forward |
1506 | */ | 1814 | */ |
1507 | 1815 | ||
1508 | static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | 1816 | static int ip6mr_forward2(struct net *net, struct mr6_table *mrt, |
1817 | struct sk_buff *skb, struct mfc6_cache *c, int vifi) | ||
1509 | { | 1818 | { |
1510 | struct ipv6hdr *ipv6h; | 1819 | struct ipv6hdr *ipv6h; |
1511 | struct net *net = mfc6_net(c); | 1820 | struct mif_device *vif = &mrt->vif6_table[vifi]; |
1512 | struct mif_device *vif = &net->ipv6.vif6_table[vifi]; | ||
1513 | struct net_device *dev; | 1821 | struct net_device *dev; |
1514 | struct dst_entry *dst; | 1822 | struct dst_entry *dst; |
1515 | struct flowi fl; | 1823 | struct flowi fl; |
@@ -1523,7 +1831,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1523 | vif->bytes_out += skb->len; | 1831 | vif->bytes_out += skb->len; |
1524 | vif->dev->stats.tx_bytes += skb->len; | 1832 | vif->dev->stats.tx_bytes += skb->len; |
1525 | vif->dev->stats.tx_packets++; | 1833 | vif->dev->stats.tx_packets++; |
1526 | ip6mr_cache_report(net, skb, vifi, MRT6MSG_WHOLEPKT); | 1834 | ip6mr_cache_report(mrt, skb, vifi, MRT6MSG_WHOLEPKT); |
1527 | goto out_free; | 1835 | goto out_free; |
1528 | } | 1836 | } |
1529 | #endif | 1837 | #endif |
@@ -1570,7 +1878,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi) | |||
1570 | 1878 | ||
1571 | IP6CB(skb)->flags |= IP6SKB_FORWARDED; | 1879 | IP6CB(skb)->flags |= IP6SKB_FORWARDED; |
1572 | 1880 | ||
1573 | return NF_HOOK(PF_INET6, NF_INET_FORWARD, skb, skb->dev, dev, | 1881 | return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dev, |
1574 | ip6mr_forward2_finish); | 1882 | ip6mr_forward2_finish); |
1575 | 1883 | ||
1576 | out_free: | 1884 | out_free: |
@@ -1578,22 +1886,22 @@ out_free: | |||
1578 | return 0; | 1886 | return 0; |
1579 | } | 1887 | } |
1580 | 1888 | ||
1581 | static int ip6mr_find_vif(struct net_device *dev) | 1889 | static int ip6mr_find_vif(struct mr6_table *mrt, struct net_device *dev) |
1582 | { | 1890 | { |
1583 | struct net *net = dev_net(dev); | ||
1584 | int ct; | 1891 | int ct; |
1585 | for (ct = net->ipv6.maxvif - 1; ct >= 0; ct--) { | 1892 | |
1586 | if (net->ipv6.vif6_table[ct].dev == dev) | 1893 | for (ct = mrt->maxvif - 1; ct >= 0; ct--) { |
1894 | if (mrt->vif6_table[ct].dev == dev) | ||
1587 | break; | 1895 | break; |
1588 | } | 1896 | } |
1589 | return ct; | 1897 | return ct; |
1590 | } | 1898 | } |
1591 | 1899 | ||
1592 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | 1900 | static int ip6_mr_forward(struct net *net, struct mr6_table *mrt, |
1901 | struct sk_buff *skb, struct mfc6_cache *cache) | ||
1593 | { | 1902 | { |
1594 | int psend = -1; | 1903 | int psend = -1; |
1595 | int vif, ct; | 1904 | int vif, ct; |
1596 | struct net *net = mfc6_net(cache); | ||
1597 | 1905 | ||
1598 | vif = cache->mf6c_parent; | 1906 | vif = cache->mf6c_parent; |
1599 | cache->mfc_un.res.pkt++; | 1907 | cache->mfc_un.res.pkt++; |
@@ -1602,30 +1910,30 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | |||
1602 | /* | 1910 | /* |
1603 | * Wrong interface: drop packet and (maybe) send PIM assert. | 1911 | * Wrong interface: drop packet and (maybe) send PIM assert. |
1604 | */ | 1912 | */ |
1605 | if (net->ipv6.vif6_table[vif].dev != skb->dev) { | 1913 | if (mrt->vif6_table[vif].dev != skb->dev) { |
1606 | int true_vifi; | 1914 | int true_vifi; |
1607 | 1915 | ||
1608 | cache->mfc_un.res.wrong_if++; | 1916 | cache->mfc_un.res.wrong_if++; |
1609 | true_vifi = ip6mr_find_vif(skb->dev); | 1917 | true_vifi = ip6mr_find_vif(mrt, skb->dev); |
1610 | 1918 | ||
1611 | if (true_vifi >= 0 && net->ipv6.mroute_do_assert && | 1919 | if (true_vifi >= 0 && mrt->mroute_do_assert && |
1612 | /* pimsm uses asserts, when switching from RPT to SPT, | 1920 | /* pimsm uses asserts, when switching from RPT to SPT, |
1613 | so that we cannot check that packet arrived on an oif. | 1921 | so that we cannot check that packet arrived on an oif. |
1614 | It is bad, but otherwise we would need to move pretty | 1922 | It is bad, but otherwise we would need to move pretty |
1615 | large chunk of pimd to kernel. Ough... --ANK | 1923 | large chunk of pimd to kernel. Ough... --ANK |
1616 | */ | 1924 | */ |
1617 | (net->ipv6.mroute_do_pim || | 1925 | (mrt->mroute_do_pim || |
1618 | cache->mfc_un.res.ttls[true_vifi] < 255) && | 1926 | cache->mfc_un.res.ttls[true_vifi] < 255) && |
1619 | time_after(jiffies, | 1927 | time_after(jiffies, |
1620 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { | 1928 | cache->mfc_un.res.last_assert + MFC_ASSERT_THRESH)) { |
1621 | cache->mfc_un.res.last_assert = jiffies; | 1929 | cache->mfc_un.res.last_assert = jiffies; |
1622 | ip6mr_cache_report(net, skb, true_vifi, MRT6MSG_WRONGMIF); | 1930 | ip6mr_cache_report(mrt, skb, true_vifi, MRT6MSG_WRONGMIF); |
1623 | } | 1931 | } |
1624 | goto dont_forward; | 1932 | goto dont_forward; |
1625 | } | 1933 | } |
1626 | 1934 | ||
1627 | net->ipv6.vif6_table[vif].pkt_in++; | 1935 | mrt->vif6_table[vif].pkt_in++; |
1628 | net->ipv6.vif6_table[vif].bytes_in += skb->len; | 1936 | mrt->vif6_table[vif].bytes_in += skb->len; |
1629 | 1937 | ||
1630 | /* | 1938 | /* |
1631 | * Forward the frame | 1939 | * Forward the frame |
@@ -1635,13 +1943,13 @@ static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache) | |||
1635 | if (psend != -1) { | 1943 | if (psend != -1) { |
1636 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 1944 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
1637 | if (skb2) | 1945 | if (skb2) |
1638 | ip6mr_forward2(skb2, cache, psend); | 1946 | ip6mr_forward2(net, mrt, skb2, cache, psend); |
1639 | } | 1947 | } |
1640 | psend = ct; | 1948 | psend = ct; |
1641 | } | 1949 | } |
1642 | } | 1950 | } |
1643 | if (psend != -1) { | 1951 | if (psend != -1) { |
1644 | ip6mr_forward2(skb, cache, psend); | 1952 | ip6mr_forward2(net, mrt, skb, cache, psend); |
1645 | return 0; | 1953 | return 0; |
1646 | } | 1954 | } |
1647 | 1955 | ||
@@ -1659,9 +1967,19 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1659 | { | 1967 | { |
1660 | struct mfc6_cache *cache; | 1968 | struct mfc6_cache *cache; |
1661 | struct net *net = dev_net(skb->dev); | 1969 | struct net *net = dev_net(skb->dev); |
1970 | struct mr6_table *mrt; | ||
1971 | struct flowi fl = { | ||
1972 | .iif = skb->dev->ifindex, | ||
1973 | .mark = skb->mark, | ||
1974 | }; | ||
1975 | int err; | ||
1976 | |||
1977 | err = ip6mr_fib_lookup(net, &fl, &mrt); | ||
1978 | if (err < 0) | ||
1979 | return err; | ||
1662 | 1980 | ||
1663 | read_lock(&mrt_lock); | 1981 | read_lock(&mrt_lock); |
1664 | cache = ip6mr_cache_find(net, | 1982 | cache = ip6mr_cache_find(mrt, |
1665 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); | 1983 | &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); |
1666 | 1984 | ||
1667 | /* | 1985 | /* |
@@ -1670,9 +1988,9 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1670 | if (cache == NULL) { | 1988 | if (cache == NULL) { |
1671 | int vif; | 1989 | int vif; |
1672 | 1990 | ||
1673 | vif = ip6mr_find_vif(skb->dev); | 1991 | vif = ip6mr_find_vif(mrt, skb->dev); |
1674 | if (vif >= 0) { | 1992 | if (vif >= 0) { |
1675 | int err = ip6mr_cache_unresolved(net, vif, skb); | 1993 | int err = ip6mr_cache_unresolved(mrt, vif, skb); |
1676 | read_unlock(&mrt_lock); | 1994 | read_unlock(&mrt_lock); |
1677 | 1995 | ||
1678 | return err; | 1996 | return err; |
@@ -1682,7 +2000,7 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1682 | return -ENODEV; | 2000 | return -ENODEV; |
1683 | } | 2001 | } |
1684 | 2002 | ||
1685 | ip6_mr_forward(skb, cache); | 2003 | ip6_mr_forward(net, mrt, skb, cache); |
1686 | 2004 | ||
1687 | read_unlock(&mrt_lock); | 2005 | read_unlock(&mrt_lock); |
1688 | 2006 | ||
@@ -1690,12 +2008,11 @@ int ip6_mr_input(struct sk_buff *skb) | |||
1690 | } | 2008 | } |
1691 | 2009 | ||
1692 | 2010 | ||
1693 | static int | 2011 | static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, |
1694 | ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) | 2012 | struct mfc6_cache *c, struct rtmsg *rtm) |
1695 | { | 2013 | { |
1696 | int ct; | 2014 | int ct; |
1697 | struct rtnexthop *nhp; | 2015 | struct rtnexthop *nhp; |
1698 | struct net *net = mfc6_net(c); | ||
1699 | u8 *b = skb_tail_pointer(skb); | 2016 | u8 *b = skb_tail_pointer(skb); |
1700 | struct rtattr *mp_head; | 2017 | struct rtattr *mp_head; |
1701 | 2018 | ||
@@ -1703,19 +2020,19 @@ ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm) | |||
1703 | if (c->mf6c_parent > MAXMIFS) | 2020 | if (c->mf6c_parent > MAXMIFS) |
1704 | return -ENOENT; | 2021 | return -ENOENT; |
1705 | 2022 | ||
1706 | if (MIF_EXISTS(net, c->mf6c_parent)) | 2023 | if (MIF_EXISTS(mrt, c->mf6c_parent)) |
1707 | RTA_PUT(skb, RTA_IIF, 4, &net->ipv6.vif6_table[c->mf6c_parent].dev->ifindex); | 2024 | RTA_PUT(skb, RTA_IIF, 4, &mrt->vif6_table[c->mf6c_parent].dev->ifindex); |
1708 | 2025 | ||
1709 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); | 2026 | mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0)); |
1710 | 2027 | ||
1711 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { | 2028 | for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) { |
1712 | if (MIF_EXISTS(net, ct) && c->mfc_un.res.ttls[ct] < 255) { | 2029 | if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) { |
1713 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) | 2030 | if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) |
1714 | goto rtattr_failure; | 2031 | goto rtattr_failure; |
1715 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); | 2032 | nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); |
1716 | nhp->rtnh_flags = 0; | 2033 | nhp->rtnh_flags = 0; |
1717 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; | 2034 | nhp->rtnh_hops = c->mfc_un.res.ttls[ct]; |
1718 | nhp->rtnh_ifindex = net->ipv6.vif6_table[ct].dev->ifindex; | 2035 | nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex; |
1719 | nhp->rtnh_len = sizeof(*nhp); | 2036 | nhp->rtnh_len = sizeof(*nhp); |
1720 | } | 2037 | } |
1721 | } | 2038 | } |
@@ -1733,11 +2050,16 @@ int ip6mr_get_route(struct net *net, | |||
1733 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 2050 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) |
1734 | { | 2051 | { |
1735 | int err; | 2052 | int err; |
2053 | struct mr6_table *mrt; | ||
1736 | struct mfc6_cache *cache; | 2054 | struct mfc6_cache *cache; |
1737 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); | 2055 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); |
1738 | 2056 | ||
2057 | mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); | ||
2058 | if (mrt == NULL) | ||
2059 | return -ENOENT; | ||
2060 | |||
1739 | read_lock(&mrt_lock); | 2061 | read_lock(&mrt_lock); |
1740 | cache = ip6mr_cache_find(net, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); | 2062 | cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); |
1741 | 2063 | ||
1742 | if (!cache) { | 2064 | if (!cache) { |
1743 | struct sk_buff *skb2; | 2065 | struct sk_buff *skb2; |
@@ -1751,7 +2073,7 @@ int ip6mr_get_route(struct net *net, | |||
1751 | } | 2073 | } |
1752 | 2074 | ||
1753 | dev = skb->dev; | 2075 | dev = skb->dev; |
1754 | if (dev == NULL || (vif = ip6mr_find_vif(dev)) < 0) { | 2076 | if (dev == NULL || (vif = ip6mr_find_vif(mrt, dev)) < 0) { |
1755 | read_unlock(&mrt_lock); | 2077 | read_unlock(&mrt_lock); |
1756 | return -ENODEV; | 2078 | return -ENODEV; |
1757 | } | 2079 | } |
@@ -1780,7 +2102,7 @@ int ip6mr_get_route(struct net *net, | |||
1780 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); | 2102 | ipv6_addr_copy(&iph->saddr, &rt->rt6i_src.addr); |
1781 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); | 2103 | ipv6_addr_copy(&iph->daddr, &rt->rt6i_dst.addr); |
1782 | 2104 | ||
1783 | err = ip6mr_cache_unresolved(net, vif, skb2); | 2105 | err = ip6mr_cache_unresolved(mrt, vif, skb2); |
1784 | read_unlock(&mrt_lock); | 2106 | read_unlock(&mrt_lock); |
1785 | 2107 | ||
1786 | return err; | 2108 | return err; |
@@ -1789,8 +2111,88 @@ int ip6mr_get_route(struct net *net, | |||
1789 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) | 2111 | if (!nowait && (rtm->rtm_flags&RTM_F_NOTIFY)) |
1790 | cache->mfc_flags |= MFC_NOTIFY; | 2112 | cache->mfc_flags |= MFC_NOTIFY; |
1791 | 2113 | ||
1792 | err = ip6mr_fill_mroute(skb, cache, rtm); | 2114 | err = __ip6mr_fill_mroute(mrt, skb, cache, rtm); |
1793 | read_unlock(&mrt_lock); | 2115 | read_unlock(&mrt_lock); |
1794 | return err; | 2116 | return err; |
1795 | } | 2117 | } |
1796 | 2118 | ||
2119 | static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb, | ||
2120 | u32 pid, u32 seq, struct mfc6_cache *c) | ||
2121 | { | ||
2122 | struct nlmsghdr *nlh; | ||
2123 | struct rtmsg *rtm; | ||
2124 | |||
2125 | nlh = nlmsg_put(skb, pid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); | ||
2126 | if (nlh == NULL) | ||
2127 | return -EMSGSIZE; | ||
2128 | |||
2129 | rtm = nlmsg_data(nlh); | ||
2130 | rtm->rtm_family = RTNL_FAMILY_IPMR; | ||
2131 | rtm->rtm_dst_len = 128; | ||
2132 | rtm->rtm_src_len = 128; | ||
2133 | rtm->rtm_tos = 0; | ||
2134 | rtm->rtm_table = mrt->id; | ||
2135 | NLA_PUT_U32(skb, RTA_TABLE, mrt->id); | ||
2136 | rtm->rtm_scope = RT_SCOPE_UNIVERSE; | ||
2137 | rtm->rtm_protocol = RTPROT_UNSPEC; | ||
2138 | rtm->rtm_flags = 0; | ||
2139 | |||
2140 | NLA_PUT(skb, RTA_SRC, 16, &c->mf6c_origin); | ||
2141 | NLA_PUT(skb, RTA_DST, 16, &c->mf6c_mcastgrp); | ||
2142 | |||
2143 | if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0) | ||
2144 | goto nla_put_failure; | ||
2145 | |||
2146 | return nlmsg_end(skb, nlh); | ||
2147 | |||
2148 | nla_put_failure: | ||
2149 | nlmsg_cancel(skb, nlh); | ||
2150 | return -EMSGSIZE; | ||
2151 | } | ||
2152 | |||
2153 | static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb) | ||
2154 | { | ||
2155 | struct net *net = sock_net(skb->sk); | ||
2156 | struct mr6_table *mrt; | ||
2157 | struct mfc6_cache *mfc; | ||
2158 | unsigned int t = 0, s_t; | ||
2159 | unsigned int h = 0, s_h; | ||
2160 | unsigned int e = 0, s_e; | ||
2161 | |||
2162 | s_t = cb->args[0]; | ||
2163 | s_h = cb->args[1]; | ||
2164 | s_e = cb->args[2]; | ||
2165 | |||
2166 | read_lock(&mrt_lock); | ||
2167 | ip6mr_for_each_table(mrt, net) { | ||
2168 | if (t < s_t) | ||
2169 | goto next_table; | ||
2170 | if (t > s_t) | ||
2171 | s_h = 0; | ||
2172 | for (h = s_h; h < MFC6_LINES; h++) { | ||
2173 | list_for_each_entry(mfc, &mrt->mfc6_cache_array[h], list) { | ||
2174 | if (e < s_e) | ||
2175 | goto next_entry; | ||
2176 | if (ip6mr_fill_mroute(mrt, skb, | ||
2177 | NETLINK_CB(cb->skb).pid, | ||
2178 | cb->nlh->nlmsg_seq, | ||
2179 | mfc) < 0) | ||
2180 | goto done; | ||
2181 | next_entry: | ||
2182 | e++; | ||
2183 | } | ||
2184 | e = s_e = 0; | ||
2185 | } | ||
2186 | s_h = 0; | ||
2187 | next_table: | ||
2188 | t++; | ||
2189 | } | ||
2190 | done: | ||
2191 | read_unlock(&mrt_lock); | ||
2192 | |||
2193 | cb->args[2] = e; | ||
2194 | cb->args[1] = h; | ||
2195 | cb->args[0] = t; | ||
2196 | |||
2197 | return skb->len; | ||
2198 | } | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 33f60fca7aa7..bd43f0152c21 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -114,9 +114,9 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk, | |||
114 | } | 114 | } |
115 | opt = xchg(&inet6_sk(sk)->opt, opt); | 115 | opt = xchg(&inet6_sk(sk)->opt, opt); |
116 | } else { | 116 | } else { |
117 | write_lock(&sk->sk_dst_lock); | 117 | spin_lock(&sk->sk_dst_lock); |
118 | opt = xchg(&inet6_sk(sk)->opt, opt); | 118 | opt = xchg(&inet6_sk(sk)->opt, opt); |
119 | write_unlock(&sk->sk_dst_lock); | 119 | spin_unlock(&sk->sk_dst_lock); |
120 | } | 120 | } |
121 | sk_dst_reset(sk); | 121 | sk_dst_reset(sk); |
122 | 122 | ||
@@ -337,6 +337,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
337 | retv = 0; | 337 | retv = 0; |
338 | break; | 338 | break; |
339 | 339 | ||
340 | case IPV6_RECVPATHMTU: | ||
341 | if (optlen < sizeof(int)) | ||
342 | goto e_inval; | ||
343 | np->rxopt.bits.rxpmtu = valbool; | ||
344 | retv = 0; | ||
345 | break; | ||
346 | |||
340 | case IPV6_HOPOPTS: | 347 | case IPV6_HOPOPTS: |
341 | case IPV6_RTHDRDSTOPTS: | 348 | case IPV6_RTHDRDSTOPTS: |
342 | case IPV6_RTHDR: | 349 | case IPV6_RTHDR: |
@@ -451,7 +458,8 @@ sticky_done: | |||
451 | msg.msg_controllen = optlen; | 458 | msg.msg_controllen = optlen; |
452 | msg.msg_control = (void*)(opt+1); | 459 | msg.msg_control = (void*)(opt+1); |
453 | 460 | ||
454 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk); | 461 | retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk, |
462 | &junk); | ||
455 | if (retv) | 463 | if (retv) |
456 | goto done; | 464 | goto done; |
457 | update: | 465 | update: |
@@ -767,6 +775,17 @@ pref_skip_coa: | |||
767 | 775 | ||
768 | break; | 776 | break; |
769 | } | 777 | } |
778 | case IPV6_MINHOPCOUNT: | ||
779 | if (optlen < sizeof(int)) | ||
780 | goto e_inval; | ||
781 | if (val < 0 || val > 255) | ||
782 | goto e_inval; | ||
783 | np->min_hopcount = val; | ||
784 | break; | ||
785 | case IPV6_DONTFRAG: | ||
786 | np->dontfrag = valbool; | ||
787 | retv = 0; | ||
788 | break; | ||
770 | } | 789 | } |
771 | 790 | ||
772 | release_sock(sk); | 791 | release_sock(sk); |
@@ -971,14 +990,13 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
971 | case IPV6_MTU: | 990 | case IPV6_MTU: |
972 | { | 991 | { |
973 | struct dst_entry *dst; | 992 | struct dst_entry *dst; |
993 | |||
974 | val = 0; | 994 | val = 0; |
975 | lock_sock(sk); | 995 | rcu_read_lock(); |
976 | dst = sk_dst_get(sk); | 996 | dst = __sk_dst_get(sk); |
977 | if (dst) { | 997 | if (dst) |
978 | val = dst_mtu(dst); | 998 | val = dst_mtu(dst); |
979 | dst_release(dst); | 999 | rcu_read_unlock(); |
980 | } | ||
981 | release_sock(sk); | ||
982 | if (!val) | 1000 | if (!val) |
983 | return -ENOTCONN; | 1001 | return -ENOTCONN; |
984 | break; | 1002 | break; |
@@ -1056,6 +1074,38 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1056 | val = np->rxopt.bits.rxflow; | 1074 | val = np->rxopt.bits.rxflow; |
1057 | break; | 1075 | break; |
1058 | 1076 | ||
1077 | case IPV6_RECVPATHMTU: | ||
1078 | val = np->rxopt.bits.rxpmtu; | ||
1079 | break; | ||
1080 | |||
1081 | case IPV6_PATHMTU: | ||
1082 | { | ||
1083 | struct dst_entry *dst; | ||
1084 | struct ip6_mtuinfo mtuinfo; | ||
1085 | |||
1086 | if (len < sizeof(mtuinfo)) | ||
1087 | return -EINVAL; | ||
1088 | |||
1089 | len = sizeof(mtuinfo); | ||
1090 | memset(&mtuinfo, 0, sizeof(mtuinfo)); | ||
1091 | |||
1092 | rcu_read_lock(); | ||
1093 | dst = __sk_dst_get(sk); | ||
1094 | if (dst) | ||
1095 | mtuinfo.ip6m_mtu = dst_mtu(dst); | ||
1096 | rcu_read_unlock(); | ||
1097 | if (!mtuinfo.ip6m_mtu) | ||
1098 | return -ENOTCONN; | ||
1099 | |||
1100 | if (put_user(len, optlen)) | ||
1101 | return -EFAULT; | ||
1102 | if (copy_to_user(optval, &mtuinfo, len)) | ||
1103 | return -EFAULT; | ||
1104 | |||
1105 | return 0; | ||
1106 | break; | ||
1107 | } | ||
1108 | |||
1059 | case IPV6_UNICAST_HOPS: | 1109 | case IPV6_UNICAST_HOPS: |
1060 | case IPV6_MULTICAST_HOPS: | 1110 | case IPV6_MULTICAST_HOPS: |
1061 | { | 1111 | { |
@@ -1066,12 +1116,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1066 | else | 1116 | else |
1067 | val = np->mcast_hops; | 1117 | val = np->mcast_hops; |
1068 | 1118 | ||
1069 | dst = sk_dst_get(sk); | 1119 | if (val < 0) { |
1070 | if (dst) { | 1120 | rcu_read_lock(); |
1071 | if (val < 0) | 1121 | dst = __sk_dst_get(sk); |
1122 | if (dst) | ||
1072 | val = ip6_dst_hoplimit(dst); | 1123 | val = ip6_dst_hoplimit(dst); |
1073 | dst_release(dst); | 1124 | rcu_read_unlock(); |
1074 | } | 1125 | } |
1126 | |||
1075 | if (val < 0) | 1127 | if (val < 0) |
1076 | val = sock_net(sk)->ipv6.devconf_all->hop_limit; | 1128 | val = sock_net(sk)->ipv6.devconf_all->hop_limit; |
1077 | break; | 1129 | break; |
@@ -1115,6 +1167,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1115 | val |= IPV6_PREFER_SRC_HOME; | 1167 | val |= IPV6_PREFER_SRC_HOME; |
1116 | break; | 1168 | break; |
1117 | 1169 | ||
1170 | case IPV6_MINHOPCOUNT: | ||
1171 | val = np->min_hopcount; | ||
1172 | break; | ||
1173 | |||
1174 | case IPV6_DONTFRAG: | ||
1175 | val = np->dontfrag; | ||
1176 | break; | ||
1177 | |||
1118 | default: | 1178 | default: |
1119 | return -ENOPROTOOPT; | 1179 | return -ENOPROTOOPT; |
1120 | } | 1180 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index c483ab9fd67b..59f1881968c7 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/proc_fs.h> | 44 | #include <linux/proc_fs.h> |
45 | #include <linux/seq_file.h> | 45 | #include <linux/seq_file.h> |
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <net/mld.h> | ||
47 | 48 | ||
48 | #include <linux/netfilter.h> | 49 | #include <linux/netfilter.h> |
49 | #include <linux/netfilter_ipv6.h> | 50 | #include <linux/netfilter_ipv6.h> |
@@ -71,54 +72,11 @@ | |||
71 | #define MDBG(x) | 72 | #define MDBG(x) |
72 | #endif | 73 | #endif |
73 | 74 | ||
74 | /* | 75 | /* Ensure that we have struct in6_addr aligned on 32bit word. */ |
75 | * These header formats should be in a separate include file, but icmpv6.h | 76 | static void *__mld2_query_bugs[] __attribute__((__unused__)) = { |
76 | * doesn't have in6_addr defined in all cases, there is no __u128, and no | 77 | BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4), |
77 | * other files reference these. | 78 | BUILD_BUG_ON_NULL(offsetof(struct mld2_report, mld2r_grec) % 4), |
78 | * | 79 | BUILD_BUG_ON_NULL(offsetof(struct mld2_grec, grec_mca) % 4) |
79 | * +-DLS 4/14/03 | ||
80 | */ | ||
81 | |||
82 | /* Multicast Listener Discovery version 2 headers */ | ||
83 | |||
84 | struct mld2_grec { | ||
85 | __u8 grec_type; | ||
86 | __u8 grec_auxwords; | ||
87 | __be16 grec_nsrcs; | ||
88 | struct in6_addr grec_mca; | ||
89 | struct in6_addr grec_src[0]; | ||
90 | }; | ||
91 | |||
92 | struct mld2_report { | ||
93 | __u8 type; | ||
94 | __u8 resv1; | ||
95 | __sum16 csum; | ||
96 | __be16 resv2; | ||
97 | __be16 ngrec; | ||
98 | struct mld2_grec grec[0]; | ||
99 | }; | ||
100 | |||
101 | struct mld2_query { | ||
102 | __u8 type; | ||
103 | __u8 code; | ||
104 | __sum16 csum; | ||
105 | __be16 mrc; | ||
106 | __be16 resv1; | ||
107 | struct in6_addr mca; | ||
108 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
109 | __u8 qrv:3, | ||
110 | suppress:1, | ||
111 | resv2:4; | ||
112 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
113 | __u8 resv2:4, | ||
114 | suppress:1, | ||
115 | qrv:3; | ||
116 | #else | ||
117 | #error "Please fix <asm/byteorder.h>" | ||
118 | #endif | ||
119 | __u8 qqic; | ||
120 | __be16 nsrcs; | ||
121 | struct in6_addr srcs[0]; | ||
122 | }; | 80 | }; |
123 | 81 | ||
124 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | 82 | static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; |
@@ -157,14 +115,6 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
157 | ((idev)->mc_v1_seen && \ | 115 | ((idev)->mc_v1_seen && \ |
158 | time_before(jiffies, (idev)->mc_v1_seen))) | 116 | time_before(jiffies, (idev)->mc_v1_seen))) |
159 | 117 | ||
160 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) | ||
161 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ | ||
162 | ((value) < (thresh) ? (value) : \ | ||
163 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ | ||
164 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | ||
165 | |||
166 | #define MLDV2_MRC(value) MLDV2_EXP(0x8000, 12, 3, value) | ||
167 | |||
168 | #define IPV6_MLD_MAX_MSF 64 | 118 | #define IPV6_MLD_MAX_MSF 64 |
169 | 119 | ||
170 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | 120 | int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; |
@@ -715,7 +665,7 @@ static void igmp6_group_added(struct ifmcaddr6 *mc) | |||
715 | if (!(mc->mca_flags&MAF_LOADED)) { | 665 | if (!(mc->mca_flags&MAF_LOADED)) { |
716 | mc->mca_flags |= MAF_LOADED; | 666 | mc->mca_flags |= MAF_LOADED; |
717 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 667 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
718 | dev_mc_add(dev, buf, dev->addr_len, 0); | 668 | dev_mc_add(dev, buf); |
719 | } | 669 | } |
720 | spin_unlock_bh(&mc->mca_lock); | 670 | spin_unlock_bh(&mc->mca_lock); |
721 | 671 | ||
@@ -741,7 +691,7 @@ static void igmp6_group_dropped(struct ifmcaddr6 *mc) | |||
741 | if (mc->mca_flags&MAF_LOADED) { | 691 | if (mc->mca_flags&MAF_LOADED) { |
742 | mc->mca_flags &= ~MAF_LOADED; | 692 | mc->mca_flags &= ~MAF_LOADED; |
743 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) | 693 | if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) |
744 | dev_mc_delete(dev, buf, dev->addr_len, 0); | 694 | dev_mc_del(dev, buf); |
745 | } | 695 | } |
746 | 696 | ||
747 | if (mc->mca_flags & MAF_NOREPORT) | 697 | if (mc->mca_flags & MAF_NOREPORT) |
@@ -1161,7 +1111,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1161 | struct in6_addr *group; | 1111 | struct in6_addr *group; |
1162 | unsigned long max_delay; | 1112 | unsigned long max_delay; |
1163 | struct inet6_dev *idev; | 1113 | struct inet6_dev *idev; |
1164 | struct icmp6hdr *hdr; | 1114 | struct mld_msg *mld; |
1165 | int group_type; | 1115 | int group_type; |
1166 | int mark = 0; | 1116 | int mark = 0; |
1167 | int len; | 1117 | int len; |
@@ -1182,8 +1132,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1182 | if (idev == NULL) | 1132 | if (idev == NULL) |
1183 | return 0; | 1133 | return 0; |
1184 | 1134 | ||
1185 | hdr = icmp6_hdr(skb); | 1135 | mld = (struct mld_msg *)icmp6_hdr(skb); |
1186 | group = (struct in6_addr *) (hdr + 1); | 1136 | group = &mld->mld_mca; |
1187 | group_type = ipv6_addr_type(group); | 1137 | group_type = ipv6_addr_type(group); |
1188 | 1138 | ||
1189 | if (group_type != IPV6_ADDR_ANY && | 1139 | if (group_type != IPV6_ADDR_ANY && |
@@ -1197,7 +1147,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1197 | /* MLDv1 router present */ | 1147 | /* MLDv1 router present */ |
1198 | 1148 | ||
1199 | /* Translate milliseconds to jiffies */ | 1149 | /* Translate milliseconds to jiffies */ |
1200 | max_delay = (ntohs(hdr->icmp6_maxdelay)*HZ)/1000; | 1150 | max_delay = (ntohs(mld->mld_maxdelay)*HZ)/1000; |
1201 | 1151 | ||
1202 | switchback = (idev->mc_qrv + 1) * max_delay; | 1152 | switchback = (idev->mc_qrv + 1) * max_delay; |
1203 | idev->mc_v1_seen = jiffies + switchback; | 1153 | idev->mc_v1_seen = jiffies + switchback; |
@@ -1216,14 +1166,14 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1216 | return -EINVAL; | 1166 | return -EINVAL; |
1217 | } | 1167 | } |
1218 | mlh2 = (struct mld2_query *)skb_transport_header(skb); | 1168 | mlh2 = (struct mld2_query *)skb_transport_header(skb); |
1219 | max_delay = (MLDV2_MRC(ntohs(mlh2->mrc))*HZ)/1000; | 1169 | max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000; |
1220 | if (!max_delay) | 1170 | if (!max_delay) |
1221 | max_delay = 1; | 1171 | max_delay = 1; |
1222 | idev->mc_maxdelay = max_delay; | 1172 | idev->mc_maxdelay = max_delay; |
1223 | if (mlh2->qrv) | 1173 | if (mlh2->mld2q_qrv) |
1224 | idev->mc_qrv = mlh2->qrv; | 1174 | idev->mc_qrv = mlh2->mld2q_qrv; |
1225 | if (group_type == IPV6_ADDR_ANY) { /* general query */ | 1175 | if (group_type == IPV6_ADDR_ANY) { /* general query */ |
1226 | if (mlh2->nsrcs) { | 1176 | if (mlh2->mld2q_nsrcs) { |
1227 | in6_dev_put(idev); | 1177 | in6_dev_put(idev); |
1228 | return -EINVAL; /* no sources allowed */ | 1178 | return -EINVAL; /* no sources allowed */ |
1229 | } | 1179 | } |
@@ -1232,9 +1182,9 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1232 | return 0; | 1182 | return 0; |
1233 | } | 1183 | } |
1234 | /* mark sources to include, if group & source-specific */ | 1184 | /* mark sources to include, if group & source-specific */ |
1235 | if (mlh2->nsrcs != 0) { | 1185 | if (mlh2->mld2q_nsrcs != 0) { |
1236 | if (!pskb_may_pull(skb, srcs_offset + | 1186 | if (!pskb_may_pull(skb, srcs_offset + |
1237 | ntohs(mlh2->nsrcs) * sizeof(struct in6_addr))) { | 1187 | ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) { |
1238 | in6_dev_put(idev); | 1188 | in6_dev_put(idev); |
1239 | return -EINVAL; | 1189 | return -EINVAL; |
1240 | } | 1190 | } |
@@ -1270,7 +1220,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1270 | ma->mca_flags &= ~MAF_GSQUERY; | 1220 | ma->mca_flags &= ~MAF_GSQUERY; |
1271 | } | 1221 | } |
1272 | if (!(ma->mca_flags & MAF_GSQUERY) || | 1222 | if (!(ma->mca_flags & MAF_GSQUERY) || |
1273 | mld_marksources(ma, ntohs(mlh2->nsrcs), mlh2->srcs)) | 1223 | mld_marksources(ma, ntohs(mlh2->mld2q_nsrcs), mlh2->mld2q_srcs)) |
1274 | igmp6_group_queried(ma, max_delay); | 1224 | igmp6_group_queried(ma, max_delay); |
1275 | spin_unlock_bh(&ma->mca_lock); | 1225 | spin_unlock_bh(&ma->mca_lock); |
1276 | break; | 1226 | break; |
@@ -1286,9 +1236,8 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1286 | int igmp6_event_report(struct sk_buff *skb) | 1236 | int igmp6_event_report(struct sk_buff *skb) |
1287 | { | 1237 | { |
1288 | struct ifmcaddr6 *ma; | 1238 | struct ifmcaddr6 *ma; |
1289 | struct in6_addr *addrp; | ||
1290 | struct inet6_dev *idev; | 1239 | struct inet6_dev *idev; |
1291 | struct icmp6hdr *hdr; | 1240 | struct mld_msg *mld; |
1292 | int addr_type; | 1241 | int addr_type; |
1293 | 1242 | ||
1294 | /* Our own report looped back. Ignore it. */ | 1243 | /* Our own report looped back. Ignore it. */ |
@@ -1300,10 +1249,10 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1300 | skb->pkt_type != PACKET_BROADCAST) | 1249 | skb->pkt_type != PACKET_BROADCAST) |
1301 | return 0; | 1250 | return 0; |
1302 | 1251 | ||
1303 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | 1252 | if (!pskb_may_pull(skb, sizeof(*mld) - sizeof(struct icmp6hdr))) |
1304 | return -EINVAL; | 1253 | return -EINVAL; |
1305 | 1254 | ||
1306 | hdr = icmp6_hdr(skb); | 1255 | mld = (struct mld_msg *)icmp6_hdr(skb); |
1307 | 1256 | ||
1308 | /* Drop reports with not link local source */ | 1257 | /* Drop reports with not link local source */ |
1309 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); | 1258 | addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr); |
@@ -1311,8 +1260,6 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1311 | !(addr_type&IPV6_ADDR_LINKLOCAL)) | 1260 | !(addr_type&IPV6_ADDR_LINKLOCAL)) |
1312 | return -EINVAL; | 1261 | return -EINVAL; |
1313 | 1262 | ||
1314 | addrp = (struct in6_addr *) (hdr + 1); | ||
1315 | |||
1316 | idev = in6_dev_get(skb->dev); | 1263 | idev = in6_dev_get(skb->dev); |
1317 | if (idev == NULL) | 1264 | if (idev == NULL) |
1318 | return -ENODEV; | 1265 | return -ENODEV; |
@@ -1323,7 +1270,7 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1323 | 1270 | ||
1324 | read_lock_bh(&idev->lock); | 1271 | read_lock_bh(&idev->lock); |
1325 | for (ma = idev->mc_list; ma; ma=ma->next) { | 1272 | for (ma = idev->mc_list; ma; ma=ma->next) { |
1326 | if (ipv6_addr_equal(&ma->mca_addr, addrp)) { | 1273 | if (ipv6_addr_equal(&ma->mca_addr, &mld->mld_mca)) { |
1327 | spin_lock(&ma->mca_lock); | 1274 | spin_lock(&ma->mca_lock); |
1328 | if (del_timer(&ma->mca_timer)) | 1275 | if (del_timer(&ma->mca_timer)) |
1329 | atomic_dec(&ma->mca_refcnt); | 1276 | atomic_dec(&ma->mca_refcnt); |
@@ -1432,11 +1379,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
1432 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); | 1379 | skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); |
1433 | skb_put(skb, sizeof(*pmr)); | 1380 | skb_put(skb, sizeof(*pmr)); |
1434 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1381 | pmr = (struct mld2_report *)skb_transport_header(skb); |
1435 | pmr->type = ICMPV6_MLD2_REPORT; | 1382 | pmr->mld2r_type = ICMPV6_MLD2_REPORT; |
1436 | pmr->resv1 = 0; | 1383 | pmr->mld2r_resv1 = 0; |
1437 | pmr->csum = 0; | 1384 | pmr->mld2r_cksum = 0; |
1438 | pmr->resv2 = 0; | 1385 | pmr->mld2r_resv2 = 0; |
1439 | pmr->ngrec = 0; | 1386 | pmr->mld2r_ngrec = 0; |
1440 | return skb; | 1387 | return skb; |
1441 | } | 1388 | } |
1442 | 1389 | ||
@@ -1458,9 +1405,10 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1458 | mldlen = skb->tail - skb->transport_header; | 1405 | mldlen = skb->tail - skb->transport_header; |
1459 | pip6->payload_len = htons(payload_len); | 1406 | pip6->payload_len = htons(payload_len); |
1460 | 1407 | ||
1461 | pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, | 1408 | pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, |
1462 | IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb), | 1409 | IPPROTO_ICMPV6, |
1463 | mldlen, 0)); | 1410 | csum_partial(skb_transport_header(skb), |
1411 | mldlen, 0)); | ||
1464 | 1412 | ||
1465 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); | 1413 | dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); |
1466 | 1414 | ||
@@ -1480,7 +1428,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1480 | 1428 | ||
1481 | payload_len = skb->len; | 1429 | payload_len = skb->len; |
1482 | 1430 | ||
1483 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1431 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1484 | dst_output); | 1432 | dst_output); |
1485 | out: | 1433 | out: |
1486 | if (!err) { | 1434 | if (!err) { |
@@ -1521,7 +1469,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1521 | pgr->grec_nsrcs = 0; | 1469 | pgr->grec_nsrcs = 0; |
1522 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ | 1470 | pgr->grec_mca = pmc->mca_addr; /* structure copy */ |
1523 | pmr = (struct mld2_report *)skb_transport_header(skb); | 1471 | pmr = (struct mld2_report *)skb_transport_header(skb); |
1524 | pmr->ngrec = htons(ntohs(pmr->ngrec)+1); | 1472 | pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1); |
1525 | *ppgr = pgr; | 1473 | *ppgr = pgr; |
1526 | return skb; | 1474 | return skb; |
1527 | } | 1475 | } |
@@ -1557,7 +1505,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1557 | 1505 | ||
1558 | /* EX and TO_EX get a fresh packet, if needed */ | 1506 | /* EX and TO_EX get a fresh packet, if needed */ |
1559 | if (truncate) { | 1507 | if (truncate) { |
1560 | if (pmr && pmr->ngrec && | 1508 | if (pmr && pmr->mld2r_ngrec && |
1561 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { | 1509 | AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { |
1562 | if (skb) | 1510 | if (skb) |
1563 | mld_sendpack(skb); | 1511 | mld_sendpack(skb); |
@@ -1770,9 +1718,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1770 | struct sock *sk = net->ipv6.igmp_sk; | 1718 | struct sock *sk = net->ipv6.igmp_sk; |
1771 | struct inet6_dev *idev; | 1719 | struct inet6_dev *idev; |
1772 | struct sk_buff *skb; | 1720 | struct sk_buff *skb; |
1773 | struct icmp6hdr *hdr; | 1721 | struct mld_msg *hdr; |
1774 | const struct in6_addr *snd_addr, *saddr; | 1722 | const struct in6_addr *snd_addr, *saddr; |
1775 | struct in6_addr *addrp; | ||
1776 | struct in6_addr addr_buf; | 1723 | struct in6_addr addr_buf; |
1777 | int err, len, payload_len, full_len; | 1724 | int err, len, payload_len, full_len; |
1778 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1725 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
@@ -1820,16 +1767,14 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1820 | 1767 | ||
1821 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1768 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
1822 | 1769 | ||
1823 | hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr)); | 1770 | hdr = (struct mld_msg *) skb_put(skb, sizeof(struct mld_msg)); |
1824 | memset(hdr, 0, sizeof(struct icmp6hdr)); | 1771 | memset(hdr, 0, sizeof(struct mld_msg)); |
1825 | hdr->icmp6_type = type; | 1772 | hdr->mld_type = type; |
1773 | ipv6_addr_copy(&hdr->mld_mca, addr); | ||
1826 | 1774 | ||
1827 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); | 1775 | hdr->mld_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
1828 | ipv6_addr_copy(addrp, addr); | 1776 | IPPROTO_ICMPV6, |
1829 | 1777 | csum_partial(hdr, len, 0)); | |
1830 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, | ||
1831 | IPPROTO_ICMPV6, | ||
1832 | csum_partial(hdr, len, 0)); | ||
1833 | 1778 | ||
1834 | idev = in6_dev_get(skb->dev); | 1779 | idev = in6_dev_get(skb->dev); |
1835 | 1780 | ||
@@ -1848,7 +1793,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1848 | goto err_out; | 1793 | goto err_out; |
1849 | 1794 | ||
1850 | skb_dst_set(skb, dst); | 1795 | skb_dst_set(skb, dst); |
1851 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, | 1796 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev, |
1852 | dst_output); | 1797 | dst_output); |
1853 | out: | 1798 | out: |
1854 | if (!err) { | 1799 | if (!err) { |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index da0a4d2adc69..0abdc242ddb7 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -536,7 +536,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
536 | idev = in6_dev_get(dst->dev); | 536 | idev = in6_dev_get(dst->dev); |
537 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 537 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
538 | 538 | ||
539 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 539 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, |
540 | dst_output); | 540 | dst_output); |
541 | if (!err) { | 541 | if (!err) { |
542 | ICMP6MSGOUT_INC_STATS(net, idev, type); | 542 | ICMP6MSGOUT_INC_STATS(net, idev, type); |
@@ -890,8 +890,6 @@ out: | |||
890 | in6_ifa_put(ifp); | 890 | in6_ifa_put(ifp); |
891 | else | 891 | else |
892 | in6_dev_put(idev); | 892 | in6_dev_put(idev); |
893 | |||
894 | return; | ||
895 | } | 893 | } |
896 | 894 | ||
897 | static void ndisc_recv_na(struct sk_buff *skb) | 895 | static void ndisc_recv_na(struct sk_buff *skb) |
@@ -1618,7 +1616,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1618 | skb_dst_set(buff, dst); | 1616 | skb_dst_set(buff, dst); |
1619 | idev = in6_dev_get(dst->dev); | 1617 | idev = in6_dev_get(dst->dev); |
1620 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1618 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
1621 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, | 1619 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, |
1622 | dst_output); | 1620 | dst_output); |
1623 | if (!err) { | 1621 | if (!err) { |
1624 | ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); | 1622 | ICMP6MSGOUT_INC_STATS(net, idev, NDISC_REDIRECT); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index d5ed92b14346..a74951c039b6 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -25,20 +25,6 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | dst = ip6_route_output(net, skb->sk, &fl); | 27 | dst = ip6_route_output(net, skb->sk, &fl); |
28 | |||
29 | #ifdef CONFIG_XFRM | ||
30 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
31 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | ||
32 | struct dst_entry *dst2 = skb_dst(skb); | ||
33 | |||
34 | if (xfrm_lookup(net, &dst2, &fl, skb->sk, 0)) { | ||
35 | skb_dst_set(skb, NULL); | ||
36 | return -1; | ||
37 | } | ||
38 | skb_dst_set(skb, dst2); | ||
39 | } | ||
40 | #endif | ||
41 | |||
42 | if (dst->error) { | 28 | if (dst->error) { |
43 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); | 29 | IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
44 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 30 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
@@ -50,6 +36,17 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
50 | skb_dst_drop(skb); | 36 | skb_dst_drop(skb); |
51 | 37 | ||
52 | skb_dst_set(skb, dst); | 38 | skb_dst_set(skb, dst); |
39 | |||
40 | #ifdef CONFIG_XFRM | ||
41 | if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
42 | xfrm_decode_session(skb, &fl, AF_INET6) == 0) { | ||
43 | skb_dst_set(skb, NULL); | ||
44 | if (xfrm_lookup(net, &dst, &fl, skb->sk, 0)) | ||
45 | return -1; | ||
46 | skb_dst_set(skb, dst); | ||
47 | } | ||
48 | #endif | ||
49 | |||
53 | return 0; | 50 | return 0; |
54 | } | 51 | } |
55 | EXPORT_SYMBOL(ip6_route_me_harder); | 52 | EXPORT_SYMBOL(ip6_route_me_harder); |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 6a68a74d14a3..8c201743d96d 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -162,8 +162,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
162 | break; | 162 | break; |
163 | 163 | ||
164 | case IPQ_COPY_PACKET: | 164 | case IPQ_COPY_PACKET: |
165 | if ((entry->skb->ip_summed == CHECKSUM_PARTIAL || | 165 | if (entry->skb->ip_summed == CHECKSUM_PARTIAL && |
166 | entry->skb->ip_summed == CHECKSUM_COMPLETE) && | ||
167 | (*errp = skb_checksum_help(entry->skb))) { | 166 | (*errp = skb_checksum_help(entry->skb))) { |
168 | read_unlock_bh(&queue_lock); | 167 | read_unlock_bh(&queue_lock); |
169 | return NULL; | 168 | return NULL; |
@@ -463,7 +462,6 @@ __ipq_rcv_skb(struct sk_buff *skb) | |||
463 | 462 | ||
464 | if (flags & NLM_F_ACK) | 463 | if (flags & NLM_F_ACK) |
465 | netlink_ack(skb, nlh, 0); | 464 | netlink_ack(skb, nlh, 0); |
466 | return; | ||
467 | } | 465 | } |
468 | 466 | ||
469 | static void | 467 | static void |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 9210e312edf1..6f517bd83692 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -40,24 +40,19 @@ MODULE_DESCRIPTION("IPv6 packet filter"); | |||
40 | /*#define DEBUG_IP_FIREWALL_USER*/ | 40 | /*#define DEBUG_IP_FIREWALL_USER*/ |
41 | 41 | ||
42 | #ifdef DEBUG_IP_FIREWALL | 42 | #ifdef DEBUG_IP_FIREWALL |
43 | #define dprintf(format, args...) printk(format , ## args) | 43 | #define dprintf(format, args...) pr_info(format , ## args) |
44 | #else | 44 | #else |
45 | #define dprintf(format, args...) | 45 | #define dprintf(format, args...) |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef DEBUG_IP_FIREWALL_USER | 48 | #ifdef DEBUG_IP_FIREWALL_USER |
49 | #define duprintf(format, args...) printk(format , ## args) | 49 | #define duprintf(format, args...) pr_info(format , ## args) |
50 | #else | 50 | #else |
51 | #define duprintf(format, args...) | 51 | #define duprintf(format, args...) |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | #ifdef CONFIG_NETFILTER_DEBUG | 54 | #ifdef CONFIG_NETFILTER_DEBUG |
55 | #define IP_NF_ASSERT(x) \ | 55 | #define IP_NF_ASSERT(x) WARN_ON(!(x)) |
56 | do { \ | ||
57 | if (!(x)) \ | ||
58 | printk("IP_NF_ASSERT: %s:%s:%u\n", \ | ||
59 | __func__, __FILE__, __LINE__); \ | ||
60 | } while(0) | ||
61 | #else | 56 | #else |
62 | #define IP_NF_ASSERT(x) | 57 | #define IP_NF_ASSERT(x) |
63 | #endif | 58 | #endif |
@@ -197,30 +192,14 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6) | |||
197 | } | 192 | } |
198 | 193 | ||
199 | static unsigned int | 194 | static unsigned int |
200 | ip6t_error(struct sk_buff *skb, const struct xt_target_param *par) | 195 | ip6t_error(struct sk_buff *skb, const struct xt_action_param *par) |
201 | { | 196 | { |
202 | if (net_ratelimit()) | 197 | if (net_ratelimit()) |
203 | printk("ip6_tables: error: `%s'\n", | 198 | pr_info("error: `%s'\n", (const char *)par->targinfo); |
204 | (const char *)par->targinfo); | ||
205 | 199 | ||
206 | return NF_DROP; | 200 | return NF_DROP; |
207 | } | 201 | } |
208 | 202 | ||
209 | /* Performance critical - called for every packet */ | ||
210 | static inline bool | ||
211 | do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb, | ||
212 | struct xt_match_param *par) | ||
213 | { | ||
214 | par->match = m->u.kernel.match; | ||
215 | par->matchinfo = m->data; | ||
216 | |||
217 | /* Stop iteration if it doesn't match */ | ||
218 | if (!m->u.kernel.match->match(skb, par)) | ||
219 | return true; | ||
220 | else | ||
221 | return false; | ||
222 | } | ||
223 | |||
224 | static inline struct ip6t_entry * | 203 | static inline struct ip6t_entry * |
225 | get_entry(const void *base, unsigned int offset) | 204 | get_entry(const void *base, unsigned int offset) |
226 | { | 205 | { |
@@ -352,18 +331,15 @@ ip6t_do_table(struct sk_buff *skb, | |||
352 | const struct net_device *out, | 331 | const struct net_device *out, |
353 | struct xt_table *table) | 332 | struct xt_table *table) |
354 | { | 333 | { |
355 | #define tb_comefrom ((struct ip6t_entry *)table_base)->comefrom | ||
356 | |||
357 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 334 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
358 | bool hotdrop = false; | ||
359 | /* Initializing verdict to NF_DROP keeps gcc happy. */ | 335 | /* Initializing verdict to NF_DROP keeps gcc happy. */ |
360 | unsigned int verdict = NF_DROP; | 336 | unsigned int verdict = NF_DROP; |
361 | const char *indev, *outdev; | 337 | const char *indev, *outdev; |
362 | const void *table_base; | 338 | const void *table_base; |
363 | struct ip6t_entry *e, *back; | 339 | struct ip6t_entry *e, **jumpstack; |
340 | unsigned int *stackptr, origptr, cpu; | ||
364 | const struct xt_table_info *private; | 341 | const struct xt_table_info *private; |
365 | struct xt_match_param mtpar; | 342 | struct xt_action_param acpar; |
366 | struct xt_target_param tgpar; | ||
367 | 343 | ||
368 | /* Initialization */ | 344 | /* Initialization */ |
369 | indev = in ? in->name : nulldevname; | 345 | indev = in ? in->name : nulldevname; |
@@ -374,39 +350,42 @@ ip6t_do_table(struct sk_buff *skb, | |||
374 | * things we don't know, ie. tcp syn flag or ports). If the | 350 | * things we don't know, ie. tcp syn flag or ports). If the |
375 | * rule is also a fragment-specific rule, non-fragments won't | 351 | * rule is also a fragment-specific rule, non-fragments won't |
376 | * match it. */ | 352 | * match it. */ |
377 | mtpar.hotdrop = &hotdrop; | 353 | acpar.hotdrop = false; |
378 | mtpar.in = tgpar.in = in; | 354 | acpar.in = in; |
379 | mtpar.out = tgpar.out = out; | 355 | acpar.out = out; |
380 | mtpar.family = tgpar.family = NFPROTO_IPV6; | 356 | acpar.family = NFPROTO_IPV6; |
381 | mtpar.hooknum = tgpar.hooknum = hook; | 357 | acpar.hooknum = hook; |
382 | 358 | ||
383 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 359 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
384 | 360 | ||
385 | xt_info_rdlock_bh(); | 361 | xt_info_rdlock_bh(); |
386 | private = table->private; | 362 | private = table->private; |
387 | table_base = private->entries[smp_processor_id()]; | 363 | cpu = smp_processor_id(); |
364 | table_base = private->entries[cpu]; | ||
365 | jumpstack = (struct ip6t_entry **)private->jumpstack[cpu]; | ||
366 | stackptr = &private->stackptr[cpu]; | ||
367 | origptr = *stackptr; | ||
388 | 368 | ||
389 | e = get_entry(table_base, private->hook_entry[hook]); | 369 | e = get_entry(table_base, private->hook_entry[hook]); |
390 | 370 | ||
391 | /* For return from builtin chain */ | ||
392 | back = get_entry(table_base, private->underflow[hook]); | ||
393 | |||
394 | do { | 371 | do { |
395 | const struct ip6t_entry_target *t; | 372 | const struct ip6t_entry_target *t; |
396 | const struct xt_entry_match *ematch; | 373 | const struct xt_entry_match *ematch; |
397 | 374 | ||
398 | IP_NF_ASSERT(e); | 375 | IP_NF_ASSERT(e); |
399 | IP_NF_ASSERT(back); | ||
400 | if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, | 376 | if (!ip6_packet_match(skb, indev, outdev, &e->ipv6, |
401 | &mtpar.thoff, &mtpar.fragoff, &hotdrop)) { | 377 | &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) { |
402 | no_match: | 378 | no_match: |
403 | e = ip6t_next_entry(e); | 379 | e = ip6t_next_entry(e); |
404 | continue; | 380 | continue; |
405 | } | 381 | } |
406 | 382 | ||
407 | xt_ematch_foreach(ematch, e) | 383 | xt_ematch_foreach(ematch, e) { |
408 | if (do_match(ematch, skb, &mtpar) != 0) | 384 | acpar.match = ematch->u.kernel.match; |
385 | acpar.matchinfo = ematch->data; | ||
386 | if (!acpar.match->match(skb, &acpar)) | ||
409 | goto no_match; | 387 | goto no_match; |
388 | } | ||
410 | 389 | ||
411 | ADD_COUNTER(e->counters, | 390 | ADD_COUNTER(e->counters, |
412 | ntohs(ipv6_hdr(skb)->payload_len) + | 391 | ntohs(ipv6_hdr(skb)->payload_len) + |
@@ -433,62 +412,47 @@ ip6t_do_table(struct sk_buff *skb, | |||
433 | verdict = (unsigned)(-v) - 1; | 412 | verdict = (unsigned)(-v) - 1; |
434 | break; | 413 | break; |
435 | } | 414 | } |
436 | e = back; | 415 | if (*stackptr == 0) |
437 | back = get_entry(table_base, back->comefrom); | 416 | e = get_entry(table_base, |
417 | private->underflow[hook]); | ||
418 | else | ||
419 | e = ip6t_next_entry(jumpstack[--*stackptr]); | ||
438 | continue; | 420 | continue; |
439 | } | 421 | } |
440 | if (table_base + v != ip6t_next_entry(e) && | 422 | if (table_base + v != ip6t_next_entry(e) && |
441 | !(e->ipv6.flags & IP6T_F_GOTO)) { | 423 | !(e->ipv6.flags & IP6T_F_GOTO)) { |
442 | /* Save old back ptr in next entry */ | 424 | if (*stackptr >= private->stacksize) { |
443 | struct ip6t_entry *next = ip6t_next_entry(e); | 425 | verdict = NF_DROP; |
444 | next->comefrom = (void *)back - table_base; | 426 | break; |
445 | /* set back pointer to next entry */ | 427 | } |
446 | back = next; | 428 | jumpstack[(*stackptr)++] = e; |
447 | } | 429 | } |
448 | 430 | ||
449 | e = get_entry(table_base, v); | 431 | e = get_entry(table_base, v); |
450 | continue; | 432 | continue; |
451 | } | 433 | } |
452 | 434 | ||
453 | /* Targets which reenter must return | 435 | acpar.target = t->u.kernel.target; |
454 | abs. verdicts */ | 436 | acpar.targinfo = t->data; |
455 | tgpar.target = t->u.kernel.target; | ||
456 | tgpar.targinfo = t->data; | ||
457 | |||
458 | #ifdef CONFIG_NETFILTER_DEBUG | ||
459 | tb_comefrom = 0xeeeeeeec; | ||
460 | #endif | ||
461 | verdict = t->u.kernel.target->target(skb, &tgpar); | ||
462 | 437 | ||
463 | #ifdef CONFIG_NETFILTER_DEBUG | 438 | verdict = t->u.kernel.target->target(skb, &acpar); |
464 | if (tb_comefrom != 0xeeeeeeec && verdict == IP6T_CONTINUE) { | ||
465 | printk("Target %s reentered!\n", | ||
466 | t->u.kernel.target->name); | ||
467 | verdict = NF_DROP; | ||
468 | } | ||
469 | tb_comefrom = 0x57acc001; | ||
470 | #endif | ||
471 | if (verdict == IP6T_CONTINUE) | 439 | if (verdict == IP6T_CONTINUE) |
472 | e = ip6t_next_entry(e); | 440 | e = ip6t_next_entry(e); |
473 | else | 441 | else |
474 | /* Verdict */ | 442 | /* Verdict */ |
475 | break; | 443 | break; |
476 | } while (!hotdrop); | 444 | } while (!acpar.hotdrop); |
477 | 445 | ||
478 | #ifdef CONFIG_NETFILTER_DEBUG | ||
479 | tb_comefrom = NETFILTER_LINK_POISON; | ||
480 | #endif | ||
481 | xt_info_rdunlock_bh(); | 446 | xt_info_rdunlock_bh(); |
447 | *stackptr = origptr; | ||
482 | 448 | ||
483 | #ifdef DEBUG_ALLOW_ALL | 449 | #ifdef DEBUG_ALLOW_ALL |
484 | return NF_ACCEPT; | 450 | return NF_ACCEPT; |
485 | #else | 451 | #else |
486 | if (hotdrop) | 452 | if (acpar.hotdrop) |
487 | return NF_DROP; | 453 | return NF_DROP; |
488 | else return verdict; | 454 | else return verdict; |
489 | #endif | 455 | #endif |
490 | |||
491 | #undef tb_comefrom | ||
492 | } | 456 | } |
493 | 457 | ||
494 | /* Figures out from what hook each rule can be called: returns 0 if | 458 | /* Figures out from what hook each rule can be called: returns 0 if |
@@ -517,7 +481,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
517 | int visited = e->comefrom & (1 << hook); | 481 | int visited = e->comefrom & (1 << hook); |
518 | 482 | ||
519 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { | 483 | if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { |
520 | printk("iptables: loop hook %u pos %u %08X.\n", | 484 | pr_err("iptables: loop hook %u pos %u %08X.\n", |
521 | hook, pos, e->comefrom); | 485 | hook, pos, e->comefrom); |
522 | return 0; | 486 | return 0; |
523 | } | 487 | } |
@@ -661,12 +625,11 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) | |||
661 | struct xt_match *match; | 625 | struct xt_match *match; |
662 | int ret; | 626 | int ret; |
663 | 627 | ||
664 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, | 628 | match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name, |
665 | m->u.user.revision), | 629 | m->u.user.revision); |
666 | "ip6t_%s", m->u.user.name); | 630 | if (IS_ERR(match)) { |
667 | if (IS_ERR(match) || !match) { | ||
668 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); | 631 | duprintf("find_check_match: `%s' not found\n", m->u.user.name); |
669 | return match ? PTR_ERR(match) : -ENOENT; | 632 | return PTR_ERR(match); |
670 | } | 633 | } |
671 | m->u.kernel.match = match; | 634 | m->u.kernel.match = match; |
672 | 635 | ||
@@ -734,13 +697,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
734 | } | 697 | } |
735 | 698 | ||
736 | t = ip6t_get_target(e); | 699 | t = ip6t_get_target(e); |
737 | target = try_then_request_module(xt_find_target(AF_INET6, | 700 | target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name, |
738 | t->u.user.name, | 701 | t->u.user.revision); |
739 | t->u.user.revision), | 702 | if (IS_ERR(target)) { |
740 | "ip6t_%s", t->u.user.name); | ||
741 | if (IS_ERR(target) || !target) { | ||
742 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); | 703 | duprintf("find_check_entry: `%s' not found\n", t->u.user.name); |
743 | ret = target ? PTR_ERR(target) : -ENOENT; | 704 | ret = PTR_ERR(target); |
744 | goto cleanup_matches; | 705 | goto cleanup_matches; |
745 | } | 706 | } |
746 | t->u.kernel.target = target; | 707 | t->u.kernel.target = target; |
@@ -873,6 +834,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, | |||
873 | if (ret != 0) | 834 | if (ret != 0) |
874 | return ret; | 835 | return ret; |
875 | ++i; | 836 | ++i; |
837 | if (strcmp(ip6t_get_target(iter)->u.user.name, | ||
838 | XT_ERROR_TARGET) == 0) | ||
839 | ++newinfo->stacksize; | ||
876 | } | 840 | } |
877 | 841 | ||
878 | if (i != repl->num_entries) { | 842 | if (i != repl->num_entries) { |
@@ -1509,13 +1473,12 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1509 | { | 1473 | { |
1510 | struct xt_match *match; | 1474 | struct xt_match *match; |
1511 | 1475 | ||
1512 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, | 1476 | match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name, |
1513 | m->u.user.revision), | 1477 | m->u.user.revision); |
1514 | "ip6t_%s", m->u.user.name); | 1478 | if (IS_ERR(match)) { |
1515 | if (IS_ERR(match) || !match) { | ||
1516 | duprintf("compat_check_calc_match: `%s' not found\n", | 1479 | duprintf("compat_check_calc_match: `%s' not found\n", |
1517 | m->u.user.name); | 1480 | m->u.user.name); |
1518 | return match ? PTR_ERR(match) : -ENOENT; | 1481 | return PTR_ERR(match); |
1519 | } | 1482 | } |
1520 | m->u.kernel.match = match; | 1483 | m->u.kernel.match = match; |
1521 | *size += xt_compat_match_offset(match); | 1484 | *size += xt_compat_match_offset(match); |
@@ -1582,14 +1545,12 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1582 | } | 1545 | } |
1583 | 1546 | ||
1584 | t = compat_ip6t_get_target(e); | 1547 | t = compat_ip6t_get_target(e); |
1585 | target = try_then_request_module(xt_find_target(AF_INET6, | 1548 | target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name, |
1586 | t->u.user.name, | 1549 | t->u.user.revision); |
1587 | t->u.user.revision), | 1550 | if (IS_ERR(target)) { |
1588 | "ip6t_%s", t->u.user.name); | ||
1589 | if (IS_ERR(target) || !target) { | ||
1590 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", | 1551 | duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", |
1591 | t->u.user.name); | 1552 | t->u.user.name); |
1592 | ret = target ? PTR_ERR(target) : -ENOENT; | 1553 | ret = PTR_ERR(target); |
1593 | goto release_matches; | 1554 | goto release_matches; |
1594 | } | 1555 | } |
1595 | t->u.kernel.target = target; | 1556 | t->u.kernel.target = target; |
@@ -2127,8 +2088,7 @@ struct xt_table *ip6t_register_table(struct net *net, | |||
2127 | { | 2088 | { |
2128 | int ret; | 2089 | int ret; |
2129 | struct xt_table_info *newinfo; | 2090 | struct xt_table_info *newinfo; |
2130 | struct xt_table_info bootstrap | 2091 | struct xt_table_info bootstrap = {0}; |
2131 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | ||
2132 | void *loc_cpu_entry; | 2092 | void *loc_cpu_entry; |
2133 | struct xt_table *new_table; | 2093 | struct xt_table *new_table; |
2134 | 2094 | ||
@@ -2188,7 +2148,7 @@ icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code, | |||
2188 | } | 2148 | } |
2189 | 2149 | ||
2190 | static bool | 2150 | static bool |
2191 | icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | 2151 | icmp6_match(const struct sk_buff *skb, struct xt_action_param *par) |
2192 | { | 2152 | { |
2193 | const struct icmp6hdr *ic; | 2153 | const struct icmp6hdr *ic; |
2194 | struct icmp6hdr _icmph; | 2154 | struct icmp6hdr _icmph; |
@@ -2204,7 +2164,7 @@ icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2204 | * can't. Hence, no choice but to drop. | 2164 | * can't. Hence, no choice but to drop. |
2205 | */ | 2165 | */ |
2206 | duprintf("Dropping evil ICMP tinygram.\n"); | 2166 | duprintf("Dropping evil ICMP tinygram.\n"); |
2207 | *par->hotdrop = true; | 2167 | par->hotdrop = true; |
2208 | return false; | 2168 | return false; |
2209 | } | 2169 | } |
2210 | 2170 | ||
@@ -2216,31 +2176,32 @@ icmp6_match(const struct sk_buff *skb, const struct xt_match_param *par) | |||
2216 | } | 2176 | } |
2217 | 2177 | ||
2218 | /* Called when user tries to insert an entry of this type. */ | 2178 | /* Called when user tries to insert an entry of this type. */ |
2219 | static bool icmp6_checkentry(const struct xt_mtchk_param *par) | 2179 | static int icmp6_checkentry(const struct xt_mtchk_param *par) |
2220 | { | 2180 | { |
2221 | const struct ip6t_icmp *icmpinfo = par->matchinfo; | 2181 | const struct ip6t_icmp *icmpinfo = par->matchinfo; |
2222 | 2182 | ||
2223 | /* Must specify no unknown invflags */ | 2183 | /* Must specify no unknown invflags */ |
2224 | return !(icmpinfo->invflags & ~IP6T_ICMP_INV); | 2184 | return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0; |
2225 | } | 2185 | } |
2226 | 2186 | ||
2227 | /* The built-in targets: standard (NULL) and error. */ | 2187 | /* The built-in targets: standard (NULL) and error. */ |
2228 | static struct xt_target ip6t_standard_target __read_mostly = { | 2188 | static struct xt_target ip6t_builtin_tg[] __read_mostly = { |
2229 | .name = IP6T_STANDARD_TARGET, | 2189 | { |
2230 | .targetsize = sizeof(int), | 2190 | .name = IP6T_STANDARD_TARGET, |
2231 | .family = NFPROTO_IPV6, | 2191 | .targetsize = sizeof(int), |
2192 | .family = NFPROTO_IPV6, | ||
2232 | #ifdef CONFIG_COMPAT | 2193 | #ifdef CONFIG_COMPAT |
2233 | .compatsize = sizeof(compat_int_t), | 2194 | .compatsize = sizeof(compat_int_t), |
2234 | .compat_from_user = compat_standard_from_user, | 2195 | .compat_from_user = compat_standard_from_user, |
2235 | .compat_to_user = compat_standard_to_user, | 2196 | .compat_to_user = compat_standard_to_user, |
2236 | #endif | 2197 | #endif |
2237 | }; | 2198 | }, |
2238 | 2199 | { | |
2239 | static struct xt_target ip6t_error_target __read_mostly = { | 2200 | .name = IP6T_ERROR_TARGET, |
2240 | .name = IP6T_ERROR_TARGET, | 2201 | .target = ip6t_error, |
2241 | .target = ip6t_error, | 2202 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, |
2242 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, | 2203 | .family = NFPROTO_IPV6, |
2243 | .family = NFPROTO_IPV6, | 2204 | }, |
2244 | }; | 2205 | }; |
2245 | 2206 | ||
2246 | static struct nf_sockopt_ops ip6t_sockopts = { | 2207 | static struct nf_sockopt_ops ip6t_sockopts = { |
@@ -2260,13 +2221,15 @@ static struct nf_sockopt_ops ip6t_sockopts = { | |||
2260 | .owner = THIS_MODULE, | 2221 | .owner = THIS_MODULE, |
2261 | }; | 2222 | }; |
2262 | 2223 | ||
2263 | static struct xt_match icmp6_matchstruct __read_mostly = { | 2224 | static struct xt_match ip6t_builtin_mt[] __read_mostly = { |
2264 | .name = "icmp6", | 2225 | { |
2265 | .match = icmp6_match, | 2226 | .name = "icmp6", |
2266 | .matchsize = sizeof(struct ip6t_icmp), | 2227 | .match = icmp6_match, |
2267 | .checkentry = icmp6_checkentry, | 2228 | .matchsize = sizeof(struct ip6t_icmp), |
2268 | .proto = IPPROTO_ICMPV6, | 2229 | .checkentry = icmp6_checkentry, |
2269 | .family = NFPROTO_IPV6, | 2230 | .proto = IPPROTO_ICMPV6, |
2231 | .family = NFPROTO_IPV6, | ||
2232 | }, | ||
2270 | }; | 2233 | }; |
2271 | 2234 | ||
2272 | static int __net_init ip6_tables_net_init(struct net *net) | 2235 | static int __net_init ip6_tables_net_init(struct net *net) |
@@ -2293,13 +2256,10 @@ static int __init ip6_tables_init(void) | |||
2293 | goto err1; | 2256 | goto err1; |
2294 | 2257 | ||
2295 | /* Noone else will be downing sem now, so we won't sleep */ | 2258 | /* Noone else will be downing sem now, so we won't sleep */ |
2296 | ret = xt_register_target(&ip6t_standard_target); | 2259 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2297 | if (ret < 0) | 2260 | if (ret < 0) |
2298 | goto err2; | 2261 | goto err2; |
2299 | ret = xt_register_target(&ip6t_error_target); | 2262 | ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2300 | if (ret < 0) | ||
2301 | goto err3; | ||
2302 | ret = xt_register_match(&icmp6_matchstruct); | ||
2303 | if (ret < 0) | 2263 | if (ret < 0) |
2304 | goto err4; | 2264 | goto err4; |
2305 | 2265 | ||
@@ -2308,15 +2268,13 @@ static int __init ip6_tables_init(void) | |||
2308 | if (ret < 0) | 2268 | if (ret < 0) |
2309 | goto err5; | 2269 | goto err5; |
2310 | 2270 | ||
2311 | printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); | 2271 | pr_info("(C) 2000-2006 Netfilter Core Team\n"); |
2312 | return 0; | 2272 | return 0; |
2313 | 2273 | ||
2314 | err5: | 2274 | err5: |
2315 | xt_unregister_match(&icmp6_matchstruct); | 2275 | xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2316 | err4: | 2276 | err4: |
2317 | xt_unregister_target(&ip6t_error_target); | 2277 | xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2318 | err3: | ||
2319 | xt_unregister_target(&ip6t_standard_target); | ||
2320 | err2: | 2278 | err2: |
2321 | unregister_pernet_subsys(&ip6_tables_net_ops); | 2279 | unregister_pernet_subsys(&ip6_tables_net_ops); |
2322 | err1: | 2280 | err1: |
@@ -2327,10 +2285,8 @@ static void __exit ip6_tables_fini(void) | |||
2327 | { | 2285 | { |
2328 | nf_unregister_sockopt(&ip6t_sockopts); | 2286 | nf_unregister_sockopt(&ip6t_sockopts); |
2329 | 2287 | ||
2330 | xt_unregister_match(&icmp6_matchstruct); | 2288 | xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt)); |
2331 | xt_unregister_target(&ip6t_error_target); | 2289 | xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2332 | xt_unregister_target(&ip6t_standard_target); | ||
2333 | |||
2334 | unregister_pernet_subsys(&ip6_tables_net_ops); | 2290 | unregister_pernet_subsys(&ip6_tables_net_ops); |
2335 | } | 2291 | } |
2336 | 2292 | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index b285fdf19050..af4ee11f2066 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -9,9 +9,8 @@ | |||
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
16 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
17 | #include <linux/ip.h> | 16 | #include <linux/ip.h> |
@@ -378,7 +377,7 @@ static struct nf_loginfo default_loginfo = { | |||
378 | .type = NF_LOG_TYPE_LOG, | 377 | .type = NF_LOG_TYPE_LOG, |
379 | .u = { | 378 | .u = { |
380 | .log = { | 379 | .log = { |
381 | .level = 0, | 380 | .level = 5, |
382 | .logflags = NF_LOG_MASK, | 381 | .logflags = NF_LOG_MASK, |
383 | }, | 382 | }, |
384 | }, | 383 | }, |
@@ -437,7 +436,7 @@ ip6t_log_packet(u_int8_t pf, | |||
437 | } | 436 | } |
438 | 437 | ||
439 | static unsigned int | 438 | static unsigned int |
440 | log_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 439 | log_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
441 | { | 440 | { |
442 | const struct ip6t_log_info *loginfo = par->targinfo; | 441 | const struct ip6t_log_info *loginfo = par->targinfo; |
443 | struct nf_loginfo li; | 442 | struct nf_loginfo li; |
@@ -452,20 +451,19 @@ log_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
452 | } | 451 | } |
453 | 452 | ||
454 | 453 | ||
455 | static bool log_tg6_check(const struct xt_tgchk_param *par) | 454 | static int log_tg6_check(const struct xt_tgchk_param *par) |
456 | { | 455 | { |
457 | const struct ip6t_log_info *loginfo = par->targinfo; | 456 | const struct ip6t_log_info *loginfo = par->targinfo; |
458 | 457 | ||
459 | if (loginfo->level >= 8) { | 458 | if (loginfo->level >= 8) { |
460 | pr_debug("LOG: level %u >= 8\n", loginfo->level); | 459 | pr_debug("level %u >= 8\n", loginfo->level); |
461 | return false; | 460 | return -EINVAL; |
462 | } | 461 | } |
463 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | 462 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { |
464 | pr_debug("LOG: prefix term %i\n", | 463 | pr_debug("prefix not null-terminated\n"); |
465 | loginfo->prefix[sizeof(loginfo->prefix)-1]); | 464 | return -EINVAL; |
466 | return false; | ||
467 | } | 465 | } |
468 | return true; | 466 | return 0; |
469 | } | 467 | } |
470 | 468 | ||
471 | static struct xt_target log_tg6_reg __read_mostly = { | 469 | static struct xt_target log_tg6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 39b50c3768e8..47d227713758 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * as published by the Free Software Foundation; either version | 14 | * as published by the Free Software Foundation; either version |
15 | * 2 of the License, or (at your option) any later version. | 15 | * 2 of the License, or (at your option) any later version. |
16 | */ | 16 | */ |
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
17 | 18 | ||
18 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -50,7 +51,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
50 | 51 | ||
51 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | 52 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || |
52 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | 53 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { |
53 | pr_debug("ip6t_REJECT: addr is not unicast.\n"); | 54 | pr_debug("addr is not unicast.\n"); |
54 | return; | 55 | return; |
55 | } | 56 | } |
56 | 57 | ||
@@ -58,7 +59,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
58 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | 59 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); |
59 | 60 | ||
60 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 61 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
61 | pr_debug("ip6t_REJECT: Can't get TCP header.\n"); | 62 | pr_debug("Cannot get TCP header.\n"); |
62 | return; | 63 | return; |
63 | } | 64 | } |
64 | 65 | ||
@@ -66,7 +67,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
66 | 67 | ||
67 | /* IP header checks: fragment, too short. */ | 68 | /* IP header checks: fragment, too short. */ |
68 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | 69 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { |
69 | pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, " | 70 | pr_debug("proto(%d) != IPPROTO_TCP, " |
70 | "or too short. otcplen = %d\n", | 71 | "or too short. otcplen = %d\n", |
71 | proto, otcplen); | 72 | proto, otcplen); |
72 | return; | 73 | return; |
@@ -77,14 +78,14 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
77 | 78 | ||
78 | /* No RST for RST. */ | 79 | /* No RST for RST. */ |
79 | if (otcph.rst) { | 80 | if (otcph.rst) { |
80 | pr_debug("ip6t_REJECT: RST is set\n"); | 81 | pr_debug("RST is set\n"); |
81 | return; | 82 | return; |
82 | } | 83 | } |
83 | 84 | ||
84 | /* Check checksum. */ | 85 | /* Check checksum. */ |
85 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, | 86 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, |
86 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { | 87 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { |
87 | pr_debug("ip6t_REJECT: TCP checksum is invalid\n"); | 88 | pr_debug("TCP checksum is invalid\n"); |
88 | return; | 89 | return; |
89 | } | 90 | } |
90 | 91 | ||
@@ -108,7 +109,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
108 | 109 | ||
109 | if (!nskb) { | 110 | if (!nskb) { |
110 | if (net_ratelimit()) | 111 | if (net_ratelimit()) |
111 | printk("ip6t_REJECT: Can't alloc skb\n"); | 112 | pr_debug("cannot alloc skb\n"); |
112 | dst_release(dst); | 113 | dst_release(dst); |
113 | return; | 114 | return; |
114 | } | 115 | } |
@@ -174,15 +175,12 @@ send_unreach(struct net *net, struct sk_buff *skb_in, unsigned char code, | |||
174 | } | 175 | } |
175 | 176 | ||
176 | static unsigned int | 177 | static unsigned int |
177 | reject_tg6(struct sk_buff *skb, const struct xt_target_param *par) | 178 | reject_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
178 | { | 179 | { |
179 | const struct ip6t_reject_info *reject = par->targinfo; | 180 | const struct ip6t_reject_info *reject = par->targinfo; |
180 | struct net *net = dev_net((par->in != NULL) ? par->in : par->out); | 181 | struct net *net = dev_net((par->in != NULL) ? par->in : par->out); |
181 | 182 | ||
182 | pr_debug("%s: medium point\n", __func__); | 183 | pr_debug("%s: medium point\n", __func__); |
183 | /* WARNING: This code causes reentry within ip6tables. | ||
184 | This means that the ip6tables jump stack is now crap. We | ||
185 | must return an absolute verdict. --RR */ | ||
186 | switch (reject->with) { | 184 | switch (reject->with) { |
187 | case IP6T_ICMP6_NO_ROUTE: | 185 | case IP6T_ICMP6_NO_ROUTE: |
188 | send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum); | 186 | send_unreach(net, skb, ICMPV6_NOROUTE, par->hooknum); |
@@ -207,30 +205,30 @@ reject_tg6(struct sk_buff *skb, const struct xt_target_param *par) | |||
207 | break; | 205 | break; |
208 | default: | 206 | default: |
209 | if (net_ratelimit()) | 207 | if (net_ratelimit()) |
210 | printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with); | 208 | pr_info("case %u not handled yet\n", reject->with); |
211 | break; | 209 | break; |
212 | } | 210 | } |
213 | 211 | ||
214 | return NF_DROP; | 212 | return NF_DROP; |
215 | } | 213 | } |
216 | 214 | ||
217 | static bool reject_tg6_check(const struct xt_tgchk_param *par) | 215 | static int reject_tg6_check(const struct xt_tgchk_param *par) |
218 | { | 216 | { |
219 | const struct ip6t_reject_info *rejinfo = par->targinfo; | 217 | const struct ip6t_reject_info *rejinfo = par->targinfo; |
220 | const struct ip6t_entry *e = par->entryinfo; | 218 | const struct ip6t_entry *e = par->entryinfo; |
221 | 219 | ||
222 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { | 220 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { |
223 | printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); | 221 | pr_info("ECHOREPLY is not supported.\n"); |
224 | return false; | 222 | return -EINVAL; |
225 | } else if (rejinfo->with == IP6T_TCP_RESET) { | 223 | } else if (rejinfo->with == IP6T_TCP_RESET) { |
226 | /* Must specify that it's a TCP packet */ | 224 | /* Must specify that it's a TCP packet */ |
227 | if (e->ipv6.proto != IPPROTO_TCP || | 225 | if (e->ipv6.proto != IPPROTO_TCP || |
228 | (e->ipv6.invflags & XT_INV_PROTO)) { | 226 | (e->ipv6.invflags & XT_INV_PROTO)) { |
229 | printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); | 227 | pr_info("TCP_RESET illegal for non-tcp\n"); |
230 | return false; | 228 | return -EINVAL; |
231 | } | 229 | } |
232 | } | 230 | } |
233 | return true; | 231 | return 0; |
234 | } | 232 | } |
235 | 233 | ||
236 | static struct xt_target reject_tg6_reg __read_mostly = { | 234 | static struct xt_target reject_tg6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index ac0b7c629d78..89cccc5a9c92 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
@@ -29,14 +29,14 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert) | |||
29 | { | 29 | { |
30 | bool r; | 30 | bool r; |
31 | 31 | ||
32 | pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x", | 32 | pr_debug("spi_match:%c 0x%x <= 0x%x <= 0x%x\n", |
33 | invert ? '!' : ' ', min, spi, max); | 33 | invert ? '!' : ' ', min, spi, max); |
34 | r = (spi >= min && spi <= max) ^ invert; | 34 | r = (spi >= min && spi <= max) ^ invert; |
35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
36 | return r; | 36 | return r; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 40 | { |
41 | struct ip_auth_hdr _ah; | 41 | struct ip_auth_hdr _ah; |
42 | const struct ip_auth_hdr *ah; | 42 | const struct ip_auth_hdr *ah; |
@@ -48,13 +48,13 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
48 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); | 48 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL); |
49 | if (err < 0) { | 49 | if (err < 0) { |
50 | if (err != -ENOENT) | 50 | if (err != -ENOENT) |
51 | *par->hotdrop = true; | 51 | par->hotdrop = true; |
52 | return false; | 52 | return false; |
53 | } | 53 | } |
54 | 54 | ||
55 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 55 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
56 | if (ah == NULL) { | 56 | if (ah == NULL) { |
57 | *par->hotdrop = true; | 57 | par->hotdrop = true; |
58 | return false; | 58 | return false; |
59 | } | 59 | } |
60 | 60 | ||
@@ -87,15 +87,15 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
87 | !(ahinfo->hdrres && ah->reserved); | 87 | !(ahinfo->hdrres && ah->reserved); |
88 | } | 88 | } |
89 | 89 | ||
90 | static bool ah_mt6_check(const struct xt_mtchk_param *par) | 90 | static int ah_mt6_check(const struct xt_mtchk_param *par) |
91 | { | 91 | { |
92 | const struct ip6t_ah *ahinfo = par->matchinfo; | 92 | const struct ip6t_ah *ahinfo = par->matchinfo; |
93 | 93 | ||
94 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { | 94 | if (ahinfo->invflags & ~IP6T_AH_INV_MASK) { |
95 | pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags); | 95 | pr_debug("unknown flags %X\n", ahinfo->invflags); |
96 | return false; | 96 | return -EINVAL; |
97 | } | 97 | } |
98 | return true; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct xt_match ah_mt6_reg __read_mostly = { | 101 | static struct xt_match ah_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index ca287f6d2bce..aab0706908c5 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -20,14 +20,14 @@ MODULE_LICENSE("GPL"); | |||
20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 20 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
21 | 21 | ||
22 | static bool | 22 | static bool |
23 | eui64_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 23 | eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
24 | { | 24 | { |
25 | unsigned char eui64[8]; | 25 | unsigned char eui64[8]; |
26 | 26 | ||
27 | if (!(skb_mac_header(skb) >= skb->head && | 27 | if (!(skb_mac_header(skb) >= skb->head && |
28 | skb_mac_header(skb) + ETH_HLEN <= skb->data) && | 28 | skb_mac_header(skb) + ETH_HLEN <= skb->data) && |
29 | par->fragoff != 0) { | 29 | par->fragoff != 0) { |
30 | *par->hotdrop = true; | 30 | par->hotdrop = true; |
31 | return false; | 31 | return false; |
32 | } | 32 | } |
33 | 33 | ||
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 7b91c2598ed5..eda898fda6ca 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -27,7 +27,7 @@ static inline bool | |||
27 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | 27 | id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
28 | { | 28 | { |
29 | bool r; | 29 | bool r; |
30 | pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ', | 30 | pr_debug("id_match:%c 0x%x <= 0x%x <= 0x%x\n", invert ? '!' : ' ', |
31 | min, id, max); | 31 | min, id, max); |
32 | r = (id >= min && id <= max) ^ invert; | 32 | r = (id >= min && id <= max) ^ invert; |
33 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 33 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
@@ -35,7 +35,7 @@ id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | static bool | 37 | static bool |
38 | frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 38 | frag_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
39 | { | 39 | { |
40 | struct frag_hdr _frag; | 40 | struct frag_hdr _frag; |
41 | const struct frag_hdr *fh; | 41 | const struct frag_hdr *fh; |
@@ -46,13 +46,13 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
46 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); | 46 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL); |
47 | if (err < 0) { | 47 | if (err < 0) { |
48 | if (err != -ENOENT) | 48 | if (err != -ENOENT) |
49 | *par->hotdrop = true; | 49 | par->hotdrop = true; |
50 | return false; | 50 | return false; |
51 | } | 51 | } |
52 | 52 | ||
53 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 53 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); |
54 | if (fh == NULL) { | 54 | if (fh == NULL) { |
55 | *par->hotdrop = true; | 55 | par->hotdrop = true; |
56 | return false; | 56 | return false; |
57 | } | 57 | } |
58 | 58 | ||
@@ -102,15 +102,15 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
102 | (ntohs(fh->frag_off) & IP6_MF)); | 102 | (ntohs(fh->frag_off) & IP6_MF)); |
103 | } | 103 | } |
104 | 104 | ||
105 | static bool frag_mt6_check(const struct xt_mtchk_param *par) | 105 | static int frag_mt6_check(const struct xt_mtchk_param *par) |
106 | { | 106 | { |
107 | const struct ip6t_frag *fraginfo = par->matchinfo; | 107 | const struct ip6t_frag *fraginfo = par->matchinfo; |
108 | 108 | ||
109 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { | 109 | if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) { |
110 | pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags); | 110 | pr_debug("unknown flags %X\n", fraginfo->invflags); |
111 | return false; | 111 | return -EINVAL; |
112 | } | 112 | } |
113 | return true; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static struct xt_match frag_mt6_reg __read_mostly = { | 116 | static struct xt_match frag_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index cbe8dec9744b..59df051eaef6 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -41,8 +41,10 @@ MODULE_ALIAS("ip6t_dst"); | |||
41 | * 5 -> RTALERT 2 x x | 41 | * 5 -> RTALERT 2 x x |
42 | */ | 42 | */ |
43 | 43 | ||
44 | static struct xt_match hbh_mt6_reg[] __read_mostly; | ||
45 | |||
44 | static bool | 46 | static bool |
45 | hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 47 | hbh_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
46 | { | 48 | { |
47 | struct ipv6_opt_hdr _optsh; | 49 | struct ipv6_opt_hdr _optsh; |
48 | const struct ipv6_opt_hdr *oh; | 50 | const struct ipv6_opt_hdr *oh; |
@@ -58,16 +60,18 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
58 | unsigned int optlen; | 60 | unsigned int optlen; |
59 | int err; | 61 | int err; |
60 | 62 | ||
61 | err = ipv6_find_hdr(skb, &ptr, par->match->data, NULL); | 63 | err = ipv6_find_hdr(skb, &ptr, |
64 | (par->match == &hbh_mt6_reg[0]) ? | ||
65 | NEXTHDR_HOP : NEXTHDR_DEST, NULL); | ||
62 | if (err < 0) { | 66 | if (err < 0) { |
63 | if (err != -ENOENT) | 67 | if (err != -ENOENT) |
64 | *par->hotdrop = true; | 68 | par->hotdrop = true; |
65 | return false; | 69 | return false; |
66 | } | 70 | } |
67 | 71 | ||
68 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | 72 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
69 | if (oh == NULL) { | 73 | if (oh == NULL) { |
70 | *par->hotdrop = true; | 74 | par->hotdrop = true; |
71 | return false; | 75 | return false; |
72 | } | 76 | } |
73 | 77 | ||
@@ -141,11 +145,11 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
141 | } | 145 | } |
142 | 146 | ||
143 | /* Step to the next */ | 147 | /* Step to the next */ |
144 | pr_debug("len%04X \n", optlen); | 148 | pr_debug("len%04X\n", optlen); |
145 | 149 | ||
146 | if ((ptr > skb->len - optlen || hdrlen < optlen) && | 150 | if ((ptr > skb->len - optlen || hdrlen < optlen) && |
147 | temp < optinfo->optsnr - 1) { | 151 | temp < optinfo->optsnr - 1) { |
148 | pr_debug("new pointer is too large! \n"); | 152 | pr_debug("new pointer is too large!\n"); |
149 | break; | 153 | break; |
150 | } | 154 | } |
151 | ptr += optlen; | 155 | ptr += optlen; |
@@ -160,32 +164,32 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
160 | return false; | 164 | return false; |
161 | } | 165 | } |
162 | 166 | ||
163 | static bool hbh_mt6_check(const struct xt_mtchk_param *par) | 167 | static int hbh_mt6_check(const struct xt_mtchk_param *par) |
164 | { | 168 | { |
165 | const struct ip6t_opts *optsinfo = par->matchinfo; | 169 | const struct ip6t_opts *optsinfo = par->matchinfo; |
166 | 170 | ||
167 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { | 171 | if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { |
168 | pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); | 172 | pr_debug("unknown flags %X\n", optsinfo->invflags); |
169 | return false; | 173 | return -EINVAL; |
170 | } | 174 | } |
171 | 175 | ||
172 | if (optsinfo->flags & IP6T_OPTS_NSTRICT) { | 176 | if (optsinfo->flags & IP6T_OPTS_NSTRICT) { |
173 | pr_debug("ip6t_opts: Not strict - not implemented"); | 177 | pr_debug("Not strict - not implemented"); |
174 | return false; | 178 | return -EINVAL; |
175 | } | 179 | } |
176 | 180 | ||
177 | return true; | 181 | return 0; |
178 | } | 182 | } |
179 | 183 | ||
180 | static struct xt_match hbh_mt6_reg[] __read_mostly = { | 184 | static struct xt_match hbh_mt6_reg[] __read_mostly = { |
181 | { | 185 | { |
186 | /* Note, hbh_mt6 relies on the order of hbh_mt6_reg */ | ||
182 | .name = "hbh", | 187 | .name = "hbh", |
183 | .family = NFPROTO_IPV6, | 188 | .family = NFPROTO_IPV6, |
184 | .match = hbh_mt6, | 189 | .match = hbh_mt6, |
185 | .matchsize = sizeof(struct ip6t_opts), | 190 | .matchsize = sizeof(struct ip6t_opts), |
186 | .checkentry = hbh_mt6_check, | 191 | .checkentry = hbh_mt6_check, |
187 | .me = THIS_MODULE, | 192 | .me = THIS_MODULE, |
188 | .data = NEXTHDR_HOP, | ||
189 | }, | 193 | }, |
190 | { | 194 | { |
191 | .name = "dst", | 195 | .name = "dst", |
@@ -194,7 +198,6 @@ static struct xt_match hbh_mt6_reg[] __read_mostly = { | |||
194 | .matchsize = sizeof(struct ip6t_opts), | 198 | .matchsize = sizeof(struct ip6t_opts), |
195 | .checkentry = hbh_mt6_check, | 199 | .checkentry = hbh_mt6_check, |
196 | .me = THIS_MODULE, | 200 | .me = THIS_MODULE, |
197 | .data = NEXTHDR_DEST, | ||
198 | }, | 201 | }, |
199 | }; | 202 | }; |
200 | 203 | ||
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 91490ad9302c..54bd9790603f 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -27,7 +27,7 @@ MODULE_DESCRIPTION("Xtables: IPv6 header types match"); | |||
27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); | 27 | MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); |
28 | 28 | ||
29 | static bool | 29 | static bool |
30 | ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 30 | ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
31 | { | 31 | { |
32 | const struct ip6t_ipv6header_info *info = par->matchinfo; | 32 | const struct ip6t_ipv6header_info *info = par->matchinfo; |
33 | unsigned int temp; | 33 | unsigned int temp; |
@@ -118,16 +118,16 @@ ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | static bool ipv6header_mt6_check(const struct xt_mtchk_param *par) | 121 | static int ipv6header_mt6_check(const struct xt_mtchk_param *par) |
122 | { | 122 | { |
123 | const struct ip6t_ipv6header_info *info = par->matchinfo; | 123 | const struct ip6t_ipv6header_info *info = par->matchinfo; |
124 | 124 | ||
125 | /* invflags is 0 or 0xff in hard mode */ | 125 | /* invflags is 0 or 0xff in hard mode */ |
126 | if ((!info->modeflag) && info->invflags != 0x00 && | 126 | if ((!info->modeflag) && info->invflags != 0x00 && |
127 | info->invflags != 0xFF) | 127 | info->invflags != 0xFF) |
128 | return false; | 128 | return -EINVAL; |
129 | 129 | ||
130 | return true; | 130 | return 0; |
131 | } | 131 | } |
132 | 132 | ||
133 | static struct xt_match ipv6header_mt6_reg __read_mostly = { | 133 | static struct xt_match ipv6header_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c index aafe4e66577b..0c90c66b1992 100644 --- a/net/ipv6/netfilter/ip6t_mh.c +++ b/net/ipv6/netfilter/ip6t_mh.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Based on net/netfilter/xt_tcpudp.c | 11 | * Based on net/netfilter/xt_tcpudp.c |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
@@ -24,12 +25,6 @@ | |||
24 | MODULE_DESCRIPTION("Xtables: IPv6 Mobility Header match"); | 25 | MODULE_DESCRIPTION("Xtables: IPv6 Mobility Header match"); |
25 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
26 | 27 | ||
27 | #ifdef DEBUG_IP_FIREWALL_USER | ||
28 | #define duprintf(format, args...) printk(format , ## args) | ||
29 | #else | ||
30 | #define duprintf(format, args...) | ||
31 | #endif | ||
32 | |||
33 | /* Returns 1 if the type is matched by the range, 0 otherwise */ | 28 | /* Returns 1 if the type is matched by the range, 0 otherwise */ |
34 | static inline bool | 29 | static inline bool |
35 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) | 30 | type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) |
@@ -37,7 +32,7 @@ type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert) | |||
37 | return (type >= min && type <= max) ^ invert; | 32 | return (type >= min && type <= max) ^ invert; |
38 | } | 33 | } |
39 | 34 | ||
40 | static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 35 | static bool mh_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
41 | { | 36 | { |
42 | struct ip6_mh _mh; | 37 | struct ip6_mh _mh; |
43 | const struct ip6_mh *mh; | 38 | const struct ip6_mh *mh; |
@@ -51,15 +46,15 @@ static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
51 | if (mh == NULL) { | 46 | if (mh == NULL) { |
52 | /* We've been asked to examine this packet, and we | 47 | /* We've been asked to examine this packet, and we |
53 | can't. Hence, no choice but to drop. */ | 48 | can't. Hence, no choice but to drop. */ |
54 | duprintf("Dropping evil MH tinygram.\n"); | 49 | pr_debug("Dropping evil MH tinygram.\n"); |
55 | *par->hotdrop = true; | 50 | par->hotdrop = true; |
56 | return false; | 51 | return false; |
57 | } | 52 | } |
58 | 53 | ||
59 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 54 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
60 | duprintf("Dropping invalid MH Payload Proto: %u\n", | 55 | pr_debug("Dropping invalid MH Payload Proto: %u\n", |
61 | mh->ip6mh_proto); | 56 | mh->ip6mh_proto); |
62 | *par->hotdrop = true; | 57 | par->hotdrop = true; |
63 | return false; | 58 | return false; |
64 | } | 59 | } |
65 | 60 | ||
@@ -67,12 +62,12 @@ static bool mh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
67 | !!(mhinfo->invflags & IP6T_MH_INV_TYPE)); | 62 | !!(mhinfo->invflags & IP6T_MH_INV_TYPE)); |
68 | } | 63 | } |
69 | 64 | ||
70 | static bool mh_mt6_check(const struct xt_mtchk_param *par) | 65 | static int mh_mt6_check(const struct xt_mtchk_param *par) |
71 | { | 66 | { |
72 | const struct ip6t_mh *mhinfo = par->matchinfo; | 67 | const struct ip6t_mh *mhinfo = par->matchinfo; |
73 | 68 | ||
74 | /* Must specify no unknown invflags */ | 69 | /* Must specify no unknown invflags */ |
75 | return !(mhinfo->invflags & ~IP6T_MH_INV_MASK); | 70 | return (mhinfo->invflags & ~IP6T_MH_INV_MASK) ? -EINVAL : 0; |
76 | } | 71 | } |
77 | 72 | ||
78 | static struct xt_match mh_mt6_reg __read_mostly = { | 73 | static struct xt_match mh_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index b77307fc8743..d8488c50a8e0 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/ipv6.h> | 12 | #include <linux/ipv6.h> |
@@ -29,14 +29,14 @@ static inline bool | |||
29 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) | 29 | segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert) |
30 | { | 30 | { |
31 | bool r; | 31 | bool r; |
32 | pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x", | 32 | pr_debug("segsleft_match:%c 0x%x <= 0x%x <= 0x%x\n", |
33 | invert ? '!' : ' ', min, id, max); | 33 | invert ? '!' : ' ', min, id, max); |
34 | r = (id >= min && id <= max) ^ invert; | 34 | r = (id >= min && id <= max) ^ invert; |
35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); | 35 | pr_debug(" result %s\n", r ? "PASS" : "FAILED"); |
36 | return r; | 36 | return r; |
37 | } | 37 | } |
38 | 38 | ||
39 | static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | 39 | static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
40 | { | 40 | { |
41 | struct ipv6_rt_hdr _route; | 41 | struct ipv6_rt_hdr _route; |
42 | const struct ipv6_rt_hdr *rh; | 42 | const struct ipv6_rt_hdr *rh; |
@@ -52,13 +52,13 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
52 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); | 52 | err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL); |
53 | if (err < 0) { | 53 | if (err < 0) { |
54 | if (err != -ENOENT) | 54 | if (err != -ENOENT) |
55 | *par->hotdrop = true; | 55 | par->hotdrop = true; |
56 | return false; | 56 | return false; |
57 | } | 57 | } |
58 | 58 | ||
59 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | 59 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
60 | if (rh == NULL) { | 60 | if (rh == NULL) { |
61 | *par->hotdrop = true; | 61 | par->hotdrop = true; |
62 | return false; | 62 | return false; |
63 | } | 63 | } |
64 | 64 | ||
@@ -183,23 +183,23 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
183 | return false; | 183 | return false; |
184 | } | 184 | } |
185 | 185 | ||
186 | static bool rt_mt6_check(const struct xt_mtchk_param *par) | 186 | static int rt_mt6_check(const struct xt_mtchk_param *par) |
187 | { | 187 | { |
188 | const struct ip6t_rt *rtinfo = par->matchinfo; | 188 | const struct ip6t_rt *rtinfo = par->matchinfo; |
189 | 189 | ||
190 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { | 190 | if (rtinfo->invflags & ~IP6T_RT_INV_MASK) { |
191 | pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags); | 191 | pr_debug("unknown flags %X\n", rtinfo->invflags); |
192 | return false; | 192 | return -EINVAL; |
193 | } | 193 | } |
194 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && | 194 | if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && |
195 | (!(rtinfo->flags & IP6T_RT_TYP) || | 195 | (!(rtinfo->flags & IP6T_RT_TYP) || |
196 | (rtinfo->rt_type != 0) || | 196 | (rtinfo->rt_type != 0) || |
197 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { | 197 | (rtinfo->invflags & IP6T_RT_INV_TYP))) { |
198 | pr_debug("`--rt-type 0' required before `--rt-0-*'"); | 198 | pr_debug("`--rt-type 0' required before `--rt-0-*'"); |
199 | return false; | 199 | return -EINVAL; |
200 | } | 200 | } |
201 | 201 | ||
202 | return true; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | static struct xt_match rt_mt6_reg __read_mostly = { | 205 | static struct xt_match rt_mt6_reg __read_mostly = { |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index d6fc9aff3163..c9e37c8fd62c 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -81,7 +81,7 @@ static int __init ip6table_filter_init(void) | |||
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | if (forward < 0 || forward > NF_MAX_VERDICT) { | 83 | if (forward < 0 || forward > NF_MAX_VERDICT) { |
84 | printk("iptables forward must be 0 or 1\n"); | 84 | pr_err("iptables forward must be 0 or 1\n"); |
85 | return -EINVAL; | 85 | return -EINVAL; |
86 | } | 86 | } |
87 | 87 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 6a102b57f356..679a0a3b7b3c 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -43,7 +43,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) | |||
43 | if (skb->len < sizeof(struct iphdr) || | 43 | if (skb->len < sizeof(struct iphdr) || |
44 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | 44 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
45 | if (net_ratelimit()) | 45 | if (net_ratelimit()) |
46 | printk("ip6t_hook: happy cracking.\n"); | 46 | pr_warning("ip6t_hook: happy cracking.\n"); |
47 | return NF_ACCEPT; | 47 | return NF_ACCEPT; |
48 | } | 48 | } |
49 | #endif | 49 | #endif |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 996c3f41fecd..ff43461704be 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -280,7 +280,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, | |||
280 | /* root is playing with raw sockets. */ | 280 | /* root is playing with raw sockets. */ |
281 | if (skb->len < sizeof(struct ipv6hdr)) { | 281 | if (skb->len < sizeof(struct ipv6hdr)) { |
282 | if (net_ratelimit()) | 282 | if (net_ratelimit()) |
283 | printk("ipv6_conntrack_local: packet too short\n"); | 283 | pr_notice("ipv6_conntrack_local: packet too short\n"); |
284 | return NF_ACCEPT; | 284 | return NF_ACCEPT; |
285 | } | 285 | } |
286 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn); | 286 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn); |
@@ -406,37 +406,37 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
406 | 406 | ||
407 | ret = nf_ct_frag6_init(); | 407 | ret = nf_ct_frag6_init(); |
408 | if (ret < 0) { | 408 | if (ret < 0) { |
409 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); | 409 | pr_err("nf_conntrack_ipv6: can't initialize frag6.\n"); |
410 | return ret; | 410 | return ret; |
411 | } | 411 | } |
412 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); | 412 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); |
413 | if (ret < 0) { | 413 | if (ret < 0) { |
414 | printk("nf_conntrack_ipv6: can't register tcp.\n"); | 414 | pr_err("nf_conntrack_ipv6: can't register tcp.\n"); |
415 | goto cleanup_frag6; | 415 | goto cleanup_frag6; |
416 | } | 416 | } |
417 | 417 | ||
418 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); | 418 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); |
419 | if (ret < 0) { | 419 | if (ret < 0) { |
420 | printk("nf_conntrack_ipv6: can't register udp.\n"); | 420 | pr_err("nf_conntrack_ipv6: can't register udp.\n"); |
421 | goto cleanup_tcp; | 421 | goto cleanup_tcp; |
422 | } | 422 | } |
423 | 423 | ||
424 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); | 424 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); |
425 | if (ret < 0) { | 425 | if (ret < 0) { |
426 | printk("nf_conntrack_ipv6: can't register icmpv6.\n"); | 426 | pr_err("nf_conntrack_ipv6: can't register icmpv6.\n"); |
427 | goto cleanup_udp; | 427 | goto cleanup_udp; |
428 | } | 428 | } |
429 | 429 | ||
430 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6); | 430 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv6); |
431 | if (ret < 0) { | 431 | if (ret < 0) { |
432 | printk("nf_conntrack_ipv6: can't register ipv6\n"); | 432 | pr_err("nf_conntrack_ipv6: can't register ipv6\n"); |
433 | goto cleanup_icmpv6; | 433 | goto cleanup_icmpv6; |
434 | } | 434 | } |
435 | 435 | ||
436 | ret = nf_register_hooks(ipv6_conntrack_ops, | 436 | ret = nf_register_hooks(ipv6_conntrack_ops, |
437 | ARRAY_SIZE(ipv6_conntrack_ops)); | 437 | ARRAY_SIZE(ipv6_conntrack_ops)); |
438 | if (ret < 0) { | 438 | if (ret < 0) { |
439 | printk("nf_conntrack_ipv6: can't register pre-routing defrag " | 439 | pr_err("nf_conntrack_ipv6: can't register pre-routing defrag " |
440 | "hook.\n"); | 440 | "hook.\n"); |
441 | goto cleanup_ipv6; | 441 | goto cleanup_ipv6; |
442 | } | 442 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index dd5b9bd61c62..6fb890187de0 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -644,7 +644,7 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
644 | s2 = s->next; | 644 | s2 = s->next; |
645 | s->next = NULL; | 645 | s->next = NULL; |
646 | 646 | ||
647 | NF_HOOK_THRESH(PF_INET6, hooknum, s, in, out, okfn, | 647 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, in, out, okfn, |
648 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | 648 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); |
649 | s = s2; | 649 | s = s2; |
650 | } | 650 | } |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 58344c0fbd13..566798d69f37 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -97,6 +97,7 @@ static const struct snmp_mib snmp6_icmp6_list[] = { | |||
97 | SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), | 97 | SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS), |
98 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), | 98 | SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS), |
99 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), | 99 | SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS), |
100 | SNMP_MIB_ITEM("Icmp6OutErrors", ICMP6_MIB_OUTERRORS), | ||
100 | SNMP_MIB_SENTINEL | 101 | SNMP_MIB_SENTINEL |
101 | }; | 102 | }; |
102 | 103 | ||
@@ -167,7 +168,6 @@ static void snmp6_seq_show_icmpv6msg(struct seq_file *seq, void __percpu **mib) | |||
167 | i & 0x100 ? "Out" : "In", i & 0xff); | 168 | i & 0x100 ? "Out" : "In", i & 0xff); |
168 | seq_printf(seq, "%-32s\t%lu\n", name, val); | 169 | seq_printf(seq, "%-32s\t%lu\n", name, val); |
169 | } | 170 | } |
170 | return; | ||
171 | } | 171 | } |
172 | 172 | ||
173 | static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, | 173 | static void snmp6_seq_show_item(struct seq_file *seq, void __percpu **mib, |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8763b1a0814a..4a4dcbe4f8b2 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -381,7 +381,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* Charge it to the socket. */ | 383 | /* Charge it to the socket. */ |
384 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 384 | if (ip_queue_rcv_skb(sk, skb) < 0) { |
385 | kfree_skb(skb); | 385 | kfree_skb(skb); |
386 | return NET_RX_DROP; | 386 | return NET_RX_DROP; |
387 | } | 387 | } |
@@ -461,6 +461,9 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
461 | if (flags & MSG_ERRQUEUE) | 461 | if (flags & MSG_ERRQUEUE) |
462 | return ipv6_recv_error(sk, msg, len); | 462 | return ipv6_recv_error(sk, msg, len); |
463 | 463 | ||
464 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
465 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
466 | |||
464 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 467 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
465 | if (!skb) | 468 | if (!skb) |
466 | goto out; | 469 | goto out; |
@@ -637,8 +640,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
637 | goto error_fault; | 640 | goto error_fault; |
638 | 641 | ||
639 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); | 642 | IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len); |
640 | err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 643 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, |
641 | dst_output); | 644 | rt->u.dst.dev, dst_output); |
642 | if (err > 0) | 645 | if (err > 0) |
643 | err = net_xmit_errno(err); | 646 | err = net_xmit_errno(err); |
644 | if (err) | 647 | if (err) |
@@ -733,6 +736,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
733 | int addr_len = msg->msg_namelen; | 736 | int addr_len = msg->msg_namelen; |
734 | int hlimit = -1; | 737 | int hlimit = -1; |
735 | int tclass = -1; | 738 | int tclass = -1; |
739 | int dontfrag = -1; | ||
736 | u16 proto; | 740 | u16 proto; |
737 | int err; | 741 | int err; |
738 | 742 | ||
@@ -811,7 +815,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
811 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 815 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
812 | opt->tot_len = sizeof(struct ipv6_txoptions); | 816 | opt->tot_len = sizeof(struct ipv6_txoptions); |
813 | 817 | ||
814 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 818 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
819 | &tclass, &dontfrag); | ||
815 | if (err < 0) { | 820 | if (err < 0) { |
816 | fl6_sock_release(flowlabel); | 821 | fl6_sock_release(flowlabel); |
817 | return err; | 822 | return err; |
@@ -880,6 +885,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
880 | if (tclass < 0) | 885 | if (tclass < 0) |
881 | tclass = np->tclass; | 886 | tclass = np->tclass; |
882 | 887 | ||
888 | if (dontfrag < 0) | ||
889 | dontfrag = np->dontfrag; | ||
890 | |||
883 | if (msg->msg_flags&MSG_CONFIRM) | 891 | if (msg->msg_flags&MSG_CONFIRM) |
884 | goto do_confirm; | 892 | goto do_confirm; |
885 | 893 | ||
@@ -890,7 +898,7 @@ back_from_confirm: | |||
890 | lock_sock(sk); | 898 | lock_sock(sk); |
891 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 899 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
892 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, | 900 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
893 | msg->msg_flags); | 901 | msg->msg_flags, dontfrag); |
894 | 902 | ||
895 | if (err) | 903 | if (err) |
896 | ip6_flush_pending_frames(sk); | 904 | ip6_flush_pending_frames(sk); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c2438e8cb9d0..294cbe8b0725 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -316,7 +316,6 @@ static void rt6_probe(struct rt6_info *rt) | |||
316 | #else | 316 | #else |
317 | static inline void rt6_probe(struct rt6_info *rt) | 317 | static inline void rt6_probe(struct rt6_info *rt) |
318 | { | 318 | { |
319 | return; | ||
320 | } | 319 | } |
321 | #endif | 320 | #endif |
322 | 321 | ||
@@ -815,7 +814,7 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
815 | { | 814 | { |
816 | int flags = 0; | 815 | int flags = 0; |
817 | 816 | ||
818 | if (rt6_need_strict(&fl->fl6_dst)) | 817 | if (fl->oif || rt6_need_strict(&fl->fl6_dst)) |
819 | flags |= RT6_LOOKUP_F_IFACE; | 818 | flags |= RT6_LOOKUP_F_IFACE; |
820 | 819 | ||
821 | if (!ipv6_addr_any(&fl->fl6_src)) | 820 | if (!ipv6_addr_any(&fl->fl6_src)) |
@@ -1553,7 +1552,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1553 | 1552 | ||
1554 | out: | 1553 | out: |
1555 | dst_release(&rt->u.dst); | 1554 | dst_release(&rt->u.dst); |
1556 | return; | ||
1557 | } | 1555 | } |
1558 | 1556 | ||
1559 | /* | 1557 | /* |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 5abae10cd884..e51e650ea80b 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -566,11 +566,9 @@ static int ipip6_rcv(struct sk_buff *skb) | |||
566 | kfree_skb(skb); | 566 | kfree_skb(skb); |
567 | return 0; | 567 | return 0; |
568 | } | 568 | } |
569 | tunnel->dev->stats.rx_packets++; | 569 | |
570 | tunnel->dev->stats.rx_bytes += skb->len; | 570 | skb_tunnel_rx(skb, tunnel->dev); |
571 | skb->dev = tunnel->dev; | 571 | |
572 | skb_dst_drop(skb); | ||
573 | nf_reset(skb); | ||
574 | ipip6_ecn_decapsulate(iph, skb); | 572 | ipip6_ecn_decapsulate(iph, skb); |
575 | netif_rx(skb); | 573 | netif_rx(skb); |
576 | rcu_read_unlock(); | 574 | rcu_read_unlock(); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c92ebe8f80d5..2b7c3a100e2c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -75,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
75 | struct request_sock *req); | 75 | struct request_sock *req); |
76 | 76 | ||
77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
78 | static void __tcp_v6_send_check(struct sk_buff *skb, | ||
79 | struct in6_addr *saddr, | ||
80 | struct in6_addr *daddr); | ||
78 | 81 | ||
79 | static const struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static const struct inet_connection_sock_af_ops ipv6_mapped; |
80 | static const struct inet_connection_sock_af_ops ipv6_specific; | 83 | static const struct inet_connection_sock_af_ops ipv6_specific; |
@@ -350,6 +353,11 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
350 | if (sk->sk_state == TCP_CLOSE) | 353 | if (sk->sk_state == TCP_CLOSE) |
351 | goto out; | 354 | goto out; |
352 | 355 | ||
356 | if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
357 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
358 | goto out; | ||
359 | } | ||
360 | |||
353 | tp = tcp_sk(sk); | 361 | tp = tcp_sk(sk); |
354 | seq = ntohl(th->seq); | 362 | seq = ntohl(th->seq); |
355 | if (sk->sk_state != TCP_LISTEN && | 363 | if (sk->sk_state != TCP_LISTEN && |
@@ -503,14 +511,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
503 | 511 | ||
504 | skb = tcp_make_synack(sk, dst, req, rvp); | 512 | skb = tcp_make_synack(sk, dst, req, rvp); |
505 | if (skb) { | 513 | if (skb) { |
506 | struct tcphdr *th = tcp_hdr(skb); | 514 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
507 | |||
508 | th->check = tcp_v6_check(skb->len, | ||
509 | &treq->loc_addr, &treq->rmt_addr, | ||
510 | csum_partial(th, skb->len, skb->csum)); | ||
511 | 515 | ||
512 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 516 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
513 | err = ip6_xmit(sk, skb, &fl, opt, 0); | 517 | err = ip6_xmit(sk, skb, &fl, opt); |
514 | err = net_xmit_eval(err); | 518 | err = net_xmit_eval(err); |
515 | } | 519 | } |
516 | 520 | ||
@@ -600,7 +604,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | |||
600 | kfree(newkey); | 604 | kfree(newkey); |
601 | return -ENOMEM; | 605 | return -ENOMEM; |
602 | } | 606 | } |
603 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 607 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
604 | } | 608 | } |
605 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 609 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
606 | kfree(newkey); | 610 | kfree(newkey); |
@@ -737,7 +741,7 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
737 | return -ENOMEM; | 741 | return -ENOMEM; |
738 | 742 | ||
739 | tp->md5sig_info = p; | 743 | tp->md5sig_info = p; |
740 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 744 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
741 | } | 745 | } |
742 | 746 | ||
743 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | 747 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); |
@@ -918,22 +922,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { | |||
918 | .twsk_destructor= tcp_twsk_destructor, | 922 | .twsk_destructor= tcp_twsk_destructor, |
919 | }; | 923 | }; |
920 | 924 | ||
921 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) | 925 | static void __tcp_v6_send_check(struct sk_buff *skb, |
926 | struct in6_addr *saddr, struct in6_addr *daddr) | ||
922 | { | 927 | { |
923 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
924 | struct tcphdr *th = tcp_hdr(skb); | 928 | struct tcphdr *th = tcp_hdr(skb); |
925 | 929 | ||
926 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 930 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
927 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); | 931 | th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); |
928 | skb->csum_start = skb_transport_header(skb) - skb->head; | 932 | skb->csum_start = skb_transport_header(skb) - skb->head; |
929 | skb->csum_offset = offsetof(struct tcphdr, check); | 933 | skb->csum_offset = offsetof(struct tcphdr, check); |
930 | } else { | 934 | } else { |
931 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, | 935 | th->check = tcp_v6_check(skb->len, saddr, daddr, |
932 | csum_partial(th, th->doff<<2, | 936 | csum_partial(th, th->doff << 2, |
933 | skb->csum)); | 937 | skb->csum)); |
934 | } | 938 | } |
935 | } | 939 | } |
936 | 940 | ||
941 | static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) | ||
942 | { | ||
943 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
944 | |||
945 | __tcp_v6_send_check(skb, &np->saddr, &np->daddr); | ||
946 | } | ||
947 | |||
937 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | 948 | static int tcp_v6_gso_send_check(struct sk_buff *skb) |
938 | { | 949 | { |
939 | struct ipv6hdr *ipv6h; | 950 | struct ipv6hdr *ipv6h; |
@@ -946,11 +957,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
946 | th = tcp_hdr(skb); | 957 | th = tcp_hdr(skb); |
947 | 958 | ||
948 | th->check = 0; | 959 | th->check = 0; |
949 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, | ||
950 | IPPROTO_TCP, 0); | ||
951 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
952 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
953 | skb->ip_summed = CHECKSUM_PARTIAL; | 960 | skb->ip_summed = CHECKSUM_PARTIAL; |
961 | __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr); | ||
954 | return 0; | 962 | return 0; |
955 | } | 963 | } |
956 | 964 | ||
@@ -1015,7 +1023,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1015 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); | 1023 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
1016 | 1024 | ||
1017 | t1 = (struct tcphdr *) skb_push(buff, tot_len); | 1025 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
1018 | skb_reset_transport_header(skb); | 1026 | skb_reset_transport_header(buff); |
1019 | 1027 | ||
1020 | /* Swap the send and the receive. */ | 1028 | /* Swap the send and the receive. */ |
1021 | memset(t1, 0, sizeof(*t1)); | 1029 | memset(t1, 0, sizeof(*t1)); |
@@ -1047,15 +1055,14 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1047 | } | 1055 | } |
1048 | #endif | 1056 | #endif |
1049 | 1057 | ||
1050 | buff->csum = csum_partial(t1, tot_len, 0); | ||
1051 | |||
1052 | memset(&fl, 0, sizeof(fl)); | 1058 | memset(&fl, 0, sizeof(fl)); |
1053 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); | 1059 | ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr); |
1054 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); | 1060 | ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr); |
1055 | 1061 | ||
1056 | t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst, | 1062 | buff->ip_summed = CHECKSUM_PARTIAL; |
1057 | tot_len, IPPROTO_TCP, | 1063 | buff->csum = 0; |
1058 | buff->csum); | 1064 | |
1065 | __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst); | ||
1059 | 1066 | ||
1060 | fl.proto = IPPROTO_TCP; | 1067 | fl.proto = IPPROTO_TCP; |
1061 | fl.oif = inet6_iif(skb); | 1068 | fl.oif = inet6_iif(skb); |
@@ -1070,7 +1077,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
1070 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { | 1077 | if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) { |
1071 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { | 1078 | if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) { |
1072 | skb_dst_set(buff, dst); | 1079 | skb_dst_set(buff, dst); |
1073 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | 1080 | ip6_xmit(ctl_sk, buff, &fl, NULL); |
1074 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1081 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1075 | if (rst) | 1082 | if (rst) |
1076 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1083 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
@@ -1233,12 +1240,12 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1233 | goto drop_and_free; | 1240 | goto drop_and_free; |
1234 | 1241 | ||
1235 | /* Secret recipe starts with IP addresses */ | 1242 | /* Secret recipe starts with IP addresses */ |
1236 | d = &ipv6_hdr(skb)->daddr.s6_addr32[0]; | 1243 | d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0]; |
1237 | *mess++ ^= *d++; | 1244 | *mess++ ^= *d++; |
1238 | *mess++ ^= *d++; | 1245 | *mess++ ^= *d++; |
1239 | *mess++ ^= *d++; | 1246 | *mess++ ^= *d++; |
1240 | *mess++ ^= *d++; | 1247 | *mess++ ^= *d++; |
1241 | d = &ipv6_hdr(skb)->saddr.s6_addr32[0]; | 1248 | d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0]; |
1242 | *mess++ ^= *d++; | 1249 | *mess++ ^= *d++; |
1243 | *mess++ ^= *d++; | 1250 | *mess++ ^= *d++; |
1244 | *mess++ ^= *d++; | 1251 | *mess++ ^= *d++; |
@@ -1676,6 +1683,7 @@ ipv6_pktoptions: | |||
1676 | static int tcp_v6_rcv(struct sk_buff *skb) | 1683 | static int tcp_v6_rcv(struct sk_buff *skb) |
1677 | { | 1684 | { |
1678 | struct tcphdr *th; | 1685 | struct tcphdr *th; |
1686 | struct ipv6hdr *hdr; | ||
1679 | struct sock *sk; | 1687 | struct sock *sk; |
1680 | int ret; | 1688 | int ret; |
1681 | struct net *net = dev_net(skb->dev); | 1689 | struct net *net = dev_net(skb->dev); |
@@ -1702,12 +1710,13 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1702 | goto bad_packet; | 1710 | goto bad_packet; |
1703 | 1711 | ||
1704 | th = tcp_hdr(skb); | 1712 | th = tcp_hdr(skb); |
1713 | hdr = ipv6_hdr(skb); | ||
1705 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | 1714 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); |
1706 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | 1715 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + |
1707 | skb->len - th->doff*4); | 1716 | skb->len - th->doff*4); |
1708 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1717 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
1709 | TCP_SKB_CB(skb)->when = 0; | 1718 | TCP_SKB_CB(skb)->when = 0; |
1710 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1719 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr); |
1711 | TCP_SKB_CB(skb)->sacked = 0; | 1720 | TCP_SKB_CB(skb)->sacked = 0; |
1712 | 1721 | ||
1713 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); | 1722 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
@@ -1718,6 +1727,11 @@ process: | |||
1718 | if (sk->sk_state == TCP_TIME_WAIT) | 1727 | if (sk->sk_state == TCP_TIME_WAIT) |
1719 | goto do_time_wait; | 1728 | goto do_time_wait; |
1720 | 1729 | ||
1730 | if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) { | ||
1731 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
1732 | goto discard_and_relse; | ||
1733 | } | ||
1734 | |||
1721 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1735 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
1722 | goto discard_and_relse; | 1736 | goto discard_and_relse; |
1723 | 1737 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 90824852f598..3d7a2c0b836a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -91,9 +91,9 @@ static unsigned int udp6_portaddr_hash(struct net *net, | |||
91 | if (ipv6_addr_any(addr6)) | 91 | if (ipv6_addr_any(addr6)) |
92 | hash = jhash_1word(0, mix); | 92 | hash = jhash_1word(0, mix); |
93 | else if (ipv6_addr_v4mapped(addr6)) | 93 | else if (ipv6_addr_v4mapped(addr6)) |
94 | hash = jhash_1word(addr6->s6_addr32[3], mix); | 94 | hash = jhash_1word((__force u32)addr6->s6_addr32[3], mix); |
95 | else | 95 | else |
96 | hash = jhash2(addr6->s6_addr32, 4, mix); | 96 | hash = jhash2((__force u32 *)addr6->s6_addr32, 4, mix); |
97 | 97 | ||
98 | return hash ^ port; | 98 | return hash ^ port; |
99 | } | 99 | } |
@@ -335,6 +335,9 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
335 | if (flags & MSG_ERRQUEUE) | 335 | if (flags & MSG_ERRQUEUE) |
336 | return ipv6_recv_error(sk, msg, len); | 336 | return ipv6_recv_error(sk, msg, len); |
337 | 337 | ||
338 | if (np->rxpmtu && np->rxopt.bits.rxpmtu) | ||
339 | return ipv6_recv_rxpmtu(sk, msg, len); | ||
340 | |||
338 | try_again: | 341 | try_again: |
339 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), | 342 | skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), |
340 | &peeked, &err); | 343 | &peeked, &err); |
@@ -421,7 +424,7 @@ out: | |||
421 | return err; | 424 | return err; |
422 | 425 | ||
423 | csum_copy_err: | 426 | csum_copy_err: |
424 | lock_sock(sk); | 427 | lock_sock_bh(sk); |
425 | if (!skb_kill_datagram(sk, skb, flags)) { | 428 | if (!skb_kill_datagram(sk, skb, flags)) { |
426 | if (is_udp4) | 429 | if (is_udp4) |
427 | UDP_INC_STATS_USER(sock_net(sk), | 430 | UDP_INC_STATS_USER(sock_net(sk), |
@@ -430,7 +433,7 @@ csum_copy_err: | |||
430 | UDP6_INC_STATS_USER(sock_net(sk), | 433 | UDP6_INC_STATS_USER(sock_net(sk), |
431 | UDP_MIB_INERRORS, is_udplite); | 434 | UDP_MIB_INERRORS, is_udplite); |
432 | } | 435 | } |
433 | release_sock(sk); | 436 | unlock_sock_bh(sk); |
434 | 437 | ||
435 | if (flags & MSG_DONTWAIT) | 438 | if (flags & MSG_DONTWAIT) |
436 | return -EAGAIN; | 439 | return -EAGAIN; |
@@ -511,7 +514,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
511 | goto drop; | 514 | goto drop; |
512 | } | 515 | } |
513 | 516 | ||
514 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 517 | if ((rc = ip_queue_rcv_skb(sk, skb)) < 0) { |
515 | /* Note that an ENOMEM error is charged twice */ | 518 | /* Note that an ENOMEM error is charged twice */ |
516 | if (rc == -ENOMEM) | 519 | if (rc == -ENOMEM) |
517 | UDP6_INC_STATS_BH(sock_net(sk), | 520 | UDP6_INC_STATS_BH(sock_net(sk), |
@@ -581,6 +584,10 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
581 | 584 | ||
582 | sk = stack[i]; | 585 | sk = stack[i]; |
583 | if (skb1) { | 586 | if (skb1) { |
587 | if (sk_rcvqueues_full(sk, skb)) { | ||
588 | kfree_skb(skb1); | ||
589 | goto drop; | ||
590 | } | ||
584 | bh_lock_sock(sk); | 591 | bh_lock_sock(sk); |
585 | if (!sock_owned_by_user(sk)) | 592 | if (!sock_owned_by_user(sk)) |
586 | udpv6_queue_rcv_skb(sk, skb1); | 593 | udpv6_queue_rcv_skb(sk, skb1); |
@@ -692,7 +699,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
692 | u32 ulen = 0; | 699 | u32 ulen = 0; |
693 | 700 | ||
694 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 701 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
695 | goto short_packet; | 702 | goto discard; |
696 | 703 | ||
697 | saddr = &ipv6_hdr(skb)->saddr; | 704 | saddr = &ipv6_hdr(skb)->saddr; |
698 | daddr = &ipv6_hdr(skb)->daddr; | 705 | daddr = &ipv6_hdr(skb)->daddr; |
@@ -756,6 +763,10 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
756 | 763 | ||
757 | /* deliver */ | 764 | /* deliver */ |
758 | 765 | ||
766 | if (sk_rcvqueues_full(sk, skb)) { | ||
767 | sock_put(sk); | ||
768 | goto discard; | ||
769 | } | ||
759 | bh_lock_sock(sk); | 770 | bh_lock_sock(sk); |
760 | if (!sock_owned_by_user(sk)) | 771 | if (!sock_owned_by_user(sk)) |
761 | udpv6_queue_rcv_skb(sk, skb); | 772 | udpv6_queue_rcv_skb(sk, skb); |
@@ -770,9 +781,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
770 | return 0; | 781 | return 0; |
771 | 782 | ||
772 | short_packet: | 783 | short_packet: |
773 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", | 784 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u\n", |
774 | proto == IPPROTO_UDPLITE ? "-Lite" : "", | 785 | proto == IPPROTO_UDPLITE ? "-Lite" : "", |
775 | ulen, skb->len); | 786 | saddr, |
787 | ntohs(uh->source), | ||
788 | ulen, | ||
789 | skb->len, | ||
790 | daddr, | ||
791 | ntohs(uh->dest)); | ||
776 | 792 | ||
777 | discard: | 793 | discard: |
778 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 794 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
@@ -919,6 +935,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
919 | int ulen = len; | 935 | int ulen = len; |
920 | int hlimit = -1; | 936 | int hlimit = -1; |
921 | int tclass = -1; | 937 | int tclass = -1; |
938 | int dontfrag = -1; | ||
922 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 939 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
923 | int err; | 940 | int err; |
924 | int connected = 0; | 941 | int connected = 0; |
@@ -1049,7 +1066,8 @@ do_udp_sendmsg: | |||
1049 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1066 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1050 | opt->tot_len = sizeof(*opt); | 1067 | opt->tot_len = sizeof(*opt); |
1051 | 1068 | ||
1052 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, &tclass); | 1069 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, |
1070 | &tclass, &dontfrag); | ||
1053 | if (err < 0) { | 1071 | if (err < 0) { |
1054 | fl6_sock_release(flowlabel); | 1072 | fl6_sock_release(flowlabel); |
1055 | return err; | 1073 | return err; |
@@ -1120,6 +1138,9 @@ do_udp_sendmsg: | |||
1120 | if (tclass < 0) | 1138 | if (tclass < 0) |
1121 | tclass = np->tclass; | 1139 | tclass = np->tclass; |
1122 | 1140 | ||
1141 | if (dontfrag < 0) | ||
1142 | dontfrag = np->dontfrag; | ||
1143 | |||
1123 | if (msg->msg_flags&MSG_CONFIRM) | 1144 | if (msg->msg_flags&MSG_CONFIRM) |
1124 | goto do_confirm; | 1145 | goto do_confirm; |
1125 | back_from_confirm: | 1146 | back_from_confirm: |
@@ -1143,7 +1164,7 @@ do_append_data: | |||
1143 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1164 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1144 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1165 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
1145 | (struct rt6_info*)dst, | 1166 | (struct rt6_info*)dst, |
1146 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 1167 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1147 | if (err) | 1168 | if (err) |
1148 | udp_v6_flush_pending_frames(sk); | 1169 | udp_v6_flush_pending_frames(sk); |
1149 | else if (!corkreq) | 1170 | else if (!corkreq) |
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 2bc98ede1235..f8c3cf842f53 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -42,7 +42,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) | |||
42 | ipv6_hdr(skb)->payload_len = htons(skb->len); | 42 | ipv6_hdr(skb)->payload_len = htons(skb->len); |
43 | __skb_push(skb, skb->data - skb_network_header(skb)); | 43 | __skb_push(skb, skb->data - skb_network_header(skb)); |
44 | 44 | ||
45 | NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, | 45 | NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL, |
46 | ip6_rcv_finish); | 46 | ip6_rcv_finish); |
47 | return -1; | 47 | return -1; |
48 | } | 48 | } |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 0c92112dcba3..6434bd5ce088 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -90,6 +90,6 @@ static int xfrm6_output_finish(struct sk_buff *skb) | |||
90 | 90 | ||
91 | int xfrm6_output(struct sk_buff *skb) | 91 | int xfrm6_output(struct sk_buff *skb) |
92 | { | 92 | { |
93 | return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb_dst(skb)->dev, | 93 | return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, |
94 | xfrm6_output_finish); | 94 | skb_dst(skb)->dev, xfrm6_output_finish); |
95 | } | 95 | } |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ae181651c75a..4a0e77e14468 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -67,36 +67,6 @@ static int xfrm6_get_saddr(struct net *net, | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct dst_entry * | ||
71 | __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) | ||
72 | { | ||
73 | struct dst_entry *dst; | ||
74 | |||
75 | /* Still not clear if we should set fl->fl6_{src,dst}... */ | ||
76 | read_lock_bh(&policy->lock); | ||
77 | for (dst = policy->bundles; dst; dst = dst->next) { | ||
78 | struct xfrm_dst *xdst = (struct xfrm_dst*)dst; | ||
79 | struct in6_addr fl_dst_prefix, fl_src_prefix; | ||
80 | |||
81 | ipv6_addr_prefix(&fl_dst_prefix, | ||
82 | &fl->fl6_dst, | ||
83 | xdst->u.rt6.rt6i_dst.plen); | ||
84 | ipv6_addr_prefix(&fl_src_prefix, | ||
85 | &fl->fl6_src, | ||
86 | xdst->u.rt6.rt6i_src.plen); | ||
87 | if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && | ||
88 | ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && | ||
89 | xfrm_bundle_ok(policy, xdst, fl, AF_INET6, | ||
90 | (xdst->u.rt6.rt6i_dst.plen != 128 || | ||
91 | xdst->u.rt6.rt6i_src.plen != 128))) { | ||
92 | dst_clone(dst); | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | read_unlock_bh(&policy->lock); | ||
97 | return dst; | ||
98 | } | ||
99 | |||
100 | static int xfrm6_get_tos(struct flowi *fl) | 70 | static int xfrm6_get_tos(struct flowi *fl) |
101 | { | 71 | { |
102 | return 0; | 72 | return 0; |
@@ -124,7 +94,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
124 | xdst->u.dst.dev = dev; | 94 | xdst->u.dst.dev = dev; |
125 | dev_hold(dev); | 95 | dev_hold(dev); |
126 | 96 | ||
127 | xdst->u.rt6.rt6i_idev = in6_dev_get(rt->u.dst.dev); | 97 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); |
128 | if (!xdst->u.rt6.rt6i_idev) | 98 | if (!xdst->u.rt6.rt6i_idev) |
129 | return -ENODEV; | 99 | return -ENODEV; |
130 | 100 | ||
@@ -291,7 +261,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
291 | .dst_ops = &xfrm6_dst_ops, | 261 | .dst_ops = &xfrm6_dst_ops, |
292 | .dst_lookup = xfrm6_dst_lookup, | 262 | .dst_lookup = xfrm6_dst_lookup, |
293 | .get_saddr = xfrm6_get_saddr, | 263 | .get_saddr = xfrm6_get_saddr, |
294 | .find_bundle = __xfrm6_find_bundle, | ||
295 | .decode_session = _decode_session6, | 264 | .decode_session = _decode_session6, |
296 | .get_tos = xfrm6_get_tos, | 265 | .get_tos = xfrm6_get_tos, |
297 | .init_path = xfrm6_init_path, | 266 | .init_path = xfrm6_init_path, |