summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2016-10-20 16:18:38 +0200
committerYves-Alexis Perez <corsac@debian.org>2016-10-20 16:18:38 +0200
commit88f22dbc6ddb53ac5b40db1d317548b0408718c9 (patch)
tree923fc438bad68d2583b27c12036a6883d73bd5f9 /src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
parent3bba989a734d13493279f8c1266176ebb1f670bd (diff)
parent25663e04c3ab01ef8dc9f906608282319cfea2db (diff)
downloadvyos-strongswan-88f22dbc6ddb53ac5b40db1d317548b0408718c9.tar.gz
vyos-strongswan-88f22dbc6ddb53ac5b40db1d317548b0408718c9.zip
Merge tag 'upstream/5.5.1'
Upstream version 5.5.1
Diffstat (limited to 'src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c')
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c113
1 files changed, 111 insertions, 2 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 9c2a7c315..f3846ec07 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1245,7 +1245,7 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
*/
static void format_mark(char *buf, int buflen, mark_t mark)
{
- if (mark.value)
+ if (mark.value | mark.mask)
{
snprintf(buf, buflen, " (mark %u/0x%08x)", mark.value, mark.mask);
}
@@ -1256,7 +1256,7 @@ static void format_mark(char *buf, int buflen, mark_t mark)
*/
static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
{
- if (mark.value)
+ if (mark.value | mark.mask)
{
struct xfrm_mark *xmrk;
@@ -2528,6 +2528,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
id->dir, markstr, cur_priority, use_count);
return SUCCESS;
}
+ policy->reqid = assigned_sa->sa->cfg.reqid;
if (this->policy_update)
{
@@ -2720,6 +2721,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
return SUCCESS;
}
current->used_by->get_first(current->used_by, (void**)&mapping);
+ current->reqid = mapping->sa->cfg.reqid;
DBG2(DBG_KNL, "updating policy %R === %R %N%s [priority %u, "
"refcount %d]", id->src_ts, id->dst_ts, policy_dir_names, id->dir,
@@ -3044,6 +3046,110 @@ METHOD(kernel_ipsec_t, destroy, void,
free(this);
}
+/**
+ * Get the currently configured SPD hashing thresholds for an address family
+ */
+static bool get_spd_hash_thresh(private_kernel_netlink_ipsec_t *this,
+ int type, uint8_t *lbits, uint8_t *rbits)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr, *out;
+ struct xfrmu_spdhthresh *thresh;
+ struct rtattr *rta;
+ size_t len, rtasize;
+ bool success = FALSE;
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST;
+ hdr->nlmsg_type = XFRM_MSG_GETSPDINFO;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(uint32_t));
+
+ if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
+ {
+ hdr = out;
+ while (NLMSG_OK(hdr, len))
+ {
+ switch (hdr->nlmsg_type)
+ {
+ case XFRM_MSG_NEWSPDINFO:
+ {
+ rta = XFRM_RTA(hdr, uint32_t);
+ rtasize = XFRM_PAYLOAD(hdr, uint32_t);
+ while (RTA_OK(rta, rtasize))
+ {
+ if (rta->rta_type == type &&
+ RTA_PAYLOAD(rta) == sizeof(*thresh))
+ {
+ thresh = RTA_DATA(rta);
+ *lbits = thresh->lbits;
+ *rbits = thresh->rbits;
+ success = TRUE;
+ break;
+ }
+ rta = RTA_NEXT(rta, rtasize);
+ }
+ break;
+ }
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *err = NLMSG_DATA(hdr);
+ DBG1(DBG_KNL, "getting SPD hash threshold failed: %s (%d)",
+ strerror(-err->error), -err->error);
+ break;
+ }
+ default:
+ hdr = NLMSG_NEXT(hdr, len);
+ continue;
+ case NLMSG_DONE:
+ break;
+ }
+ break;
+ }
+ free(out);
+ }
+ return success;
+}
+
+/**
+ * Configure SPD hashing threshold for an address family
+ */
+static void setup_spd_hash_thresh(private_kernel_netlink_ipsec_t *this,
+ char *key, int type, uint8_t def)
+{
+ struct xfrmu_spdhthresh *thresh;
+ struct nlmsghdr *hdr;
+ netlink_buf_t request;
+ uint8_t lbits, rbits;
+
+ if (!get_spd_hash_thresh(this, type, &lbits, &rbits))
+ {
+ return;
+ }
+ memset(&request, 0, sizeof(request));
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = XFRM_MSG_NEWSPDINFO;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(uint32_t));
+
+ thresh = netlink_reserve(hdr, sizeof(request), type, sizeof(*thresh));
+ thresh->lbits = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.spdh_thresh.%s.lbits",
+ def, lib->ns, key);
+ thresh->rbits = lib->settings->get_int(lib->settings,
+ "%s.plugins.kernel-netlink.spdh_thresh.%s.rbits",
+ def, lib->ns, key);
+ if (thresh->lbits != lbits || thresh->rbits != rbits)
+ {
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "setting SPD hash threshold failed");
+ }
+ }
+}
+
/*
* Described in header.
*/
@@ -3114,6 +3220,9 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
return NULL;
}
+ setup_spd_hash_thresh(this, "ipv4", XFRMA_SPD_IPV4_HTHRESH, 32);
+ setup_spd_hash_thresh(this, "ipv6", XFRMA_SPD_IPV6_HTHRESH, 128);
+
if (register_for_events)
{
struct sockaddr_nl addr;