diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 77 | ||||
| -rw-r--r-- | net/ipv6/addrconf_core.c | 19 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 12 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_NPT.c | 4 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_rpfilter.c | 8 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 12 | ||||
| -rw-r--r-- | net/ipv6/reassembly.c | 20 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 8 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 8 |
9 files changed, 119 insertions, 49 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f2c7e615f902..dae802c0af7c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -168,8 +168,6 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
| 168 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 168 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
| 169 | struct net_device *dev); | 169 | struct net_device *dev); |
| 170 | 170 | ||
| 171 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | ||
| 172 | |||
| 173 | static struct ipv6_devconf ipv6_devconf __read_mostly = { | 171 | static struct ipv6_devconf ipv6_devconf __read_mostly = { |
| 174 | .forwarding = 0, | 172 | .forwarding = 0, |
| 175 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, | 173 | .hop_limit = IPV6_DEFAULT_HOPLIMIT, |
| @@ -837,7 +835,7 @@ out2: | |||
| 837 | rcu_read_unlock_bh(); | 835 | rcu_read_unlock_bh(); |
| 838 | 836 | ||
| 839 | if (likely(err == 0)) | 837 | if (likely(err == 0)) |
| 840 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); | 838 | inet6addr_notifier_call_chain(NETDEV_UP, ifa); |
| 841 | else { | 839 | else { |
| 842 | kfree(ifa); | 840 | kfree(ifa); |
| 843 | ifa = ERR_PTR(err); | 841 | ifa = ERR_PTR(err); |
| @@ -927,7 +925,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 927 | 925 | ||
| 928 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 926 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
| 929 | 927 | ||
| 930 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); | 928 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifp); |
| 931 | 929 | ||
| 932 | /* | 930 | /* |
| 933 | * Purge or update corresponding prefix | 931 | * Purge or update corresponding prefix |
| @@ -2529,6 +2527,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
| 2529 | static void init_loopback(struct net_device *dev) | 2527 | static void init_loopback(struct net_device *dev) |
| 2530 | { | 2528 | { |
| 2531 | struct inet6_dev *idev; | 2529 | struct inet6_dev *idev; |
| 2530 | struct net_device *sp_dev; | ||
| 2531 | struct inet6_ifaddr *sp_ifa; | ||
| 2532 | struct rt6_info *sp_rt; | ||
| 2532 | 2533 | ||
| 2533 | /* ::1 */ | 2534 | /* ::1 */ |
| 2534 | 2535 | ||
| @@ -2540,6 +2541,30 @@ static void init_loopback(struct net_device *dev) | |||
| 2540 | } | 2541 | } |
| 2541 | 2542 | ||
| 2542 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); | 2543 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
| 2544 | |||
| 2545 | /* Add routes to other interface's IPv6 addresses */ | ||
| 2546 | for_each_netdev(dev_net(dev), sp_dev) { | ||
| 2547 | if (!strcmp(sp_dev->name, dev->name)) | ||
| 2548 | continue; | ||
| 2549 | |||
| 2550 | idev = __in6_dev_get(sp_dev); | ||
| 2551 | if (!idev) | ||
| 2552 | continue; | ||
| 2553 | |||
| 2554 | read_lock_bh(&idev->lock); | ||
| 2555 | list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { | ||
| 2556 | |||
| 2557 | if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) | ||
| 2558 | continue; | ||
| 2559 | |||
| 2560 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | ||
| 2561 | |||
| 2562 | /* Failure cases are ignored */ | ||
| 2563 | if (!IS_ERR(sp_rt)) | ||
| 2564 | ip6_ins_rt(sp_rt); | ||
| 2565 | } | ||
| 2566 | read_unlock_bh(&idev->lock); | ||
| 2567 | } | ||
| 2543 | } | 2568 | } |
| 2544 | 2569 | ||
| 2545 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) | 2570 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) |
| @@ -2961,7 +2986,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2961 | 2986 | ||
| 2962 | if (state != INET6_IFADDR_STATE_DEAD) { | 2987 | if (state != INET6_IFADDR_STATE_DEAD) { |
| 2963 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2988 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
| 2964 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2989 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifa); |
| 2965 | } | 2990 | } |
| 2966 | in6_ifa_put(ifa); | 2991 | in6_ifa_put(ifa); |
| 2967 | 2992 | ||
| @@ -4784,26 +4809,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 4784 | 4809 | ||
| 4785 | static int __net_init addrconf_init_net(struct net *net) | 4810 | static int __net_init addrconf_init_net(struct net *net) |
| 4786 | { | 4811 | { |
| 4787 | int err; | 4812 | int err = -ENOMEM; |
| 4788 | struct ipv6_devconf *all, *dflt; | 4813 | struct ipv6_devconf *all, *dflt; |
| 4789 | 4814 | ||
| 4790 | err = -ENOMEM; | 4815 | all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); |
| 4791 | all = &ipv6_devconf; | 4816 | if (all == NULL) |
| 4792 | dflt = &ipv6_devconf_dflt; | 4817 | goto err_alloc_all; |
| 4793 | 4818 | ||
| 4794 | if (!net_eq(net, &init_net)) { | 4819 | dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); |
| 4795 | all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); | 4820 | if (dflt == NULL) |
| 4796 | if (all == NULL) | 4821 | goto err_alloc_dflt; |
| 4797 | goto err_alloc_all; | ||
| 4798 | 4822 | ||
| 4799 | dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); | 4823 | /* these will be inherited by all namespaces */ |
| 4800 | if (dflt == NULL) | 4824 | dflt->autoconf = ipv6_defaults.autoconf; |
| 4801 | goto err_alloc_dflt; | 4825 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; |
| 4802 | } else { | ||
| 4803 | /* these will be inherited by all namespaces */ | ||
| 4804 | dflt->autoconf = ipv6_defaults.autoconf; | ||
| 4805 | dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; | ||
| 4806 | } | ||
| 4807 | 4826 | ||
| 4808 | net->ipv6.devconf_all = all; | 4827 | net->ipv6.devconf_all = all; |
| 4809 | net->ipv6.devconf_dflt = dflt; | 4828 | net->ipv6.devconf_dflt = dflt; |
| @@ -4848,22 +4867,6 @@ static struct pernet_operations addrconf_ops = { | |||
| 4848 | .exit = addrconf_exit_net, | 4867 | .exit = addrconf_exit_net, |
| 4849 | }; | 4868 | }; |
| 4850 | 4869 | ||
| 4851 | /* | ||
| 4852 | * Device notifier | ||
| 4853 | */ | ||
| 4854 | |||
| 4855 | int register_inet6addr_notifier(struct notifier_block *nb) | ||
| 4856 | { | ||
| 4857 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | ||
| 4858 | } | ||
| 4859 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
| 4860 | |||
| 4861 | int unregister_inet6addr_notifier(struct notifier_block *nb) | ||
| 4862 | { | ||
| 4863 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); | ||
| 4864 | } | ||
| 4865 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
| 4866 | |||
| 4867 | static struct rtnl_af_ops inet6_ops = { | 4870 | static struct rtnl_af_ops inet6_ops = { |
| 4868 | .family = AF_INET6, | 4871 | .family = AF_INET6, |
| 4869 | .fill_link_af = inet6_fill_link_af, | 4872 | .fill_link_af = inet6_fill_link_af, |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index d051e5f4bf34..72104562c864 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
| @@ -78,3 +78,22 @@ int __ipv6_addr_type(const struct in6_addr *addr) | |||
| 78 | } | 78 | } |
| 79 | EXPORT_SYMBOL(__ipv6_addr_type); | 79 | EXPORT_SYMBOL(__ipv6_addr_type); |
| 80 | 80 | ||
| 81 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | ||
| 82 | |||
| 83 | int register_inet6addr_notifier(struct notifier_block *nb) | ||
| 84 | { | ||
| 85 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL(register_inet6addr_notifier); | ||
| 88 | |||
| 89 | int unregister_inet6addr_notifier(struct notifier_block *nb) | ||
| 90 | { | ||
| 91 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); | ||
| 92 | } | ||
| 93 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | ||
| 94 | |||
| 95 | int inet6addr_notifier_call_chain(unsigned long val, void *v) | ||
| 96 | { | ||
| 97 | return atomic_notifier_call_chain(&inet6addr_chain, val, v); | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL(inet6addr_notifier_call_chain); | ||
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index e33fe0ab2568..2bab2aa59745 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 118 | ipv6_addr_loopback(&hdr->daddr)) | 118 | ipv6_addr_loopback(&hdr->daddr)) |
| 119 | goto err; | 119 | goto err; |
| 120 | 120 | ||
| 121 | /* RFC4291 Errata ID: 3480 | ||
| 122 | * Interface-Local scope spans only a single interface on a | ||
| 123 | * node and is useful only for loopback transmission of | ||
| 124 | * multicast. Packets with interface-local scope received | ||
| 125 | * from another node must be discarded. | ||
| 126 | */ | ||
| 127 | if (!(skb->pkt_type == PACKET_LOOPBACK || | ||
| 128 | dev->flags & IFF_LOOPBACK) && | ||
| 129 | ipv6_addr_is_multicast(&hdr->daddr) && | ||
| 130 | IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) | ||
| 131 | goto err; | ||
| 132 | |||
| 121 | /* RFC4291 2.7 | 133 | /* RFC4291 2.7 |
| 122 | * Nodes must not originate a packet to a multicast address whose scope | 134 | * Nodes must not originate a packet to a multicast address whose scope |
| 123 | * field contains the reserved value 0; if such a packet is received, it | 135 | * field contains the reserved value 0; if such a packet is received, it |
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 83acc1405a18..cb631143721c 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
| @@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, | |||
| 57 | if (pfx_len - i >= 32) | 57 | if (pfx_len - i >= 32) |
| 58 | mask = 0; | 58 | mask = 0; |
| 59 | else | 59 | else |
| 60 | mask = htonl(~((1 << (pfx_len - i)) - 1)); | 60 | mask = htonl((1 << (i - pfx_len + 32)) - 1); |
| 61 | 61 | ||
| 62 | idx = i / 32; | 62 | idx = i / 32; |
| 63 | addr->s6_addr32[idx] &= mask; | 63 | addr->s6_addr32[idx] &= mask; |
| @@ -114,6 +114,7 @@ ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 114 | static struct xt_target ip6t_npt_target_reg[] __read_mostly = { | 114 | static struct xt_target ip6t_npt_target_reg[] __read_mostly = { |
| 115 | { | 115 | { |
| 116 | .name = "SNPT", | 116 | .name = "SNPT", |
| 117 | .table = "mangle", | ||
| 117 | .target = ip6t_snpt_tg, | 118 | .target = ip6t_snpt_tg, |
| 118 | .targetsize = sizeof(struct ip6t_npt_tginfo), | 119 | .targetsize = sizeof(struct ip6t_npt_tginfo), |
| 119 | .checkentry = ip6t_npt_checkentry, | 120 | .checkentry = ip6t_npt_checkentry, |
| @@ -124,6 +125,7 @@ static struct xt_target ip6t_npt_target_reg[] __read_mostly = { | |||
| 124 | }, | 125 | }, |
| 125 | { | 126 | { |
| 126 | .name = "DNPT", | 127 | .name = "DNPT", |
| 128 | .table = "mangle", | ||
| 127 | .target = ip6t_dnpt_tg, | 129 | .target = ip6t_dnpt_tg, |
| 128 | .targetsize = sizeof(struct ip6t_npt_tginfo), | 130 | .targetsize = sizeof(struct ip6t_npt_tginfo), |
| 129 | .checkentry = ip6t_npt_checkentry, | 131 | .checkentry = ip6t_npt_checkentry, |
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c index 5060d54199ab..e0983f3648a6 100644 --- a/net/ipv6/netfilter/ip6t_rpfilter.c +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
| @@ -71,6 +71,12 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, | |||
| 71 | return ret; | 71 | return ret; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | static bool rpfilter_is_local(const struct sk_buff *skb) | ||
| 75 | { | ||
| 76 | const struct rt6_info *rt = (const void *) skb_dst(skb); | ||
| 77 | return rt && (rt->rt6i_flags & RTF_LOCAL); | ||
| 78 | } | ||
| 79 | |||
| 74 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | 80 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) |
| 75 | { | 81 | { |
| 76 | const struct xt_rpfilter_info *info = par->matchinfo; | 82 | const struct xt_rpfilter_info *info = par->matchinfo; |
| @@ -78,7 +84,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 78 | struct ipv6hdr *iph; | 84 | struct ipv6hdr *iph; |
| 79 | bool invert = info->flags & XT_RPFILTER_INVERT; | 85 | bool invert = info->flags & XT_RPFILTER_INVERT; |
| 80 | 86 | ||
| 81 | if (par->in->flags & IFF_LOOPBACK) | 87 | if (rpfilter_is_local(skb)) |
| 82 | return true ^ invert; | 88 | return true ^ invert; |
| 83 | 89 | ||
| 84 | iph = ipv6_hdr(skb); | 90 | iph = ipv6_hdr(skb); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 54087e96d7b8..6700069949dd 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | * 2 of the License, or (at your option) any later version. | 14 | * 2 of the License, or (at your option) any later version. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #define pr_fmt(fmt) "IPv6-nf: " fmt | ||
| 18 | |||
| 17 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
| 18 | #include <linux/types.h> | 20 | #include <linux/types.h> |
| 19 | #include <linux/string.h> | 21 | #include <linux/string.h> |
| @@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |||
| 180 | 182 | ||
| 181 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); | 183 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); |
| 182 | local_bh_enable(); | 184 | local_bh_enable(); |
| 183 | if (q == NULL) | 185 | if (IS_ERR_OR_NULL(q)) { |
| 184 | goto oom; | 186 | inet_frag_maybe_warn_overflow(q, pr_fmt()); |
| 185 | 187 | return NULL; | |
| 188 | } | ||
| 186 | return container_of(q, struct frag_queue, q); | 189 | return container_of(q, struct frag_queue, q); |
| 187 | |||
| 188 | oom: | ||
| 189 | return NULL; | ||
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | 192 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3c6a77290c6e..0ba10e53a629 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -26,6 +26,9 @@ | |||
| 26 | * YOSHIFUJI,H. @USAGI Always remove fragment header to | 26 | * YOSHIFUJI,H. @USAGI Always remove fragment header to |
| 27 | * calculate ICV correctly. | 27 | * calculate ICV correctly. |
| 28 | */ | 28 | */ |
| 29 | |||
| 30 | #define pr_fmt(fmt) "IPv6: " fmt | ||
| 31 | |||
| 29 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
| 30 | #include <linux/types.h> | 33 | #include <linux/types.h> |
| 31 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| @@ -185,9 +188,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6 | |||
| 185 | hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); | 188 | hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); |
| 186 | 189 | ||
| 187 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 190 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
| 188 | if (q == NULL) | 191 | if (IS_ERR_OR_NULL(q)) { |
| 192 | inet_frag_maybe_warn_overflow(q, pr_fmt()); | ||
| 189 | return NULL; | 193 | return NULL; |
| 190 | 194 | } | |
| 191 | return container_of(q, struct frag_queue, q); | 195 | return container_of(q, struct frag_queue, q); |
| 192 | } | 196 | } |
| 193 | 197 | ||
| @@ -326,9 +330,17 @@ found: | |||
| 326 | } | 330 | } |
| 327 | 331 | ||
| 328 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 332 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
| 329 | fq->q.meat == fq->q.len) | 333 | fq->q.meat == fq->q.len) { |
| 330 | return ip6_frag_reasm(fq, prev, dev); | 334 | int res; |
| 335 | unsigned long orefdst = skb->_skb_refdst; | ||
| 336 | |||
| 337 | skb->_skb_refdst = 0UL; | ||
| 338 | res = ip6_frag_reasm(fq, prev, dev); | ||
| 339 | skb->_skb_refdst = orefdst; | ||
| 340 | return res; | ||
| 341 | } | ||
| 331 | 342 | ||
| 343 | skb_dst_drop(skb); | ||
| 332 | inet_frag_lru_move(&fq->q); | 344 | inet_frag_lru_move(&fq->q); |
| 333 | return -1; | 345 | return -1; |
| 334 | 346 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9b6460055df5..46a5be85be87 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -386,9 +386,17 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 386 | 386 | ||
| 387 | if (dst) | 387 | if (dst) |
| 388 | dst->ops->redirect(dst, sk, skb); | 388 | dst->ops->redirect(dst, sk, skb); |
| 389 | goto out; | ||
| 389 | } | 390 | } |
| 390 | 391 | ||
| 391 | if (type == ICMPV6_PKT_TOOBIG) { | 392 | if (type == ICMPV6_PKT_TOOBIG) { |
| 393 | /* We are not interested in TCP_LISTEN and open_requests | ||
| 394 | * (SYN-ACKs send out by Linux are always <576bytes so | ||
| 395 | * they should go through unfragmented). | ||
| 396 | */ | ||
| 397 | if (sk->sk_state == TCP_LISTEN) | ||
| 398 | goto out; | ||
| 399 | |||
| 392 | tp->mtu_info = ntohl(info); | 400 | tp->mtu_info = ntohl(info); |
| 393 | if (!sock_owned_by_user(sk)) | 401 | if (!sock_owned_by_user(sk)) |
| 394 | tcp_v6_mtu_reduced(sk); | 402 | tcp_v6_mtu_reduced(sk); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 599e1ba6d1ce..d8e5e852fc7a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -1285,10 +1285,18 @@ do_confirm: | |||
| 1285 | 1285 | ||
| 1286 | void udpv6_destroy_sock(struct sock *sk) | 1286 | void udpv6_destroy_sock(struct sock *sk) |
| 1287 | { | 1287 | { |
| 1288 | struct udp_sock *up = udp_sk(sk); | ||
| 1288 | lock_sock(sk); | 1289 | lock_sock(sk); |
| 1289 | udp_v6_flush_pending_frames(sk); | 1290 | udp_v6_flush_pending_frames(sk); |
| 1290 | release_sock(sk); | 1291 | release_sock(sk); |
| 1291 | 1292 | ||
| 1293 | if (static_key_false(&udpv6_encap_needed) && up->encap_type) { | ||
| 1294 | void (*encap_destroy)(struct sock *sk); | ||
| 1295 | encap_destroy = ACCESS_ONCE(up->encap_destroy); | ||
| 1296 | if (encap_destroy) | ||
| 1297 | encap_destroy(sk); | ||
| 1298 | } | ||
| 1299 | |||
| 1292 | inet6_destroy_sock(sk); | 1300 | inet6_destroy_sock(sk); |
| 1293 | } | 1301 | } |
| 1294 | 1302 | ||
