ipv4: fix error handling in icmp_protocol.
authorLi Wei <lw@cn.fujitsu.com>
Thu, 21 Feb 2013 22:18:44 +0000 (22:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Feb 2013 20:10:18 +0000 (15:10 -0500)
Now we handle icmp errors in each transport protocol's err_handler,
for icmp protocols, that is ping_err. Since this handler only care
of those icmp errors triggered by echo request, errors triggered
by echo reply(which sent by kernel) are sliently ignored.

So wrap ping_err() with icmp_err() to deal with those icmp errors.

Signed-off-by: Li Wei <lw@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/icmp.h
net/ipv4/af_inet.c
net/ipv4/icmp.c

index 9ac2524d1402d38a401613fa1b91d5c1918f858e..081439fd070ed7ce932ff1e1877398d1d119207c 100644 (file)
@@ -41,6 +41,7 @@ struct net;
 
 extern void    icmp_send(struct sk_buff *skb_in,  int type, int code, __be32 info);
 extern int     icmp_rcv(struct sk_buff *skb);
+extern void    icmp_err(struct sk_buff *, u32 info);
 extern int     icmp_init(void);
 extern void    icmp_out_count(struct net *net, unsigned char type);
 
index 9cbcb94a4c6df5e205a835ee8e77dc750a866576..15847e19b7ddc55b5d7b0ca81ba1f092d9ef54bd 100644 (file)
@@ -1577,7 +1577,7 @@ static const struct net_offload udp_offload = {
 
 static const struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
-       .err_handler =  ping_err,
+       .err_handler =  icmp_err,
        .no_policy =    1,
        .netns_ok =     1,
 };
index 17ff9fd7cddab0db42c718173cfd85a9586d6d16..3ac5dff7962755166b26e1b96f7c775d28508a16 100644 (file)
@@ -934,6 +934,29 @@ error:
        goto drop;
 }
 
+void icmp_err(struct sk_buff *skb, u32 info)
+{
+       struct iphdr *iph = (struct iphdr *)skb->data;
+       struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2));
+       int type = icmp_hdr(skb)->type;
+       int code = icmp_hdr(skb)->code;
+       struct net *net = dev_net(skb->dev);
+
+       /*
+        * Use ping_err to handle all icmp errors except those
+        * triggered by ICMP_ECHOREPLY which sent from kernel.
+        */
+       if (icmph->type != ICMP_ECHOREPLY) {
+               ping_err(skb, info);
+               return;
+       }
+
+       if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+               ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ICMP, 0);
+       else if (type == ICMP_REDIRECT)
+               ipv4_redirect(skb, net, 0, 0, IPPROTO_ICMP, 0);
+}
+
 /*
  *     This table is the definition of how we handle ICMP.
  */