Added support for combined IPComp/ESP/AH policies in kernel_netlink plugin.

This commit is contained in:
Tobias Brunner
2010-09-02 19:04:19 +02:00
parent b4872c1e09
commit 55be07a15f
@@ -1626,6 +1626,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
netlink_buf_t request; netlink_buf_t request;
struct xfrm_userpolicy_info *policy_info; struct xfrm_userpolicy_info *policy_info;
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
int i;
/* create a policy */ /* create a policy */
policy = malloc_thing(policy_entry_t); 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); struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
rthdr->rta_type = XFRMA_TMPL; rthdr->rta_type = XFRMA_TMPL;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); rthdr->rta_len = 0; /* actual length is set below */
hdr->nlmsg_len += rthdr->rta_len;
if (hdr->nlmsg_len > sizeof(request))
{
return FAILED;
}
struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr); struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
if (ipcomp != IPCOMP_NONE) struct {
u_int8_t proto;
bool use;
} protos[] = {
{ IPPROTO_COMP, ipcomp != IPCOMP_NONE },
{ IPPROTO_ESP, spi != 0 },
{ IPPROTO_AH, ah_spi != 0 },
};
for (i = 0; i < countof(protos); i++)
{ {
tmpl->reqid = reqid; if (!protos[i].use)
tmpl->id.proto = IPPROTO_COMP; {
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; continue;
tmpl->mode = mode2kernel(mode); }
tmpl->optional = direction != POLICY_OUT;
tmpl->family = src->get_family(src);
host2xfrm(src, &tmpl->saddr);
host2xfrm(dst, &tmpl->id.daddr);
/* add an additional xfrm_user_tmpl */
rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
@@ -1736,23 +1734,26 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
return FAILED; return FAILED;
} }
tmpl++; 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);
/* use transport mode for ESP if we have a tunnel mode IPcomp SA */ if (mode == MODE_TUNNEL)
mode = MODE_TRANSPORT; { /* only for tunnel mode */
}
else
{
/* when using IPcomp, only the IPcomp SA uses tmp src/dst addresses */
host2xfrm(src, &tmpl->saddr); host2xfrm(src, &tmpl->saddr);
host2xfrm(dst, &tmpl->id.daddr); host2xfrm(dst, &tmpl->id.daddr);
} }
tmpl->reqid = reqid; tmpl++;
tmpl->id.proto = spi ? IPPROTO_ESP : IPPROTO_AH;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; /* use transport mode for other SAs */
tmpl->mode = mode2kernel(mode); mode = MODE_TRANSPORT;
tmpl->family = src->get_family(src); }
rthdr = XFRM_RTA_NEXT(rthdr); rthdr = XFRM_RTA_NEXT(rthdr);
if (mark.value) if (mark.value)