traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
mark_t mark, bool unrouted)
{
- policy_entry_t *current, policy, *to_delete = NULL;
+ policy_entry_t *current, policy;
+ enumerator_t *enumerator;
+ policy_sa_t *sa;
netlink_buf_t request;
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
+ bool is_installed = TRUE;
if (mark.value)
{
/* find the policy */
this->mutex->lock(this->mutex);
current = this->policies->get(this->policies, &policy);
- if (current)
+ if (!current)
{
- enumerator_t *enumerator;
- policy_sa_t *sa;
- bool is_installed = TRUE;
- /* remove cached SA */
- enumerator = current->sas->create_enumerator(current->sas);
- while (enumerator->enumerate(enumerator, (void**)&sa))
+ if (mark.value)
{
- if (reqid == sa->cfg.reqid)
- {
- current->sas->remove_at(current->sas, enumerator);
- break;
- }
- is_installed = FALSE;
+ DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) "
+ "failed, not found", src_ts, dst_ts, policy_dir_names,
+ direction, mark.value, mark.mask);
}
- enumerator->destroy(enumerator);
-
- if (current->sas->get_count(current->sas) > 0)
- { /* policy is used by more SAs, keep in kernel */
- DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
- if (!is_installed)
- { /* no need to update the policy as it was not installed */
- this->mutex->unlock(this->mutex);
- policy_sa_destroy(sa);
- return SUCCESS;
- }
- policy_sa_destroy(sa);
+ else
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
+ this->mutex->unlock(this->mutex);
+ return NOT_FOUND;
+ }
- if (mark.value)
- {
- DBG2(DBG_KNL, "updating policy %R === %R %N (mark %u/0x%8x)",
- src_ts, dst_ts, policy_dir_names, direction,
- mark.value, mark.mask);
- }
- else
- {
- DBG2(DBG_KNL, "updating policy %R === %R %N",
- src_ts, dst_ts, policy_dir_names, direction);
- }
+ /* remove cached SA by reqid */
+ enumerator = current->sas->create_enumerator(current->sas);
+ while (enumerator->enumerate(enumerator, (void**)&sa))
+ {
+ if (reqid == sa->cfg.reqid)
+ {
+ current->sas->remove_at(current->sas, enumerator);
+ break;
+ }
+ is_installed = FALSE;
+ }
+ enumerator->destroy(enumerator);
- current->sas->get_first(current->sas, (void**)&sa);
- if (add_policy_internal(this, current, sa, TRUE) != SUCCESS)
- {
- DBG1(DBG_KNL, "unable to update policy %R === %R %N",
- src_ts, dst_ts, policy_dir_names, direction);
- return FAILED;
- }
+ if (current->sas->get_count(current->sas) > 0)
+ { /* policy is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ if (!is_installed)
+ { /* no need to update as the policy was not installed for this SA */
+ this->mutex->unlock(this->mutex);
+ policy_sa_destroy(sa);
return SUCCESS;
}
- /* remove if last reference */
policy_sa_destroy(sa);
- this->policies->remove(this->policies, current);
- to_delete = current;
- }
- this->mutex->unlock(this->mutex);
- if (!to_delete)
- {
if (mark.value)
{
- DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) "
- "failed, not found", src_ts, dst_ts, policy_dir_names,
- direction, mark.value, mark.mask);
+ DBG2(DBG_KNL, "updating policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
}
else
{
- DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+ DBG2(DBG_KNL, "updating policy %R === %R %N",
src_ts, dst_ts, policy_dir_names, direction);
}
- return NOT_FOUND;
+
+ current->sas->get_first(current->sas, (void**)&sa);
+ if (add_policy_internal(this, current, sa, TRUE) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to update policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ return FAILED;
+ }
+ return SUCCESS;
}
+ policy_sa_destroy(sa);
memset(&request, 0, sizeof(request));
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_id));
policy_id = (struct xfrm_userpolicy_id*)NLMSG_DATA(hdr);
- policy_id->sel = to_delete->sel;
+ policy_id->sel = current->sel;
policy_id->dir = direction;
if (mark.value)
mrk->m = mark.mask;
}
- if (to_delete->route)
+ if (current->route)
{
- route_entry_t *route = to_delete->route;
+ route_entry_t *route = current->route;
if (hydra->kernel_interface->del_route(hydra->kernel_interface,
route->dst_net, route->prefixlen, route->gateway,
route->src_ip, route->if_name) != SUCCESS)
}
}
+ this->policies->remove(this->policies, current);
+ policy_entry_destroy(current);
+ this->mutex->unlock(this->mutex);
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
if (mark.value)
DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
src_ts, dst_ts, policy_dir_names, direction);
}
- policy_entry_destroy(to_delete);
return FAILED;
}
- policy_entry_destroy(to_delete);
return SUCCESS;
}