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:
parent
a9f14ada34
commit
bbd9df25a9
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue