diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0db9e57013f..d19e274b9c4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -346,6 +346,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
346 | struct xfrm_policy *pol, **p; | 346 | struct xfrm_policy *pol, **p; |
347 | struct xfrm_policy *delpol = NULL; | 347 | struct xfrm_policy *delpol = NULL; |
348 | struct xfrm_policy **newpos = NULL; | 348 | struct xfrm_policy **newpos = NULL; |
349 | struct dst_entry *gc_list; | ||
349 | 350 | ||
350 | write_lock_bh(&xfrm_policy_lock); | 351 | write_lock_bh(&xfrm_policy_lock); |
351 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { | 352 | for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { |
@@ -381,9 +382,36 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
381 | xfrm_pol_hold(policy); | 382 | xfrm_pol_hold(policy); |
382 | write_unlock_bh(&xfrm_policy_lock); | 383 | write_unlock_bh(&xfrm_policy_lock); |
383 | 384 | ||
384 | if (delpol) { | 385 | if (delpol) |
385 | xfrm_policy_kill(delpol); | 386 | xfrm_policy_kill(delpol); |
387 | |||
388 | read_lock_bh(&xfrm_policy_lock); | ||
389 | gc_list = NULL; | ||
390 | for (policy = policy->next; policy; policy = policy->next) { | ||
391 | struct dst_entry *dst; | ||
392 | |||
393 | write_lock(&policy->lock); | ||
394 | dst = policy->bundles; | ||
395 | if (dst) { | ||
396 | struct dst_entry *tail = dst; | ||
397 | while (tail->next) | ||
398 | tail = tail->next; | ||
399 | tail->next = gc_list; | ||
400 | gc_list = dst; | ||
401 | |||
402 | policy->bundles = NULL; | ||
403 | } | ||
404 | write_unlock(&policy->lock); | ||
405 | } | ||
406 | read_unlock_bh(&xfrm_policy_lock); | ||
407 | |||
408 | while (gc_list) { | ||
409 | struct dst_entry *dst = gc_list; | ||
410 | |||
411 | gc_list = dst->next; | ||
412 | dst_free(dst); | ||
386 | } | 413 | } |
414 | |||
387 | return 0; | 415 | return 0; |
388 | } | 416 | } |
389 | EXPORT_SYMBOL(xfrm_policy_insert); | 417 | EXPORT_SYMBOL(xfrm_policy_insert); |
@@ -1014,13 +1042,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
1014 | } | 1042 | } |
1015 | EXPORT_SYMBOL(__xfrm_route_forward); | 1043 | EXPORT_SYMBOL(__xfrm_route_forward); |
1016 | 1044 | ||
1017 | /* Optimize later using cookies and generation ids. */ | ||
1018 | |||
1019 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) | 1045 | static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) |
1020 | { | 1046 | { |
1021 | if (!stale_bundle(dst)) | 1047 | /* If it is marked obsolete, which is how we even get here, |
1022 | return dst; | 1048 | * then we have purged it from the policy bundle list and we |
1023 | 1049 | * did that for a good reason. | |
1050 | */ | ||
1024 | return NULL; | 1051 | return NULL; |
1025 | } | 1052 | } |
1026 | 1053 | ||
@@ -1104,6 +1131,16 @@ int xfrm_flush_bundles(void) | |||
1104 | return 0; | 1131 | return 0; |
1105 | } | 1132 | } |
1106 | 1133 | ||
1134 | static int always_true(struct dst_entry *dst) | ||
1135 | { | ||
1136 | return 1; | ||
1137 | } | ||
1138 | |||
1139 | void xfrm_flush_all_bundles(void) | ||
1140 | { | ||
1141 | xfrm_prune_bundles(always_true); | ||
1142 | } | ||
1143 | |||
1107 | void xfrm_init_pmtu(struct dst_entry *dst) | 1144 | void xfrm_init_pmtu(struct dst_entry *dst) |
1108 | { | 1145 | { |
1109 | do { | 1146 | do { |