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);
 
 
 
 static const struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
-       .err_handler =  ping_err,
+       .err_handler =  icmp_err,
        .no_policy =    1,
        .netns_ok =     1,
 };
 
        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.
  */