Merge branch 'netlink-align'
Fixes some Netlink alignment issues, and then refactors Netlink XFRM message attribute handling.
This commit is contained in:
@@ -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')
|
||||||
@@ -176,8 +170,6 @@ ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_REPLAY_ESN_VAL,
|
|||||||
"XFRMA_REPLAY_ESN_VAL",
|
"XFRMA_REPLAY_ESN_VAL",
|
||||||
);
|
);
|
||||||
|
|
||||||
#define END_OF_LIST -1
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Algorithms for encryption
|
* Algorithms for encryption
|
||||||
*/
|
*/
|
||||||
@@ -208,7 +200,6 @@ static kernel_algorithm_t encryption_algs[] = {
|
|||||||
/* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */
|
/* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */
|
||||||
{ENCR_SERPENT_CBC, "serpent" },
|
{ENCR_SERPENT_CBC, "serpent" },
|
||||||
{ENCR_TWOFISH_CBC, "twofish" },
|
{ENCR_TWOFISH_CBC, "twofish" },
|
||||||
{END_OF_LIST, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +217,6 @@ static kernel_algorithm_t integrity_algs[] = {
|
|||||||
/* {AUTH_DES_MAC, "***" }, */
|
/* {AUTH_DES_MAC, "***" }, */
|
||||||
/* {AUTH_KPDK_MD5, "***" }, */
|
/* {AUTH_KPDK_MD5, "***" }, */
|
||||||
{AUTH_AES_XCBC_96, "xcbc(aes)" },
|
{AUTH_AES_XCBC_96, "xcbc(aes)" },
|
||||||
{END_OF_LIST, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -237,7 +227,6 @@ static kernel_algorithm_t compression_algs[] = {
|
|||||||
{IPCOMP_DEFLATE, "deflate" },
|
{IPCOMP_DEFLATE, "deflate" },
|
||||||
{IPCOMP_LZS, "lzs" },
|
{IPCOMP_LZS, "lzs" },
|
||||||
{IPCOMP_LZJH, "lzjh" },
|
{IPCOMP_LZJH, "lzjh" },
|
||||||
{END_OF_LIST, NULL }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,33 +235,39 @@ static kernel_algorithm_t compression_algs[] = {
|
|||||||
static char* lookup_algorithm(transform_type_t type, int ikev2)
|
static char* lookup_algorithm(transform_type_t type, int ikev2)
|
||||||
{
|
{
|
||||||
kernel_algorithm_t *list;
|
kernel_algorithm_t *list;
|
||||||
char *name = NULL;
|
int i, count;
|
||||||
|
char *name;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ENCRYPTION_ALGORITHM:
|
case ENCRYPTION_ALGORITHM:
|
||||||
list = encryption_algs;
|
list = encryption_algs;
|
||||||
|
count = countof(encryption_algs);
|
||||||
break;
|
break;
|
||||||
case INTEGRITY_ALGORITHM:
|
case INTEGRITY_ALGORITHM:
|
||||||
list = integrity_algs;
|
list = integrity_algs;
|
||||||
|
count = countof(integrity_algs);
|
||||||
break;
|
break;
|
||||||
case COMPRESSION_ALGORITHM:
|
case COMPRESSION_ALGORITHM:
|
||||||
list = compression_algs;
|
list = compression_algs;
|
||||||
|
count = countof(compression_algs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
while (list->ikev2 != END_OF_LIST)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (list->ikev2 == ikev2)
|
if (list[i].ikev2 == ikev2)
|
||||||
{
|
{
|
||||||
return list->name;
|
return list[i].name;
|
||||||
}
|
}
|
||||||
list++;
|
|
||||||
}
|
}
|
||||||
hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2,
|
if (hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface,
|
||||||
type, NULL, &name);
|
ikev2, type, NULL, &name))
|
||||||
return name;
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
|
typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
|
||||||
@@ -1150,6 +1145,26 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a XFRM mark to message if required
|
||||||
|
*/
|
||||||
|
static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
|
||||||
|
{
|
||||||
|
if (mark.value)
|
||||||
|
{
|
||||||
|
struct xfrm_mark *xmrk;
|
||||||
|
|
||||||
|
xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk));
|
||||||
|
if (!xmrk)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
xmrk->v = mark.value;
|
||||||
|
xmrk->m = mark.mask;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, add_sa, status_t,
|
METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||||
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
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,
|
u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
|
||||||
@@ -1222,8 +1237,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:
|
||||||
@@ -1256,23 +1269,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 += 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:
|
||||||
@@ -1289,21 +1296,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 += RTA_ALIGN(rthdr->rta_len);
|
if (!algo)
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1341,17 +1343,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 += 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));
|
||||||
@@ -1362,27 +1359,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);
|
||||||
|
if (!algo)
|
||||||
hdr->nlmsg_len += 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)
|
||||||
{
|
{
|
||||||
@@ -1393,35 +1386,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 += 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 += 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));
|
||||||
@@ -1436,44 +1420,24 @@ 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 (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
goto failed;
|
||||||
|
|
||||||
rthdr->rta_type = XFRMA_MARK;
|
|
||||||
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
|
|
||||||
|
|
||||||
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
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));
|
||||||
|
if (!tfcpad)
|
||||||
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
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)
|
||||||
@@ -1484,24 +1448,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 += 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)");
|
||||||
@@ -1573,22 +1531,9 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
|
|||||||
aevent_id->sa_id.proto = protocol;
|
aevent_id->sa_id.proto = protocol;
|
||||||
aevent_id->sa_id.family = dst->get_family(dst);
|
aevent_id->sa_id.family = dst->get_family(dst);
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
||||||
@@ -1674,22 +1619,9 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
|
|||||||
sa_id->proto = protocol;
|
sa_id->proto = protocol;
|
||||||
sa_id->family = dst->get_family(dst);
|
sa_id->family = dst->get_family(dst);
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return FAILED;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
||||||
@@ -1777,22 +1709,9 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
|
|||||||
sa_id->proto = protocol;
|
sa_id->proto = protocol;
|
||||||
sa_id->family = dst->get_family(dst);
|
sa_id->family = dst->get_family(dst);
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return FAILED;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
|
switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr))
|
||||||
@@ -1824,7 +1743,6 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
bool old_encap, bool new_encap, mark_t mark)
|
bool old_encap, bool new_encap, mark_t mark)
|
||||||
{
|
{
|
||||||
netlink_buf_t request;
|
netlink_buf_t request;
|
||||||
u_char *pos;
|
|
||||||
struct nlmsghdr *hdr, *out = NULL;
|
struct nlmsghdr *hdr, *out = NULL;
|
||||||
struct xfrm_usersa_id *sa_id;
|
struct xfrm_usersa_id *sa_id;
|
||||||
struct xfrm_usersa_info *out_sa = NULL, *sa;
|
struct xfrm_usersa_info *out_sa = NULL, *sa;
|
||||||
@@ -1859,22 +1777,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
sa_id->proto = protocol;
|
sa_id->proto = protocol;
|
||||||
sa_id->family = dst->get_family(dst);
|
sa_id->family = dst->get_family(dst);
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return FAILED;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
||||||
@@ -1925,11 +1830,11 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
|
|||||||
ntohl(spi), src, dst, new_src, new_dst);
|
ntohl(spi), src, dst, new_src, new_dst);
|
||||||
/* copy over the SA from out to request */
|
/* copy over the SA from out to request */
|
||||||
hdr = (struct nlmsghdr*)request;
|
hdr = (struct nlmsghdr*)request;
|
||||||
memcpy(hdr, out, min(out->nlmsg_len, sizeof(request)));
|
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||||
hdr->nlmsg_type = XFRM_MSG_NEWSA;
|
hdr->nlmsg_type = XFRM_MSG_NEWSA;
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
|
||||||
sa = NLMSG_DATA(hdr);
|
sa = NLMSG_DATA(hdr);
|
||||||
|
memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info));
|
||||||
sa->family = new_dst->get_family(new_dst);
|
sa->family = new_dst->get_family(new_dst);
|
||||||
|
|
||||||
if (!src->ip_equals(src, new_src))
|
if (!src->ip_equals(src, new_src))
|
||||||
@@ -1943,75 +1848,60 @@ 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);
|
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)
|
||||||
{
|
{
|
||||||
if (rta->rta_type == XFRMA_ENCAP)
|
if (rta->rta_type == XFRMA_ENCAP)
|
||||||
{ /* update encap tmpl */
|
{ /* update encap tmpl */
|
||||||
tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta);
|
tmpl = RTA_DATA(rta);
|
||||||
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));
|
||||||
}
|
}
|
||||||
memcpy(pos, rta, rta->rta_len);
|
netlink_add_attribute(hdr, rta->rta_type,
|
||||||
pos += RTA_ALIGN(rta->rta_len);
|
chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)),
|
||||||
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
|
sizeof(request));
|
||||||
}
|
}
|
||||||
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 += 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);
|
|
||||||
|
|
||||||
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
|
state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL,
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
sizeof(*state) + this->replay_bmp);
|
||||||
|
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 += 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
|
||||||
{
|
{
|
||||||
@@ -2108,11 +1998,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;
|
||||||
@@ -2122,9 +2010,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++)
|
||||||
{
|
{
|
||||||
@@ -2132,15 +2033,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 += 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,27 +2052,12 @@ 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 (!add_mark(hdr, sizeof(request), ipsec->mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
this->mutex->unlock(this->mutex);
|
||||||
|
return FAILED;
|
||||||
rthdr->rta_type = XFRMA_MARK;
|
|
||||||
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
|
|
||||||
|
|
||||||
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = ipsec->mark.value;
|
|
||||||
mrk->m = ipsec->mark.mask;
|
|
||||||
}
|
}
|
||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
|
|
||||||
@@ -2407,23 +2284,9 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
|
|||||||
policy_id->sel = ts2selector(src_ts, dst_ts);
|
policy_id->sel = ts2selector(src_ts, dst_ts);
|
||||||
policy_id->dir = direction;
|
policy_id->dir = direction;
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return FAILED;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
||||||
@@ -2579,23 +2442,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
|
|||||||
policy_id->sel = current->sel;
|
policy_id->sel = current->sel;
|
||||||
policy_id->dir = direction;
|
policy_id->dir = direction;
|
||||||
|
|
||||||
if (mark.value)
|
if (!add_mark(hdr, sizeof(request), mark))
|
||||||
{
|
{
|
||||||
struct xfrm_mark *mrk;
|
return FAILED;
|
||||||
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 += RTA_ALIGN(rthdr->rta_len);
|
|
||||||
if (hdr->nlmsg_len > sizeof(request))
|
|
||||||
{
|
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mrk = (struct xfrm_mark*)RTA_DATA(rthdr);
|
|
||||||
mrk->v = mark.value;
|
|
||||||
mrk->m = mark.mask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current->route)
|
if (current->route)
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
|
|||||||
{
|
{
|
||||||
struct rtattr *rta;
|
struct rtattr *rta;
|
||||||
|
|
||||||
if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(data.len) > buflen)
|
if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_LENGTH(data.len) > buflen)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "unable to add attribute, buffer too small");
|
DBG1(DBG_KNL, "unable to add attribute, buffer too small");
|
||||||
return;
|
return;
|
||||||
@@ -304,3 +304,24 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
|
|||||||
memcpy(RTA_DATA(rta), data.ptr, data.len);
|
memcpy(RTA_DATA(rta), data.ptr, data.len);
|
||||||
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len;
|
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len)
|
||||||
|
{
|
||||||
|
struct rtattr *rta;
|
||||||
|
|
||||||
|
if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_LENGTH(len) > buflen)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to add attribute, buffer too small");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rta = ((void*)hdr) + NLMSG_ALIGN(hdr->nlmsg_len);
|
||||||
|
rta->rta_type = type;
|
||||||
|
rta->rta_len = RTA_LENGTH(len);
|
||||||
|
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len;
|
||||||
|
|
||||||
|
return RTA_DATA(rta);
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ struct netlink_socket_t {
|
|||||||
* @param out received netlink message
|
* @param out received netlink message
|
||||||
* @param out_len length of the received message
|
* @param out_len length of the received message
|
||||||
*/
|
*/
|
||||||
status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out, size_t *out_len);
|
status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in,
|
||||||
|
struct nlmsghdr **out, size_t *out_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a netlink message and wait for its acknowledge.
|
* Send a netlink message and wait for its acknowledge.
|
||||||
@@ -67,11 +68,23 @@ netlink_socket_t *netlink_socket_create(int protocol);
|
|||||||
/**
|
/**
|
||||||
* Creates an rtattr and adds it to the given netlink message.
|
* Creates an rtattr and adds it to the given netlink message.
|
||||||
*
|
*
|
||||||
* @param hdr netlink message
|
* @param hdr netlink message
|
||||||
* @param rta_type type of the rtattr
|
* @param rta_type type of the rtattr
|
||||||
* @param data data to add to the rtattr
|
* @param data data to add to the rtattr
|
||||||
* @param buflen length of the netlink message buffer
|
* @param buflen length of the netlink message buffer
|
||||||
*/
|
*/
|
||||||
void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, size_t buflen);
|
void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data,
|
||||||
|
size_t buflen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve space in a netlink message for given size and type, returning buffer.
|
||||||
|
*
|
||||||
|
* @param hdr netlink message
|
||||||
|
* @param buflen size of full netlink buffer
|
||||||
|
* @param type RTA type
|
||||||
|
* @param len length of RTA data
|
||||||
|
* @return buffer to len bytes of attribute data, NULL on error
|
||||||
|
*/
|
||||||
|
void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len);
|
||||||
|
|
||||||
#endif /* KERNEL_NETLINK_SHARED_H_ */
|
#endif /* KERNEL_NETLINK_SHARED_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user