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 | } |