aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-13 21:55:53 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-08-13 21:55:53 -0400
commitd49c73c729e2ef644558a1f441c044bfacdc9744 (patch)
treedb35cd20d57fe5d9a7fcac5f40539902b6abbdf9 /net
parent1c7628bd7a458faf7c96ef521f6d3a5ea9b106b8 (diff)
[IPSEC]: Validate properly in xfrm_dst_check()
If dst->obsolete is -1, this is a signal from the bundle creator that we want the XFRM dst and the dsts that it references to be validated on every use. I misunderstood this intention when I changed xfrm_dst_check() to always return NULL. Now, when we purge a dst entry, by running dst_free() on it. This will set the dst->obsolete to a positive integer, and we want to return NULL in that case so that the socket does a relookup for the route. Thus, if dst->obsolete<0, let stale_bundle() validate the state, else always return NULL. In general, we need to do things more intelligently here because we flush too much state during rule changes. Herbert Xu has some ideas wherein the key manager gives us some help in this area. We can also use smarter state management algorithms inside of the kernel as well. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_policy.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f35bc676128c..3da67ca2c3ce 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1134,12 +1134,33 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
1134} 1134}
1135EXPORT_SYMBOL(__xfrm_route_forward); 1135EXPORT_SYMBOL(__xfrm_route_forward);
1136 1136
1137/* Optimize later using cookies and generation ids. */
1138
1137static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) 1139static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
1138{ 1140{
1139 /* If it is marked obsolete, which is how we even get here, 1141 /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete
1140 * then we have purged it from the policy bundle list and we 1142 * to "-1" to force all XFRM destinations to get validated by
1141 * did that for a good reason. 1143 * dst_ops->check on every use. We do this because when a
1144 * normal route referenced by an XFRM dst is obsoleted we do
1145 * not go looking around for all parent referencing XFRM dsts
1146 * so that we can invalidate them. It is just too much work.
1147 * Instead we make the checks here on every use. For example:
1148 *
1149 * XFRM dst A --> IPv4 dst X
1150 *
1151 * X is the "xdst->route" of A (X is also the "dst->path" of A
1152 * in this example). If X is marked obsolete, "A" will not
1153 * notice. That's what we are validating here via the
1154 * stale_bundle() check.
1155 *
1156 * When a policy's bundle is pruned, we dst_free() the XFRM
1157 * dst which causes it's ->obsolete field to be set to a
1158 * positive non-zero integer. If an XFRM dst has been pruned
1159 * like this, we want to force a new route lookup.
1142 */ 1160 */
1161 if (dst->obsolete < 0 && !stale_bundle(dst))
1162 return dst;
1163
1143 return NULL; 1164 return NULL;
1144} 1165}
1145 1166