diff options
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink')
-rw-r--r-- | src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c index b21485e62..add4761f6 100644 --- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -473,6 +473,9 @@ struct policy_sa_t { /** Priority assigned to the policy when installed with this SA */ uint32_t priority; + /** Automatic priority assigned to the policy when installed with this SA */ + uint32_t auto_priority; + /** Type of the policy */ policy_type_t type; @@ -2434,8 +2437,9 @@ METHOD(kernel_ipsec_t, add_policy, status_t, /* cache the assigned IPsec SA */ assigned_sa = policy_sa_create(this, id->dir, data->type, data->src, data->dst, id->src_ts, id->dst_ts, id->mark, data->sa); + assigned_sa->auto_priority = get_priority(policy, data->prio, id->interface); assigned_sa->priority = data->manual_prio ? data->manual_prio : - get_priority(policy, data->prio, id->interface); + assigned_sa->auto_priority; /* insert the SA according to its priority */ enumerator = policy->used_by->create_enumerator(policy->used_by); @@ -2445,16 +2449,23 @@ METHOD(kernel_ipsec_t, add_policy, status_t, { break; } - /* prefer SAs with a reqid over those without */ - if (current_sa->priority == assigned_sa->priority && - (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid)) + if (current_sa->priority == assigned_sa->priority) { - break; + /* in case of equal manual prios order SAs by automatic priority */ + if (current_sa->auto_priority > assigned_sa->auto_priority) + { + break; + } + /* prefer SAs with a reqid over those without */ + if (current_sa->auto_priority == assigned_sa->auto_priority && + (!current_sa->sa->cfg.reqid || assigned_sa->sa->cfg.reqid)) + { + break; + } } update = FALSE; } - policy->used_by->insert_before(policy->used_by, enumerator, - assigned_sa); + policy->used_by->insert_before(policy->used_by, enumerator, assigned_sa); enumerator->destroy(enumerator); if (!update) @@ -2575,7 +2586,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t, struct nlmsghdr *hdr; struct xfrm_userpolicy_id *policy_id; bool is_installed = TRUE; - uint32_t priority; + uint32_t priority, auto_priority; ipsec_sa_t assigned_sa = { .src = data->src, .dst = data->dst, @@ -2614,13 +2625,15 @@ METHOD(kernel_ipsec_t, del_policy, status_t, } /* remove mapping to SA by reqid and priority */ - priority = data->manual_prio ? data->manual_prio : - get_priority(current, data->prio,id->interface); + auto_priority = get_priority(current, data->prio,id->interface); + priority = data->manual_prio ? data->manual_prio : auto_priority; enumerator = current->used_by->create_enumerator(current->used_by); while (enumerator->enumerate(enumerator, (void**)&mapping)) { - if (priority == mapping->priority && data->type == mapping->type && + if (priority == mapping->priority && + auto_priority == mapping->auto_priority && + data->type == mapping->type && ipsec_sa_equals(mapping->sa, &assigned_sa)) { current->used_by->remove_at(current->used_by, enumerator); |