@@ -673,7 +673,8 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
673
673
return ;
674
674
}
675
675
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 )
677
678
{
678
679
__be32 new_gw = icmp_hdr (skb )-> un .gateway ;
679
680
__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
728
729
update_or_create_fnhe (nh , fl4 -> daddr , new_gw ,
729
730
0 , 0 );
730
731
}
731
- rt -> rt_gateway = new_gw ;
732
- rt -> rt_flags |= RTCF_REDIRECTED ;
732
+ if ( kill_route )
733
+ rt -> dst . obsolete = DST_OBSOLETE_KILL ;
733
734
call_netevent_notifiers (NETEVENT_NEIGH_UPDATE , n );
734
735
}
735
736
neigh_release (n );
@@ -760,7 +761,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
760
761
rt = (struct rtable * ) dst ;
761
762
762
763
ip_rt_build_flow_key (& fl4 , sk , skb );
763
- __ip_do_redirect (rt , skb , & fl4 );
764
+ __ip_do_redirect (rt , skb , & fl4 , true );
764
765
}
765
766
766
767
static struct dst_entry * ipv4_negative_advice (struct dst_entry * dst )
@@ -919,7 +920,7 @@ out: kfree_skb(skb);
919
920
return 0 ;
920
921
}
921
922
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 )
923
924
{
924
925
struct fib_result res ;
925
926
@@ -932,8 +933,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
932
933
update_or_create_fnhe (nh , fl4 -> daddr , 0 , mtu ,
933
934
jiffies + ip_rt_mtu_expires );
934
935
}
935
- rt -> rt_pmtu = mtu ;
936
- dst_set_expires (& rt -> dst , ip_rt_mtu_expires );
936
+ return mtu ;
937
937
}
938
938
939
939
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,
943
943
struct flowi4 fl4 ;
944
944
945
945
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
+ }
947
954
}
948
955
949
956
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,
989
996
RT_TOS (iph -> tos ), protocol , mark , flow_flags );
990
997
rt = __ip_route_output_key (net , & fl4 );
991
998
if (!IS_ERR (rt )) {
992
- __ip_do_redirect (rt , skb , & fl4 );
999
+ __ip_do_redirect (rt , skb , & fl4 , false );
993
1000
ip_rt_put (rt );
994
1001
}
995
1002
}
@@ -1004,7 +1011,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
1004
1011
__build_flow_key (& fl4 , sk , iph , 0 , 0 , 0 , 0 , 0 );
1005
1012
rt = __ip_route_output_key (sock_net (sk ), & fl4 );
1006
1013
if (!IS_ERR (rt )) {
1007
- __ip_do_redirect (rt , skb , & fl4 );
1014
+ __ip_do_redirect (rt , skb , & fl4 , false );
1008
1015
ip_rt_put (rt );
1009
1016
}
1010
1017
}
@@ -1014,7 +1021,15 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1014
1021
{
1015
1022
struct rtable * rt = (struct rtable * ) dst ;
1016
1023
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 ))
1018
1033
return NULL ;
1019
1034
return dst ;
1020
1035
}
@@ -1186,8 +1201,10 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh *nh, __be32 daddr
1186
1201
dst_set_expires (& rt -> dst , diff );
1187
1202
}
1188
1203
}
1189
- if (gw )
1204
+ if (gw ) {
1205
+ rt -> rt_flags |= RTCF_REDIRECTED ;
1190
1206
rt -> rt_gateway = gw ;
1207
+ }
1191
1208
fnhe -> fnhe_stamp = jiffies ;
1192
1209
break ;
1193
1210
}
0 commit comments