@@ -673,7 +673,8 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
673673 return ;
674674}
675675
676- static void __ip_do_redirect (struct rtable * rt , struct sk_buff * skb , struct flowi4 * fl4 )
676+ static void __ip_do_redirect (struct rtable * rt , struct sk_buff * skb , struct flowi4 * fl4 ,
677+ bool kill_route )
677678{
678679 __be32 new_gw = icmp_hdr (skb )-> un .gateway ;
679680 __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
728729 update_or_create_fnhe (nh , fl4 -> daddr , new_gw ,
729730 0 , 0 );
730731 }
731- rt -> rt_gateway = new_gw ;
732- rt -> rt_flags |= RTCF_REDIRECTED ;
732+ if ( kill_route )
733+ rt -> dst . obsolete = DST_OBSOLETE_KILL ;
733734 call_netevent_notifiers (NETEVENT_NEIGH_UPDATE , n );
734735 }
735736 neigh_release (n );
@@ -760,7 +761,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
760761 rt = (struct rtable * ) dst ;
761762
762763 ip_rt_build_flow_key (& fl4 , sk , skb );
763- __ip_do_redirect (rt , skb , & fl4 );
764+ __ip_do_redirect (rt , skb , & fl4 , true );
764765}
765766
766767static struct dst_entry * ipv4_negative_advice (struct dst_entry * dst )
@@ -919,7 +920,7 @@ out: kfree_skb(skb);
919920 return 0 ;
920921}
921922
922- static void __ip_rt_update_pmtu (struct rtable * rt , struct flowi4 * fl4 , u32 mtu )
923+ static u32 __ip_rt_update_pmtu (struct rtable * rt , struct flowi4 * fl4 , u32 mtu )
923924{
924925 struct fib_result res ;
925926
@@ -932,8 +933,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
932933 update_or_create_fnhe (nh , fl4 -> daddr , 0 , mtu ,
933934 jiffies + ip_rt_mtu_expires );
934935 }
935- rt -> rt_pmtu = mtu ;
936- dst_set_expires (& rt -> dst , ip_rt_mtu_expires );
936+ return mtu ;
937937}
938938
939939static 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,
943943 struct flowi4 fl4 ;
944944
945945 ip_rt_build_flow_key (& fl4 , sk , skb );
946- __ip_rt_update_pmtu (rt , & fl4 , mtu );
946+ mtu = __ip_rt_update_pmtu (rt , & fl4 , mtu );
947+
948+ if (!rt -> rt_pmtu ) {
949+ dst -> obsolete = DST_OBSOLETE_KILL ;
950+ } else {
951+ rt -> rt_pmtu = mtu ;
952+ dst_set_expires (& rt -> dst , ip_rt_mtu_expires );
953+ }
947954}
948955
949956void 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,
989996 RT_TOS (iph -> tos ), protocol , mark , flow_flags );
990997 rt = __ip_route_output_key (net , & fl4 );
991998 if (!IS_ERR (rt )) {
992- __ip_do_redirect (rt , skb , & fl4 );
999+ __ip_do_redirect (rt , skb , & fl4 , false );
9931000 ip_rt_put (rt );
9941001 }
9951002}
@@ -1004,7 +1011,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
10041011 __build_flow_key (& fl4 , sk , iph , 0 , 0 , 0 , 0 , 0 );
10051012 rt = __ip_route_output_key (sock_net (sk ), & fl4 );
10061013 if (!IS_ERR (rt )) {
1007- __ip_do_redirect (rt , skb , & fl4 );
1014+ __ip_do_redirect (rt , skb , & fl4 , false );
10081015 ip_rt_put (rt );
10091016 }
10101017}
@@ -1014,7 +1021,15 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
10141021{
10151022 struct rtable * rt = (struct rtable * ) dst ;
10161023
1017- if (rt_is_expired (rt ))
1024+ /* All IPV4 dsts are created with ->obsolete set to the value
1025+ * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1026+ * into this function always.
1027+ *
1028+ * When a PMTU/redirect information update invalidates a
1029+ * route, this is indicated by setting obsolete to
1030+ * DST_OBSOLETE_KILL.
1031+ */
1032+ if (dst -> obsolete == DST_OBSOLETE_KILL || rt_is_expired (rt ))
10181033 return NULL ;
10191034 return dst ;
10201035}
@@ -1186,8 +1201,10 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh *nh, __be32 daddr
11861201 dst_set_expires (& rt -> dst , diff );
11871202 }
11881203 }
1189- if (gw )
1204+ if (gw ) {
1205+ rt -> rt_flags |= RTCF_REDIRECTED ;
11901206 rt -> rt_gateway = gw ;
1207+ }
11911208 fnhe -> fnhe_stamp = jiffies ;
11921209 break ;
11931210 }
0 commit comments