aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/icmp.c')
-rw-r--r--net/ipv6/icmp.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 091a2971c7b7..24d69dbca4d6 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -188,14 +188,16 @@ static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
188 } else { 188 } else {
189 struct rt6_info *rt = (struct rt6_info *)dst; 189 struct rt6_info *rt = (struct rt6_info *)dst;
190 int tmo = net->ipv6.sysctl.icmpv6_time; 190 int tmo = net->ipv6.sysctl.icmpv6_time;
191 struct inet_peer *peer;
191 192
192 /* Give more bandwidth to wider prefixes. */ 193 /* Give more bandwidth to wider prefixes. */
193 if (rt->rt6i_dst.plen < 128) 194 if (rt->rt6i_dst.plen < 128)
194 tmo >>= ((128 - rt->rt6i_dst.plen)>>5); 195 tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
195 196
196 if (!rt->rt6i_peer) 197 peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
197 rt6_bind_peer(rt, 1); 198 res = inet_peer_xrlim_allow(peer, tmo);
198 res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo); 199 if (peer)
200 inet_putpeer(peer);
199 } 201 }
200 dst_release(dst); 202 dst_release(dst);
201 return res; 203 return res;
@@ -596,13 +598,12 @@ out:
596 icmpv6_xmit_unlock(sk); 598 icmpv6_xmit_unlock(sk);
597} 599}
598 600
599static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) 601void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
600{ 602{
601 const struct inet6_protocol *ipprot; 603 const struct inet6_protocol *ipprot;
602 int inner_offset; 604 int inner_offset;
603 int hash;
604 u8 nexthdr;
605 __be16 frag_off; 605 __be16 frag_off;
606 u8 nexthdr;
606 607
607 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 608 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
608 return; 609 return;
@@ -629,10 +630,8 @@ static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
629 --ANK (980726) 630 --ANK (980726)
630 */ 631 */
631 632
632 hash = nexthdr & (MAX_INET_PROTOS - 1);
633
634 rcu_read_lock(); 633 rcu_read_lock();
635 ipprot = rcu_dereference(inet6_protos[hash]); 634 ipprot = rcu_dereference(inet6_protos[nexthdr]);
636 if (ipprot && ipprot->err_handler) 635 if (ipprot && ipprot->err_handler)
637 ipprot->err_handler(skb, NULL, type, code, inner_offset, info); 636 ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
638 rcu_read_unlock(); 637 rcu_read_unlock();
@@ -649,7 +648,6 @@ static int icmpv6_rcv(struct sk_buff *skb)
649 struct net_device *dev = skb->dev; 648 struct net_device *dev = skb->dev;
650 struct inet6_dev *idev = __in6_dev_get(dev); 649 struct inet6_dev *idev = __in6_dev_get(dev);
651 const struct in6_addr *saddr, *daddr; 650 const struct in6_addr *saddr, *daddr;
652 const struct ipv6hdr *orig_hdr;
653 struct icmp6hdr *hdr; 651 struct icmp6hdr *hdr;
654 u8 type; 652 u8 type;
655 653
@@ -661,7 +659,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
661 XFRM_STATE_ICMP)) 659 XFRM_STATE_ICMP))
662 goto drop_no_count; 660 goto drop_no_count;
663 661
664 if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(*orig_hdr))) 662 if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(struct ipv6hdr)))
665 goto drop_no_count; 663 goto drop_no_count;
666 664
667 nh = skb_network_offset(skb); 665 nh = skb_network_offset(skb);
@@ -722,9 +720,6 @@ static int icmpv6_rcv(struct sk_buff *skb)
722 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 720 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
723 goto discard_it; 721 goto discard_it;
724 hdr = icmp6_hdr(skb); 722 hdr = icmp6_hdr(skb);
725 orig_hdr = (struct ipv6hdr *) (hdr + 1);
726 rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev,
727 ntohl(hdr->icmp6_mtu));
728 723
729 /* 724 /*
730 * Drop through to notify 725 * Drop through to notify