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 0db9e57013fd..d19e274b9c4a 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 { |
