forked from mirrors/linux
		
	ipv4: Cache ip_error() routes even when not forwarding.
And account for the fact that, when we are not forwarding, we should bump statistic counters rather than emit an ICMP response. RP-filter rejected lookups are still not cached. Since -EHOSTUNREACH and -ENETUNREACH can now no longer be seen in ip_rcv_finish(), remove those checks. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									df67e6c9a6
								
							
						
					
					
						commit
						251da41301
					
				
					 2 changed files with 20 additions and 18 deletions
				
			
		|  | @ -342,13 +342,7 @@ static int ip_rcv_finish(struct sk_buff *skb) | ||||||
| 			err = ip_route_input_noref(skb, iph->daddr, iph->saddr, | 			err = ip_route_input_noref(skb, iph->daddr, iph->saddr, | ||||||
| 						   iph->tos, skb->dev); | 						   iph->tos, skb->dev); | ||||||
| 			if (unlikely(err)) { | 			if (unlikely(err)) { | ||||||
| 				if (err == -EHOSTUNREACH) | 				if (err == -EXDEV) | ||||||
| 					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) |  | ||||||
| 					NET_INC_STATS_BH(dev_net(skb->dev), | 					NET_INC_STATS_BH(dev_net(skb->dev), | ||||||
| 							 LINUX_MIB_IPRPFILTER); | 							 LINUX_MIB_IPRPFILTER); | ||||||
| 				goto drop; | 				goto drop; | ||||||
|  |  | ||||||
|  | @ -1609,12 +1609,28 @@ void ip_rt_send_redirect(struct sk_buff *skb) | ||||||
| 
 | 
 | ||||||
| static int ip_error(struct sk_buff *skb) | 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 rtable *rt = skb_rtable(skb); | ||||||
| 	struct inet_peer *peer; | 	struct inet_peer *peer; | ||||||
| 	unsigned long now; | 	unsigned long now; | ||||||
|  | 	struct net *net; | ||||||
| 	bool send; | 	bool send; | ||||||
| 	int code; | 	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) { | 	switch (rt->dst.error) { | ||||||
| 	case EINVAL: | 	case EINVAL: | ||||||
| 	default: | 	default: | ||||||
|  | @ -1624,8 +1640,7 @@ static int ip_error(struct sk_buff *skb) | ||||||
| 		break; | 		break; | ||||||
| 	case ENETUNREACH: | 	case ENETUNREACH: | ||||||
| 		code = ICMP_NET_UNREACH; | 		code = ICMP_NET_UNREACH; | ||||||
| 		IP_INC_STATS_BH(dev_net(rt->dst.dev), | 		IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES); | ||||||
| 				IPSTATS_MIB_INNOROUTES); |  | ||||||
| 		break; | 		break; | ||||||
| 	case EACCES: | 	case EACCES: | ||||||
| 		code = ICMP_PKT_FILTERED; | 		code = ICMP_PKT_FILTERED; | ||||||
|  | @ -2255,11 +2270,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | ||||||
| 	fl4.daddr = daddr; | 	fl4.daddr = daddr; | ||||||
| 	fl4.saddr = saddr; | 	fl4.saddr = saddr; | ||||||
| 	err = fib_lookup(net, &fl4, &res); | 	err = fib_lookup(net, &fl4, &res); | ||||||
| 	if (err != 0) { | 	if (err != 0) | ||||||
| 		if (!IN_DEV_FORWARD(in_dev)) |  | ||||||
| 			goto e_hostunreach; |  | ||||||
| 		goto no_route; | 		goto no_route; | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	RT_CACHE_STAT_INC(in_slow_tot); | 	RT_CACHE_STAT_INC(in_slow_tot); | ||||||
| 
 | 
 | ||||||
|  | @ -2279,7 +2291,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!IN_DEV_FORWARD(in_dev)) | 	if (!IN_DEV_FORWARD(in_dev)) | ||||||
| 		goto e_hostunreach; | 		goto no_route; | ||||||
| 	if (res.type != RTN_UNICAST) | 	if (res.type != RTN_UNICAST) | ||||||
| 		goto martian_destination; | 		goto martian_destination; | ||||||
| 
 | 
 | ||||||
|  | @ -2367,10 +2379,6 @@ out:	return err; | ||||||
| 				     &daddr, &saddr, dev->name); | 				     &daddr, &saddr, dev->name); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| e_hostunreach: |  | ||||||
| 	err = -EHOSTUNREACH; |  | ||||||
| 	goto out; |  | ||||||
| 
 |  | ||||||
| e_inval: | e_inval: | ||||||
| 	err = -EINVAL; | 	err = -EINVAL; | ||||||
| 	goto out; | 	goto out; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 David S. Miller
						David S. Miller