err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
                                                   iph->tos, skb->dev);
                        if (unlikely(err)) {
-                               if (err == -EHOSTUNREACH)
-                                       IP_INC_STATS_BH(dev_net(skb->dev),
-                                                       IPSTATS_MIB_INADDRERRORS);
-                               else if (err == -ENETUNREACH)
-                                       IP_INC_STATS_BH(dev_net(skb->dev),
-                                                       IPSTATS_MIB_INNOROUTES);
-                               else if (err == -EXDEV)
+                               if (err == -EXDEV)
                                        NET_INC_STATS_BH(dev_net(skb->dev),
                                                         LINUX_MIB_IPRPFILTER);
                                goto drop;
 
 
 static int ip_error(struct sk_buff *skb)
 {
+       struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
        struct rtable *rt = skb_rtable(skb);
        struct inet_peer *peer;
        unsigned long now;
+       struct net *net;
        bool send;
        int code;
 
+       net = dev_net(rt->dst.dev);
+       if (!IN_DEV_FORWARD(in_dev)) {
+               switch (rt->dst.error) {
+               case EHOSTUNREACH:
+                       IP_INC_STATS_BH(net, IPSTATS_MIB_INADDRERRORS);
+                       break;
+
+               case ENETUNREACH:
+                       IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES);
+                       break;
+               }
+               goto out;
+       }
+
        switch (rt->dst.error) {
        case EINVAL:
        default:
                break;
        case ENETUNREACH:
                code = ICMP_NET_UNREACH;
-               IP_INC_STATS_BH(dev_net(rt->dst.dev),
-                               IPSTATS_MIB_INNOROUTES);
+               IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES);
                break;
        case EACCES:
                code = ICMP_PKT_FILTERED;
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        err = fib_lookup(net, &fl4, &res);
-       if (err != 0) {
-               if (!IN_DEV_FORWARD(in_dev))
-                       goto e_hostunreach;
+       if (err != 0)
                goto no_route;
-       }
 
        RT_CACHE_STAT_INC(in_slow_tot);
 
        }
 
        if (!IN_DEV_FORWARD(in_dev))
-               goto e_hostunreach;
+               goto no_route;
        if (res.type != RTN_UNICAST)
                goto martian_destination;
 
                                     &daddr, &saddr, dev->name);
 #endif
 
-e_hostunreach:
-       err = -EHOSTUNREACH;
-       goto out;
-
 e_inval:
        err = -EINVAL;
        goto out;