#define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \
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
* (after 'usual' netlink data x like 'struct xfrm_usersa_info')
*/
sa->lft.soft_use_expires_seconds = 0;
sa->lft.hard_use_expires_seconds = 0;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info);
-
switch (enc_alg)
{
case ENCR_UNDEFINED:
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_key.len * 8);
- rthdr->rta_type = XFRMA_ALG_AEAD;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) +
- enc_key.len);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
- RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD,
+ sizeof(*algo) + enc_key.len);
+ if (!algo)
{
goto failed;
}
-
- algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8;
algo->alg_icv_len = icv_size;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
-
- rthdr = XFRM_RTA_NEXT(rthdr);
break;
}
default:
DBG2(DBG_KNL, " using encryption algorithm %N with key size %d",
encryption_algorithm_names, enc_alg, enc_key.len * 8);
- rthdr->rta_type = XFRMA_ALG_CRYPT;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
- RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT,
+ sizeof(*algo) + enc_key.len);
+ if (!algo)
{
goto failed;
}
-
- algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = enc_key.len * 8;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, enc_key.ptr, enc_key.len);
-
- rthdr = XFRM_RTA_NEXT(rthdr);
}
}
/* the kernel uses SHA256 with 96 bit truncation by default,
* use specified truncation size supported by newer kernels.
* also use this for untruncated MD5 and SHA1. */
- rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) +
- int_key.len);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
- RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC,
+ sizeof(*algo) + int_key.len);
+ if (!algo)
{
goto failed;
}
-
- algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8;
algo->alg_trunc_len = trunc_len;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
{
struct xfrm_algo* algo;
- rthdr->rta_type = XFRMA_ALG_AUTH;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
- RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH,
+ sizeof(*algo) + int_key.len);
+ if (!algo)
{
goto failed;
}
-
- algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = int_key.len * 8;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
memcpy(algo->alg_key, int_key.ptr, int_key.len);
}
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (ipcomp != IPCOMP_NONE)
{
- rthdr->rta_type = XFRMA_ALG_COMP;
+ struct xfrm_algo* algo;
+
alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp);
if (alg_name == NULL)
{
DBG2(DBG_KNL, " using compression algorithm %N",
ipcomp_transform_names, ipcomp);
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP,
+ sizeof(*algo));
+ if (!algo)
{
goto failed;
}
-
- struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr);
algo->alg_key_len = 0;
strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name));
algo->alg_name[sizeof(algo->alg_name) - 1] = '\0';
-
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (encap)
{
struct xfrm_encap_tmpl *tmpl;
- rthdr->rta_type = XFRMA_ENCAP;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
+ if (!tmpl)
{
goto failed;
}
-
- tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
tmpl->encap_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = htons(src->get_port(src));
tmpl->encap_dport = htons(dst->get_port(dst));
* No. The reason the kernel ignores NAT-OA is that it recomputes
* (or, rather, just ignores) the checksum. If packets pass the IPsec
* checks it marks them "checksum ok" so OA isn't needed. */
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (mark.value)
{
struct xfrm_mark *mrk;
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
-
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
goto failed;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (tfc)
{
u_int32_t *tfcpad;
- rthdr->rta_type = XFRMA_TFCPAD;
- rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD,
+ sizeof(*tfcpad));
+ if (!tfcpad)
{
goto failed;
}
-
- tfcpad = (u_int32_t*)RTA_DATA(rthdr);
*tfcpad = tfc;
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (protocol != IPPROTO_COMP)
* XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */
struct xfrm_replay_state_esn *replay;
- rthdr->rta_type = XFRMA_REPLAY_ESN_VAL;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) +
- (this->replay_window + 7) / 8);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
- RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
+ sizeof(*replay) + (this->replay_window + 7) / 8);
+ if (!replay)
{
goto failed;
}
-
- replay = (struct xfrm_replay_state_esn*)RTA_DATA(rthdr);
/* bmp_len contains number uf __u32's */
replay->bmp_len = this->replay_bmp;
replay->replay_window = this->replay_window;
DBG2(DBG_KNL, " using replay window of %u packets",
this->replay_window);
- rthdr = XFRM_RTA_NEXT(rthdr);
if (esn)
{
DBG2(DBG_KNL, " using extended sequence numbers (ESN)");
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
return;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}
rta = XFRM_RTA(out, struct xfrm_usersa_info);
rtasize = XFRM_PAYLOAD(out, 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 */
if (rta->rta_type != XFRMA_ENCAP || new_encap)
rta = RTA_NEXT(rta, rtasize);
}
- rta = (struct rtattr*)pos;
if (tmpl == NULL && new_encap)
{ /* add tmpl if we are enabling it */
- rta->rta_type = XFRMA_ENCAP;
- rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl));
+ if (!tmpl)
{
goto failed;
}
-
- tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta);
tmpl->encap_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = ntohs(new_src->get_port(new_src));
tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t));
-
- rta = XFRM_RTA_NEXT(rta);
}
if (replay_esn)
{
- rta->rta_type = XFRMA_REPLAY_ESN_VAL;
- rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) +
- this->replay_bmp);
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ struct xfrm_replay_state_esn *state;
+
+ state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
+ sizeof(*state) + this->replay_bmp);
+ if (!state)
{
goto failed;
}
- memcpy(RTA_DATA(rta), replay_esn,
- sizeof(struct xfrm_replay_state_esn) + this->replay_bmp);
-
- rta = XFRM_RTA_NEXT(rta);
+ memcpy(state, replay_esn, sizeof(*state) + this->replay_bmp);
}
else if (replay)
{
- rta->rta_type = XFRMA_REPLAY_VAL;
- rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ struct xfrm_replay_state *state;
+
+ state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL,
+ sizeof(*state));
+ if (!state)
{
goto failed;
}
- memcpy(RTA_DATA(rta), replay, sizeof(struct xfrm_replay_state));
-
- rta = XFRM_RTA_NEXT(rta);
+ memcpy(state, replay, sizeof(*state));
}
else
{
policy_info->lft.soft_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)
{
- struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr);
+ struct xfrm_user_tmpl *tmpl;
struct {
u_int8_t proto;
bool use;
{ IPPROTO_AH, ipsec->cfg.ah.use },
};
ipsec_mode_t proto_mode = ipsec->cfg.mode;
-
- rthdr->rta_type = XFRMA_TMPL;
- rthdr->rta_len = 0; /* actual length is set below */
+ int count = 0;
for (i = 0; i < countof(protos); i++)
{
- if (!protos[i].use)
+ if (protos[i].use)
{
- continue;
+ count++;
}
+ }
+ tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL,
+ count * sizeof(*tmpl));
+ if (!tmpl)
+ {
+ this->mutex->unlock(this->mutex);
+ return FAILED;
+ }
- 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))
+ for (i = 0; i < countof(protos); i++)
+ {
+ if (!protos[i].use)
{
- this->mutex->unlock(this->mutex);
- return FAILED;
+ continue;
}
-
tmpl->reqid = ipsec->cfg.reqid;
tmpl->id.proto = protos[i].proto;
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
/* use transport mode for other SAs */
proto_mode = MODE_TRANSPORT;
}
-
- rthdr = XFRM_RTA_NEXT(rthdr);
}
if (ipsec->mark.value)
{
struct xfrm_mark *mrk;
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
-
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
this->mutex->unlock(this->mutex);
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = ipsec->mark.value;
mrk->m = ipsec->mark.mask;
}
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}
if (mark.value)
{
struct xfrm_mark *mrk;
- struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id);
- rthdr->rta_type = XFRMA_MARK;
- rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
- hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
- if (hdr->nlmsg_len > sizeof(request))
+ mrk = netlink_reserve(hdr, sizeof(request), XFRMA_MARK, sizeof(*mrk));
+ if (!mrk)
{
- this->mutex->unlock(this->mutex);
return FAILED;
}
-
- mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
mrk->v = mark.value;
mrk->m = mark.mask;
}