mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ipv4: Kill routes during PMTU/redirect updates.
Mark them obsolete so there will be a re-lookup to fetch the FIB nexthop exception info. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									f5b0a87436
								
							
						
					
					
						commit
						ceb3320610
					
				
					 2 changed files with 30 additions and 12 deletions
				
			
		| 
						 | 
					@ -78,6 +78,7 @@ struct dst_entry {
 | 
				
			||||||
#define DST_OBSOLETE_NONE	0
 | 
					#define DST_OBSOLETE_NONE	0
 | 
				
			||||||
#define DST_OBSOLETE_DEAD	2
 | 
					#define DST_OBSOLETE_DEAD	2
 | 
				
			||||||
#define DST_OBSOLETE_FORCE_CHK	-1
 | 
					#define DST_OBSOLETE_FORCE_CHK	-1
 | 
				
			||||||
 | 
					#define DST_OBSOLETE_KILL	-2
 | 
				
			||||||
	unsigned short		header_len;	/* more space at head required */
 | 
						unsigned short		header_len;	/* more space at head required */
 | 
				
			||||||
	unsigned short		trailer_len;	/* space to reserve at tail */
 | 
						unsigned short		trailer_len;	/* space to reserve at tail */
 | 
				
			||||||
#ifdef CONFIG_IP_ROUTE_CLASSID
 | 
					#ifdef CONFIG_IP_ROUTE_CLASSID
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -673,7 +673,8 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4)
 | 
					static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4,
 | 
				
			||||||
 | 
								     bool kill_route)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	__be32 new_gw = icmp_hdr(skb)->un.gateway;
 | 
						__be32 new_gw = icmp_hdr(skb)->un.gateway;
 | 
				
			||||||
	__be32 old_gw = ip_hdr(skb)->saddr;
 | 
						__be32 old_gw = ip_hdr(skb)->saddr;
 | 
				
			||||||
| 
						 | 
					@ -728,8 +729,8 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
 | 
				
			||||||
				update_or_create_fnhe(nh, fl4->daddr, new_gw,
 | 
									update_or_create_fnhe(nh, fl4->daddr, new_gw,
 | 
				
			||||||
						      0, 0);
 | 
											      0, 0);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			rt->rt_gateway = new_gw;
 | 
								if (kill_route)
 | 
				
			||||||
			rt->rt_flags |= RTCF_REDIRECTED;
 | 
									rt->dst.obsolete = DST_OBSOLETE_KILL;
 | 
				
			||||||
			call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
 | 
								call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		neigh_release(n);
 | 
							neigh_release(n);
 | 
				
			||||||
| 
						 | 
					@ -760,7 +761,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
 | 
				
			||||||
	rt = (struct rtable *) dst;
 | 
						rt = (struct rtable *) dst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip_rt_build_flow_key(&fl4, sk, skb);
 | 
						ip_rt_build_flow_key(&fl4, sk, skb);
 | 
				
			||||||
	__ip_do_redirect(rt, skb, &fl4);
 | 
						__ip_do_redirect(rt, skb, &fl4, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 | 
					static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 | 
				
			||||||
| 
						 | 
					@ -919,7 +920,7 @@ out:	kfree_skb(skb);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 | 
					static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct fib_result res;
 | 
						struct fib_result res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -932,8 +933,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 | 
				
			||||||
		update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
 | 
							update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
 | 
				
			||||||
				      jiffies + ip_rt_mtu_expires);
 | 
									      jiffies + ip_rt_mtu_expires);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rt->rt_pmtu = mtu;
 | 
						return mtu;
 | 
				
			||||||
	dst_set_expires(&rt->dst, ip_rt_mtu_expires);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 | 
					static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 | 
				
			||||||
| 
						 | 
					@ -943,7 +943,14 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
 | 
				
			||||||
	struct flowi4 fl4;
 | 
						struct flowi4 fl4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ip_rt_build_flow_key(&fl4, sk, skb);
 | 
						ip_rt_build_flow_key(&fl4, sk, skb);
 | 
				
			||||||
	__ip_rt_update_pmtu(rt, &fl4, mtu);
 | 
						mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!rt->rt_pmtu) {
 | 
				
			||||||
 | 
							dst->obsolete = DST_OBSOLETE_KILL;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							rt->rt_pmtu = mtu;
 | 
				
			||||||
 | 
							dst_set_expires(&rt->dst, ip_rt_mtu_expires);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
 | 
					void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
 | 
				
			||||||
| 
						 | 
					@ -989,7 +996,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
 | 
				
			||||||
			 RT_TOS(iph->tos), protocol, mark, flow_flags);
 | 
								 RT_TOS(iph->tos), protocol, mark, flow_flags);
 | 
				
			||||||
	rt = __ip_route_output_key(net, &fl4);
 | 
						rt = __ip_route_output_key(net, &fl4);
 | 
				
			||||||
	if (!IS_ERR(rt)) {
 | 
						if (!IS_ERR(rt)) {
 | 
				
			||||||
		__ip_do_redirect(rt, skb, &fl4);
 | 
							__ip_do_redirect(rt, skb, &fl4, false);
 | 
				
			||||||
		ip_rt_put(rt);
 | 
							ip_rt_put(rt);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1004,7 +1011,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
 | 
				
			||||||
	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
 | 
						__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
 | 
				
			||||||
	rt = __ip_route_output_key(sock_net(sk), &fl4);
 | 
						rt = __ip_route_output_key(sock_net(sk), &fl4);
 | 
				
			||||||
	if (!IS_ERR(rt)) {
 | 
						if (!IS_ERR(rt)) {
 | 
				
			||||||
		__ip_do_redirect(rt, skb, &fl4);
 | 
							__ip_do_redirect(rt, skb, &fl4, false);
 | 
				
			||||||
		ip_rt_put(rt);
 | 
							ip_rt_put(rt);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1014,7 +1021,15 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rtable *rt = (struct rtable *) dst;
 | 
						struct rtable *rt = (struct rtable *) dst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (rt_is_expired(rt))
 | 
						/* All IPV4 dsts are created with ->obsolete set to the value
 | 
				
			||||||
 | 
						 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
 | 
				
			||||||
 | 
						 * into this function always.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * When a PMTU/redirect information update invalidates a
 | 
				
			||||||
 | 
						 * route, this is indicated by setting obsolete to
 | 
				
			||||||
 | 
						 * DST_OBSOLETE_KILL.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	return dst;
 | 
						return dst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1186,8 +1201,10 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh *nh, __be32 daddr
 | 
				
			||||||
				dst_set_expires(&rt->dst, diff);
 | 
									dst_set_expires(&rt->dst, diff);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (gw)
 | 
							if (gw) {
 | 
				
			||||||
 | 
								rt->rt_flags |= RTCF_REDIRECTED;
 | 
				
			||||||
			rt->rt_gateway = gw;
 | 
								rt->rt_gateway = gw;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		fnhe->fnhe_stamp = jiffies;
 | 
							fnhe->fnhe_stamp = jiffies;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue