diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 27 |
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 | } |
| 1135 | EXPORT_SYMBOL(__xfrm_route_forward); | 1135 | EXPORT_SYMBOL(__xfrm_route_forward); |
| 1136 | 1136 | ||
| 1137 | /* Optimize later using cookies and generation ids. */ | ||
| 1138 | |||
| 1137 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | 1139 | static 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 | ||
