diff options
Diffstat (limited to 'net/ipv6')
31 files changed, 1021 insertions, 472 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5667b3003af9..3e118dfddd02 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -108,11 +108,12 @@ static inline u32 cstamp_delta(unsigned long cstamp) | |||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | #ifdef CONFIG_SYSCTL | 110 | #ifdef CONFIG_SYSCTL |
| 111 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 111 | static int addrconf_sysctl_register(struct inet6_dev *idev); |
| 112 | static void addrconf_sysctl_unregister(struct inet6_dev *idev); | 112 | static void addrconf_sysctl_unregister(struct inet6_dev *idev); |
| 113 | #else | 113 | #else |
| 114 | static inline void addrconf_sysctl_register(struct inet6_dev *idev) | 114 | static inline int addrconf_sysctl_register(struct inet6_dev *idev) |
| 115 | { | 115 | { |
| 116 | return 0; | ||
| 116 | } | 117 | } |
| 117 | 118 | ||
| 118 | static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | 119 | static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) |
| @@ -186,6 +187,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
| 186 | .max_desync_factor = MAX_DESYNC_FACTOR, | 187 | .max_desync_factor = MAX_DESYNC_FACTOR, |
| 187 | .max_addresses = IPV6_MAX_ADDRESSES, | 188 | .max_addresses = IPV6_MAX_ADDRESSES, |
| 188 | .accept_ra_defrtr = 1, | 189 | .accept_ra_defrtr = 1, |
| 190 | .accept_ra_from_local = 0, | ||
| 189 | .accept_ra_pinfo = 1, | 191 | .accept_ra_pinfo = 1, |
| 190 | #ifdef CONFIG_IPV6_ROUTER_PREF | 192 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| 191 | .accept_ra_rtr_pref = 1, | 193 | .accept_ra_rtr_pref = 1, |
| @@ -222,6 +224,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
| 222 | .max_desync_factor = MAX_DESYNC_FACTOR, | 224 | .max_desync_factor = MAX_DESYNC_FACTOR, |
| 223 | .max_addresses = IPV6_MAX_ADDRESSES, | 225 | .max_addresses = IPV6_MAX_ADDRESSES, |
| 224 | .accept_ra_defrtr = 1, | 226 | .accept_ra_defrtr = 1, |
| 227 | .accept_ra_from_local = 0, | ||
| 225 | .accept_ra_pinfo = 1, | 228 | .accept_ra_pinfo = 1, |
| 226 | #ifdef CONFIG_IPV6_ROUTER_PREF | 229 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| 227 | .accept_ra_rtr_pref = 1, | 230 | .accept_ra_rtr_pref = 1, |
| @@ -308,16 +311,16 @@ err_ip: | |||
| 308 | static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | 311 | static struct inet6_dev *ipv6_add_dev(struct net_device *dev) |
| 309 | { | 312 | { |
| 310 | struct inet6_dev *ndev; | 313 | struct inet6_dev *ndev; |
| 314 | int err = -ENOMEM; | ||
| 311 | 315 | ||
| 312 | ASSERT_RTNL(); | 316 | ASSERT_RTNL(); |
| 313 | 317 | ||
| 314 | if (dev->mtu < IPV6_MIN_MTU) | 318 | if (dev->mtu < IPV6_MIN_MTU) |
| 315 | return NULL; | 319 | return ERR_PTR(-EINVAL); |
| 316 | 320 | ||
| 317 | ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL); | 321 | ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL); |
| 318 | |||
| 319 | if (ndev == NULL) | 322 | if (ndev == NULL) |
| 320 | return NULL; | 323 | return ERR_PTR(err); |
| 321 | 324 | ||
| 322 | rwlock_init(&ndev->lock); | 325 | rwlock_init(&ndev->lock); |
| 323 | ndev->dev = dev; | 326 | ndev->dev = dev; |
| @@ -330,7 +333,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
| 330 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | 333 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); |
| 331 | if (ndev->nd_parms == NULL) { | 334 | if (ndev->nd_parms == NULL) { |
| 332 | kfree(ndev); | 335 | kfree(ndev); |
| 333 | return NULL; | 336 | return ERR_PTR(err); |
| 334 | } | 337 | } |
| 335 | if (ndev->cnf.forwarding) | 338 | if (ndev->cnf.forwarding) |
| 336 | dev_disable_lro(dev); | 339 | dev_disable_lro(dev); |
| @@ -344,17 +347,14 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
| 344 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 347 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
| 345 | dev_put(dev); | 348 | dev_put(dev); |
| 346 | kfree(ndev); | 349 | kfree(ndev); |
| 347 | return NULL; | 350 | return ERR_PTR(err); |
| 348 | } | 351 | } |
| 349 | 352 | ||
| 350 | if (snmp6_register_dev(ndev) < 0) { | 353 | if (snmp6_register_dev(ndev) < 0) { |
| 351 | ADBG(KERN_WARNING | 354 | ADBG(KERN_WARNING |
| 352 | "%s: cannot create /proc/net/dev_snmp6/%s\n", | 355 | "%s: cannot create /proc/net/dev_snmp6/%s\n", |
| 353 | __func__, dev->name); | 356 | __func__, dev->name); |
| 354 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 357 | goto err_release; |
| 355 | ndev->dead = 1; | ||
| 356 | in6_dev_finish_destroy(ndev); | ||
| 357 | return NULL; | ||
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | /* One reference from device. We must do this before | 360 | /* One reference from device. We must do this before |
| @@ -392,7 +392,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
| 392 | 392 | ||
| 393 | ipv6_mc_init_dev(ndev); | 393 | ipv6_mc_init_dev(ndev); |
| 394 | ndev->tstamp = jiffies; | 394 | ndev->tstamp = jiffies; |
| 395 | addrconf_sysctl_register(ndev); | 395 | err = addrconf_sysctl_register(ndev); |
| 396 | if (err) { | ||
| 397 | ipv6_mc_destroy_dev(ndev); | ||
| 398 | del_timer(&ndev->regen_timer); | ||
| 399 | goto err_release; | ||
| 400 | } | ||
| 396 | /* protected by rtnl_lock */ | 401 | /* protected by rtnl_lock */ |
| 397 | rcu_assign_pointer(dev->ip6_ptr, ndev); | 402 | rcu_assign_pointer(dev->ip6_ptr, ndev); |
| 398 | 403 | ||
| @@ -407,6 +412,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
| 407 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); | 412 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); |
| 408 | 413 | ||
| 409 | return ndev; | 414 | return ndev; |
| 415 | |||
| 416 | err_release: | ||
| 417 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | ||
| 418 | ndev->dead = 1; | ||
| 419 | in6_dev_finish_destroy(ndev); | ||
| 420 | return ERR_PTR(err); | ||
| 410 | } | 421 | } |
| 411 | 422 | ||
| 412 | static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | 423 | static struct inet6_dev *ipv6_find_idev(struct net_device *dev) |
| @@ -418,7 +429,7 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | |||
| 418 | idev = __in6_dev_get(dev); | 429 | idev = __in6_dev_get(dev); |
| 419 | if (!idev) { | 430 | if (!idev) { |
| 420 | idev = ipv6_add_dev(dev); | 431 | idev = ipv6_add_dev(dev); |
| 421 | if (!idev) | 432 | if (IS_ERR(idev)) |
| 422 | return NULL; | 433 | return NULL; |
| 423 | } | 434 | } |
| 424 | 435 | ||
| @@ -1679,14 +1690,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
| 1679 | addrconf_mod_dad_work(ifp, 0); | 1690 | addrconf_mod_dad_work(ifp, 0); |
| 1680 | } | 1691 | } |
| 1681 | 1692 | ||
| 1682 | /* Join to solicited addr multicast group. */ | 1693 | /* Join to solicited addr multicast group. |
| 1683 | 1694 | * caller must hold RTNL */ | |
| 1684 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | 1695 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) |
| 1685 | { | 1696 | { |
| 1686 | struct in6_addr maddr; | 1697 | struct in6_addr maddr; |
| 1687 | 1698 | ||
| 1688 | ASSERT_RTNL(); | ||
| 1689 | |||
| 1690 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1699 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
| 1691 | return; | 1700 | return; |
| 1692 | 1701 | ||
| @@ -1694,12 +1703,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | |||
| 1694 | ipv6_dev_mc_inc(dev, &maddr); | 1703 | ipv6_dev_mc_inc(dev, &maddr); |
| 1695 | } | 1704 | } |
| 1696 | 1705 | ||
| 1706 | /* caller must hold RTNL */ | ||
| 1697 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | 1707 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) |
| 1698 | { | 1708 | { |
| 1699 | struct in6_addr maddr; | 1709 | struct in6_addr maddr; |
| 1700 | 1710 | ||
| 1701 | ASSERT_RTNL(); | ||
| 1702 | |||
| 1703 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1711 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
| 1704 | return; | 1712 | return; |
| 1705 | 1713 | ||
| @@ -1707,12 +1715,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 1707 | __ipv6_dev_mc_dec(idev, &maddr); | 1715 | __ipv6_dev_mc_dec(idev, &maddr); |
| 1708 | } | 1716 | } |
| 1709 | 1717 | ||
| 1718 | /* caller must hold RTNL */ | ||
| 1710 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1719 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
| 1711 | { | 1720 | { |
| 1712 | struct in6_addr addr; | 1721 | struct in6_addr addr; |
| 1713 | 1722 | ||
| 1714 | ASSERT_RTNL(); | ||
| 1715 | |||
| 1716 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1723 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
| 1717 | return; | 1724 | return; |
| 1718 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1725 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
| @@ -1721,12 +1728,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
| 1721 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); | 1728 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); |
| 1722 | } | 1729 | } |
| 1723 | 1730 | ||
| 1731 | /* caller must hold RTNL */ | ||
| 1724 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1732 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
| 1725 | { | 1733 | { |
| 1726 | struct in6_addr addr; | 1734 | struct in6_addr addr; |
| 1727 | 1735 | ||
| 1728 | ASSERT_RTNL(); | ||
| 1729 | |||
| 1730 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1736 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
| 1731 | return; | 1737 | return; |
| 1732 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1738 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
| @@ -2728,9 +2734,25 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr | |||
| 2728 | } | 2734 | } |
| 2729 | } | 2735 | } |
| 2730 | 2736 | ||
| 2737 | static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) | ||
| 2738 | { | ||
| 2739 | if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) { | ||
| 2740 | struct in6_addr addr; | ||
| 2741 | |||
| 2742 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
| 2743 | /* addrconf_add_linklocal also adds a prefix_route and we | ||
| 2744 | * only need to care about prefix routes if ipv6_generate_eui64 | ||
| 2745 | * couldn't generate one. | ||
| 2746 | */ | ||
| 2747 | if (ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) == 0) | ||
| 2748 | addrconf_add_linklocal(idev, &addr); | ||
| 2749 | else if (prefix_route) | ||
| 2750 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); | ||
| 2751 | } | ||
| 2752 | } | ||
| 2753 | |||
| 2731 | static void addrconf_dev_config(struct net_device *dev) | 2754 | static void addrconf_dev_config(struct net_device *dev) |
| 2732 | { | 2755 | { |
| 2733 | struct in6_addr addr; | ||
| 2734 | struct inet6_dev *idev; | 2756 | struct inet6_dev *idev; |
| 2735 | 2757 | ||
| 2736 | ASSERT_RTNL(); | 2758 | ASSERT_RTNL(); |
| @@ -2751,11 +2773,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
| 2751 | if (IS_ERR(idev)) | 2773 | if (IS_ERR(idev)) |
| 2752 | return; | 2774 | return; |
| 2753 | 2775 | ||
| 2754 | memset(&addr, 0, sizeof(struct in6_addr)); | 2776 | addrconf_addr_gen(idev, false); |
| 2755 | addr.s6_addr32[0] = htonl(0xFE800000); | ||
| 2756 | |||
| 2757 | if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0) | ||
| 2758 | addrconf_add_linklocal(idev, &addr); | ||
| 2759 | } | 2777 | } |
| 2760 | 2778 | ||
| 2761 | #if IS_ENABLED(CONFIG_IPV6_SIT) | 2779 | #if IS_ENABLED(CONFIG_IPV6_SIT) |
| @@ -2777,11 +2795,7 @@ static void addrconf_sit_config(struct net_device *dev) | |||
| 2777 | } | 2795 | } |
| 2778 | 2796 | ||
| 2779 | if (dev->priv_flags & IFF_ISATAP) { | 2797 | if (dev->priv_flags & IFF_ISATAP) { |
| 2780 | struct in6_addr addr; | 2798 | addrconf_addr_gen(idev, false); |
| 2781 | |||
| 2782 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
| 2783 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
| 2784 | addrconf_add_linklocal(idev, &addr); | ||
| 2785 | return; | 2799 | return; |
| 2786 | } | 2800 | } |
| 2787 | 2801 | ||
| @@ -2796,7 +2810,6 @@ static void addrconf_sit_config(struct net_device *dev) | |||
| 2796 | static void addrconf_gre_config(struct net_device *dev) | 2810 | static void addrconf_gre_config(struct net_device *dev) |
| 2797 | { | 2811 | { |
| 2798 | struct inet6_dev *idev; | 2812 | struct inet6_dev *idev; |
| 2799 | struct in6_addr addr; | ||
| 2800 | 2813 | ||
| 2801 | ASSERT_RTNL(); | 2814 | ASSERT_RTNL(); |
| 2802 | 2815 | ||
| @@ -2805,11 +2818,7 @@ static void addrconf_gre_config(struct net_device *dev) | |||
| 2805 | return; | 2818 | return; |
| 2806 | } | 2819 | } |
| 2807 | 2820 | ||
| 2808 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 2821 | addrconf_addr_gen(idev, true); |
| 2809 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
| 2810 | addrconf_add_linklocal(idev, &addr); | ||
| 2811 | else | ||
| 2812 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
| 2813 | } | 2822 | } |
| 2814 | #endif | 2823 | #endif |
| 2815 | 2824 | ||
| @@ -2825,8 +2834,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2825 | case NETDEV_REGISTER: | 2834 | case NETDEV_REGISTER: |
| 2826 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2835 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
| 2827 | idev = ipv6_add_dev(dev); | 2836 | idev = ipv6_add_dev(dev); |
| 2828 | if (!idev) | 2837 | if (IS_ERR(idev)) |
| 2829 | return notifier_from_errno(-ENOMEM); | 2838 | return notifier_from_errno(PTR_ERR(idev)); |
| 2830 | } | 2839 | } |
| 2831 | break; | 2840 | break; |
| 2832 | 2841 | ||
| @@ -2846,7 +2855,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2846 | if (!idev && dev->mtu >= IPV6_MIN_MTU) | 2855 | if (!idev && dev->mtu >= IPV6_MIN_MTU) |
| 2847 | idev = ipv6_add_dev(dev); | 2856 | idev = ipv6_add_dev(dev); |
| 2848 | 2857 | ||
| 2849 | if (idev) { | 2858 | if (!IS_ERR_OR_NULL(idev)) { |
| 2850 | idev->if_flags |= IF_READY; | 2859 | idev->if_flags |= IF_READY; |
| 2851 | run_pending = 1; | 2860 | run_pending = 1; |
| 2852 | } | 2861 | } |
| @@ -2889,7 +2898,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2889 | break; | 2898 | break; |
| 2890 | } | 2899 | } |
| 2891 | 2900 | ||
| 2892 | if (idev) { | 2901 | if (!IS_ERR_OR_NULL(idev)) { |
| 2893 | if (run_pending) | 2902 | if (run_pending) |
| 2894 | addrconf_dad_run(idev); | 2903 | addrconf_dad_run(idev); |
| 2895 | 2904 | ||
| @@ -2924,7 +2933,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2924 | 2933 | ||
| 2925 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2934 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
| 2926 | idev = ipv6_add_dev(dev); | 2935 | idev = ipv6_add_dev(dev); |
| 2927 | if (idev) | 2936 | if (!IS_ERR(idev)) |
| 2928 | break; | 2937 | break; |
| 2929 | } | 2938 | } |
| 2930 | 2939 | ||
| @@ -2945,10 +2954,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2945 | if (idev) { | 2954 | if (idev) { |
| 2946 | snmp6_unregister_dev(idev); | 2955 | snmp6_unregister_dev(idev); |
| 2947 | addrconf_sysctl_unregister(idev); | 2956 | addrconf_sysctl_unregister(idev); |
| 2948 | addrconf_sysctl_register(idev); | 2957 | err = addrconf_sysctl_register(idev); |
| 2949 | err = snmp6_register_dev(idev); | ||
| 2950 | if (err) | 2958 | if (err) |
| 2951 | return notifier_from_errno(err); | 2959 | return notifier_from_errno(err); |
| 2960 | err = snmp6_register_dev(idev); | ||
| 2961 | if (err) { | ||
| 2962 | addrconf_sysctl_unregister(idev); | ||
| 2963 | return notifier_from_errno(err); | ||
| 2964 | } | ||
| 2952 | } | 2965 | } |
| 2953 | break; | 2966 | break; |
| 2954 | 2967 | ||
| @@ -3081,11 +3094,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 3081 | 3094 | ||
| 3082 | write_unlock_bh(&idev->lock); | 3095 | write_unlock_bh(&idev->lock); |
| 3083 | 3096 | ||
| 3084 | /* Step 5: Discard multicast list */ | 3097 | /* Step 5: Discard anycast and multicast list */ |
| 3085 | if (how) | 3098 | if (how) { |
| 3099 | ipv6_ac_destroy_dev(idev); | ||
| 3086 | ipv6_mc_destroy_dev(idev); | 3100 | ipv6_mc_destroy_dev(idev); |
| 3087 | else | 3101 | } else { |
| 3088 | ipv6_mc_down(idev); | 3102 | ipv6_mc_down(idev); |
| 3103 | } | ||
| 3089 | 3104 | ||
| 3090 | idev->tstamp = jiffies; | 3105 | idev->tstamp = jiffies; |
| 3091 | 3106 | ||
| @@ -4321,6 +4336,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
| 4321 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; | 4336 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; |
| 4322 | array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; | 4337 | array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; |
| 4323 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; | 4338 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; |
| 4339 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; | ||
| 4324 | } | 4340 | } |
| 4325 | 4341 | ||
| 4326 | static inline size_t inet6_ifla6_size(void) | 4342 | static inline size_t inet6_ifla6_size(void) |
| @@ -4420,6 +4436,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) | |||
| 4420 | nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); | 4436 | nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); |
| 4421 | if (nla == NULL) | 4437 | if (nla == NULL) |
| 4422 | goto nla_put_failure; | 4438 | goto nla_put_failure; |
| 4439 | |||
| 4440 | if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->addr_gen_mode)) | ||
| 4441 | goto nla_put_failure; | ||
| 4442 | |||
| 4423 | read_lock_bh(&idev->lock); | 4443 | read_lock_bh(&idev->lock); |
| 4424 | memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla)); | 4444 | memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla)); |
| 4425 | read_unlock_bh(&idev->lock); | 4445 | read_unlock_bh(&idev->lock); |
| @@ -4524,8 +4544,21 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) | |||
| 4524 | if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0) | 4544 | if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0) |
| 4525 | BUG(); | 4545 | BUG(); |
| 4526 | 4546 | ||
| 4527 | if (tb[IFLA_INET6_TOKEN]) | 4547 | if (tb[IFLA_INET6_TOKEN]) { |
| 4528 | err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); | 4548 | err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); |
| 4549 | if (err) | ||
| 4550 | return err; | ||
| 4551 | } | ||
| 4552 | |||
| 4553 | if (tb[IFLA_INET6_ADDR_GEN_MODE]) { | ||
| 4554 | u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]); | ||
| 4555 | |||
| 4556 | if (mode != IN6_ADDR_GEN_MODE_EUI64 && | ||
| 4557 | mode != IN6_ADDR_GEN_MODE_NONE) | ||
| 4558 | return -EINVAL; | ||
| 4559 | idev->addr_gen_mode = mode; | ||
| 4560 | err = 0; | ||
| 4561 | } | ||
| 4529 | 4562 | ||
| 4530 | return err; | 4563 | return err; |
| 4531 | } | 4564 | } |
| @@ -4737,24 +4770,21 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
| 4737 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4770 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
| 4738 | if (!ipv6_addr_any(&ifp->peer_addr)) { | 4771 | if (!ipv6_addr_any(&ifp->peer_addr)) { |
| 4739 | struct rt6_info *rt; | 4772 | struct rt6_info *rt; |
| 4740 | struct net_device *dev = ifp->idev->dev; | 4773 | |
| 4741 | 4774 | rt = addrconf_get_prefix_route(&ifp->peer_addr, 128, | |
| 4742 | rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL, | 4775 | ifp->idev->dev, 0, 0); |
| 4743 | dev->ifindex, 1); | 4776 | if (rt && ip6_del_rt(rt)) |
| 4744 | if (rt) { | 4777 | dst_free(&rt->dst); |
| 4745 | dst_hold(&rt->dst); | ||
| 4746 | if (ip6_del_rt(rt)) | ||
| 4747 | dst_free(&rt->dst); | ||
| 4748 | } | ||
| 4749 | } | 4778 | } |
| 4750 | dst_hold(&ifp->rt->dst); | 4779 | dst_hold(&ifp->rt->dst); |
| 4751 | 4780 | ||
| 4752 | if (ip6_del_rt(ifp->rt)) | 4781 | if (ip6_del_rt(ifp->rt)) |
| 4753 | dst_free(&ifp->rt->dst); | 4782 | dst_free(&ifp->rt->dst); |
| 4783 | |||
| 4784 | rt_genid_bump_ipv6(net); | ||
| 4754 | break; | 4785 | break; |
| 4755 | } | 4786 | } |
| 4756 | atomic_inc(&net->ipv6.dev_addr_genid); | 4787 | atomic_inc(&net->ipv6.dev_addr_genid); |
| 4757 | rt_genid_bump_ipv6(net); | ||
| 4758 | } | 4788 | } |
| 4759 | 4789 | ||
| 4760 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4790 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
| @@ -5168,6 +5198,13 @@ static struct addrconf_sysctl_table | |||
| 5168 | .proc_handler = proc_dointvec | 5198 | .proc_handler = proc_dointvec |
| 5169 | }, | 5199 | }, |
| 5170 | { | 5200 | { |
| 5201 | .procname = "accept_ra_from_local", | ||
| 5202 | .data = &ipv6_devconf.accept_ra_from_local, | ||
| 5203 | .maxlen = sizeof(int), | ||
| 5204 | .mode = 0644, | ||
| 5205 | .proc_handler = proc_dointvec, | ||
| 5206 | }, | ||
| 5207 | { | ||
| 5171 | /* sentinel */ | 5208 | /* sentinel */ |
| 5172 | } | 5209 | } |
| 5173 | }, | 5210 | }, |
| @@ -5218,12 +5255,23 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
| 5218 | kfree(t); | 5255 | kfree(t); |
| 5219 | } | 5256 | } |
| 5220 | 5257 | ||
| 5221 | static void addrconf_sysctl_register(struct inet6_dev *idev) | 5258 | static int addrconf_sysctl_register(struct inet6_dev *idev) |
| 5222 | { | 5259 | { |
| 5223 | neigh_sysctl_register(idev->dev, idev->nd_parms, | 5260 | int err; |
| 5224 | &ndisc_ifinfo_sysctl_change); | 5261 | |
| 5225 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 5262 | if (!sysctl_dev_name_is_allowed(idev->dev->name)) |
| 5226 | idev, &idev->cnf); | 5263 | return -EINVAL; |
| 5264 | |||
| 5265 | err = neigh_sysctl_register(idev->dev, idev->nd_parms, | ||
| 5266 | &ndisc_ifinfo_sysctl_change); | ||
| 5267 | if (err) | ||
| 5268 | return err; | ||
| 5269 | err = __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | ||
| 5270 | idev, &idev->cnf); | ||
| 5271 | if (err) | ||
| 5272 | neigh_sysctl_unregister(idev->nd_parms); | ||
| 5273 | |||
| 5274 | return err; | ||
| 5227 | } | 5275 | } |
| 5228 | 5276 | ||
| 5229 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) | 5277 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) |
| @@ -5308,6 +5356,7 @@ static struct rtnl_af_ops inet6_ops = { | |||
| 5308 | 5356 | ||
| 5309 | int __init addrconf_init(void) | 5357 | int __init addrconf_init(void) |
| 5310 | { | 5358 | { |
| 5359 | struct inet6_dev *idev; | ||
| 5311 | int i, err; | 5360 | int i, err; |
| 5312 | 5361 | ||
| 5313 | err = ipv6_addr_label_init(); | 5362 | err = ipv6_addr_label_init(); |
| @@ -5346,11 +5395,12 @@ int __init addrconf_init(void) | |||
| 5346 | * device and it being up should be removed. | 5395 | * device and it being up should be removed. |
| 5347 | */ | 5396 | */ |
| 5348 | rtnl_lock(); | 5397 | rtnl_lock(); |
| 5349 | if (!ipv6_add_dev(init_net.loopback_dev)) | 5398 | idev = ipv6_add_dev(init_net.loopback_dev); |
| 5350 | err = -ENOMEM; | ||
| 5351 | rtnl_unlock(); | 5399 | rtnl_unlock(); |
| 5352 | if (err) | 5400 | if (IS_ERR(idev)) { |
| 5401 | err = PTR_ERR(idev); | ||
| 5353 | goto errlo; | 5402 | goto errlo; |
| 5403 | } | ||
| 5354 | 5404 | ||
| 5355 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 5405 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
| 5356 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | 5406 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index e6960457f625..98cc4cd570e2 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
| @@ -8,6 +8,13 @@ | |||
| 8 | #include <net/addrconf.h> | 8 | #include <net/addrconf.h> |
| 9 | #include <net/ip.h> | 9 | #include <net/ip.h> |
| 10 | 10 | ||
| 11 | /* if ipv6 module registers this function is used by xfrm to force all | ||
| 12 | * sockets to relookup their nodes - this is fairly expensive, be | ||
| 13 | * careful | ||
| 14 | */ | ||
| 15 | void (*__fib6_flush_trees)(struct net *); | ||
| 16 | EXPORT_SYMBOL(__fib6_flush_trees); | ||
| 17 | |||
| 11 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) | 18 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
| 12 | 19 | ||
| 13 | static inline unsigned int ipv6_addr_scope2type(unsigned int scope) | 20 | static inline unsigned int ipv6_addr_scope2type(unsigned int scope) |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 731e1e1722d9..fd0dc47f471d 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
| @@ -277,7 +277,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
| 277 | last = p; | 277 | last = p; |
| 278 | } | 278 | } |
| 279 | if (last) | 279 | if (last) |
| 280 | hlist_add_after_rcu(&last->list, &newp->list); | 280 | hlist_add_behind_rcu(&newp->list, &last->list); |
| 281 | else | 281 | else |
| 282 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | 282 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); |
| 283 | out: | 283 | out: |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 7cb4392690dd..2daa3a133e49 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -197,7 +197,7 @@ lookup_protocol: | |||
| 197 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; | 197 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; |
| 198 | np->mc_loop = 1; | 198 | np->mc_loop = 1; |
| 199 | np->pmtudisc = IPV6_PMTUDISC_WANT; | 199 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
| 200 | np->ipv6only = net->ipv6.sysctl.bindv6only; | 200 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; |
| 201 | 201 | ||
| 202 | /* Init the ipv4 part of the socket since we can have sockets | 202 | /* Init the ipv4 part of the socket since we can have sockets |
| 203 | * using v6 API for ipv4. | 203 | * using v6 API for ipv4. |
| @@ -294,7 +294,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 294 | /* Binding to v4-mapped address on a v6-only socket | 294 | /* Binding to v4-mapped address on a v6-only socket |
| 295 | * makes no sense | 295 | * makes no sense |
| 296 | */ | 296 | */ |
| 297 | if (np->ipv6only) { | 297 | if (sk->sk_ipv6only) { |
| 298 | err = -EINVAL; | 298 | err = -EINVAL; |
| 299 | goto out; | 299 | goto out; |
| 300 | } | 300 | } |
| @@ -371,7 +371,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 371 | if (addr_type != IPV6_ADDR_ANY) { | 371 | if (addr_type != IPV6_ADDR_ANY) { |
| 372 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; | 372 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; |
| 373 | if (addr_type != IPV6_ADDR_MAPPED) | 373 | if (addr_type != IPV6_ADDR_MAPPED) |
| 374 | np->ipv6only = 1; | 374 | sk->sk_ipv6only = 1; |
| 375 | } | 375 | } |
| 376 | if (snum) | 376 | if (snum) |
| 377 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 377 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; |
| @@ -765,6 +765,7 @@ static int __net_init inet6_net_init(struct net *net) | |||
| 765 | net->ipv6.sysctl.bindv6only = 0; | 765 | net->ipv6.sysctl.bindv6only = 0; |
| 766 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 766 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
| 767 | net->ipv6.sysctl.flowlabel_consistency = 1; | 767 | net->ipv6.sysctl.flowlabel_consistency = 1; |
| 768 | net->ipv6.sysctl.auto_flowlabels = 0; | ||
| 768 | atomic_set(&net->ipv6.rt_genid, 0); | 769 | atomic_set(&net->ipv6.rt_genid, 0); |
| 769 | 770 | ||
| 770 | err = ipv6_init_mibs(net); | 771 | err = ipv6_init_mibs(net); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 210183244689..9a386842fd62 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
| @@ -77,6 +77,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 77 | pac->acl_next = NULL; | 77 | pac->acl_next = NULL; |
| 78 | pac->acl_addr = *addr; | 78 | pac->acl_addr = *addr; |
| 79 | 79 | ||
| 80 | rtnl_lock(); | ||
| 80 | rcu_read_lock(); | 81 | rcu_read_lock(); |
| 81 | if (ifindex == 0) { | 82 | if (ifindex == 0) { |
| 82 | struct rt6_info *rt; | 83 | struct rt6_info *rt; |
| @@ -137,6 +138,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 137 | 138 | ||
| 138 | error: | 139 | error: |
| 139 | rcu_read_unlock(); | 140 | rcu_read_unlock(); |
| 141 | rtnl_unlock(); | ||
| 140 | if (pac) | 142 | if (pac) |
| 141 | sock_kfree_s(sk, pac, sizeof(*pac)); | 143 | sock_kfree_s(sk, pac, sizeof(*pac)); |
| 142 | return err; | 144 | return err; |
| @@ -171,11 +173,13 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 171 | 173 | ||
| 172 | spin_unlock_bh(&ipv6_sk_ac_lock); | 174 | spin_unlock_bh(&ipv6_sk_ac_lock); |
| 173 | 175 | ||
| 176 | rtnl_lock(); | ||
| 174 | rcu_read_lock(); | 177 | rcu_read_lock(); |
| 175 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); | 178 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
| 176 | if (dev) | 179 | if (dev) |
| 177 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 180 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
| 178 | rcu_read_unlock(); | 181 | rcu_read_unlock(); |
| 182 | rtnl_unlock(); | ||
| 179 | 183 | ||
| 180 | sock_kfree_s(sk, pac, sizeof(*pac)); | 184 | sock_kfree_s(sk, pac, sizeof(*pac)); |
| 181 | return 0; | 185 | return 0; |
| @@ -198,6 +202,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
| 198 | spin_unlock_bh(&ipv6_sk_ac_lock); | 202 | spin_unlock_bh(&ipv6_sk_ac_lock); |
| 199 | 203 | ||
| 200 | prev_index = 0; | 204 | prev_index = 0; |
| 205 | rtnl_lock(); | ||
| 201 | rcu_read_lock(); | 206 | rcu_read_lock(); |
| 202 | while (pac) { | 207 | while (pac) { |
| 203 | struct ipv6_ac_socklist *next = pac->acl_next; | 208 | struct ipv6_ac_socklist *next = pac->acl_next; |
| @@ -212,6 +217,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
| 212 | pac = next; | 217 | pac = next; |
| 213 | } | 218 | } |
| 214 | rcu_read_unlock(); | 219 | rcu_read_unlock(); |
| 220 | rtnl_unlock(); | ||
| 215 | } | 221 | } |
| 216 | 222 | ||
| 217 | static void aca_put(struct ifacaddr6 *ac) | 223 | static void aca_put(struct ifacaddr6 *ac) |
| @@ -233,6 +239,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) | |||
| 233 | struct rt6_info *rt; | 239 | struct rt6_info *rt; |
| 234 | int err; | 240 | int err; |
| 235 | 241 | ||
| 242 | ASSERT_RTNL(); | ||
| 243 | |||
| 236 | idev = in6_dev_get(dev); | 244 | idev = in6_dev_get(dev); |
| 237 | 245 | ||
| 238 | if (idev == NULL) | 246 | if (idev == NULL) |
| @@ -302,6 +310,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 302 | { | 310 | { |
| 303 | struct ifacaddr6 *aca, *prev_aca; | 311 | struct ifacaddr6 *aca, *prev_aca; |
| 304 | 312 | ||
| 313 | ASSERT_RTNL(); | ||
| 314 | |||
| 305 | write_lock_bh(&idev->lock); | 315 | write_lock_bh(&idev->lock); |
| 306 | prev_aca = NULL; | 316 | prev_aca = NULL; |
| 307 | for (aca = idev->ac_list; aca; aca = aca->aca_next) { | 317 | for (aca = idev->ac_list; aca; aca = aca->aca_next) { |
| @@ -341,6 +351,27 @@ static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) | |||
| 341 | return __ipv6_dev_ac_dec(idev, addr); | 351 | return __ipv6_dev_ac_dec(idev, addr); |
| 342 | } | 352 | } |
| 343 | 353 | ||
| 354 | void ipv6_ac_destroy_dev(struct inet6_dev *idev) | ||
| 355 | { | ||
| 356 | struct ifacaddr6 *aca; | ||
| 357 | |||
| 358 | write_lock_bh(&idev->lock); | ||
| 359 | while ((aca = idev->ac_list) != NULL) { | ||
| 360 | idev->ac_list = aca->aca_next; | ||
| 361 | write_unlock_bh(&idev->lock); | ||
| 362 | |||
| 363 | addrconf_leave_solict(idev, &aca->aca_addr); | ||
| 364 | |||
| 365 | dst_hold(&aca->aca_rt->dst); | ||
| 366 | ip6_del_rt(aca->aca_rt); | ||
| 367 | |||
| 368 | aca_put(aca); | ||
| 369 | |||
| 370 | write_lock_bh(&idev->lock); | ||
| 371 | } | ||
| 372 | write_unlock_bh(&idev->lock); | ||
| 373 | } | ||
| 374 | |||
| 344 | /* | 375 | /* |
| 345 | * check if the interface has this anycast address | 376 | * check if the interface has this anycast address |
| 346 | * called with rcu_read_lock() | 377 | * called with rcu_read_lock() |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index c3bf2d2e519e..2753319524f1 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -199,6 +199,7 @@ ipv4_connected: | |||
| 199 | NULL); | 199 | NULL); |
| 200 | 200 | ||
| 201 | sk->sk_state = TCP_ESTABLISHED; | 201 | sk->sk_state = TCP_ESTABLISHED; |
| 202 | ip6_set_txhash(sk); | ||
| 202 | out: | 203 | out: |
| 203 | fl6_sock_release(flowlabel); | 204 | fl6_sock_release(flowlabel); |
| 204 | return err; | 205 | return err; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f6c84a6eb238..06ba3e58320b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -626,9 +626,10 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
| 626 | int inner_offset; | 626 | int inner_offset; |
| 627 | __be16 frag_off; | 627 | __be16 frag_off; |
| 628 | u8 nexthdr; | 628 | u8 nexthdr; |
| 629 | struct net *net = dev_net(skb->dev); | ||
| 629 | 630 | ||
| 630 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 631 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
| 631 | return; | 632 | goto out; |
| 632 | 633 | ||
| 633 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; | 634 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; |
| 634 | if (ipv6_ext_hdr(nexthdr)) { | 635 | if (ipv6_ext_hdr(nexthdr)) { |
| @@ -636,14 +637,14 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
| 636 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), | 637 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), |
| 637 | &nexthdr, &frag_off); | 638 | &nexthdr, &frag_off); |
| 638 | if (inner_offset<0) | 639 | if (inner_offset<0) |
| 639 | return; | 640 | goto out; |
| 640 | } else { | 641 | } else { |
| 641 | inner_offset = sizeof(struct ipv6hdr); | 642 | inner_offset = sizeof(struct ipv6hdr); |
| 642 | } | 643 | } |
| 643 | 644 | ||
| 644 | /* Checkin header including 8 bytes of inner protocol header. */ | 645 | /* Checkin header including 8 bytes of inner protocol header. */ |
| 645 | if (!pskb_may_pull(skb, inner_offset+8)) | 646 | if (!pskb_may_pull(skb, inner_offset+8)) |
| 646 | return; | 647 | goto out; |
| 647 | 648 | ||
| 648 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 649 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
| 649 | Without this we will not able f.e. to make source routed | 650 | Without this we will not able f.e. to make source routed |
| @@ -652,13 +653,15 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
| 652 | --ANK (980726) | 653 | --ANK (980726) |
| 653 | */ | 654 | */ |
| 654 | 655 | ||
| 655 | rcu_read_lock(); | ||
| 656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); | 656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); |
| 657 | if (ipprot && ipprot->err_handler) | 657 | if (ipprot && ipprot->err_handler) |
| 658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); | 658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); |
| 659 | rcu_read_unlock(); | ||
| 660 | 659 | ||
| 661 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); | 660 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); |
| 661 | return; | ||
| 662 | |||
| 663 | out: | ||
| 664 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | ||
| 662 | } | 665 | } |
| 663 | 666 | ||
| 664 | /* | 667 | /* |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index cb4459bd1d29..97b9fa8de377 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -643,7 +643,7 @@ static int fib6_commit_metrics(struct dst_entry *dst, | |||
| 643 | if (dst->flags & DST_HOST) { | 643 | if (dst->flags & DST_HOST) { |
| 644 | mp = dst_metrics_write_ptr(dst); | 644 | mp = dst_metrics_write_ptr(dst); |
| 645 | } else { | 645 | } else { |
| 646 | mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | 646 | mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC); |
| 647 | if (!mp) | 647 | if (!mp) |
| 648 | return -ENOMEM; | 648 | return -ENOMEM; |
| 649 | dst_init_metrics(dst, mp, 0); | 649 | dst_init_metrics(dst, mp, 0); |
| @@ -1605,6 +1605,24 @@ static void fib6_prune_clones(struct net *net, struct fib6_node *fn) | |||
| 1605 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL); | 1605 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL); |
| 1606 | } | 1606 | } |
| 1607 | 1607 | ||
| 1608 | static int fib6_update_sernum(struct rt6_info *rt, void *arg) | ||
| 1609 | { | ||
| 1610 | __u32 sernum = *(__u32 *)arg; | ||
| 1611 | |||
| 1612 | if (rt->rt6i_node && | ||
| 1613 | rt->rt6i_node->fn_sernum != sernum) | ||
| 1614 | rt->rt6i_node->fn_sernum = sernum; | ||
| 1615 | |||
| 1616 | return 0; | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | static void fib6_flush_trees(struct net *net) | ||
| 1620 | { | ||
| 1621 | __u32 new_sernum = fib6_new_sernum(); | ||
| 1622 | |||
| 1623 | fib6_clean_all(net, fib6_update_sernum, &new_sernum); | ||
| 1624 | } | ||
| 1625 | |||
| 1608 | /* | 1626 | /* |
| 1609 | * Garbage collection | 1627 | * Garbage collection |
| 1610 | */ | 1628 | */ |
| @@ -1788,6 +1806,8 @@ int __init fib6_init(void) | |||
| 1788 | NULL); | 1806 | NULL); |
| 1789 | if (ret) | 1807 | if (ret) |
| 1790 | goto out_unregister_subsys; | 1808 | goto out_unregister_subsys; |
| 1809 | |||
| 1810 | __fib6_flush_trees = fib6_flush_trees; | ||
| 1791 | out: | 1811 | out: |
| 1792 | return ret; | 1812 | return ret; |
| 1793 | 1813 | ||
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 3873181ed856..f304471477dc 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -314,6 +314,8 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, | |||
| 314 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | 314 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); |
| 315 | 315 | ||
| 316 | t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); | 316 | t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); |
| 317 | if (t && create) | ||
| 318 | return NULL; | ||
| 317 | if (t || !create) | 319 | if (t || !create) |
| 318 | return t; | 320 | return t; |
| 319 | 321 | ||
| @@ -322,7 +324,8 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, | |||
| 322 | else | 324 | else |
| 323 | strcpy(name, "ip6gre%d"); | 325 | strcpy(name, "ip6gre%d"); |
| 324 | 326 | ||
| 325 | dev = alloc_netdev(sizeof(*t), name, ip6gre_tunnel_setup); | 327 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
| 328 | ip6gre_tunnel_setup); | ||
| 326 | if (!dev) | 329 | if (!dev) |
| 327 | return NULL; | 330 | return NULL; |
| 328 | 331 | ||
| @@ -723,7 +726,8 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
| 723 | * Push down and install the IP header. | 726 | * Push down and install the IP header. |
| 724 | */ | 727 | */ |
| 725 | ipv6h = ipv6_hdr(skb); | 728 | ipv6h = ipv6_hdr(skb); |
| 726 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); | 729 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), |
| 730 | ip6_make_flowlabel(net, skb, fl6->flowlabel, false)); | ||
| 727 | ipv6h->hop_limit = tunnel->parms.hop_limit; | 731 | ipv6h->hop_limit = tunnel->parms.hop_limit; |
| 728 | ipv6h->nexthdr = proto; | 732 | ipv6h->nexthdr = proto; |
| 729 | ipv6h->saddr = fl6->saddr; | 733 | ipv6h->saddr = fl6->saddr; |
| @@ -1174,7 +1178,9 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, | |||
| 1174 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); | 1178 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); |
| 1175 | __be16 *p = (__be16 *)(ipv6h+1); | 1179 | __be16 *p = (__be16 *)(ipv6h+1); |
| 1176 | 1180 | ||
| 1177 | ip6_flow_hdr(ipv6h, 0, t->fl.u.ip6.flowlabel); | 1181 | ip6_flow_hdr(ipv6h, 0, |
| 1182 | ip6_make_flowlabel(dev_net(dev), skb, | ||
| 1183 | t->fl.u.ip6.flowlabel, false)); | ||
| 1178 | ipv6h->hop_limit = t->parms.hop_limit; | 1184 | ipv6h->hop_limit = t->parms.hop_limit; |
| 1179 | ipv6h->nexthdr = NEXTHDR_GRE; | 1185 | ipv6h->nexthdr = NEXTHDR_GRE; |
| 1180 | ipv6h->saddr = t->parms.laddr; | 1186 | ipv6h->saddr = t->parms.laddr; |
| @@ -1323,7 +1329,8 @@ static int __net_init ip6gre_init_net(struct net *net) | |||
| 1323 | int err; | 1329 | int err; |
| 1324 | 1330 | ||
| 1325 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", | 1331 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", |
| 1326 | ip6gre_tunnel_setup); | 1332 | NET_NAME_UNKNOWN, |
| 1333 | ip6gre_tunnel_setup); | ||
| 1327 | if (!ign->fb_tunnel_dev) { | 1334 | if (!ign->fb_tunnel_dev) { |
| 1328 | err = -ENOMEM; | 1335 | err = -ENOMEM; |
| 1329 | goto err_alloc_dev; | 1336 | goto err_alloc_dev; |
| @@ -1719,4 +1726,5 @@ MODULE_LICENSE("GPL"); | |||
| 1719 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); | 1726 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); |
| 1720 | MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); | 1727 | MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); |
| 1721 | MODULE_ALIAS_RTNL_LINK("ip6gre"); | 1728 | MODULE_ALIAS_RTNL_LINK("ip6gre"); |
| 1729 | MODULE_ALIAS_RTNL_LINK("ip6gretap"); | ||
| 1722 | MODULE_ALIAS_NETDEV("ip6gre0"); | 1730 | MODULE_ALIAS_NETDEV("ip6gre0"); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 45702b8cd141..0a3448b2888f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -205,7 +205,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
| 205 | if (hlimit < 0) | 205 | if (hlimit < 0) |
| 206 | hlimit = ip6_dst_hoplimit(dst); | 206 | hlimit = ip6_dst_hoplimit(dst); |
| 207 | 207 | ||
| 208 | ip6_flow_hdr(hdr, tclass, fl6->flowlabel); | 208 | ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, |
| 209 | np->autoflowlabel)); | ||
| 209 | 210 | ||
| 210 | hdr->payload_len = htons(seg_len); | 211 | hdr->payload_len = htons(seg_len); |
| 211 | hdr->nexthdr = proto; | 212 | hdr->nexthdr = proto; |
| @@ -802,8 +803,8 @@ slow_path: | |||
| 802 | /* | 803 | /* |
| 803 | * Copy a block of the IP datagram. | 804 | * Copy a block of the IP datagram. |
| 804 | */ | 805 | */ |
| 805 | if (skb_copy_bits(skb, ptr, skb_transport_header(frag), len)) | 806 | BUG_ON(skb_copy_bits(skb, ptr, skb_transport_header(frag), |
| 806 | BUG(); | 807 | len)); |
| 807 | left -= len; | 808 | left -= len; |
| 808 | 809 | ||
| 809 | fh->frag_off = htons(offset); | 810 | fh->frag_off = htons(offset); |
| @@ -1008,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
| 1008 | if (final_dst) | 1009 | if (final_dst) |
| 1009 | fl6->daddr = *final_dst; | 1010 | fl6->daddr = *final_dst; |
| 1010 | 1011 | ||
| 1011 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | 1012 | return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
| 1012 | } | 1013 | } |
| 1013 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | 1014 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); |
| 1014 | 1015 | ||
| @@ -1040,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
| 1040 | if (final_dst) | 1041 | if (final_dst) |
| 1041 | fl6->daddr = *final_dst; | 1042 | fl6->daddr = *final_dst; |
| 1042 | 1043 | ||
| 1043 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | 1044 | return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
| 1044 | } | 1045 | } |
| 1045 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); | 1046 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
| 1046 | 1047 | ||
| @@ -1156,6 +1157,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1156 | int err; | 1157 | int err; |
| 1157 | int offset = 0; | 1158 | int offset = 0; |
| 1158 | __u8 tx_flags = 0; | 1159 | __u8 tx_flags = 0; |
| 1160 | u32 tskey = 0; | ||
| 1159 | 1161 | ||
| 1160 | if (flags&MSG_PROBE) | 1162 | if (flags&MSG_PROBE) |
| 1161 | return 0; | 1163 | return 0; |
| @@ -1271,9 +1273,12 @@ emsgsize: | |||
| 1271 | } | 1273 | } |
| 1272 | } | 1274 | } |
| 1273 | 1275 | ||
| 1274 | /* For UDP, check if TX timestamp is enabled */ | 1276 | if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { |
| 1275 | if (sk->sk_type == SOCK_DGRAM) | ||
| 1276 | sock_tx_timestamp(sk, &tx_flags); | 1277 | sock_tx_timestamp(sk, &tx_flags); |
| 1278 | if (tx_flags & SKBTX_ANY_SW_TSTAMP && | ||
| 1279 | sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) | ||
| 1280 | tskey = sk->sk_tskey++; | ||
| 1281 | } | ||
| 1277 | 1282 | ||
| 1278 | /* | 1283 | /* |
| 1279 | * Let's try using as much space as possible. | 1284 | * Let's try using as much space as possible. |
| @@ -1381,12 +1386,6 @@ alloc_new_skb: | |||
| 1381 | sk->sk_allocation); | 1386 | sk->sk_allocation); |
| 1382 | if (unlikely(skb == NULL)) | 1387 | if (unlikely(skb == NULL)) |
| 1383 | err = -ENOBUFS; | 1388 | err = -ENOBUFS; |
| 1384 | else { | ||
| 1385 | /* Only the initial fragment | ||
| 1386 | * is time stamped. | ||
| 1387 | */ | ||
| 1388 | tx_flags = 0; | ||
| 1389 | } | ||
| 1390 | } | 1389 | } |
| 1391 | if (skb == NULL) | 1390 | if (skb == NULL) |
| 1392 | goto error; | 1391 | goto error; |
| @@ -1400,8 +1399,11 @@ alloc_new_skb: | |||
| 1400 | skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + | 1399 | skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + |
| 1401 | dst_exthdrlen); | 1400 | dst_exthdrlen); |
| 1402 | 1401 | ||
| 1403 | if (sk->sk_type == SOCK_DGRAM) | 1402 | /* Only the initial fragment is time stamped */ |
| 1404 | skb_shinfo(skb)->tx_flags = tx_flags; | 1403 | skb_shinfo(skb)->tx_flags = tx_flags; |
| 1404 | tx_flags = 0; | ||
| 1405 | skb_shinfo(skb)->tskey = tskey; | ||
| 1406 | tskey = 0; | ||
| 1405 | 1407 | ||
| 1406 | /* | 1408 | /* |
| 1407 | * Find where to start putting bytes | 1409 | * Find where to start putting bytes |
| @@ -1571,7 +1573,9 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1571 | skb_reset_network_header(skb); | 1573 | skb_reset_network_header(skb); |
| 1572 | hdr = ipv6_hdr(skb); | 1574 | hdr = ipv6_hdr(skb); |
| 1573 | 1575 | ||
| 1574 | ip6_flow_hdr(hdr, np->cork.tclass, fl6->flowlabel); | 1576 | ip6_flow_hdr(hdr, np->cork.tclass, |
| 1577 | ip6_make_flowlabel(net, skb, fl6->flowlabel, | ||
| 1578 | np->autoflowlabel)); | ||
| 1575 | hdr->hop_limit = np->cork.hop_limit; | 1579 | hdr->hop_limit = np->cork.hop_limit; |
| 1576 | hdr->nexthdr = proto; | 1580 | hdr->nexthdr = proto; |
| 1577 | hdr->saddr = fl6->saddr; | 1581 | hdr->saddr = fl6->saddr; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index afa082458360..69a84b464009 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -315,7 +315,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) | |||
| 315 | else | 315 | else |
| 316 | sprintf(name, "ip6tnl%%d"); | 316 | sprintf(name, "ip6tnl%%d"); |
| 317 | 317 | ||
| 318 | dev = alloc_netdev(sizeof (*t), name, ip6_tnl_dev_setup); | 318 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
| 319 | ip6_tnl_dev_setup); | ||
| 319 | if (dev == NULL) | 320 | if (dev == NULL) |
| 320 | goto failed; | 321 | goto failed; |
| 321 | 322 | ||
| @@ -363,8 +364,12 @@ static struct ip6_tnl *ip6_tnl_locate(struct net *net, | |||
| 363 | (t = rtnl_dereference(*tp)) != NULL; | 364 | (t = rtnl_dereference(*tp)) != NULL; |
| 364 | tp = &t->next) { | 365 | tp = &t->next) { |
| 365 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 366 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
| 366 | ipv6_addr_equal(remote, &t->parms.raddr)) | 367 | ipv6_addr_equal(remote, &t->parms.raddr)) { |
| 368 | if (create) | ||
| 369 | return NULL; | ||
| 370 | |||
| 367 | return t; | 371 | return t; |
| 372 | } | ||
| 368 | } | 373 | } |
| 369 | if (!create) | 374 | if (!create) |
| 370 | return NULL; | 375 | return NULL; |
| @@ -1046,7 +1051,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
| 1046 | skb_push(skb, sizeof(struct ipv6hdr)); | 1051 | skb_push(skb, sizeof(struct ipv6hdr)); |
| 1047 | skb_reset_network_header(skb); | 1052 | skb_reset_network_header(skb); |
| 1048 | ipv6h = ipv6_hdr(skb); | 1053 | ipv6h = ipv6_hdr(skb); |
| 1049 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); | 1054 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), |
| 1055 | ip6_make_flowlabel(net, skb, fl6->flowlabel, false)); | ||
| 1050 | ipv6h->hop_limit = t->parms.hop_limit; | 1056 | ipv6h->hop_limit = t->parms.hop_limit; |
| 1051 | ipv6h->nexthdr = proto; | 1057 | ipv6h->nexthdr = proto; |
| 1052 | ipv6h->saddr = fl6->saddr; | 1058 | ipv6h->saddr = fl6->saddr; |
| @@ -1772,7 +1778,7 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
| 1772 | 1778 | ||
| 1773 | err = -ENOMEM; | 1779 | err = -ENOMEM; |
| 1774 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | 1780 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", |
| 1775 | ip6_tnl_dev_setup); | 1781 | NET_NAME_UNKNOWN, ip6_tnl_dev_setup); |
| 1776 | 1782 | ||
| 1777 | if (!ip6n->fb_tnl_dev) | 1783 | if (!ip6n->fb_tnl_dev) |
| 1778 | goto err_alloc_dev; | 1784 | goto err_alloc_dev; |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 9aaa6bb229e4..5833a2244467 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
| @@ -204,7 +204,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p | |||
| 204 | else | 204 | else |
| 205 | sprintf(name, "ip6_vti%%d"); | 205 | sprintf(name, "ip6_vti%%d"); |
| 206 | 206 | ||
| 207 | dev = alloc_netdev(sizeof(*t), name, vti6_dev_setup); | 207 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, vti6_dev_setup); |
| 208 | if (dev == NULL) | 208 | if (dev == NULL) |
| 209 | goto failed; | 209 | goto failed; |
| 210 | 210 | ||
| @@ -253,8 +253,12 @@ static struct ip6_tnl *vti6_locate(struct net *net, struct __ip6_tnl_parm *p, | |||
| 253 | (t = rtnl_dereference(*tp)) != NULL; | 253 | (t = rtnl_dereference(*tp)) != NULL; |
| 254 | tp = &t->next) { | 254 | tp = &t->next) { |
| 255 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 255 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
| 256 | ipv6_addr_equal(remote, &t->parms.raddr)) | 256 | ipv6_addr_equal(remote, &t->parms.raddr)) { |
| 257 | if (create) | ||
| 258 | return NULL; | ||
| 259 | |||
| 257 | return t; | 260 | return t; |
| 261 | } | ||
| 258 | } | 262 | } |
| 259 | if (!create) | 263 | if (!create) |
| 260 | return NULL; | 264 | return NULL; |
| @@ -1020,7 +1024,7 @@ static int __net_init vti6_init_net(struct net *net) | |||
| 1020 | 1024 | ||
| 1021 | err = -ENOMEM; | 1025 | err = -ENOMEM; |
| 1022 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", | 1026 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", |
| 1023 | vti6_dev_setup); | 1027 | NET_NAME_UNKNOWN, vti6_dev_setup); |
| 1024 | 1028 | ||
| 1025 | if (!ip6n->fb_tnl_dev) | 1029 | if (!ip6n->fb_tnl_dev) |
| 1026 | goto err_alloc_dev; | 1030 | goto err_alloc_dev; |
| @@ -1089,36 +1093,26 @@ static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = { | |||
| 1089 | **/ | 1093 | **/ |
| 1090 | static int __init vti6_tunnel_init(void) | 1094 | static int __init vti6_tunnel_init(void) |
| 1091 | { | 1095 | { |
| 1092 | int err; | 1096 | const char *msg; |
| 1097 | int err; | ||
| 1093 | 1098 | ||
| 1099 | msg = "tunnel device"; | ||
| 1094 | err = register_pernet_device(&vti6_net_ops); | 1100 | err = register_pernet_device(&vti6_net_ops); |
| 1095 | if (err < 0) | 1101 | if (err < 0) |
| 1096 | goto out_pernet; | 1102 | goto pernet_dev_failed; |
| 1097 | 1103 | ||
| 1104 | msg = "tunnel protocols"; | ||
| 1098 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); | 1105 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); |
| 1099 | if (err < 0) { | 1106 | if (err < 0) |
| 1100 | pr_err("%s: can't register vti6 protocol\n", __func__); | 1107 | goto xfrm_proto_esp_failed; |
| 1101 | |||
| 1102 | goto out; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); | 1108 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); |
| 1106 | if (err < 0) { | 1109 | if (err < 0) |
| 1107 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1110 | goto xfrm_proto_ah_failed; |
| 1108 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
| 1109 | |||
| 1110 | goto out; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); | 1111 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); |
| 1114 | if (err < 0) { | 1112 | if (err < 0) |
| 1115 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | 1113 | goto xfrm_proto_comp_failed; |
| 1116 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | ||
| 1117 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
| 1118 | |||
| 1119 | goto out; | ||
| 1120 | } | ||
| 1121 | 1114 | ||
| 1115 | msg = "netlink interface"; | ||
| 1122 | err = rtnl_link_register(&vti6_link_ops); | 1116 | err = rtnl_link_register(&vti6_link_ops); |
| 1123 | if (err < 0) | 1117 | if (err < 0) |
| 1124 | goto rtnl_link_failed; | 1118 | goto rtnl_link_failed; |
| @@ -1127,11 +1121,14 @@ static int __init vti6_tunnel_init(void) | |||
| 1127 | 1121 | ||
| 1128 | rtnl_link_failed: | 1122 | rtnl_link_failed: |
| 1129 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); | 1123 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
| 1124 | xfrm_proto_comp_failed: | ||
| 1130 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | 1125 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
| 1126 | xfrm_proto_ah_failed: | ||
| 1131 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1127 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
| 1132 | out: | 1128 | xfrm_proto_esp_failed: |
| 1133 | unregister_pernet_device(&vti6_net_ops); | 1129 | unregister_pernet_device(&vti6_net_ops); |
| 1134 | out_pernet: | 1130 | pernet_dev_failed: |
| 1131 | pr_err("vti6 init: failed to register %s\n", msg); | ||
| 1135 | return err; | 1132 | return err; |
| 1136 | } | 1133 | } |
| 1137 | 1134 | ||
| @@ -1141,13 +1138,9 @@ out_pernet: | |||
| 1141 | static void __exit vti6_tunnel_cleanup(void) | 1138 | static void __exit vti6_tunnel_cleanup(void) |
| 1142 | { | 1139 | { |
| 1143 | rtnl_link_unregister(&vti6_link_ops); | 1140 | rtnl_link_unregister(&vti6_link_ops); |
| 1144 | if (xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP)) | 1141 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
| 1145 | pr_info("%s: can't deregister protocol\n", __func__); | 1142 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
| 1146 | if (xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH)) | 1143 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
| 1147 | pr_info("%s: can't deregister protocol\n", __func__); | ||
| 1148 | if (xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP)) | ||
| 1149 | pr_info("%s: can't deregister protocol\n", __func__); | ||
| 1150 | |||
| 1151 | unregister_pernet_device(&vti6_net_ops); | 1144 | unregister_pernet_device(&vti6_net_ops); |
| 1152 | } | 1145 | } |
| 1153 | 1146 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8250474ab7dc..f9a3fd320d1d 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -744,7 +744,7 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) | |||
| 744 | else | 744 | else |
| 745 | sprintf(name, "pim6reg%u", mrt->id); | 745 | sprintf(name, "pim6reg%u", mrt->id); |
| 746 | 746 | ||
| 747 | dev = alloc_netdev(0, name, reg_vif_setup); | 747 | dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup); |
| 748 | if (dev == NULL) | 748 | if (dev == NULL) |
| 749 | return NULL; | 749 | return NULL; |
| 750 | 750 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index edb58aff4ae7..0c289982796d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -235,7 +235,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 235 | if (optlen < sizeof(int) || | 235 | if (optlen < sizeof(int) || |
| 236 | inet_sk(sk)->inet_num) | 236 | inet_sk(sk)->inet_num) |
| 237 | goto e_inval; | 237 | goto e_inval; |
| 238 | np->ipv6only = valbool; | 238 | sk->sk_ipv6only = valbool; |
| 239 | retv = 0; | 239 | retv = 0; |
| 240 | break; | 240 | break; |
| 241 | 241 | ||
| @@ -834,6 +834,10 @@ pref_skip_coa: | |||
| 834 | np->dontfrag = valbool; | 834 | np->dontfrag = valbool; |
| 835 | retv = 0; | 835 | retv = 0; |
| 836 | break; | 836 | break; |
| 837 | case IPV6_AUTOFLOWLABEL: | ||
| 838 | np->autoflowlabel = valbool; | ||
| 839 | retv = 0; | ||
| 840 | break; | ||
| 837 | } | 841 | } |
| 838 | 842 | ||
| 839 | release_sock(sk); | 843 | release_sock(sk); |
| @@ -1058,7 +1062,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1058 | } | 1062 | } |
| 1059 | 1063 | ||
| 1060 | case IPV6_V6ONLY: | 1064 | case IPV6_V6ONLY: |
| 1061 | val = np->ipv6only; | 1065 | val = sk->sk_ipv6only; |
| 1062 | break; | 1066 | break; |
| 1063 | 1067 | ||
| 1064 | case IPV6_RECVPKTINFO: | 1068 | case IPV6_RECVPKTINFO: |
| @@ -1158,7 +1162,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1158 | return -EFAULT; | 1162 | return -EFAULT; |
| 1159 | 1163 | ||
| 1160 | return 0; | 1164 | return 0; |
| 1161 | break; | ||
| 1162 | } | 1165 | } |
| 1163 | 1166 | ||
| 1164 | case IPV6_TRANSPARENT: | 1167 | case IPV6_TRANSPARENT: |
| @@ -1273,6 +1276,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1273 | val = np->dontfrag; | 1276 | val = np->dontfrag; |
| 1274 | break; | 1277 | break; |
| 1275 | 1278 | ||
| 1279 | case IPV6_AUTOFLOWLABEL: | ||
| 1280 | val = np->autoflowlabel; | ||
| 1281 | break; | ||
| 1282 | |||
| 1276 | default: | 1283 | default: |
| 1277 | return -ENOPROTOOPT; | 1284 | return -ENOPROTOOPT; |
| 1278 | } | 1285 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 617f0958e164..a23b655a7627 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -172,6 +172,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 172 | mc_lst->next = NULL; | 172 | mc_lst->next = NULL; |
| 173 | mc_lst->addr = *addr; | 173 | mc_lst->addr = *addr; |
| 174 | 174 | ||
| 175 | rtnl_lock(); | ||
| 175 | rcu_read_lock(); | 176 | rcu_read_lock(); |
| 176 | if (ifindex == 0) { | 177 | if (ifindex == 0) { |
| 177 | struct rt6_info *rt; | 178 | struct rt6_info *rt; |
| @@ -185,6 +186,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 185 | 186 | ||
| 186 | if (dev == NULL) { | 187 | if (dev == NULL) { |
| 187 | rcu_read_unlock(); | 188 | rcu_read_unlock(); |
| 189 | rtnl_unlock(); | ||
| 188 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 190 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 189 | return -ENODEV; | 191 | return -ENODEV; |
| 190 | } | 192 | } |
| @@ -202,6 +204,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 202 | 204 | ||
| 203 | if (err) { | 205 | if (err) { |
| 204 | rcu_read_unlock(); | 206 | rcu_read_unlock(); |
| 207 | rtnl_unlock(); | ||
| 205 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 208 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
| 206 | return err; | 209 | return err; |
| 207 | } | 210 | } |
| @@ -212,6 +215,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 212 | spin_unlock(&ipv6_sk_mc_lock); | 215 | spin_unlock(&ipv6_sk_mc_lock); |
| 213 | 216 | ||
| 214 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
| 218 | rtnl_unlock(); | ||
| 215 | 219 | ||
| 216 | return 0; | 220 | return 0; |
| 217 | } | 221 | } |
| @@ -229,6 +233,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 229 | if (!ipv6_addr_is_multicast(addr)) | 233 | if (!ipv6_addr_is_multicast(addr)) |
| 230 | return -EINVAL; | 234 | return -EINVAL; |
| 231 | 235 | ||
| 236 | rtnl_lock(); | ||
| 232 | spin_lock(&ipv6_sk_mc_lock); | 237 | spin_lock(&ipv6_sk_mc_lock); |
| 233 | for (lnk = &np->ipv6_mc_list; | 238 | for (lnk = &np->ipv6_mc_list; |
| 234 | (mc_lst = rcu_dereference_protected(*lnk, | 239 | (mc_lst = rcu_dereference_protected(*lnk, |
| @@ -252,12 +257,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
| 252 | } else | 257 | } else |
| 253 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 258 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
| 254 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
| 260 | rtnl_unlock(); | ||
| 261 | |||
| 255 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); | 262 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); |
| 256 | kfree_rcu(mc_lst, rcu); | 263 | kfree_rcu(mc_lst, rcu); |
| 257 | return 0; | 264 | return 0; |
| 258 | } | 265 | } |
| 259 | } | 266 | } |
| 260 | spin_unlock(&ipv6_sk_mc_lock); | 267 | spin_unlock(&ipv6_sk_mc_lock); |
| 268 | rtnl_unlock(); | ||
| 261 | 269 | ||
| 262 | return -EADDRNOTAVAIL; | 270 | return -EADDRNOTAVAIL; |
| 263 | } | 271 | } |
| @@ -302,6 +310,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
| 302 | if (!rcu_access_pointer(np->ipv6_mc_list)) | 310 | if (!rcu_access_pointer(np->ipv6_mc_list)) |
| 303 | return; | 311 | return; |
| 304 | 312 | ||
| 313 | rtnl_lock(); | ||
| 305 | spin_lock(&ipv6_sk_mc_lock); | 314 | spin_lock(&ipv6_sk_mc_lock); |
| 306 | while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, | 315 | while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, |
| 307 | lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { | 316 | lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { |
| @@ -328,6 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
| 328 | spin_lock(&ipv6_sk_mc_lock); | 337 | spin_lock(&ipv6_sk_mc_lock); |
| 329 | } | 338 | } |
| 330 | spin_unlock(&ipv6_sk_mc_lock); | 339 | spin_unlock(&ipv6_sk_mc_lock); |
| 340 | rtnl_unlock(); | ||
| 331 | } | 341 | } |
| 332 | 342 | ||
| 333 | int ip6_mc_source(int add, int omode, struct sock *sk, | 343 | int ip6_mc_source(int add, int omode, struct sock *sk, |
| @@ -845,6 +855,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
| 845 | struct ifmcaddr6 *mc; | 855 | struct ifmcaddr6 *mc; |
| 846 | struct inet6_dev *idev; | 856 | struct inet6_dev *idev; |
| 847 | 857 | ||
| 858 | ASSERT_RTNL(); | ||
| 859 | |||
| 848 | /* we need to take a reference on idev */ | 860 | /* we need to take a reference on idev */ |
| 849 | idev = in6_dev_get(dev); | 861 | idev = in6_dev_get(dev); |
| 850 | 862 | ||
| @@ -916,6 +928,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
| 916 | { | 928 | { |
| 917 | struct ifmcaddr6 *ma, **map; | 929 | struct ifmcaddr6 *ma, **map; |
| 918 | 930 | ||
| 931 | ASSERT_RTNL(); | ||
| 932 | |||
| 919 | write_lock_bh(&idev->lock); | 933 | write_lock_bh(&idev->lock); |
| 920 | for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { | 934 | for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { |
| 921 | if (ipv6_addr_equal(&ma->mca_addr, addr)) { | 935 | if (ipv6_addr_equal(&ma->mca_addr, addr)) { |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ca8d4ea48a5d..339078f95d1b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1070,6 +1070,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1070 | optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - | 1070 | optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - |
| 1071 | sizeof(struct ra_msg); | 1071 | sizeof(struct ra_msg); |
| 1072 | 1072 | ||
| 1073 | ND_PRINTK(2, info, | ||
| 1074 | "RA: %s, dev: %s\n", | ||
| 1075 | __func__, skb->dev->name); | ||
| 1073 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1076 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
| 1074 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); | 1077 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); |
| 1075 | return; | 1078 | return; |
| @@ -1102,13 +1105,21 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1102 | return; | 1105 | return; |
| 1103 | } | 1106 | } |
| 1104 | 1107 | ||
| 1105 | if (!ipv6_accept_ra(in6_dev)) | 1108 | if (!ipv6_accept_ra(in6_dev)) { |
| 1109 | ND_PRINTK(2, info, | ||
| 1110 | "RA: %s, did not accept ra for dev: %s\n", | ||
| 1111 | __func__, skb->dev->name); | ||
| 1106 | goto skip_linkparms; | 1112 | goto skip_linkparms; |
| 1113 | } | ||
| 1107 | 1114 | ||
| 1108 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1115 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
| 1109 | /* skip link-specific parameters from interior routers */ | 1116 | /* skip link-specific parameters from interior routers */ |
| 1110 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | 1117 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) { |
| 1118 | ND_PRINTK(2, info, | ||
| 1119 | "RA: %s, nodetype is NODEFAULT, dev: %s\n", | ||
| 1120 | __func__, skb->dev->name); | ||
| 1111 | goto skip_linkparms; | 1121 | goto skip_linkparms; |
| 1122 | } | ||
| 1112 | #endif | 1123 | #endif |
| 1113 | 1124 | ||
| 1114 | if (in6_dev->if_flags & IF_RS_SENT) { | 1125 | if (in6_dev->if_flags & IF_RS_SENT) { |
| @@ -1130,11 +1141,24 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1130 | (ra_msg->icmph.icmp6_addrconf_other ? | 1141 | (ra_msg->icmph.icmp6_addrconf_other ? |
| 1131 | IF_RA_OTHERCONF : 0); | 1142 | IF_RA_OTHERCONF : 0); |
| 1132 | 1143 | ||
| 1133 | if (!in6_dev->cnf.accept_ra_defrtr) | 1144 | if (!in6_dev->cnf.accept_ra_defrtr) { |
| 1145 | ND_PRINTK(2, info, | ||
| 1146 | "RA: %s, defrtr is false for dev: %s\n", | ||
| 1147 | __func__, skb->dev->name); | ||
| 1134 | goto skip_defrtr; | 1148 | goto skip_defrtr; |
| 1149 | } | ||
| 1135 | 1150 | ||
| 1136 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | 1151 | /* Do not accept RA with source-addr found on local machine unless |
| 1152 | * accept_ra_from_local is set to true. | ||
| 1153 | */ | ||
| 1154 | if (!in6_dev->cnf.accept_ra_from_local && | ||
| 1155 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | ||
| 1156 | NULL, 0)) { | ||
| 1157 | ND_PRINTK(2, info, | ||
| 1158 | "RA from local address detected on dev: %s: default router ignored\n", | ||
| 1159 | skb->dev->name); | ||
| 1137 | goto skip_defrtr; | 1160 | goto skip_defrtr; |
| 1161 | } | ||
| 1138 | 1162 | ||
| 1139 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); | 1163 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); |
| 1140 | 1164 | ||
| @@ -1163,8 +1187,10 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1163 | rt = NULL; | 1187 | rt = NULL; |
| 1164 | } | 1188 | } |
| 1165 | 1189 | ||
| 1190 | ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n", | ||
| 1191 | rt, lifetime, skb->dev->name); | ||
| 1166 | if (rt == NULL && lifetime) { | 1192 | if (rt == NULL && lifetime) { |
| 1167 | ND_PRINTK(3, dbg, "RA: adding default router\n"); | 1193 | ND_PRINTK(3, info, "RA: adding default router\n"); |
| 1168 | 1194 | ||
| 1169 | rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); | 1195 | rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); |
| 1170 | if (rt == NULL) { | 1196 | if (rt == NULL) { |
| @@ -1260,12 +1286,22 @@ skip_linkparms: | |||
| 1260 | NEIGH_UPDATE_F_ISROUTER); | 1286 | NEIGH_UPDATE_F_ISROUTER); |
| 1261 | } | 1287 | } |
| 1262 | 1288 | ||
| 1263 | if (!ipv6_accept_ra(in6_dev)) | 1289 | if (!ipv6_accept_ra(in6_dev)) { |
| 1290 | ND_PRINTK(2, info, | ||
| 1291 | "RA: %s, accept_ra is false for dev: %s\n", | ||
| 1292 | __func__, skb->dev->name); | ||
| 1264 | goto out; | 1293 | goto out; |
| 1294 | } | ||
| 1265 | 1295 | ||
| 1266 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1296 | #ifdef CONFIG_IPV6_ROUTE_INFO |
| 1267 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | 1297 | if (!in6_dev->cnf.accept_ra_from_local && |
| 1298 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | ||
| 1299 | NULL, 0)) { | ||
| 1300 | ND_PRINTK(2, info, | ||
| 1301 | "RA from local address detected on dev: %s: router info ignored.\n", | ||
| 1302 | skb->dev->name); | ||
| 1268 | goto skip_routeinfo; | 1303 | goto skip_routeinfo; |
| 1304 | } | ||
| 1269 | 1305 | ||
| 1270 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { | 1306 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { |
| 1271 | struct nd_opt_hdr *p; | 1307 | struct nd_opt_hdr *p; |
| @@ -1293,8 +1329,12 @@ skip_routeinfo: | |||
| 1293 | 1329 | ||
| 1294 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1330 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
| 1295 | /* skip link-specific ndopts from interior routers */ | 1331 | /* skip link-specific ndopts from interior routers */ |
| 1296 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | 1332 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) { |
| 1333 | ND_PRINTK(2, info, | ||
| 1334 | "RA: %s, nodetype is NODEFAULT (interior routes), dev: %s\n", | ||
| 1335 | __func__, skb->dev->name); | ||
| 1297 | goto out; | 1336 | goto out; |
| 1337 | } | ||
| 1298 | #endif | 1338 | #endif |
| 1299 | 1339 | ||
| 1300 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { | 1340 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { |
| @@ -1728,7 +1768,7 @@ int __init ndisc_init(void) | |||
| 1728 | 1768 | ||
| 1729 | #ifdef CONFIG_SYSCTL | 1769 | #ifdef CONFIG_SYSCTL |
| 1730 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, | 1770 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, |
| 1731 | &ndisc_ifinfo_sysctl_change); | 1771 | ndisc_ifinfo_sysctl_change); |
| 1732 | if (err) | 1772 | if (err) |
| 1733 | goto out_unregister_pernet; | 1773 | goto out_unregister_pernet; |
| 1734 | out: | 1774 | out: |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 4bff1f297e39..2812816aabdc 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -55,6 +55,21 @@ config NFT_REJECT_IPV6 | |||
| 55 | default NFT_REJECT | 55 | default NFT_REJECT |
| 56 | tristate | 56 | tristate |
| 57 | 57 | ||
| 58 | config NF_LOG_IPV6 | ||
| 59 | tristate "IPv6 packet logging" | ||
| 60 | default m if NETFILTER_ADVANCED=n | ||
| 61 | select NF_LOG_COMMON | ||
| 62 | |||
| 63 | config NF_NAT_IPV6 | ||
| 64 | tristate "IPv6 NAT" | ||
| 65 | depends on NF_CONNTRACK_IPV6 | ||
| 66 | depends on NETFILTER_ADVANCED | ||
| 67 | select NF_NAT | ||
| 68 | help | ||
| 69 | The IPv6 NAT option allows masquerading, port forwarding and other | ||
| 70 | forms of full Network Address Port Translation. This can be | ||
| 71 | controlled by iptables or nft. | ||
| 72 | |||
| 58 | config IP6_NF_IPTABLES | 73 | config IP6_NF_IPTABLES |
| 59 | tristate "IP6 tables support (required for filtering)" | 74 | tristate "IP6 tables support (required for filtering)" |
| 60 | depends on INET && IPV6 | 75 | depends on INET && IPV6 |
| @@ -227,19 +242,21 @@ config IP6_NF_SECURITY | |||
| 227 | 242 | ||
| 228 | If unsure, say N. | 243 | If unsure, say N. |
| 229 | 244 | ||
| 230 | config NF_NAT_IPV6 | 245 | config IP6_NF_NAT |
| 231 | tristate "IPv6 NAT" | 246 | tristate "ip6tables NAT support" |
| 232 | depends on NF_CONNTRACK_IPV6 | 247 | depends on NF_CONNTRACK_IPV6 |
| 233 | depends on NETFILTER_ADVANCED | 248 | depends on NETFILTER_ADVANCED |
| 234 | select NF_NAT | 249 | select NF_NAT |
| 250 | select NF_NAT_IPV6 | ||
| 251 | select NETFILTER_XT_NAT | ||
| 235 | help | 252 | help |
| 236 | The IPv6 NAT option allows masquerading, port forwarding and other | 253 | This enables the `nat' table in ip6tables. This allows masquerading, |
| 237 | forms of full Network Address Port Translation. It is controlled by | 254 | port forwarding and other forms of full Network Address Port |
| 238 | the `nat' table in ip6tables, see the man page for ip6tables(8). | 255 | Translation. |
| 239 | 256 | ||
| 240 | To compile it as a module, choose M here. If unsure, say N. | 257 | To compile it as a module, choose M here. If unsure, say N. |
| 241 | 258 | ||
| 242 | if NF_NAT_IPV6 | 259 | if IP6_NF_NAT |
| 243 | 260 | ||
| 244 | config IP6_NF_TARGET_MASQUERADE | 261 | config IP6_NF_TARGET_MASQUERADE |
| 245 | tristate "MASQUERADE target support" | 262 | tristate "MASQUERADE target support" |
| @@ -260,7 +277,7 @@ config IP6_NF_TARGET_NPT | |||
| 260 | 277 | ||
| 261 | To compile it as a module, choose M here. If unsure, say N. | 278 | To compile it as a module, choose M here. If unsure, say N. |
| 262 | 279 | ||
| 263 | endif # NF_NAT_IPV6 | 280 | endif # IP6_NF_NAT |
| 264 | 281 | ||
| 265 | endif # IP6_NF_IPTABLES | 282 | endif # IP6_NF_IPTABLES |
| 266 | 283 | ||
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 70d3dd66f2cd..c3d3286db4bb 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -8,7 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | |||
| 8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
| 9 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 9 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
| 10 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | 10 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o |
| 11 | obj-$(CONFIG_NF_NAT_IPV6) += ip6table_nat.o | 11 | obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o |
| 12 | 12 | ||
| 13 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
| 14 | nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o | 14 | nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o |
| @@ -23,6 +23,9 @@ obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o | |||
| 23 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | 23 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o |
| 24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | 24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o |
| 25 | 25 | ||
| 26 | # logging | ||
| 27 | obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o | ||
| 28 | |||
| 26 | # nf_tables | 29 | # nf_tables |
| 27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 30 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
| 28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 54bd9790603f..8b147440fbdc 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
| @@ -94,7 +94,6 @@ ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 94 | break; | 94 | break; |
| 95 | default: | 95 | default: |
| 96 | return false; | 96 | return false; |
| 97 | break; | ||
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | nexthdr = hp->nexthdr; | 99 | nexthdr = hp->nexthdr; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 0d5279fd852a..6f187c8d8a1b 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
| 51 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 51 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
| 52 | 52 | ||
| 53 | static const char nf_frags_cache_name[] = "nf-frags"; | ||
| 53 | 54 | ||
| 54 | struct nf_ct_frag6_skb_cb | 55 | struct nf_ct_frag6_skb_cb |
| 55 | { | 56 | { |
| @@ -63,6 +64,8 @@ struct nf_ct_frag6_skb_cb | |||
| 63 | static struct inet_frags nf_frags; | 64 | static struct inet_frags nf_frags; |
| 64 | 65 | ||
| 65 | #ifdef CONFIG_SYSCTL | 66 | #ifdef CONFIG_SYSCTL |
| 67 | static int zero; | ||
| 68 | |||
| 66 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { | 69 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { |
| 67 | { | 70 | { |
| 68 | .procname = "nf_conntrack_frag6_timeout", | 71 | .procname = "nf_conntrack_frag6_timeout", |
| @@ -76,14 +79,17 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = { | |||
| 76 | .data = &init_net.nf_frag.frags.low_thresh, | 79 | .data = &init_net.nf_frag.frags.low_thresh, |
| 77 | .maxlen = sizeof(unsigned int), | 80 | .maxlen = sizeof(unsigned int), |
| 78 | .mode = 0644, | 81 | .mode = 0644, |
| 79 | .proc_handler = proc_dointvec, | 82 | .proc_handler = proc_dointvec_minmax, |
| 83 | .extra1 = &zero, | ||
| 84 | .extra2 = &init_net.nf_frag.frags.high_thresh | ||
| 80 | }, | 85 | }, |
| 81 | { | 86 | { |
| 82 | .procname = "nf_conntrack_frag6_high_thresh", | 87 | .procname = "nf_conntrack_frag6_high_thresh", |
| 83 | .data = &init_net.nf_frag.frags.high_thresh, | 88 | .data = &init_net.nf_frag.frags.high_thresh, |
| 84 | .maxlen = sizeof(unsigned int), | 89 | .maxlen = sizeof(unsigned int), |
| 85 | .mode = 0644, | 90 | .mode = 0644, |
| 86 | .proc_handler = proc_dointvec, | 91 | .proc_handler = proc_dointvec_minmax, |
| 92 | .extra1 = &init_net.nf_frag.frags.low_thresh | ||
| 87 | }, | 93 | }, |
| 88 | { } | 94 | { } |
| 89 | }; | 95 | }; |
| @@ -102,7 +108,10 @@ static int nf_ct_frag6_sysctl_register(struct net *net) | |||
| 102 | 108 | ||
| 103 | table[0].data = &net->nf_frag.frags.timeout; | 109 | table[0].data = &net->nf_frag.frags.timeout; |
| 104 | table[1].data = &net->nf_frag.frags.low_thresh; | 110 | table[1].data = &net->nf_frag.frags.low_thresh; |
| 111 | table[1].extra2 = &net->nf_frag.frags.high_thresh; | ||
| 105 | table[2].data = &net->nf_frag.frags.high_thresh; | 112 | table[2].data = &net->nf_frag.frags.high_thresh; |
| 113 | table[2].extra1 = &net->nf_frag.frags.low_thresh; | ||
| 114 | table[2].extra2 = &init_net.nf_frag.frags.high_thresh; | ||
| 106 | } | 115 | } |
| 107 | 116 | ||
| 108 | hdr = register_net_sysctl(net, "net/netfilter", table); | 117 | hdr = register_net_sysctl(net, "net/netfilter", table); |
| @@ -147,16 +156,13 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h) | |||
| 147 | static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr, | 156 | static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr, |
| 148 | const struct in6_addr *daddr) | 157 | const struct in6_addr *daddr) |
| 149 | { | 158 | { |
| 150 | u32 c; | ||
| 151 | |||
| 152 | net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd)); | 159 | net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd)); |
| 153 | c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), | 160 | return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), |
| 154 | (__force u32)id, nf_frags.rnd); | 161 | (__force u32)id, nf_frags.rnd); |
| 155 | return c & (INETFRAGS_HASHSZ - 1); | ||
| 156 | } | 162 | } |
| 157 | 163 | ||
| 158 | 164 | ||
| 159 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 165 | static unsigned int nf_hashfn(const struct inet_frag_queue *q) |
| 160 | { | 166 | { |
| 161 | const struct frag_queue *nq; | 167 | const struct frag_queue *nq; |
| 162 | 168 | ||
| @@ -196,7 +202,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |||
| 196 | arg.dst = dst; | 202 | arg.dst = dst; |
| 197 | arg.ecn = ecn; | 203 | arg.ecn = ecn; |
| 198 | 204 | ||
| 199 | read_lock_bh(&nf_frags.lock); | 205 | local_bh_disable(); |
| 200 | hash = nf_hash_frag(id, src, dst); | 206 | hash = nf_hash_frag(id, src, dst); |
| 201 | 207 | ||
| 202 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); | 208 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); |
| @@ -217,7 +223,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 217 | int offset, end; | 223 | int offset, end; |
| 218 | u8 ecn; | 224 | u8 ecn; |
| 219 | 225 | ||
| 220 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 226 | if (fq->q.flags & INET_FRAG_COMPLETE) { |
| 221 | pr_debug("Already completed\n"); | 227 | pr_debug("Already completed\n"); |
| 222 | goto err; | 228 | goto err; |
| 223 | } | 229 | } |
| @@ -248,11 +254,11 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 248 | * or have different end, the segment is corrupted. | 254 | * or have different end, the segment is corrupted. |
| 249 | */ | 255 | */ |
| 250 | if (end < fq->q.len || | 256 | if (end < fq->q.len || |
| 251 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) { | 257 | ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len)) { |
| 252 | pr_debug("already received last fragment\n"); | 258 | pr_debug("already received last fragment\n"); |
| 253 | goto err; | 259 | goto err; |
| 254 | } | 260 | } |
| 255 | fq->q.last_in |= INET_FRAG_LAST_IN; | 261 | fq->q.flags |= INET_FRAG_LAST_IN; |
| 256 | fq->q.len = end; | 262 | fq->q.len = end; |
| 257 | } else { | 263 | } else { |
| 258 | /* Check if the fragment is rounded to 8 bytes. | 264 | /* Check if the fragment is rounded to 8 bytes. |
| @@ -267,7 +273,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 267 | } | 273 | } |
| 268 | if (end > fq->q.len) { | 274 | if (end > fq->q.len) { |
| 269 | /* Some bits beyond end -> corruption. */ | 275 | /* Some bits beyond end -> corruption. */ |
| 270 | if (fq->q.last_in & INET_FRAG_LAST_IN) { | 276 | if (fq->q.flags & INET_FRAG_LAST_IN) { |
| 271 | pr_debug("last packet already reached.\n"); | 277 | pr_debug("last packet already reached.\n"); |
| 272 | goto err; | 278 | goto err; |
| 273 | } | 279 | } |
| @@ -349,10 +355,9 @@ found: | |||
| 349 | */ | 355 | */ |
| 350 | if (offset == 0) { | 356 | if (offset == 0) { |
| 351 | fq->nhoffset = nhoff; | 357 | fq->nhoffset = nhoff; |
| 352 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 358 | fq->q.flags |= INET_FRAG_FIRST_IN; |
| 353 | } | 359 | } |
| 354 | 360 | ||
| 355 | inet_frag_lru_move(&fq->q); | ||
| 356 | return 0; | 361 | return 0; |
| 357 | 362 | ||
| 358 | discard_fq: | 363 | discard_fq: |
| @@ -597,10 +602,6 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
| 597 | hdr = ipv6_hdr(clone); | 602 | hdr = ipv6_hdr(clone); |
| 598 | fhdr = (struct frag_hdr *)skb_transport_header(clone); | 603 | fhdr = (struct frag_hdr *)skb_transport_header(clone); |
| 599 | 604 | ||
| 600 | local_bh_disable(); | ||
| 601 | inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false); | ||
| 602 | local_bh_enable(); | ||
| 603 | |||
| 604 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, | 605 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, |
| 605 | ip6_frag_ecn(hdr)); | 606 | ip6_frag_ecn(hdr)); |
| 606 | if (fq == NULL) { | 607 | if (fq == NULL) { |
| @@ -617,7 +618,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
| 617 | goto ret_orig; | 618 | goto ret_orig; |
| 618 | } | 619 | } |
| 619 | 620 | ||
| 620 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 621 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
| 621 | fq->q.meat == fq->q.len) { | 622 | fq->q.meat == fq->q.len) { |
| 622 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 623 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
| 623 | if (ret_skb == NULL) | 624 | if (ret_skb == NULL) |
| @@ -677,13 +678,15 @@ int nf_ct_frag6_init(void) | |||
| 677 | nf_frags.qsize = sizeof(struct frag_queue); | 678 | nf_frags.qsize = sizeof(struct frag_queue); |
| 678 | nf_frags.match = ip6_frag_match; | 679 | nf_frags.match = ip6_frag_match; |
| 679 | nf_frags.frag_expire = nf_ct_frag6_expire; | 680 | nf_frags.frag_expire = nf_ct_frag6_expire; |
| 680 | nf_frags.secret_interval = 10 * 60 * HZ; | 681 | nf_frags.frags_cache_name = nf_frags_cache_name; |
| 681 | inet_frags_init(&nf_frags); | 682 | ret = inet_frags_init(&nf_frags); |
| 682 | 683 | if (ret) | |
| 684 | goto out; | ||
| 683 | ret = register_pernet_subsys(&nf_ct_net_ops); | 685 | ret = register_pernet_subsys(&nf_ct_net_ops); |
| 684 | if (ret) | 686 | if (ret) |
| 685 | inet_frags_fini(&nf_frags); | 687 | inet_frags_fini(&nf_frags); |
| 686 | 688 | ||
| 689 | out: | ||
| 687 | return ret; | 690 | return ret; |
| 688 | } | 691 | } |
| 689 | 692 | ||
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c new file mode 100644 index 000000000000..7b17a0be93e7 --- /dev/null +++ b/net/ipv6/netfilter/nf_log_ipv6.c | |||
| @@ -0,0 +1,417 @@ | |||
| 1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
| 2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/spinlock.h> | ||
| 11 | #include <linux/skbuff.h> | ||
| 12 | #include <linux/if_arp.h> | ||
| 13 | #include <linux/ip.h> | ||
| 14 | #include <net/ipv6.h> | ||
| 15 | #include <net/icmp.h> | ||
| 16 | #include <net/udp.h> | ||
| 17 | #include <net/tcp.h> | ||
| 18 | #include <net/route.h> | ||
| 19 | |||
| 20 | #include <linux/netfilter.h> | ||
| 21 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
| 22 | #include <linux/netfilter/xt_LOG.h> | ||
| 23 | #include <net/netfilter/nf_log.h> | ||
| 24 | |||
| 25 | static struct nf_loginfo default_loginfo = { | ||
| 26 | .type = NF_LOG_TYPE_LOG, | ||
| 27 | .u = { | ||
| 28 | .log = { | ||
| 29 | .level = 5, | ||
| 30 | .logflags = NF_LOG_MASK, | ||
| 31 | }, | ||
| 32 | }, | ||
| 33 | }; | ||
| 34 | |||
| 35 | /* One level of recursion won't kill us */ | ||
| 36 | static void dump_ipv6_packet(struct nf_log_buf *m, | ||
| 37 | const struct nf_loginfo *info, | ||
| 38 | const struct sk_buff *skb, unsigned int ip6hoff, | ||
| 39 | int recurse) | ||
| 40 | { | ||
| 41 | u_int8_t currenthdr; | ||
| 42 | int fragment; | ||
| 43 | struct ipv6hdr _ip6h; | ||
| 44 | const struct ipv6hdr *ih; | ||
| 45 | unsigned int ptr; | ||
| 46 | unsigned int hdrlen = 0; | ||
| 47 | unsigned int logflags; | ||
| 48 | |||
| 49 | if (info->type == NF_LOG_TYPE_LOG) | ||
| 50 | logflags = info->u.log.logflags; | ||
| 51 | else | ||
| 52 | logflags = NF_LOG_MASK; | ||
| 53 | |||
| 54 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | ||
| 55 | if (ih == NULL) { | ||
| 56 | nf_log_buf_add(m, "TRUNCATED"); | ||
| 57 | return; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | ||
| 61 | nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | ||
| 62 | |||
| 63 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | ||
| 64 | nf_log_buf_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | ||
| 65 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | ||
| 66 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | ||
| 67 | ih->hop_limit, | ||
| 68 | (ntohl(*(__be32 *)ih) & 0x000fffff)); | ||
| 69 | |||
| 70 | fragment = 0; | ||
| 71 | ptr = ip6hoff + sizeof(struct ipv6hdr); | ||
| 72 | currenthdr = ih->nexthdr; | ||
| 73 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { | ||
| 74 | struct ipv6_opt_hdr _hdr; | ||
| 75 | const struct ipv6_opt_hdr *hp; | ||
| 76 | |||
| 77 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 78 | if (hp == NULL) { | ||
| 79 | nf_log_buf_add(m, "TRUNCATED"); | ||
| 80 | return; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Max length: 48 "OPT (...) " */ | ||
| 84 | if (logflags & XT_LOG_IPOPT) | ||
| 85 | nf_log_buf_add(m, "OPT ( "); | ||
| 86 | |||
| 87 | switch (currenthdr) { | ||
| 88 | case IPPROTO_FRAGMENT: { | ||
| 89 | struct frag_hdr _fhdr; | ||
| 90 | const struct frag_hdr *fh; | ||
| 91 | |||
| 92 | nf_log_buf_add(m, "FRAG:"); | ||
| 93 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | ||
| 94 | &_fhdr); | ||
| 95 | if (fh == NULL) { | ||
| 96 | nf_log_buf_add(m, "TRUNCATED "); | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Max length: 6 "65535 " */ | ||
| 101 | nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); | ||
| 102 | |||
| 103 | /* Max length: 11 "INCOMPLETE " */ | ||
| 104 | if (fh->frag_off & htons(0x0001)) | ||
| 105 | nf_log_buf_add(m, "INCOMPLETE "); | ||
| 106 | |||
| 107 | nf_log_buf_add(m, "ID:%08x ", | ||
| 108 | ntohl(fh->identification)); | ||
| 109 | |||
| 110 | if (ntohs(fh->frag_off) & 0xFFF8) | ||
| 111 | fragment = 1; | ||
| 112 | |||
| 113 | hdrlen = 8; | ||
| 114 | |||
| 115 | break; | ||
| 116 | } | ||
| 117 | case IPPROTO_DSTOPTS: | ||
| 118 | case IPPROTO_ROUTING: | ||
| 119 | case IPPROTO_HOPOPTS: | ||
| 120 | if (fragment) { | ||
| 121 | if (logflags & XT_LOG_IPOPT) | ||
| 122 | nf_log_buf_add(m, ")"); | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | hdrlen = ipv6_optlen(hp); | ||
| 126 | break; | ||
| 127 | /* Max Length */ | ||
| 128 | case IPPROTO_AH: | ||
| 129 | if (logflags & XT_LOG_IPOPT) { | ||
| 130 | struct ip_auth_hdr _ahdr; | ||
| 131 | const struct ip_auth_hdr *ah; | ||
| 132 | |||
| 133 | /* Max length: 3 "AH " */ | ||
| 134 | nf_log_buf_add(m, "AH "); | ||
| 135 | |||
| 136 | if (fragment) { | ||
| 137 | nf_log_buf_add(m, ")"); | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | |||
| 141 | ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), | ||
| 142 | &_ahdr); | ||
| 143 | if (ah == NULL) { | ||
| 144 | /* | ||
| 145 | * Max length: 26 "INCOMPLETE [65535 | ||
| 146 | * bytes] )" | ||
| 147 | */ | ||
| 148 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] )", | ||
| 149 | skb->len - ptr); | ||
| 150 | return; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* Length: 15 "SPI=0xF1234567 */ | ||
| 154 | nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
| 155 | |||
| 156 | } | ||
| 157 | |||
| 158 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 159 | break; | ||
| 160 | case IPPROTO_ESP: | ||
| 161 | if (logflags & XT_LOG_IPOPT) { | ||
| 162 | struct ip_esp_hdr _esph; | ||
| 163 | const struct ip_esp_hdr *eh; | ||
| 164 | |||
| 165 | /* Max length: 4 "ESP " */ | ||
| 166 | nf_log_buf_add(m, "ESP "); | ||
| 167 | |||
| 168 | if (fragment) { | ||
| 169 | nf_log_buf_add(m, ")"); | ||
| 170 | return; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Max length: 26 "INCOMPLETE [65535 bytes] )" | ||
| 175 | */ | ||
| 176 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | ||
| 177 | &_esph); | ||
| 178 | if (eh == NULL) { | ||
| 179 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] )", | ||
| 180 | skb->len - ptr); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Length: 16 "SPI=0xF1234567 )" */ | ||
| 185 | nf_log_buf_add(m, "SPI=0x%x )", | ||
| 186 | ntohl(eh->spi)); | ||
| 187 | } | ||
| 188 | return; | ||
| 189 | default: | ||
| 190 | /* Max length: 20 "Unknown Ext Hdr 255" */ | ||
| 191 | nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | if (logflags & XT_LOG_IPOPT) | ||
| 195 | nf_log_buf_add(m, ") "); | ||
| 196 | |||
| 197 | currenthdr = hp->nexthdr; | ||
| 198 | ptr += hdrlen; | ||
| 199 | } | ||
| 200 | |||
| 201 | switch (currenthdr) { | ||
| 202 | case IPPROTO_TCP: | ||
| 203 | if (nf_log_dump_tcp_header(m, skb, currenthdr, fragment, | ||
| 204 | ptr, logflags)) | ||
| 205 | return; | ||
| 206 | break; | ||
| 207 | case IPPROTO_UDP: | ||
| 208 | case IPPROTO_UDPLITE: | ||
| 209 | if (nf_log_dump_udp_header(m, skb, currenthdr, fragment, ptr)) | ||
| 210 | return; | ||
| 211 | break; | ||
| 212 | case IPPROTO_ICMPV6: { | ||
| 213 | struct icmp6hdr _icmp6h; | ||
| 214 | const struct icmp6hdr *ic; | ||
| 215 | |||
| 216 | /* Max length: 13 "PROTO=ICMPv6 " */ | ||
| 217 | nf_log_buf_add(m, "PROTO=ICMPv6 "); | ||
| 218 | |||
| 219 | if (fragment) | ||
| 220 | break; | ||
| 221 | |||
| 222 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
| 223 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | ||
| 224 | if (ic == NULL) { | ||
| 225 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
| 226 | skb->len - ptr); | ||
| 227 | return; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
| 231 | nf_log_buf_add(m, "TYPE=%u CODE=%u ", | ||
| 232 | ic->icmp6_type, ic->icmp6_code); | ||
| 233 | |||
| 234 | switch (ic->icmp6_type) { | ||
| 235 | case ICMPV6_ECHO_REQUEST: | ||
| 236 | case ICMPV6_ECHO_REPLY: | ||
| 237 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
| 238 | nf_log_buf_add(m, "ID=%u SEQ=%u ", | ||
| 239 | ntohs(ic->icmp6_identifier), | ||
| 240 | ntohs(ic->icmp6_sequence)); | ||
| 241 | break; | ||
| 242 | case ICMPV6_MGM_QUERY: | ||
| 243 | case ICMPV6_MGM_REPORT: | ||
| 244 | case ICMPV6_MGM_REDUCTION: | ||
| 245 | break; | ||
| 246 | |||
| 247 | case ICMPV6_PARAMPROB: | ||
| 248 | /* Max length: 17 "POINTER=ffffffff " */ | ||
| 249 | nf_log_buf_add(m, "POINTER=%08x ", | ||
| 250 | ntohl(ic->icmp6_pointer)); | ||
| 251 | /* Fall through */ | ||
| 252 | case ICMPV6_DEST_UNREACH: | ||
| 253 | case ICMPV6_PKT_TOOBIG: | ||
| 254 | case ICMPV6_TIME_EXCEED: | ||
| 255 | /* Max length: 3+maxlen */ | ||
| 256 | if (recurse) { | ||
| 257 | nf_log_buf_add(m, "["); | ||
| 258 | dump_ipv6_packet(m, info, skb, | ||
| 259 | ptr + sizeof(_icmp6h), 0); | ||
| 260 | nf_log_buf_add(m, "] "); | ||
| 261 | } | ||
| 262 | |||
| 263 | /* Max length: 10 "MTU=65535 " */ | ||
| 264 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) { | ||
| 265 | nf_log_buf_add(m, "MTU=%u ", | ||
| 266 | ntohl(ic->icmp6_mtu)); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | /* Max length: 10 "PROTO=255 " */ | ||
| 272 | default: | ||
| 273 | nf_log_buf_add(m, "PROTO=%u ", currenthdr); | ||
| 274 | } | ||
| 275 | |||
| 276 | /* Max length: 15 "UID=4294967295 " */ | ||
| 277 | if ((logflags & XT_LOG_UID) && recurse) | ||
| 278 | nf_log_dump_sk_uid_gid(m, skb->sk); | ||
| 279 | |||
| 280 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
| 281 | if (recurse && skb->mark) | ||
| 282 | nf_log_buf_add(m, "MARK=0x%x ", skb->mark); | ||
| 283 | } | ||
| 284 | |||
| 285 | static void dump_ipv6_mac_header(struct nf_log_buf *m, | ||
| 286 | const struct nf_loginfo *info, | ||
| 287 | const struct sk_buff *skb) | ||
| 288 | { | ||
| 289 | struct net_device *dev = skb->dev; | ||
| 290 | unsigned int logflags = 0; | ||
| 291 | |||
| 292 | if (info->type == NF_LOG_TYPE_LOG) | ||
| 293 | logflags = info->u.log.logflags; | ||
| 294 | |||
| 295 | if (!(logflags & XT_LOG_MACDECODE)) | ||
| 296 | goto fallback; | ||
| 297 | |||
| 298 | switch (dev->type) { | ||
| 299 | case ARPHRD_ETHER: | ||
| 300 | nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
| 301 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
| 302 | ntohs(eth_hdr(skb)->h_proto)); | ||
| 303 | return; | ||
| 304 | default: | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | |||
| 308 | fallback: | ||
| 309 | nf_log_buf_add(m, "MAC="); | ||
| 310 | if (dev->hard_header_len && | ||
| 311 | skb->mac_header != skb->network_header) { | ||
| 312 | const unsigned char *p = skb_mac_header(skb); | ||
| 313 | unsigned int len = dev->hard_header_len; | ||
| 314 | unsigned int i; | ||
| 315 | |||
| 316 | if (dev->type == ARPHRD_SIT) { | ||
| 317 | p -= ETH_HLEN; | ||
| 318 | |||
| 319 | if (p < skb->head) | ||
| 320 | p = NULL; | ||
| 321 | } | ||
| 322 | |||
| 323 | if (p != NULL) { | ||
| 324 | nf_log_buf_add(m, "%02x", *p++); | ||
| 325 | for (i = 1; i < len; i++) | ||
| 326 | nf_log_buf_add(m, ":%02x", *p++); | ||
| 327 | } | ||
| 328 | nf_log_buf_add(m, " "); | ||
| 329 | |||
| 330 | if (dev->type == ARPHRD_SIT) { | ||
| 331 | const struct iphdr *iph = | ||
| 332 | (struct iphdr *)skb_mac_header(skb); | ||
| 333 | nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, | ||
| 334 | &iph->daddr); | ||
| 335 | } | ||
| 336 | } else { | ||
| 337 | nf_log_buf_add(m, " "); | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | static void nf_log_ip6_packet(struct net *net, u_int8_t pf, | ||
| 342 | unsigned int hooknum, const struct sk_buff *skb, | ||
| 343 | const struct net_device *in, | ||
| 344 | const struct net_device *out, | ||
| 345 | const struct nf_loginfo *loginfo, | ||
| 346 | const char *prefix) | ||
| 347 | { | ||
| 348 | struct nf_log_buf *m; | ||
| 349 | |||
| 350 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
| 351 | if (!net_eq(net, &init_net)) | ||
| 352 | return; | ||
| 353 | |||
| 354 | m = nf_log_buf_open(); | ||
| 355 | |||
| 356 | if (!loginfo) | ||
| 357 | loginfo = &default_loginfo; | ||
| 358 | |||
| 359 | nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, | ||
| 360 | loginfo, prefix); | ||
| 361 | |||
| 362 | if (in != NULL) | ||
| 363 | dump_ipv6_mac_header(m, loginfo, skb); | ||
| 364 | |||
| 365 | dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
| 366 | |||
| 367 | nf_log_buf_close(m); | ||
| 368 | } | ||
| 369 | |||
| 370 | static struct nf_logger nf_ip6_logger __read_mostly = { | ||
| 371 | .name = "nf_log_ipv6", | ||
| 372 | .type = NF_LOG_TYPE_LOG, | ||
| 373 | .logfn = nf_log_ip6_packet, | ||
| 374 | .me = THIS_MODULE, | ||
| 375 | }; | ||
| 376 | |||
| 377 | static int __net_init nf_log_ipv6_net_init(struct net *net) | ||
| 378 | { | ||
| 379 | nf_log_set(net, NFPROTO_IPV6, &nf_ip6_logger); | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static void __net_exit nf_log_ipv6_net_exit(struct net *net) | ||
| 384 | { | ||
| 385 | nf_log_unset(net, &nf_ip6_logger); | ||
| 386 | } | ||
| 387 | |||
| 388 | static struct pernet_operations nf_log_ipv6_net_ops = { | ||
| 389 | .init = nf_log_ipv6_net_init, | ||
| 390 | .exit = nf_log_ipv6_net_exit, | ||
| 391 | }; | ||
| 392 | |||
| 393 | static int __init nf_log_ipv6_init(void) | ||
| 394 | { | ||
| 395 | int ret; | ||
| 396 | |||
| 397 | ret = register_pernet_subsys(&nf_log_ipv6_net_ops); | ||
| 398 | if (ret < 0) | ||
| 399 | return ret; | ||
| 400 | |||
| 401 | nf_log_register(NFPROTO_IPV6, &nf_ip6_logger); | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static void __exit nf_log_ipv6_exit(void) | ||
| 406 | { | ||
| 407 | unregister_pernet_subsys(&nf_log_ipv6_net_ops); | ||
| 408 | nf_log_unregister(&nf_ip6_logger); | ||
| 409 | } | ||
| 410 | |||
| 411 | module_init(nf_log_ipv6_init); | ||
| 412 | module_exit(nf_log_ipv6_exit); | ||
| 413 | |||
| 414 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
| 415 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | ||
| 416 | MODULE_LICENSE("GPL"); | ||
| 417 | MODULE_ALIAS_NF_LOGGER(AF_INET6, 0); | ||
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index abfe75a2e316..fc8e49b2ff3e 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | |||
| @@ -158,6 +158,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, | |||
| 158 | htons(oldlen), htons(datalen), 1); | 158 | htons(oldlen), htons(datalen), 1); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
| 161 | static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], | 162 | static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], |
| 162 | struct nf_nat_range *range) | 163 | struct nf_nat_range *range) |
| 163 | { | 164 | { |
| @@ -175,6 +176,7 @@ static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], | |||
| 175 | 176 | ||
| 176 | return 0; | 177 | return 0; |
| 177 | } | 178 | } |
| 179 | #endif | ||
| 178 | 180 | ||
| 179 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { | 181 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { |
| 180 | .l3proto = NFPROTO_IPV6, | 182 | .l3proto = NFPROTO_IPV6, |
| @@ -183,7 +185,9 @@ static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { | |||
| 183 | .manip_pkt = nf_nat_ipv6_manip_pkt, | 185 | .manip_pkt = nf_nat_ipv6_manip_pkt, |
| 184 | .csum_update = nf_nat_ipv6_csum_update, | 186 | .csum_update = nf_nat_ipv6_csum_update, |
| 185 | .csum_recalc = nf_nat_ipv6_csum_recalc, | 187 | .csum_recalc = nf_nat_ipv6_csum_recalc, |
| 188 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
| 186 | .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, | 189 | .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, |
| 190 | #endif | ||
| 187 | #ifdef CONFIG_XFRM | 191 | #ifdef CONFIG_XFRM |
| 188 | .decode_session = nf_nat_ipv6_decode_session, | 192 | .decode_session = nf_nat_ipv6_decode_session, |
| 189 | #endif | 193 | #endif |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 3317440ea341..2d6f860e5c1e 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | static int sockstat6_seq_show(struct seq_file *seq, void *v) | 33 | static int sockstat6_seq_show(struct seq_file *seq, void *v) |
| 34 | { | 34 | { |
| 35 | struct net *net = seq->private; | 35 | struct net *net = seq->private; |
| 36 | unsigned int frag_mem = ip6_frag_mem(net); | ||
| 36 | 37 | ||
| 37 | seq_printf(seq, "TCP6: inuse %d\n", | 38 | seq_printf(seq, "TCP6: inuse %d\n", |
| 38 | sock_prot_inuse_get(net, &tcpv6_prot)); | 39 | sock_prot_inuse_get(net, &tcpv6_prot)); |
| @@ -42,8 +43,7 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
| 42 | sock_prot_inuse_get(net, &udplitev6_prot)); | 43 | sock_prot_inuse_get(net, &udplitev6_prot)); |
| 43 | seq_printf(seq, "RAW6: inuse %d\n", | 44 | seq_printf(seq, "RAW6: inuse %d\n", |
| 44 | sock_prot_inuse_get(net, &rawv6_prot)); | 45 | sock_prot_inuse_get(net, &rawv6_prot)); |
| 45 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 46 | seq_printf(seq, "FRAG6: inuse %u memory %u\n", !!frag_mem, frag_mem); |
| 46 | ip6_frag_nqueues(net), ip6_frag_mem(net)); | ||
| 47 | return 0; | 47 | return 0; |
| 48 | } | 48 | } |
| 49 | 49 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index b2dc60b0c764..39d44226e402 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -176,7 +176,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
| 176 | goto out; | 176 | goto out; |
| 177 | 177 | ||
| 178 | net = dev_net(skb->dev); | 178 | net = dev_net(skb->dev); |
| 179 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | 179 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb)); |
| 180 | 180 | ||
| 181 | while (sk) { | 181 | while (sk) { |
| 182 | int filtered; | 182 | int filtered; |
| @@ -220,7 +220,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| 222 | sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, | 222 | sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, |
| 223 | IP6CB(skb)->iif); | 223 | inet6_iif(skb)); |
| 224 | } | 224 | } |
| 225 | out: | 225 | out: |
| 226 | read_unlock(&raw_v6_hashinfo.lock); | 226 | read_unlock(&raw_v6_hashinfo.lock); |
| @@ -375,7 +375,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
| 375 | net = dev_net(skb->dev); | 375 | net = dev_net(skb->dev); |
| 376 | 376 | ||
| 377 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, | 377 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
| 378 | IP6CB(skb)->iif))) { | 378 | inet6_iif(skb)))) { |
| 379 | rawv6_err(sk, skb, NULL, type, code, | 379 | rawv6_err(sk, skb, NULL, type, code, |
| 380 | inner_offset, info); | 380 | inner_offset, info); |
| 381 | sk = sk_next(sk); | 381 | sk = sk_next(sk); |
| @@ -506,7 +506,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 506 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 506 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
| 507 | sin6->sin6_flowinfo = 0; | 507 | sin6->sin6_flowinfo = 0; |
| 508 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, | 508 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, |
| 509 | IP6CB(skb)->iif); | 509 | inet6_iif(skb)); |
| 510 | *addr_len = sizeof(*sin6); | 510 | *addr_len = sizeof(*sin6); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| @@ -588,8 +588,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
| 588 | } | 588 | } |
| 589 | 589 | ||
| 590 | offset += skb_transport_offset(skb); | 590 | offset += skb_transport_offset(skb); |
| 591 | if (skb_copy_bits(skb, offset, &csum, 2)) | 591 | BUG_ON(skb_copy_bits(skb, offset, &csum, 2)); |
| 592 | BUG(); | ||
| 593 | 592 | ||
| 594 | /* in case cksum was not initialized */ | 593 | /* in case cksum was not initialized */ |
| 595 | if (unlikely(csum)) | 594 | if (unlikely(csum)) |
| @@ -601,8 +600,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
| 601 | if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) | 600 | if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) |
| 602 | csum = CSUM_MANGLED_0; | 601 | csum = CSUM_MANGLED_0; |
| 603 | 602 | ||
| 604 | if (skb_store_bits(skb, offset, &csum, 2)) | 603 | BUG_ON(skb_store_bits(skb, offset, &csum, 2)); |
| 605 | BUG(); | ||
| 606 | 604 | ||
| 607 | send: | 605 | send: |
| 608 | err = ip6_push_pending_frames(sk); | 606 | err = ip6_push_pending_frames(sk); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index cc85a9ba5010..c6557d9f7808 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -60,6 +60,8 @@ | |||
| 60 | #include <net/inet_frag.h> | 60 | #include <net/inet_frag.h> |
| 61 | #include <net/inet_ecn.h> | 61 | #include <net/inet_ecn.h> |
| 62 | 62 | ||
| 63 | static const char ip6_frag_cache_name[] = "ip6-frags"; | ||
| 64 | |||
| 63 | struct ip6frag_skb_cb | 65 | struct ip6frag_skb_cb |
| 64 | { | 66 | { |
| 65 | struct inet6_skb_parm h; | 67 | struct inet6_skb_parm h; |
| @@ -85,27 +87,23 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 85 | static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, | 87 | static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, |
| 86 | const struct in6_addr *daddr) | 88 | const struct in6_addr *daddr) |
| 87 | { | 89 | { |
| 88 | u32 c; | ||
| 89 | |||
| 90 | net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd)); | 90 | net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd)); |
| 91 | c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), | 91 | return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), |
| 92 | (__force u32)id, ip6_frags.rnd); | 92 | (__force u32)id, ip6_frags.rnd); |
| 93 | |||
| 94 | return c & (INETFRAGS_HASHSZ - 1); | ||
| 95 | } | 93 | } |
| 96 | 94 | ||
| 97 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) | 95 | static unsigned int ip6_hashfn(const struct inet_frag_queue *q) |
| 98 | { | 96 | { |
| 99 | struct frag_queue *fq; | 97 | const struct frag_queue *fq; |
| 100 | 98 | ||
| 101 | fq = container_of(q, struct frag_queue, q); | 99 | fq = container_of(q, struct frag_queue, q); |
| 102 | return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr); | 100 | return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr); |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | bool ip6_frag_match(struct inet_frag_queue *q, void *a) | 103 | bool ip6_frag_match(const struct inet_frag_queue *q, const void *a) |
| 106 | { | 104 | { |
| 107 | struct frag_queue *fq; | 105 | const struct frag_queue *fq; |
| 108 | struct ip6_create_arg *arg = a; | 106 | const struct ip6_create_arg *arg = a; |
| 109 | 107 | ||
| 110 | fq = container_of(q, struct frag_queue, q); | 108 | fq = container_of(q, struct frag_queue, q); |
| 111 | return fq->id == arg->id && | 109 | return fq->id == arg->id && |
| @@ -115,10 +113,10 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
| 115 | } | 113 | } |
| 116 | EXPORT_SYMBOL(ip6_frag_match); | 114 | EXPORT_SYMBOL(ip6_frag_match); |
| 117 | 115 | ||
| 118 | void ip6_frag_init(struct inet_frag_queue *q, void *a) | 116 | void ip6_frag_init(struct inet_frag_queue *q, const void *a) |
| 119 | { | 117 | { |
| 120 | struct frag_queue *fq = container_of(q, struct frag_queue, q); | 118 | struct frag_queue *fq = container_of(q, struct frag_queue, q); |
| 121 | struct ip6_create_arg *arg = a; | 119 | const struct ip6_create_arg *arg = a; |
| 122 | 120 | ||
| 123 | fq->id = arg->id; | 121 | fq->id = arg->id; |
| 124 | fq->user = arg->user; | 122 | fq->user = arg->user; |
| @@ -135,7 +133,7 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | |||
| 135 | 133 | ||
| 136 | spin_lock(&fq->q.lock); | 134 | spin_lock(&fq->q.lock); |
| 137 | 135 | ||
| 138 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 136 | if (fq->q.flags & INET_FRAG_COMPLETE) |
| 139 | goto out; | 137 | goto out; |
| 140 | 138 | ||
| 141 | inet_frag_kill(&fq->q, frags); | 139 | inet_frag_kill(&fq->q, frags); |
| @@ -145,17 +143,20 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | |||
| 145 | if (!dev) | 143 | if (!dev) |
| 146 | goto out_rcu_unlock; | 144 | goto out_rcu_unlock; |
| 147 | 145 | ||
| 148 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
| 149 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 146 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); |
| 150 | 147 | ||
| 148 | if (fq->q.flags & INET_FRAG_EVICTED) | ||
| 149 | goto out_rcu_unlock; | ||
| 150 | |||
| 151 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
| 152 | |||
| 151 | /* Don't send error if the first segment did not arrive. */ | 153 | /* Don't send error if the first segment did not arrive. */ |
| 152 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) | 154 | if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !fq->q.fragments) |
| 153 | goto out_rcu_unlock; | 155 | goto out_rcu_unlock; |
| 154 | 156 | ||
| 155 | /* | 157 | /* But use as source device on which LAST ARRIVED |
| 156 | But use as source device on which LAST ARRIVED | 158 | * segment was received. And do not use fq->dev |
| 157 | segment was received. And do not use fq->dev | 159 | * pointer directly, device might already disappeared. |
| 158 | pointer directly, device might already disappeared. | ||
| 159 | */ | 160 | */ |
| 160 | fq->q.fragments->dev = dev; | 161 | fq->q.fragments->dev = dev; |
| 161 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); | 162 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); |
| @@ -192,7 +193,6 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, | |||
| 192 | arg.dst = dst; | 193 | arg.dst = dst; |
| 193 | arg.ecn = ecn; | 194 | arg.ecn = ecn; |
| 194 | 195 | ||
| 195 | read_lock(&ip6_frags.lock); | ||
| 196 | hash = inet6_hash_frag(id, src, dst); | 196 | hash = inet6_hash_frag(id, src, dst); |
| 197 | 197 | ||
| 198 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 198 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
| @@ -212,7 +212,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 212 | struct net *net = dev_net(skb_dst(skb)->dev); | 212 | struct net *net = dev_net(skb_dst(skb)->dev); |
| 213 | u8 ecn; | 213 | u8 ecn; |
| 214 | 214 | ||
| 215 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 215 | if (fq->q.flags & INET_FRAG_COMPLETE) |
| 216 | goto err; | 216 | goto err; |
| 217 | 217 | ||
| 218 | offset = ntohs(fhdr->frag_off) & ~0x7; | 218 | offset = ntohs(fhdr->frag_off) & ~0x7; |
| @@ -243,9 +243,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 243 | * or have different end, the segment is corrupted. | 243 | * or have different end, the segment is corrupted. |
| 244 | */ | 244 | */ |
| 245 | if (end < fq->q.len || | 245 | if (end < fq->q.len || |
| 246 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) | 246 | ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len)) |
| 247 | goto err; | 247 | goto err; |
| 248 | fq->q.last_in |= INET_FRAG_LAST_IN; | 248 | fq->q.flags |= INET_FRAG_LAST_IN; |
| 249 | fq->q.len = end; | 249 | fq->q.len = end; |
| 250 | } else { | 250 | } else { |
| 251 | /* Check if the fragment is rounded to 8 bytes. | 251 | /* Check if the fragment is rounded to 8 bytes. |
| @@ -263,7 +263,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
| 263 | } | 263 | } |
| 264 | if (end > fq->q.len) { | 264 | if (end > fq->q.len) { |
| 265 | /* Some bits beyond end -> corruption. */ | 265 | /* Some bits beyond end -> corruption. */ |
| 266 | if (fq->q.last_in & INET_FRAG_LAST_IN) | 266 | if (fq->q.flags & INET_FRAG_LAST_IN) |
| 267 | goto err; | 267 | goto err; |
| 268 | fq->q.len = end; | 268 | fq->q.len = end; |
| 269 | } | 269 | } |
| @@ -338,10 +338,10 @@ found: | |||
| 338 | */ | 338 | */ |
| 339 | if (offset == 0) { | 339 | if (offset == 0) { |
| 340 | fq->nhoffset = nhoff; | 340 | fq->nhoffset = nhoff; |
| 341 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 341 | fq->q.flags |= INET_FRAG_FIRST_IN; |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 344 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
| 345 | fq->q.meat == fq->q.len) { | 345 | fq->q.meat == fq->q.len) { |
| 346 | int res; | 346 | int res; |
| 347 | unsigned long orefdst = skb->_skb_refdst; | 347 | unsigned long orefdst = skb->_skb_refdst; |
| @@ -353,14 +353,13 @@ found: | |||
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | skb_dst_drop(skb); | 355 | skb_dst_drop(skb); |
| 356 | inet_frag_lru_move(&fq->q); | ||
| 357 | return -1; | 356 | return -1; |
| 358 | 357 | ||
| 359 | discard_fq: | 358 | discard_fq: |
| 360 | inet_frag_kill(&fq->q, &ip6_frags); | 359 | inet_frag_kill(&fq->q, &ip6_frags); |
| 361 | err: | 360 | err: |
| 362 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 361 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), |
| 363 | IPSTATS_MIB_REASMFAILS); | 362 | IPSTATS_MIB_REASMFAILS); |
| 364 | kfree_skb(skb); | 363 | kfree_skb(skb); |
| 365 | return -1; | 364 | return -1; |
| 366 | } | 365 | } |
| @@ -523,7 +522,6 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
| 523 | struct frag_queue *fq; | 522 | struct frag_queue *fq; |
| 524 | const struct ipv6hdr *hdr = ipv6_hdr(skb); | 523 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
| 525 | struct net *net = dev_net(skb_dst(skb)->dev); | 524 | struct net *net = dev_net(skb_dst(skb)->dev); |
| 526 | int evicted; | ||
| 527 | 525 | ||
| 528 | if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) | 526 | if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) |
| 529 | goto fail_hdr; | 527 | goto fail_hdr; |
| @@ -552,11 +550,6 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
| 552 | return 1; | 550 | return 1; |
| 553 | } | 551 | } |
| 554 | 552 | ||
| 555 | evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false); | ||
| 556 | if (evicted) | ||
| 557 | IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), | ||
| 558 | IPSTATS_MIB_REASMFAILS, evicted); | ||
| 559 | |||
| 560 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, | 553 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, |
| 561 | ip6_frag_ecn(hdr)); | 554 | ip6_frag_ecn(hdr)); |
| 562 | if (fq != NULL) { | 555 | if (fq != NULL) { |
| @@ -576,7 +569,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
| 576 | return -1; | 569 | return -1; |
| 577 | 570 | ||
| 578 | fail_hdr: | 571 | fail_hdr: |
| 579 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); | 572 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), |
| 573 | IPSTATS_MIB_INHDRERRORS); | ||
| 580 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); | 574 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); |
| 581 | return -1; | 575 | return -1; |
| 582 | } | 576 | } |
| @@ -588,20 +582,25 @@ static const struct inet6_protocol frag_protocol = | |||
| 588 | }; | 582 | }; |
| 589 | 583 | ||
| 590 | #ifdef CONFIG_SYSCTL | 584 | #ifdef CONFIG_SYSCTL |
| 585 | static int zero; | ||
| 586 | |||
| 591 | static struct ctl_table ip6_frags_ns_ctl_table[] = { | 587 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
| 592 | { | 588 | { |
| 593 | .procname = "ip6frag_high_thresh", | 589 | .procname = "ip6frag_high_thresh", |
| 594 | .data = &init_net.ipv6.frags.high_thresh, | 590 | .data = &init_net.ipv6.frags.high_thresh, |
| 595 | .maxlen = sizeof(int), | 591 | .maxlen = sizeof(int), |
| 596 | .mode = 0644, | 592 | .mode = 0644, |
| 597 | .proc_handler = proc_dointvec | 593 | .proc_handler = proc_dointvec_minmax, |
| 594 | .extra1 = &init_net.ipv6.frags.low_thresh | ||
| 598 | }, | 595 | }, |
| 599 | { | 596 | { |
| 600 | .procname = "ip6frag_low_thresh", | 597 | .procname = "ip6frag_low_thresh", |
| 601 | .data = &init_net.ipv6.frags.low_thresh, | 598 | .data = &init_net.ipv6.frags.low_thresh, |
| 602 | .maxlen = sizeof(int), | 599 | .maxlen = sizeof(int), |
| 603 | .mode = 0644, | 600 | .mode = 0644, |
| 604 | .proc_handler = proc_dointvec | 601 | .proc_handler = proc_dointvec_minmax, |
| 602 | .extra1 = &zero, | ||
| 603 | .extra2 = &init_net.ipv6.frags.high_thresh | ||
| 605 | }, | 604 | }, |
| 606 | { | 605 | { |
| 607 | .procname = "ip6frag_time", | 606 | .procname = "ip6frag_time", |
| @@ -613,10 +612,12 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = { | |||
| 613 | { } | 612 | { } |
| 614 | }; | 613 | }; |
| 615 | 614 | ||
| 615 | /* secret interval has been deprecated */ | ||
| 616 | static int ip6_frags_secret_interval_unused; | ||
| 616 | static struct ctl_table ip6_frags_ctl_table[] = { | 617 | static struct ctl_table ip6_frags_ctl_table[] = { |
| 617 | { | 618 | { |
| 618 | .procname = "ip6frag_secret_interval", | 619 | .procname = "ip6frag_secret_interval", |
| 619 | .data = &ip6_frags.secret_interval, | 620 | .data = &ip6_frags_secret_interval_unused, |
| 620 | .maxlen = sizeof(int), | 621 | .maxlen = sizeof(int), |
| 621 | .mode = 0644, | 622 | .mode = 0644, |
| 622 | .proc_handler = proc_dointvec_jiffies, | 623 | .proc_handler = proc_dointvec_jiffies, |
| @@ -636,7 +637,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net) | |||
| 636 | goto err_alloc; | 637 | goto err_alloc; |
| 637 | 638 | ||
| 638 | table[0].data = &net->ipv6.frags.high_thresh; | 639 | table[0].data = &net->ipv6.frags.high_thresh; |
| 640 | table[0].extra1 = &net->ipv6.frags.low_thresh; | ||
| 641 | table[0].extra2 = &init_net.ipv6.frags.high_thresh; | ||
| 639 | table[1].data = &net->ipv6.frags.low_thresh; | 642 | table[1].data = &net->ipv6.frags.low_thresh; |
| 643 | table[1].extra2 = &net->ipv6.frags.high_thresh; | ||
| 640 | table[2].data = &net->ipv6.frags.timeout; | 644 | table[2].data = &net->ipv6.frags.timeout; |
| 641 | 645 | ||
| 642 | /* Don't export sysctls to unprivileged users */ | 646 | /* Don't export sysctls to unprivileged users */ |
| @@ -746,8 +750,10 @@ int __init ipv6_frag_init(void) | |||
| 746 | ip6_frags.qsize = sizeof(struct frag_queue); | 750 | ip6_frags.qsize = sizeof(struct frag_queue); |
| 747 | ip6_frags.match = ip6_frag_match; | 751 | ip6_frags.match = ip6_frag_match; |
| 748 | ip6_frags.frag_expire = ip6_frag_expire; | 752 | ip6_frags.frag_expire = ip6_frag_expire; |
| 749 | ip6_frags.secret_interval = 10 * 60 * HZ; | 753 | ip6_frags.frags_cache_name = ip6_frag_cache_name; |
| 750 | inet_frags_init(&ip6_frags); | 754 | ret = inet_frags_init(&ip6_frags); |
| 755 | if (ret) | ||
| 756 | goto err_pernet; | ||
| 751 | out: | 757 | out: |
| 752 | return ret; | 758 | return ret; |
| 753 | 759 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f23fbd28a501..bafde82324c5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -314,7 +314,6 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, | |||
| 314 | 314 | ||
| 315 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); | 315 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); |
| 316 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); | 316 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); |
| 317 | rt->rt6i_genid = rt_genid_ipv6(net); | ||
| 318 | INIT_LIST_HEAD(&rt->rt6i_siblings); | 317 | INIT_LIST_HEAD(&rt->rt6i_siblings); |
| 319 | } | 318 | } |
| 320 | return rt; | 319 | return rt; |
| @@ -1098,9 +1097,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
| 1098 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | 1097 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down |
| 1099 | * into this function always. | 1098 | * into this function always. |
| 1100 | */ | 1099 | */ |
| 1101 | if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) | ||
| 1102 | return NULL; | ||
| 1103 | |||
| 1104 | if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) | 1100 | if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) |
| 1105 | return NULL; | 1101 | return NULL; |
| 1106 | 1102 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 4f408176dc64..6163f851dc01 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -101,19 +101,19 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, | |||
| 101 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { | 101 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { |
| 102 | if (local == t->parms.iph.saddr && | 102 | if (local == t->parms.iph.saddr && |
| 103 | remote == t->parms.iph.daddr && | 103 | remote == t->parms.iph.daddr && |
| 104 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 104 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
| 105 | (t->dev->flags & IFF_UP)) | 105 | (t->dev->flags & IFF_UP)) |
| 106 | return t; | 106 | return t; |
| 107 | } | 107 | } |
| 108 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { | 108 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { |
| 109 | if (remote == t->parms.iph.daddr && | 109 | if (remote == t->parms.iph.daddr && |
| 110 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 110 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
| 111 | (t->dev->flags & IFF_UP)) | 111 | (t->dev->flags & IFF_UP)) |
| 112 | return t; | 112 | return t; |
| 113 | } | 113 | } |
| 114 | for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { | 114 | for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { |
| 115 | if (local == t->parms.iph.saddr && | 115 | if (local == t->parms.iph.saddr && |
| 116 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 116 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
| 117 | (t->dev->flags & IFF_UP)) | 117 | (t->dev->flags & IFF_UP)) |
| 118 | return t; | 118 | return t; |
| 119 | } | 119 | } |
| @@ -250,7 +250,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | |||
| 250 | else | 250 | else |
| 251 | strcpy(name, "sit%d"); | 251 | strcpy(name, "sit%d"); |
| 252 | 252 | ||
| 253 | dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); | 253 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
| 254 | ipip6_tunnel_setup); | ||
| 254 | if (dev == NULL) | 255 | if (dev == NULL) |
| 255 | return NULL; | 256 | return NULL; |
| 256 | 257 | ||
| @@ -1729,6 +1730,7 @@ static int __net_init sit_init_net(struct net *net) | |||
| 1729 | sitn->tunnels[3] = sitn->tunnels_r_l; | 1730 | sitn->tunnels[3] = sitn->tunnels_r_l; |
| 1730 | 1731 | ||
| 1731 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | 1732 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", |
| 1733 | NET_NAME_UNKNOWN, | ||
| 1732 | ipip6_tunnel_setup); | 1734 | ipip6_tunnel_setup); |
| 1733 | if (!sitn->fb_tunnel_dev) { | 1735 | if (!sitn->fb_tunnel_dev) { |
| 1734 | err = -ENOMEM; | 1736 | err = -ENOMEM; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index a822b880689b..83cea1d39466 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
| @@ -187,7 +187,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
| 187 | goto out; | 187 | goto out; |
| 188 | 188 | ||
| 189 | ret = NULL; | 189 | ret = NULL; |
| 190 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 190 | req = inet_reqsk_alloc(&tcp6_request_sock_ops); |
| 191 | if (!req) | 191 | if (!req) |
| 192 | goto out; | 192 | goto out; |
| 193 | 193 | ||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 058f3eca2e53..0c56c93619e0 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
| @@ -39,6 +39,13 @@ static struct ctl_table ipv6_table_template[] = { | |||
| 39 | .proc_handler = proc_dointvec | 39 | .proc_handler = proc_dointvec |
| 40 | }, | 40 | }, |
| 41 | { | 41 | { |
| 42 | .procname = "auto_flowlabels", | ||
| 43 | .data = &init_net.ipv6.sysctl.auto_flowlabels, | ||
| 44 | .maxlen = sizeof(int), | ||
| 45 | .mode = 0644, | ||
| 46 | .proc_handler = proc_dointvec | ||
| 47 | }, | ||
| 48 | { | ||
| 42 | .procname = "fwmark_reflect", | 49 | .procname = "fwmark_reflect", |
| 43 | .data = &init_net.ipv6.sysctl.fwmark_reflect, | 50 | .data = &init_net.ipv6.sysctl.fwmark_reflect, |
| 44 | .maxlen = sizeof(int), | 51 | .maxlen = sizeof(int), |
| @@ -74,6 +81,8 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) | |||
| 74 | ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; | 81 | ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; |
| 75 | ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply; | 82 | ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply; |
| 76 | ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency; | 83 | ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency; |
| 84 | ipv6_table[3].data = &net->ipv6.sysctl.auto_flowlabels; | ||
| 85 | ipv6_table[4].data = &net->ipv6.sysctl.fwmark_reflect; | ||
| 77 | 86 | ||
| 78 | ipv6_route_table = ipv6_route_sysctl_init(net); | 87 | ipv6_route_table = ipv6_route_sysctl_init(net); |
| 79 | if (!ipv6_route_table) | 88 | if (!ipv6_route_table) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 229239ad96b1..29964c3d363c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -198,6 +198,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
| 198 | sk->sk_v6_daddr = usin->sin6_addr; | 198 | sk->sk_v6_daddr = usin->sin6_addr; |
| 199 | np->flow_label = fl6.flowlabel; | 199 | np->flow_label = fl6.flowlabel; |
| 200 | 200 | ||
| 201 | ip6_set_txhash(sk); | ||
| 202 | |||
| 201 | /* | 203 | /* |
| 202 | * TCP over IPv4 | 204 | * TCP over IPv4 |
| 203 | */ | 205 | */ |
| @@ -470,13 +472,14 @@ out: | |||
| 470 | 472 | ||
| 471 | 473 | ||
| 472 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | 474 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, |
| 473 | struct flowi6 *fl6, | 475 | struct flowi *fl, |
| 474 | struct request_sock *req, | 476 | struct request_sock *req, |
| 475 | u16 queue_mapping, | 477 | u16 queue_mapping, |
| 476 | struct tcp_fastopen_cookie *foc) | 478 | struct tcp_fastopen_cookie *foc) |
| 477 | { | 479 | { |
| 478 | struct inet_request_sock *ireq = inet_rsk(req); | 480 | struct inet_request_sock *ireq = inet_rsk(req); |
| 479 | struct ipv6_pinfo *np = inet6_sk(sk); | 481 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 482 | struct flowi6 *fl6 = &fl->u.ip6; | ||
| 480 | struct sk_buff *skb; | 483 | struct sk_buff *skb; |
| 481 | int err = -ENOMEM; | 484 | int err = -ENOMEM; |
| 482 | 485 | ||
| @@ -503,18 +506,6 @@ done: | |||
| 503 | return err; | 506 | return err; |
| 504 | } | 507 | } |
| 505 | 508 | ||
| 506 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req) | ||
| 507 | { | ||
| 508 | struct flowi6 fl6; | ||
| 509 | int res; | ||
| 510 | |||
| 511 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0, NULL); | ||
| 512 | if (!res) { | ||
| 513 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
| 514 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
| 515 | } | ||
| 516 | return res; | ||
| 517 | } | ||
| 518 | 509 | ||
| 519 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 510 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
| 520 | { | 511 | { |
| @@ -676,7 +667,8 @@ clear_hash_noput: | |||
| 676 | return 1; | 667 | return 1; |
| 677 | } | 668 | } |
| 678 | 669 | ||
| 679 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | 670 | static int __tcp_v6_inbound_md5_hash(struct sock *sk, |
| 671 | const struct sk_buff *skb) | ||
| 680 | { | 672 | { |
| 681 | const __u8 *hash_location = NULL; | 673 | const __u8 *hash_location = NULL; |
| 682 | struct tcp_md5sig_key *hash_expected; | 674 | struct tcp_md5sig_key *hash_expected; |
| @@ -716,24 +708,80 @@ static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
| 716 | } | 708 | } |
| 717 | return 0; | 709 | return 0; |
| 718 | } | 710 | } |
| 711 | |||
| 712 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | ||
| 713 | { | ||
| 714 | int ret; | ||
| 715 | |||
| 716 | rcu_read_lock(); | ||
| 717 | ret = __tcp_v6_inbound_md5_hash(sk, skb); | ||
| 718 | rcu_read_unlock(); | ||
| 719 | |||
| 720 | return ret; | ||
| 721 | } | ||
| 722 | |||
| 719 | #endif | 723 | #endif |
| 720 | 724 | ||
| 725 | static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, | ||
| 726 | struct sk_buff *skb) | ||
| 727 | { | ||
| 728 | struct inet_request_sock *ireq = inet_rsk(req); | ||
| 729 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
| 730 | |||
| 731 | ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; | ||
| 732 | ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; | ||
| 733 | |||
| 734 | ireq->ir_iif = sk->sk_bound_dev_if; | ||
| 735 | |||
| 736 | /* So that link locals have meaning */ | ||
| 737 | if (!sk->sk_bound_dev_if && | ||
| 738 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
| 739 | ireq->ir_iif = inet6_iif(skb); | ||
| 740 | |||
| 741 | if (!TCP_SKB_CB(skb)->when && | ||
| 742 | (ipv6_opt_accepted(sk, skb) || np->rxopt.bits.rxinfo || | ||
| 743 | np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim || | ||
| 744 | np->rxopt.bits.rxohlim || np->repflow)) { | ||
| 745 | atomic_inc(&skb->users); | ||
| 746 | ireq->pktopts = skb; | ||
| 747 | } | ||
| 748 | } | ||
| 749 | |||
| 750 | static struct dst_entry *tcp_v6_route_req(struct sock *sk, struct flowi *fl, | ||
| 751 | const struct request_sock *req, | ||
| 752 | bool *strict) | ||
| 753 | { | ||
| 754 | if (strict) | ||
| 755 | *strict = true; | ||
| 756 | return inet6_csk_route_req(sk, &fl->u.ip6, req); | ||
| 757 | } | ||
| 758 | |||
| 721 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 759 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
| 722 | .family = AF_INET6, | 760 | .family = AF_INET6, |
| 723 | .obj_size = sizeof(struct tcp6_request_sock), | 761 | .obj_size = sizeof(struct tcp6_request_sock), |
| 724 | .rtx_syn_ack = tcp_v6_rtx_synack, | 762 | .rtx_syn_ack = tcp_rtx_synack, |
| 725 | .send_ack = tcp_v6_reqsk_send_ack, | 763 | .send_ack = tcp_v6_reqsk_send_ack, |
| 726 | .destructor = tcp_v6_reqsk_destructor, | 764 | .destructor = tcp_v6_reqsk_destructor, |
| 727 | .send_reset = tcp_v6_send_reset, | 765 | .send_reset = tcp_v6_send_reset, |
| 728 | .syn_ack_timeout = tcp_syn_ack_timeout, | 766 | .syn_ack_timeout = tcp_syn_ack_timeout, |
| 729 | }; | 767 | }; |
| 730 | 768 | ||
| 731 | #ifdef CONFIG_TCP_MD5SIG | ||
| 732 | static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | 769 | static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { |
| 770 | .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - | ||
| 771 | sizeof(struct ipv6hdr), | ||
| 772 | #ifdef CONFIG_TCP_MD5SIG | ||
| 733 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 773 | .md5_lookup = tcp_v6_reqsk_md5_lookup, |
| 734 | .calc_md5_hash = tcp_v6_md5_hash_skb, | 774 | .calc_md5_hash = tcp_v6_md5_hash_skb, |
| 735 | }; | ||
| 736 | #endif | 775 | #endif |
| 776 | .init_req = tcp_v6_init_req, | ||
| 777 | #ifdef CONFIG_SYN_COOKIES | ||
| 778 | .cookie_init_seq = cookie_v6_init_sequence, | ||
| 779 | #endif | ||
| 780 | .route_req = tcp_v6_route_req, | ||
| 781 | .init_seq = tcp_v6_init_sequence, | ||
| 782 | .send_synack = tcp_v6_send_synack, | ||
| 783 | .queue_hash_add = inet6_csk_reqsk_queue_hash_add, | ||
| 784 | }; | ||
| 737 | 785 | ||
| 738 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 786 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
| 739 | u32 tsval, u32 tsecr, int oif, | 787 | u32 tsval, u32 tsecr, int oif, |
| @@ -973,153 +1021,17 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
| 973 | return sk; | 1021 | return sk; |
| 974 | } | 1022 | } |
| 975 | 1023 | ||
| 976 | /* FIXME: this is substantially similar to the ipv4 code. | ||
| 977 | * Can some kind of merge be done? -- erics | ||
| 978 | */ | ||
| 979 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1024 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
| 980 | { | 1025 | { |
| 981 | struct tcp_options_received tmp_opt; | ||
| 982 | struct request_sock *req; | ||
| 983 | struct inet_request_sock *ireq; | ||
| 984 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
| 985 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 986 | __u32 isn = TCP_SKB_CB(skb)->when; | ||
| 987 | struct dst_entry *dst = NULL; | ||
| 988 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
| 989 | bool want_cookie = false, fastopen; | ||
| 990 | struct flowi6 fl6; | ||
| 991 | int err; | ||
| 992 | |||
| 993 | if (skb->protocol == htons(ETH_P_IP)) | 1026 | if (skb->protocol == htons(ETH_P_IP)) |
| 994 | return tcp_v4_conn_request(sk, skb); | 1027 | return tcp_v4_conn_request(sk, skb); |
| 995 | 1028 | ||
| 996 | if (!ipv6_unicast_destination(skb)) | 1029 | if (!ipv6_unicast_destination(skb)) |
| 997 | goto drop; | 1030 | goto drop; |
| 998 | 1031 | ||
| 999 | if ((sysctl_tcp_syncookies == 2 || | 1032 | return tcp_conn_request(&tcp6_request_sock_ops, |
| 1000 | inet_csk_reqsk_queue_is_full(sk)) && !isn) { | 1033 | &tcp_request_sock_ipv6_ops, sk, skb); |
| 1001 | want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6"); | ||
| 1002 | if (!want_cookie) | ||
| 1003 | goto drop; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { | ||
| 1007 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
| 1008 | goto drop; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | ||
| 1012 | if (req == NULL) | ||
| 1013 | goto drop; | ||
| 1014 | |||
| 1015 | #ifdef CONFIG_TCP_MD5SIG | ||
| 1016 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; | ||
| 1017 | #endif | ||
| 1018 | |||
| 1019 | tcp_clear_options(&tmp_opt); | ||
| 1020 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | ||
| 1021 | tmp_opt.user_mss = tp->rx_opt.user_mss; | ||
| 1022 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); | ||
| 1023 | |||
| 1024 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
| 1025 | tcp_clear_options(&tmp_opt); | ||
| 1026 | |||
| 1027 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | ||
| 1028 | tcp_openreq_init(req, &tmp_opt, skb); | ||
| 1029 | |||
| 1030 | ireq = inet_rsk(req); | ||
| 1031 | ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; | ||
| 1032 | ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; | ||
| 1033 | if (!want_cookie || tmp_opt.tstamp_ok) | ||
| 1034 | TCP_ECN_create_request(req, skb, sock_net(sk)); | ||
| 1035 | |||
| 1036 | ireq->ir_iif = sk->sk_bound_dev_if; | ||
| 1037 | ireq->ir_mark = inet_request_mark(sk, skb); | ||
| 1038 | |||
| 1039 | /* So that link locals have meaning */ | ||
| 1040 | if (!sk->sk_bound_dev_if && | ||
| 1041 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
| 1042 | ireq->ir_iif = inet6_iif(skb); | ||
| 1043 | |||
| 1044 | if (!isn) { | ||
| 1045 | if (ipv6_opt_accepted(sk, skb) || | ||
| 1046 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
| 1047 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim || | ||
| 1048 | np->repflow) { | ||
| 1049 | atomic_inc(&skb->users); | ||
| 1050 | ireq->pktopts = skb; | ||
| 1051 | } | ||
| 1052 | 1034 | ||
| 1053 | if (want_cookie) { | ||
| 1054 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
| 1055 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
| 1056 | goto have_isn; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | /* VJ's idea. We save last timestamp seen | ||
| 1060 | * from the destination in peer table, when entering | ||
| 1061 | * state TIME-WAIT, and check against it before | ||
| 1062 | * accepting new connection request. | ||
| 1063 | * | ||
| 1064 | * If "isn" is not zero, this request hit alive | ||
| 1065 | * timewait bucket, so that all the necessary checks | ||
| 1066 | * are made in the function processing timewait state. | ||
| 1067 | */ | ||
| 1068 | if (tmp_opt.saw_tstamp && | ||
| 1069 | tcp_death_row.sysctl_tw_recycle && | ||
| 1070 | (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL) { | ||
| 1071 | if (!tcp_peer_is_proven(req, dst, true)) { | ||
| 1072 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
| 1073 | goto drop_and_release; | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | /* Kill the following clause, if you dislike this way. */ | ||
| 1077 | else if (!sysctl_tcp_syncookies && | ||
| 1078 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
| 1079 | (sysctl_max_syn_backlog >> 2)) && | ||
| 1080 | !tcp_peer_is_proven(req, dst, false)) { | ||
| 1081 | /* Without syncookies last quarter of | ||
| 1082 | * backlog is filled with destinations, | ||
| 1083 | * proven to be alive. | ||
| 1084 | * It means that we continue to communicate | ||
| 1085 | * to destinations, already remembered | ||
| 1086 | * to the moment of synflood. | ||
| 1087 | */ | ||
| 1088 | LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n", | ||
| 1089 | &ireq->ir_v6_rmt_addr, ntohs(tcp_hdr(skb)->source)); | ||
| 1090 | goto drop_and_release; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | isn = tcp_v6_init_sequence(skb); | ||
| 1094 | } | ||
| 1095 | have_isn: | ||
| 1096 | |||
| 1097 | if (security_inet_conn_request(sk, skb, req)) | ||
| 1098 | goto drop_and_release; | ||
| 1099 | |||
| 1100 | if (!dst && (dst = inet6_csk_route_req(sk, &fl6, req)) == NULL) | ||
| 1101 | goto drop_and_free; | ||
| 1102 | |||
| 1103 | tcp_rsk(req)->snt_isn = isn; | ||
| 1104 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
| 1105 | tcp_openreq_init_rwin(req, sk, dst); | ||
| 1106 | fastopen = !want_cookie && | ||
| 1107 | tcp_try_fastopen(sk, skb, req, &foc, dst); | ||
| 1108 | err = tcp_v6_send_synack(sk, dst, &fl6, req, | ||
| 1109 | skb_get_queue_mapping(skb), &foc); | ||
| 1110 | if (!fastopen) { | ||
| 1111 | if (err || want_cookie) | ||
| 1112 | goto drop_and_free; | ||
| 1113 | |||
| 1114 | tcp_rsk(req)->listener = NULL; | ||
| 1115 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
| 1116 | } | ||
| 1117 | return 0; | ||
| 1118 | |||
| 1119 | drop_and_release: | ||
| 1120 | dst_release(dst); | ||
| 1121 | drop_and_free: | ||
| 1122 | reqsk_free(req); | ||
| 1123 | drop: | 1035 | drop: |
| 1124 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1036 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
| 1125 | return 0; /* don't send reset */ | 1037 | return 0; /* don't send reset */ |
| @@ -1235,6 +1147,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1235 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; | 1147 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; |
| 1236 | newsk->sk_bound_dev_if = ireq->ir_iif; | 1148 | newsk->sk_bound_dev_if = ireq->ir_iif; |
| 1237 | 1149 | ||
| 1150 | ip6_set_txhash(newsk); | ||
| 1151 | |||
| 1238 | /* Now IPv6 options... | 1152 | /* Now IPv6 options... |
| 1239 | 1153 | ||
| 1240 | First: no IPv4 options. | 1154 | First: no IPv4 options. |
| @@ -1346,11 +1260,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 1346 | if (skb->protocol == htons(ETH_P_IP)) | 1260 | if (skb->protocol == htons(ETH_P_IP)) |
| 1347 | return tcp_v4_do_rcv(sk, skb); | 1261 | return tcp_v4_do_rcv(sk, skb); |
| 1348 | 1262 | ||
| 1349 | #ifdef CONFIG_TCP_MD5SIG | ||
| 1350 | if (tcp_v6_inbound_md5_hash(sk, skb)) | ||
| 1351 | goto discard; | ||
| 1352 | #endif | ||
| 1353 | |||
| 1354 | if (sk_filter(sk, skb)) | 1263 | if (sk_filter(sk, skb)) |
| 1355 | goto discard; | 1264 | goto discard; |
| 1356 | 1265 | ||
| @@ -1523,6 +1432,11 @@ process: | |||
| 1523 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1432 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1524 | goto discard_and_relse; | 1433 | goto discard_and_relse; |
| 1525 | 1434 | ||
| 1435 | #ifdef CONFIG_TCP_MD5SIG | ||
| 1436 | if (tcp_v6_inbound_md5_hash(sk, skb)) | ||
| 1437 | goto discard_and_relse; | ||
| 1438 | #endif | ||
| 1439 | |||
| 1526 | if (sk_filter(sk, skb)) | 1440 | if (sk_filter(sk, skb)) |
| 1527 | goto discard_and_relse; | 1441 | goto discard_and_relse; |
| 1528 | 1442 | ||
| @@ -1681,6 +1595,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { | |||
| 1681 | .compat_setsockopt = compat_ipv6_setsockopt, | 1595 | .compat_setsockopt = compat_ipv6_setsockopt, |
| 1682 | .compat_getsockopt = compat_ipv6_getsockopt, | 1596 | .compat_getsockopt = compat_ipv6_getsockopt, |
| 1683 | #endif | 1597 | #endif |
| 1598 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
| 1684 | }; | 1599 | }; |
| 1685 | 1600 | ||
| 1686 | #ifdef CONFIG_TCP_MD5SIG | 1601 | #ifdef CONFIG_TCP_MD5SIG |
| @@ -1711,6 +1626,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
| 1711 | .compat_setsockopt = compat_ipv6_setsockopt, | 1626 | .compat_setsockopt = compat_ipv6_setsockopt, |
| 1712 | .compat_getsockopt = compat_ipv6_getsockopt, | 1627 | .compat_getsockopt = compat_ipv6_getsockopt, |
| 1713 | #endif | 1628 | #endif |
| 1629 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
| 1714 | }; | 1630 | }; |
| 1715 | 1631 | ||
| 1716 | #ifdef CONFIG_TCP_MD5SIG | 1632 | #ifdef CONFIG_TCP_MD5SIG |
| @@ -1950,7 +1866,6 @@ struct proto tcpv6_prot = { | |||
| 1950 | .sendpage = tcp_sendpage, | 1866 | .sendpage = tcp_sendpage, |
| 1951 | .backlog_rcv = tcp_v6_do_rcv, | 1867 | .backlog_rcv = tcp_v6_do_rcv, |
| 1952 | .release_cb = tcp_release_cb, | 1868 | .release_cb = tcp_release_cb, |
| 1953 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
| 1954 | .hash = tcp_v6_hash, | 1869 | .hash = tcp_v6_hash, |
| 1955 | .unhash = inet_unhash, | 1870 | .unhash = inet_unhash, |
| 1956 | .get_port = inet_csk_get_port, | 1871 | .get_port = inet_csk_get_port, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 7092ff78fd84..4836af8f582d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -79,7 +79,6 @@ static unsigned int udp6_ehashfn(struct net *net, | |||
| 79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) |
| 80 | { | 80 | { |
| 81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
| 82 | int sk_ipv6only = ipv6_only_sock(sk); | ||
| 83 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 82 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
| 84 | int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); | 83 | int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); |
| 85 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | 84 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; |
| @@ -95,7 +94,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
| 95 | return 1; | 94 | return 1; |
| 96 | 95 | ||
| 97 | if (addr_type == IPV6_ADDR_ANY && | 96 | if (addr_type == IPV6_ADDR_ANY && |
| 98 | !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) | 97 | !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) |
| 99 | return 1; | 98 | return 1; |
| 100 | 99 | ||
| 101 | if (sk2_rcv_saddr6 && | 100 | if (sk2_rcv_saddr6 && |
| @@ -473,7 +472,7 @@ try_again: | |||
| 473 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 472 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
| 474 | sin6->sin6_scope_id = | 473 | sin6->sin6_scope_id = |
| 475 | ipv6_iface_scope_id(&sin6->sin6_addr, | 474 | ipv6_iface_scope_id(&sin6->sin6_addr, |
| 476 | IP6CB(skb)->iif); | 475 | inet6_iif(skb)); |
| 477 | } | 476 | } |
| 478 | *addr_len = sizeof(*sin6); | 477 | *addr_len = sizeof(*sin6); |
| 479 | } | 478 | } |
| @@ -534,11 +533,15 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 534 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 533 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
| 535 | struct sock *sk; | 534 | struct sock *sk; |
| 536 | int err; | 535 | int err; |
| 536 | struct net *net = dev_net(skb->dev); | ||
| 537 | 537 | ||
| 538 | sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, | 538 | sk = __udp6_lib_lookup(net, daddr, uh->dest, |
| 539 | saddr, uh->source, inet6_iif(skb), udptable); | 539 | saddr, uh->source, inet6_iif(skb), udptable); |
| 540 | if (sk == NULL) | 540 | if (sk == NULL) { |
| 541 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), | ||
| 542 | ICMP6_MIB_INERRORS); | ||
| 541 | return; | 543 | return; |
| 544 | } | ||
| 542 | 545 | ||
| 543 | if (type == ICMPV6_PKT_TOOBIG) { | 546 | if (type == ICMPV6_PKT_TOOBIG) { |
| 544 | if (!ip6_sk_accept_pmtu(sk)) | 547 | if (!ip6_sk_accept_pmtu(sk)) |
| @@ -674,7 +677,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 674 | goto csum_error; | 677 | goto csum_error; |
| 675 | } | 678 | } |
| 676 | 679 | ||
| 677 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { | 680 | if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { |
| 678 | UDP6_INC_STATS_BH(sock_net(sk), | 681 | UDP6_INC_STATS_BH(sock_net(sk), |
| 679 | UDP_MIB_RCVBUFERRORS, is_udplite); | 682 | UDP_MIB_RCVBUFERRORS, is_udplite); |
| 680 | goto drop; | 683 | goto drop; |
| @@ -703,43 +706,26 @@ drop: | |||
| 703 | return -1; | 706 | return -1; |
| 704 | } | 707 | } |
| 705 | 708 | ||
| 706 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | 709 | static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, |
| 707 | __be16 loc_port, const struct in6_addr *loc_addr, | 710 | __be16 loc_port, const struct in6_addr *loc_addr, |
| 708 | __be16 rmt_port, const struct in6_addr *rmt_addr, | 711 | __be16 rmt_port, const struct in6_addr *rmt_addr, |
| 709 | int dif) | 712 | int dif, unsigned short hnum) |
| 710 | { | 713 | { |
| 711 | struct hlist_nulls_node *node; | 714 | struct inet_sock *inet = inet_sk(sk); |
| 712 | unsigned short num = ntohs(loc_port); | ||
| 713 | |||
| 714 | sk_nulls_for_each_from(sk, node) { | ||
| 715 | struct inet_sock *inet = inet_sk(sk); | ||
| 716 | |||
| 717 | if (!net_eq(sock_net(sk), net)) | ||
| 718 | continue; | ||
| 719 | |||
| 720 | if (udp_sk(sk)->udp_port_hash == num && | ||
| 721 | sk->sk_family == PF_INET6) { | ||
| 722 | if (inet->inet_dport) { | ||
| 723 | if (inet->inet_dport != rmt_port) | ||
| 724 | continue; | ||
| 725 | } | ||
| 726 | if (!ipv6_addr_any(&sk->sk_v6_daddr) && | ||
| 727 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) | ||
| 728 | continue; | ||
| 729 | |||
| 730 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) | ||
| 731 | continue; | ||
| 732 | 715 | ||
| 733 | if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { | 716 | if (!net_eq(sock_net(sk), net)) |
| 734 | if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) | 717 | return false; |
| 735 | continue; | 718 | |
| 736 | } | 719 | if (udp_sk(sk)->udp_port_hash != hnum || |
| 737 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | 720 | sk->sk_family != PF_INET6 || |
| 738 | continue; | 721 | (inet->inet_dport && inet->inet_dport != rmt_port) || |
| 739 | return sk; | 722 | (!ipv6_addr_any(&sk->sk_v6_daddr) && |
| 740 | } | 723 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || |
| 741 | } | 724 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) |
| 742 | return NULL; | 725 | return false; |
| 726 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | ||
| 727 | return false; | ||
| 728 | return true; | ||
| 743 | } | 729 | } |
| 744 | 730 | ||
| 745 | static void flush_stack(struct sock **stack, unsigned int count, | 731 | static void flush_stack(struct sock **stack, unsigned int count, |
| @@ -763,6 +749,7 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
| 763 | 749 | ||
| 764 | if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) | 750 | if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) |
| 765 | skb1 = NULL; | 751 | skb1 = NULL; |
| 752 | sock_put(sk); | ||
| 766 | } | 753 | } |
| 767 | if (unlikely(skb1)) | 754 | if (unlikely(skb1)) |
| 768 | kfree_skb(skb1); | 755 | kfree_skb(skb1); |
| @@ -788,43 +775,51 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
| 788 | { | 775 | { |
| 789 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; | 776 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
| 790 | const struct udphdr *uh = udp_hdr(skb); | 777 | const struct udphdr *uh = udp_hdr(skb); |
| 791 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); | 778 | struct hlist_nulls_node *node; |
| 792 | int dif; | 779 | unsigned short hnum = ntohs(uh->dest); |
| 793 | unsigned int i, count = 0; | 780 | struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); |
| 781 | int dif = inet6_iif(skb); | ||
| 782 | unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); | ||
| 783 | unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); | ||
| 784 | |||
| 785 | if (use_hash2) { | ||
| 786 | hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & | ||
| 787 | udp_table.mask; | ||
| 788 | hash2 = udp6_portaddr_hash(net, daddr, hnum) & udp_table.mask; | ||
| 789 | start_lookup: | ||
| 790 | hslot = &udp_table.hash2[hash2]; | ||
| 791 | offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); | ||
| 792 | } | ||
| 794 | 793 | ||
| 795 | spin_lock(&hslot->lock); | 794 | spin_lock(&hslot->lock); |
| 796 | sk = sk_nulls_head(&hslot->head); | 795 | sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) { |
| 797 | dif = inet6_iif(skb); | 796 | if (__udp_v6_is_mcast_sock(net, sk, |
| 798 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 797 | uh->dest, daddr, |
| 799 | while (sk) { | 798 | uh->source, saddr, |
| 800 | /* If zero checksum and no_check is not on for | 799 | dif, hnum) && |
| 801 | * the socket then skip it. | 800 | /* If zero checksum and no_check is not on for |
| 802 | */ | 801 | * the socket then skip it. |
| 803 | if (uh->check || udp_sk(sk)->no_check6_rx) | 802 | */ |
| 803 | (uh->check || udp_sk(sk)->no_check6_rx)) { | ||
| 804 | if (unlikely(count == ARRAY_SIZE(stack))) { | ||
| 805 | flush_stack(stack, count, skb, ~0); | ||
| 806 | count = 0; | ||
| 807 | } | ||
| 804 | stack[count++] = sk; | 808 | stack[count++] = sk; |
| 805 | 809 | sock_hold(sk); | |
| 806 | sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, | ||
| 807 | uh->source, saddr, dif); | ||
| 808 | if (unlikely(count == ARRAY_SIZE(stack))) { | ||
| 809 | if (!sk) | ||
| 810 | break; | ||
| 811 | flush_stack(stack, count, skb, ~0); | ||
| 812 | count = 0; | ||
| 813 | } | 810 | } |
| 814 | } | 811 | } |
| 815 | /* | ||
| 816 | * before releasing the lock, we must take reference on sockets | ||
| 817 | */ | ||
| 818 | for (i = 0; i < count; i++) | ||
| 819 | sock_hold(stack[i]); | ||
| 820 | 812 | ||
| 821 | spin_unlock(&hslot->lock); | 813 | spin_unlock(&hslot->lock); |
| 822 | 814 | ||
| 815 | /* Also lookup *:port if we are using hash2 and haven't done so yet. */ | ||
| 816 | if (use_hash2 && hash2 != hash2_any) { | ||
| 817 | hash2 = hash2_any; | ||
| 818 | goto start_lookup; | ||
| 819 | } | ||
| 820 | |||
| 823 | if (count) { | 821 | if (count) { |
| 824 | flush_stack(stack, count, skb, count - 1); | 822 | flush_stack(stack, count, skb, count - 1); |
| 825 | |||
| 826 | for (i = 0; i < count; i++) | ||
| 827 | sock_put(stack[i]); | ||
| 828 | } else { | 823 | } else { |
| 829 | kfree_skb(skb); | 824 | kfree_skb(skb); |
| 830 | } | 825 | } |
