Use netlink_reserve() helper function in XFRM to simplify message construction

This commit is contained in:
Martin Willi
2013-03-15 16:02:01 +01:00
parent 6359ab04f4
commit 6dfc633927
@@ -94,12 +94,6 @@
*/ */
#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \ #define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \
NLMSG_ALIGN(sizeof(x)))) NLMSG_ALIGN(sizeof(x))))
/**
* Returns a pointer to the next rtattr following rta.
* !!! Do not use this to parse messages. Use RTA_NEXT and RTA_OK instead !!!
*/
#define XFRM_RTA_NEXT(rta) ((struct rtattr*)(((char*)(rta)) + \
RTA_ALIGN((rta)->rta_len)))
/** /**
* Returns the total size of attached rta data * Returns the total size of attached rta data
* (after 'usual' netlink data x like 'struct xfrm_usersa_info') * (after 'usual' netlink data x like 'struct xfrm_usersa_info')
@@ -1223,8 +1217,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa->lft.soft_use_expires_seconds = 0; sa->lft.soft_use_expires_seconds = 0;
sa->lft.hard_use_expires_seconds = 0; sa->lft.hard_use_expires_seconds = 0;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info);
switch (enc_alg) switch (enc_alg)
{ {
case ENCR_UNDEFINED: case ENCR_UNDEFINED:
@@ -1257,24 +1249,17 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_key.len * 8); encryption_algorithm_names, enc_alg, enc_key.len * 8);
rthdr->rta_type = XFRMA_ALG_AEAD; algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + sizeof(*algo) + enc_key.len);
enc_key.len); if (!algo)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8; algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size; algo->alg_icv_len = icv_size;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len); memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
break; break;
} }
default: default:
@@ -1291,22 +1276,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_key.len * 8); encryption_algorithm_names, enc_alg, enc_key.len * 8);
rthdr->rta_type = XFRMA_ALG_CRYPT; algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len); sizeof(*algo) + enc_key.len);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + if (!algo)
RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8; algo->alg_key_len = enc_key.len * 8;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len); memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
rthdr = XFRM_RTA_NEXT(rthdr);
} }
} }
@@ -1344,17 +1323,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
/* the kernel uses SHA256 with 96 bit truncation by default, /* the kernel uses SHA256 with 96 bit truncation by default,
* use specified truncation size supported by newer kernels. * use specified truncation size supported by newer kernels.
* also use this for untruncated MD5 and SHA1. */ * also use this for untruncated MD5 and SHA1. */
rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC; algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC,
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + sizeof(*algo) + int_key.len);
int_key.len); if (!algo)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8; algo->alg_key_len = int_key.len * 8;
algo->alg_trunc_len = trunc_len; algo->alg_trunc_len = trunc_len;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
@@ -1365,27 +1339,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
{ {
struct xfrm_algo* algo; struct xfrm_algo* algo;
rthdr->rta_type = XFRMA_ALG_AUTH; algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH,
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len); sizeof(*algo) + int_key.len);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + if (!algo)
RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8; algo->alg_key_len = int_key.len * 8;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, int_key.ptr, int_key.len); memcpy(algo->alg_key, int_key.ptr, int_key.len);
} }
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (ipcomp != IPCOMP_NONE) if (ipcomp != IPCOMP_NONE)
{ {
rthdr->rta_type = XFRMA_ALG_COMP; struct xfrm_algo* algo;
alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp); alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
if (alg_name == NULL) if (alg_name == NULL)
{ {
@@ -1396,34 +1366,26 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
DBG2(DBG_KNL, " using compression algorithm %N", DBG2(DBG_KNL, " using compression algorithm %N",
ipcomp_transform_names, ipcomp); ipcomp_transform_names, ipcomp);
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP,
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); sizeof(*algo));
if (hdr->nlmsg_len > sizeof(request)) if (!algo)
{ {
goto failed; goto failed;
} }
struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = 0; algo->alg_key_len = 0;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (encap) if (encap)
{ {
struct xfrm_encap_tmpl *tmpl; struct xfrm_encap_tmpl *tmpl;
rthdr->rta_type = XFRMA_ENCAP; tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); if (!tmpl)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = htons(src->get_port(src)); tmpl->encap_sport = htons(src->get_port(src));
tmpl->encap_dport = htons(dst->get_port(dst)); tmpl->encap_dport = htons(dst->get_port(dst));
@@ -1438,43 +1400,32 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
* No. The reason the kernel ignores NAT-OA is that it recomputes * No. The reason the kernel ignores NAT-OA is that it recomputes
* (or, rather, just ignores) the checksum. If packets pass the IPsec * (or, rather, just ignores) the checksum. If packets pass the IPsec
* checks it marks them "checksum ok" so OA isn't needed. */ * checks it marks them "checksum ok" so OA isn't needed. */
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (tfc) if (tfc)
{ {
u_int32_t *tfcpad; u_int32_t *tfcpad;
rthdr->rta_type = XFRMA_TFCPAD; tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD,
rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); sizeof(*tfcpad));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (!tfcpad)
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
tfcpad = (u_int32_t*)RTA_DATA(rthdr);
*tfcpad = tfc; *tfcpad = tfc;
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (protocol != IPPROTO_COMP) if (protocol != IPPROTO_COMP)
@@ -1485,24 +1436,18 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
* XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */ * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */
struct xfrm_replay_state_esn *replay; struct xfrm_replay_state_esn *replay;
rthdr->rta_type = XFRMA_REPLAY_ESN_VAL; replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + sizeof(*replay) + (this->replay_window + 7) / 8);
(this->replay_window + 7) / 8); if (!replay)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
replay = (struct xfrm_replay_state_esn*)RTA_DATA(rthdr);
/* bmp_len contains number uf __u32's */ /* bmp_len contains number uf __u32's */
replay->bmp_len = this->replay_bmp; replay->bmp_len = this->replay_bmp;
replay->replay_window = this->replay_window; replay->replay_window = this->replay_window;
DBG2(DBG_KNL, " using replay window of %u packets", DBG2(DBG_KNL, " using replay window of %u packets",
this->replay_window); this->replay_window);
rthdr = XFRM_RTA_NEXT(rthdr);
if (esn) if (esn)
{ {
DBG2(DBG_KNL, " using extended sequence numbers (ESN)"); DBG2(DBG_KNL, " using extended sequence numbers (ESN)");
@@ -1577,17 +1522,12 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
return; return;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }
@@ -1678,17 +1618,12 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }
@@ -1781,17 +1716,12 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }
@@ -1863,17 +1793,12 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }
@@ -1945,7 +1870,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
rta = XFRM_RTA(out, struct xfrm_usersa_info); rta = XFRM_RTA(out, struct xfrm_usersa_info);
rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info); rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info);
pos = (u_char*)XFRM_RTA(hdr, struct xfrm_usersa_info); pos = (u_char*)XFRM_RTA(hdr, struct xfrm_usersa_info);
while(RTA_OK(rta, rtasize)) while (RTA_OK(rta, rtasize))
{ {
/* copy all attributes, but not XFRMA_ENCAP if we are disabling it */ /* copy all attributes, but not XFRMA_ENCAP if we are disabling it */
if (rta->rta_type != XFRMA_ENCAP || new_encap) if (rta->rta_type != XFRMA_ENCAP || new_encap)
@@ -1964,53 +1889,42 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
rta = RTA_NEXT(rta, rtasize); rta = RTA_NEXT(rta, rtasize);
} }
rta = (struct rtattr*)pos;
if (tmpl == NULL && new_encap) if (tmpl == NULL && new_encap)
{ /* add tmpl if we are enabling it */ { /* add tmpl if we are enabling it */
rta->rta_type = XFRMA_ENCAP; tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); if (!tmpl)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
} }
tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta);
tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = ntohs(new_src->get_port(new_src)); tmpl->encap_sport = ntohs(new_src->get_port(new_src));
tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t)); memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
rta = XFRM_RTA_NEXT(rta);
} }
if (replay_esn) if (replay_esn)
{ {
rta->rta_type = XFRMA_REPLAY_ESN_VAL; struct xfrm_replay_state_esn *state;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) +
this->replay_bmp); state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); sizeof(*state) + this->replay_bmp);
if (hdr->nlmsg_len > sizeof(request)) if (!state)
{ {
goto failed; goto failed;
} }
memcpy(RTA_DATA(rta), replay_esn, memcpy(state, replay_esn, sizeof(*state) + this->replay_bmp);
sizeof(struct xfrm_replay_state_esn) + this->replay_bmp);
rta = XFRM_RTA_NEXT(rta);
} }
else if (replay) else if (replay)
{ {
rta->rta_type = XFRMA_REPLAY_VAL; struct xfrm_replay_state *state;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL,
if (hdr->nlmsg_len > sizeof(request)) sizeof(*state));
if (!state)
{ {
goto failed; goto failed;
} }
memcpy(RTA_DATA(rta), replay, sizeof(struct xfrm_replay_state)); memcpy(state, replay, sizeof(*state));
rta = XFRM_RTA_NEXT(rta);
} }
else else
{ {
@@ -2107,11 +2021,9 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
policy_info->lft.soft_use_expires_seconds = 0; policy_info->lft.soft_use_expires_seconds = 0;
policy_info->lft.hard_use_expires_seconds = 0; policy_info->lft.hard_use_expires_seconds = 0;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info);
if (mapping->type == POLICY_IPSEC) if (mapping->type == POLICY_IPSEC)
{ {
struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr); struct xfrm_user_tmpl *tmpl;
struct { struct {
u_int8_t proto; u_int8_t proto;
bool use; bool use;
@@ -2121,9 +2033,22 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
{ IPPROTO_AH, ipsec->cfg.ah.use }, { IPPROTO_AH, ipsec->cfg.ah.use },
}; };
ipsec_mode_t proto_mode = ipsec->cfg.mode; ipsec_mode_t proto_mode = ipsec->cfg.mode;
int count = 0;
rthdr->rta_type = XFRMA_TMPL; for (i = 0; i < countof(protos); i++)
rthdr->rta_len = 0; /* actual length is set below */ {
if (protos[i].use)
{
count++;
}
}
tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL,
count * sizeof(*tmpl));
if (!tmpl)
{
this->mutex->unlock(this->mutex);
return FAILED;
}
for (i = 0; i < countof(protos); i++) for (i = 0; i < countof(protos); i++)
{ {
@@ -2131,16 +2056,6 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
{ {
continue; continue;
} }
rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
RTA_ALIGN(RTA_LENGTH(sizeof(struct xfrm_user_tmpl)));
if (hdr->nlmsg_len > sizeof(request))
{
this->mutex->unlock(this->mutex);
return FAILED;
}
tmpl->reqid = ipsec->cfg.reqid; tmpl->reqid = ipsec->cfg.reqid;
tmpl->id.proto = protos[i].proto; tmpl->id.proto = protos[i].proto;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
@@ -2160,25 +2075,18 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
/* use transport mode for other SAs */ /* use transport mode for other SAs */
proto_mode = MODE_TRANSPORT; proto_mode = MODE_TRANSPORT;
} }
rthdr = XFRM_RTA_NEXT(rthdr);
} }
if (ipsec->mark.value) if (ipsec->mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = ipsec->mark.value; mrk->v = ipsec->mark.value;
mrk->m = ipsec->mark.mask; mrk->m = ipsec->mark.mask;
} }
@@ -2410,17 +2318,12 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }
@@ -2581,18 +2484,12 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
if (mark.value) if (mark.value)
{ {
struct xfrm_mark *mrk; struct xfrm_mark *mrk;
struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
rthdr->rta_type = XFRMA_MARK; mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); if (!mrk)
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request))
{ {
this->mutex->unlock(this->mutex);
return FAILED; return FAILED;
} }
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value; mrk->v = mark.value;
mrk->m = mark.mask; mrk->m = mark.mask;
} }