]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/icmp.c
ipv4: Deliver ICMP redirects to sockets too.
[karo-tx-linux.git] / net / ipv4 / icmp.c
index 4bce5a2830aaee18dfd5838bf908b61d3df28b3d..588514627aa7060fba774d65ff0693a1c999739e 100644 (file)
@@ -254,9 +254,10 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
 
        /* Limit if icmp type is enabled in ratemask. */
        if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) {
-               struct inet_peer *peer = rt_get_peer_create(rt, fl4->daddr);
+               struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1);
                rc = inet_peer_xrlim_allow(peer,
                                           net->ipv4.sysctl_icmp_ratelimit);
+               inet_putpeer(peer);
        }
 out:
        return rc;
@@ -633,18 +634,31 @@ out:;
 EXPORT_SYMBOL(icmp_send);
 
 
+static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
+{
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       const struct net_protocol *ipprot;
+       int protocol = iph->protocol;
+
+       raw_icmp_error(skb, protocol, info);
+
+       rcu_read_lock();
+       ipprot = rcu_dereference(inet_protos[protocol]);
+       if (ipprot && ipprot->err_handler)
+               ipprot->err_handler(skb, info);
+       rcu_read_unlock();
+}
+
 /*
  *     Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, and ICMP_QUENCH.
  */
 
 static void icmp_unreach(struct sk_buff *skb)
 {
-       const struct net_protocol *ipprot;
        const struct iphdr *iph;
        struct icmphdr *icmph;
        struct net *net;
        u32 info = 0;
-       int protocol;
 
        net = dev_net(skb_dst(skb)->dev);
 
@@ -725,19 +739,7 @@ static void icmp_unreach(struct sk_buff *skb)
        if (!pskb_may_pull(skb, iph->ihl * 4 + 8))
                goto out;
 
-       iph = (const struct iphdr *)skb->data;
-       protocol = iph->protocol;
-
-       /*
-        *      Deliver ICMP message to raw sockets. Pretty useless feature?
-        */
-       raw_icmp_error(skb, protocol, info);
-
-       rcu_read_lock();
-       ipprot = rcu_dereference(inet_protos[protocol]);
-       if (ipprot && ipprot->err_handler)
-               ipprot->err_handler(skb, info);
-       rcu_read_unlock();
+       icmp_socket_deliver(skb, info);
 
 out:
        return;
@@ -780,13 +782,7 @@ static void icmp_redirect(struct sk_buff *skb)
                break;
        }
 
-       /* Ping wants to see redirects.
-         * Let's pretend they are errors of sorts... */
-       if (iph->protocol == IPPROTO_ICMP &&
-           iph->ihl >= 5 &&
-           pskb_may_pull(skb, (iph->ihl<<2)+8)) {
-               ping_err(skb, icmp_hdr(skb)->un.gateway);
-       }
+       icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway);
 
 out:
        return;