aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-05-23 17:00:04 +0200
committerTobias Brunner <tobias@strongswan.org>2017-05-23 17:00:04 +0200
commit6b9361f71418239fb0835e9ff5bf0b1816f9dc04 (patch)
treeed9ce9dd7faab3e99ed2ea7a00dac14c2594f21f /src/libcharon/plugins
parent7caec9e4a40142803f22ed195704cdd46b097db1 (diff)
parent48ea65501668bbae49a0ab48001ee15fe95b657e (diff)
downloadstrongswan-6b9361f71418239fb0835e9ff5bf0b1816f9dc04.tar.bz2
strongswan-6b9361f71418239fb0835e9ff5bf0b1816f9dc04.tar.xz
Merge branch 'hw-offload'
Allows enabling hardware offload for IPsec SAs as introduced by Linux 4.11 for specific hardware.
Diffstat (limited to 'src/libcharon/plugins')
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c87
-rw-r--r--src/libcharon/plugins/sql/sql_config.c4
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c8
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c2
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c2
-rw-r--r--src/libcharon/plugins/vici/vici_config.c80
-rw-r--r--src/libcharon/plugins/vici/vici_query.c2
7 files changed, 147 insertions, 38 deletions
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index becf6b5dc..9a40927d2 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1639,6 +1639,31 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
data->replay_window);
sa->replay_window = data->replay_window;
}
+ if (data->hw_offload)
+ {
+ host_t *local = data->inbound ? id->dst : id->src;
+ char *ifname;
+
+ if (charon->kernel->get_interface(charon->kernel, local, &ifname))
+ {
+ struct xfrm_user_offload *offload;
+
+ offload = netlink_reserve(hdr, sizeof(request),
+ XFRMA_OFFLOAD_DEV, sizeof(*offload));
+ if (!offload)
+ {
+ free(ifname);
+ goto failed;
+ }
+ offload->ifindex = if_nametoindex(ifname);
+ if (local->get_family(local) == AF_INET6)
+ {
+ offload->flags |= XFRM_OFFLOAD_IPV6;
+ }
+ offload->flags |= data->inbound ? XFRM_OFFLOAD_INBOUND : 0;
+ free(ifname);
+ }
+ }
}
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
@@ -1919,13 +1944,13 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
kernel_ipsec_update_sa_t *data)
{
netlink_buf_t request;
- struct nlmsghdr *hdr, *out = NULL;
+ struct nlmsghdr *hdr, *out_hdr = NULL, *out = NULL;
struct xfrm_usersa_id *sa_id;
- struct xfrm_usersa_info *out_sa = NULL, *sa;
+ struct xfrm_usersa_info *sa;
size_t len;
struct rtattr *rta;
size_t rtasize;
- struct xfrm_encap_tmpl* tmpl = NULL;
+ struct xfrm_encap_tmpl* encap = NULL;
struct xfrm_replay_state *replay = NULL;
struct xfrm_replay_state_esn *replay_esn = NULL;
struct xfrm_lifetime_cur *lifetime = NULL;
@@ -1983,7 +2008,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{
case XFRM_MSG_NEWSA:
{
- out_sa = NLMSG_DATA(hdr);
+ out_hdr = hdr;
break;
}
case NLMSG_ERROR:
@@ -2002,7 +2027,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
break;
}
}
- if (out_sa == NULL)
+ if (!out_hdr)
{
DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x%s",
ntohl(id->spi), markstr);
@@ -2029,7 +2054,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
hdr->nlmsg_type = XFRM_MSG_NEWSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
sa = NLMSG_DATA(hdr);
- memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
+ memcpy(sa, NLMSG_DATA(out_hdr), sizeof(struct xfrm_usersa_info));
sa->family = data->new_dst->get_family(data->new_dst);
if (!id->src->ip_equals(id->src, data->new_src))
@@ -2041,8 +2066,8 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
host2xfrm(data->new_dst, &sa->id.daddr);
}
- rta = XFRM_RTA(out, struct xfrm_usersa_info);
- rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
+ rta = XFRM_RTA(out_hdr, struct xfrm_usersa_info);
+ rtasize = XFRM_PAYLOAD(out_hdr, struct xfrm_usersa_info);
while (RTA_OK(rta, rtasize))
{
/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
@@ -2050,9 +2075,34 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{
if (rta->rta_type == XFRMA_ENCAP)
{ /* update encap tmpl */
- tmpl = RTA_DATA(rta);
- tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
- tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ encap = RTA_DATA(rta);
+ encap->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+ encap->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ }
+ if (rta->rta_type == XFRMA_OFFLOAD_DEV)
+ { /* update offload device */
+ struct xfrm_user_offload *offload;
+ host_t *local;
+ char *ifname;
+
+ offload = RTA_DATA(rta);
+ local = offload->flags & XFRM_OFFLOAD_INBOUND ? data->new_dst
+ : data->new_src;
+
+ if (charon->kernel->get_interface(charon->kernel, local,
+ &ifname))
+ {
+ offload->ifindex = if_nametoindex(ifname);
+ if (local->get_family(local) == AF_INET6)
+ {
+ offload->flags |= XFRM_OFFLOAD_IPV6;
+ }
+ else
+ {
+ offload->flags &= ~XFRM_OFFLOAD_IPV6;
+ }
+ free(ifname);
+ }
}
netlink_add_attribute(hdr, rta->rta_type,
chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
@@ -2061,17 +2111,18 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
rta = RTA_NEXT(rta, rtasize);
}
- if (tmpl == NULL && data->new_encap)
+ if (encap == NULL && data->new_encap)
{ /* add tmpl if we are enabling it */
- tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
- if (!tmpl)
+ encap = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP,
+ sizeof(*encap));
+ if (!encap)
{
goto failed;
}
- tmpl->encap_type = UDP_ENCAP_ESPINUDP;
- tmpl->encap_sport = ntohs(data->new_src->get_port(data->new_src));
- tmpl->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
- memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
+ encap->encap_type = UDP_ENCAP_ESPINUDP;
+ encap->encap_sport = ntohs(data->new_src->get_port(data->new_src));
+ encap->encap_dport = ntohs(data->new_dst->get_port(data->new_dst));
+ memset(&encap->encap_oa, 0, sizeof (xfrm_address_t));
}
if (replay_esn)
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 88cac7f26..cf7c3b814 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -173,7 +173,8 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
child_cfg_create_t child = {
.mode = mode,
.reqid = reqid,
- .ipcomp = ipcomp,
+ .options = (ipcomp ? OPT_IPCOMP : 0) |
+ (hostaccess ? OPT_HOSTACCESS : 0),
.lifetime = {
.time = {
.life = lifetime, .rekey = rekeytime, .jitter = jitter
@@ -183,7 +184,6 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
.dpd_action = dpd,
.close_action = close,
.updown = updown,
- .hostaccess = hostaccess,
};
child_cfg = child_cfg_create(name, &child);
add_esp_proposals(this, child_cfg, id);
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index bbdc2116d..a9d073684 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -1071,15 +1071,15 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
},
.reqid = msg->add_conn.reqid,
.mode = msg->add_conn.mode,
- .proxy_mode = msg->add_conn.proxy_mode,
- .ipcomp = msg->add_conn.ipcomp,
+ .options = (msg->add_conn.proxy_mode ? OPT_PROXY_MODE : 0) |
+ (msg->add_conn.ipcomp ? OPT_IPCOMP : 0) |
+ (msg->add_conn.me.hostaccess ? OPT_HOSTACCESS : 0) |
+ (msg->add_conn.install_policy ? 0 : OPT_NO_POLICIES),
.tfc = msg->add_conn.tfc,
.inactivity = msg->add_conn.inactivity,
.dpd_action = map_action(msg->add_conn.dpd.action),
.close_action = map_action(msg->add_conn.close_action),
.updown = msg->add_conn.me.updown,
- .hostaccess = msg->add_conn.me.hostaccess,
- .suppress_policies = !msg->add_conn.install_policy,
};
child_cfg = child_cfg_create(msg->add_conn.name, &child);
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 92e368669..a33316658 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -218,7 +218,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
child_sa_state_names, child_sa->get_state(child_sa),
ipsec_mode_names, child_sa->get_mode(child_sa),
- config->use_proxy_mode(config) ? "_PROXY" : "",
+ config->has_option(config, OPT_PROXY_MODE) ? "_PROXY" : "",
child_sa->get_reqid(child_sa));
if (child_sa->get_state(child_sa) == CHILD_INSTALLED)
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index 6a1581c85..bbefd6a02 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -366,7 +366,7 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
push_env(envp, countof(envp), "PLUTO_IPCOMP=1");
}
push_dns_env(this, ike_sa, envp, countof(envp));
- if (config->get_hostaccess(config))
+ if (config->has_option(config, OPT_HOSTACCESS))
{
push_env(envp, countof(envp), "PLUTO_HOST_ACCESS=1");
}
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index baa350784..46eaf5cff 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -478,7 +478,6 @@ typedef struct {
linked_list_t *remote_ts;
uint32_t replay_window;
bool policies;
- bool policies_fwd_out;
child_cfg_create_t cfg;
} child_data_t;
@@ -500,12 +499,12 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " life_packets = %llu", cfg->lifetime.packets.life);
DBG2(DBG_CFG, " rand_packets = %llu", cfg->lifetime.packets.jitter);
DBG2(DBG_CFG, " updown = %s", cfg->updown);
- DBG2(DBG_CFG, " hostaccess = %u", cfg->hostaccess);
- DBG2(DBG_CFG, " ipcomp = %u", cfg->ipcomp);
+ DBG2(DBG_CFG, " hostaccess = %u", cfg->options & OPT_HOSTACCESS);
+ DBG2(DBG_CFG, " ipcomp = %u", cfg->options & OPT_IPCOMP);
DBG2(DBG_CFG, " mode = %N%s", ipsec_mode_names, cfg->mode,
- cfg->proxy_mode ? "_PROXY" : "");
+ cfg->options & OPT_PROXY_MODE ? "_PROXY" : "");
DBG2(DBG_CFG, " policies = %u", data->policies);
- DBG2(DBG_CFG, " policies_fwd_out = %u", data->policies_fwd_out);
+ DBG2(DBG_CFG, " policies_fwd_out = %u", cfg->options & OPT_FWD_OUT_POLICIES);
if (data->replay_window != REPLAY_UNDEFINED)
{
DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
@@ -525,6 +524,7 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " proposals = %#P", data->proposals);
DBG2(DBG_CFG, " local_ts = %#R", data->local_ts);
DBG2(DBG_CFG, " remote_ts = %#R", data->remote_ts);
+ DBG2(DBG_CFG, " hw_offload = %u", cfg->options & OPT_HW_OFFLOAD);
}
/**
@@ -827,13 +827,71 @@ CALLBACK(parse_mode, bool,
if (parse_map(map, countof(map), &d, v))
{
cfg->mode = d;
- cfg->proxy_mode = (d == MODE_TRANSPORT) && (v.len > 9);
+ if ((d == MODE_TRANSPORT) && (v.len > 9))
+ {
+ cfg->options |= OPT_PROXY_MODE;
+ }
return TRUE;
}
return FALSE;
}
/**
+ * Enable a child_cfg_option_t
+ */
+static bool parse_option(child_cfg_option_t *out, child_cfg_option_t opt,
+ chunk_t v)
+{
+ bool val;
+
+ if (parse_bool(&val, v))
+ {
+ if (val)
+ {
+ *out |= opt;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse OPT_HOSTACCESS option
+ */
+CALLBACK(parse_opt_haccess, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_HOSTACCESS, v);
+}
+
+/**
+ * Parse OPT_FWD_OUT_POLICIES option
+ */
+CALLBACK(parse_opt_fwd_out, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_FWD_OUT_POLICIES, v);
+}
+
+/**
+ * Parse OPT_FWD_OUT_POLICIES option
+ */
+CALLBACK(parse_opt_ipcomp, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_IPCOMP, v);
+}
+
+/**
+ * Parse OPT_HW_OFFLOAD option
+ */
+CALLBACK(parse_opt_hw_offl, bool,
+ child_cfg_option_t *out, chunk_t v)
+{
+ return parse_option(out, OPT_HW_OFFLOAD, v);
+}
+
+/**
* Parse an action_t
*/
CALLBACK(parse_action, bool,
@@ -1466,10 +1524,10 @@ CALLBACK(child_kv, bool,
{
parse_rule_t rules[] = {
{ "updown", parse_string, &child->cfg.updown },
- { "hostaccess", parse_bool, &child->cfg.hostaccess },
+ { "hostaccess", parse_opt_haccess, &child->cfg.options },
{ "mode", parse_mode, &child->cfg },
{ "policies", parse_bool, &child->policies },
- { "policies_fwd_out", parse_bool, &child->policies_fwd_out },
+ { "policies_fwd_out", parse_opt_fwd_out, &child->cfg.options },
{ "replay_window", parse_uint32, &child->replay_window },
{ "rekey_time", parse_time, &child->cfg.lifetime.time.rekey },
{ "life_time", parse_time, &child->cfg.lifetime.time.life },
@@ -1483,7 +1541,7 @@ CALLBACK(child_kv, bool,
{ "dpd_action", parse_action, &child->cfg.dpd_action },
{ "start_action", parse_action, &child->cfg.start_action },
{ "close_action", parse_action, &child->cfg.close_action },
- { "ipcomp", parse_bool, &child->cfg.ipcomp },
+ { "ipcomp", parse_opt_ipcomp, &child->cfg.options },
{ "inactivity", parse_time, &child->cfg.inactivity },
{ "reqid", parse_uint32, &child->cfg.reqid },
{ "mark_in", parse_mark, &child->cfg.mark_in },
@@ -1491,6 +1549,7 @@ CALLBACK(child_kv, bool,
{ "tfc_padding", parse_tfc, &child->cfg.tfc },
{ "priority", parse_uint32, &child->cfg.priority },
{ "interface", parse_string, &child->cfg.interface },
+ { "hw_offload", parse_opt_hw_offl, &child->cfg.options },
};
return parse_rules(rules, countof(rules), name, value,
@@ -1756,8 +1815,7 @@ CALLBACK(children_sn, bool,
child.proposals->insert_last(child.proposals, proposal);
}
}
- child.cfg.suppress_policies = !child.policies;
- child.cfg.fwd_out_policies = child.policies_fwd_out;
+ child.cfg.options |= child.policies ? 0 : OPT_NO_POLICIES;
check_lifetimes(&child.cfg.lifetime);
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index c0f4e2de9..2cc59591f 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -107,7 +107,7 @@ static void list_mode(vici_builder_t *b, child_sa_t *child, child_cfg_t *cfg)
cfg = child->get_config(child);
}
mode = child ? child->get_mode(child) : cfg->get_mode(cfg);
- if (mode == MODE_TRANSPORT && cfg->use_proxy_mode(cfg))
+ if (mode == MODE_TRANSPORT && cfg->has_option(cfg, OPT_PROXY_MODE))
{ /* only report this if the negotiated mode is actually TRANSPORT */
sub_mode = "_PROXY";
}