aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2010-07-19 12:31:39 +0200
committerTobias Brunner <tobias@strongswan.org>2010-09-02 19:04:19 +0200
commit55be07a15f78909069d7da41bc3d6a1e4b04c05e (patch)
tree2be4967e117d366e452819972a15a1e9e097a68e
parentb4872c1e0963010525ff24c9562e26097fdd0d1b (diff)
downloadstrongswan-55be07a15f78909069d7da41bc3d6a1e4b04c05e.tar.bz2
strongswan-55be07a15f78909069d7da41bc3d6a1e4b04c05e.tar.xz
Added support for combined IPComp/ESP/AH policies in kernel_netlink plugin.
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c63
1 files changed, 32 insertions, 31 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 3fd78626b..0f243361e 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -865,7 +865,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
u_int16_t cpi, bool encap, bool inbound,
traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{
@@ -1626,6 +1626,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
netlink_buf_t request;
struct xfrm_userpolicy_info *policy_info;
struct nlmsghdr *hdr;
+ int i;
/* create a policy */
policy = malloc_thing(policy_entry_t);
@@ -1706,29 +1707,26 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
rthdr->rta_type = XFRMA_TMPL;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
-
- hdr->nlmsg_len += rthdr->rta_len;
- if (hdr->nlmsg_len > sizeof(request))
- {
- return FAILED;
- }
+ rthdr->rta_len = 0; /* actual length is set below */
struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
- if (ipcomp != IPCOMP_NONE)
- {
- tmpl->reqid = reqid;
- tmpl->id.proto = IPPROTO_COMP;
- tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
- tmpl->mode = mode2kernel(mode);
- tmpl->optional = direction != POLICY_OUT;
- tmpl->family = src->get_family(src);
+ struct {
+ u_int8_t proto;
+ bool use;
+ } protos[] = {
+ { IPPROTO_COMP, ipcomp != IPCOMP_NONE },
+ { IPPROTO_ESP, spi != 0 },
+ { IPPROTO_AH, ah_spi != 0 },
+ };
- host2xfrm(src, &tmpl->saddr);
- host2xfrm(dst, &tmpl->id.daddr);
+ for (i = 0; i < countof(protos); i++)
+ {
+ if (!protos[i].use)
+ {
+ continue;
+ }
- /* add an additional xfrm_user_tmpl */
rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
if (hdr->nlmsg_len > sizeof(request))
@@ -1736,23 +1734,26 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
return FAILED;
}
+ tmpl->reqid = reqid;
+ tmpl->id.proto = protos[i].proto;
+ tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
+ tmpl->mode = mode2kernel(mode);
+ tmpl->optional = protos[i].proto == IPPROTO_COMP &&
+ direction != POLICY_OUT;
+ tmpl->family = src->get_family(src);
+
+ if (mode == MODE_TUNNEL)
+ { /* only for tunnel mode */
+ host2xfrm(src, &tmpl->saddr);
+ host2xfrm(dst, &tmpl->id.daddr);
+ }
+
tmpl++;
- /* use transport mode for ESP if we have a tunnel mode IPcomp SA */
+ /* use transport mode for other SAs */
mode = MODE_TRANSPORT;
}
- else
- {
- /* when using IPcomp, only the IPcomp SA uses tmp src/dst addresses */
- host2xfrm(src, &tmpl->saddr);
- host2xfrm(dst, &tmpl->id.daddr);
- }
- tmpl->reqid = reqid;
- tmpl->id.proto = spi ? IPPROTO_ESP : IPPROTO_AH;
- tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
- tmpl->mode = mode2kernel(mode);
- tmpl->family = src->get_family(src);
rthdr = XFRM_RTA_NEXT(rthdr);
if (mark.value)