kernel-pfkey: Remove latest IPsec SA mapping when deleting a policy

If IPsec SAs are rekeyed due to an address change (e.g. because
update_sa is not supported) the exact same policy with the same reqid
will be installed, but with different addresses.  After the rekeying the
old SA and its policies are removed, using the first matching mapping
breaks the mapping between the policies and the new SA (at least on
FreeBSD, the Linux kernel might only use the reqid for this).  Using the
oldest matching SA is still an approximation but it solves the above
issue.
This commit is contained in:
Tobias Brunner 2013-07-10 11:08:01 +02:00
parent a9f14ada34
commit bbd9df25a9
1 changed files with 12 additions and 5 deletions

View File

@ -2479,9 +2479,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct sadb_msg *msg, *out;
struct sadb_x_policy *pol;
policy_entry_t *policy, *found = NULL;
policy_sa_t *mapping;
policy_sa_t *mapping, *to_remove = NULL;
enumerator_t *enumerator;
bool is_installed = TRUE;
bool first = TRUE, is_installed = TRUE;
u_int32_t priority;
size_t len;
@ -2511,19 +2511,26 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_entry_destroy(policy, this);
policy = found;
/* remove mapping to SA by reqid and priority */
/* remove mapping to SA by reqid and priority, if multiple match, which
* could happen when rekeying due to an address change, remove the oldest */
priority = get_priority(policy, prio);
enumerator = policy->used_by->create_enumerator(policy->used_by);
while (enumerator->enumerate(enumerator, (void**)&mapping))
{
if (reqid == mapping->sa->cfg.reqid && priority == mapping->priority)
{
policy->used_by->remove_at(policy->used_by, enumerator);
to_remove = mapping;
is_installed = first;
}
else if (priority < mapping->priority)
{
break;
}
is_installed = FALSE;
first = FALSE;
}
enumerator->destroy(enumerator);
policy->used_by->remove(policy->used_by, to_remove, NULL);
mapping = to_remove;
if (policy->used_by->get_count(policy->used_by) > 0)
{ /* policy is used by more SAs, keep in kernel */