Merge branch 'sa-dir'
Configures the direction of IPsec SAs in the Linux kernel if possible (6.10+).
This commit is contained in:
@@ -30,7 +30,7 @@ struct xfrm_sec_ctx {
|
|||||||
__u8 ctx_alg;
|
__u8 ctx_alg;
|
||||||
__u16 ctx_len;
|
__u16 ctx_len;
|
||||||
__u32 ctx_sid;
|
__u32 ctx_sid;
|
||||||
char ctx_str[0];
|
char ctx_str[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Security Context Domains of Interpretation */
|
/* Security Context Domains of Interpretation */
|
||||||
@@ -93,27 +93,27 @@ struct xfrm_replay_state_esn {
|
|||||||
__u32 oseq_hi;
|
__u32 oseq_hi;
|
||||||
__u32 seq_hi;
|
__u32 seq_hi;
|
||||||
__u32 replay_window;
|
__u32 replay_window;
|
||||||
__u32 bmp[0];
|
__u32 bmp[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xfrm_algo {
|
struct xfrm_algo {
|
||||||
char alg_name[64];
|
char alg_name[64];
|
||||||
unsigned int alg_key_len; /* in bits */
|
unsigned int alg_key_len; /* in bits */
|
||||||
char alg_key[0];
|
char alg_key[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xfrm_algo_auth {
|
struct xfrm_algo_auth {
|
||||||
char alg_name[64];
|
char alg_name[64];
|
||||||
unsigned int alg_key_len; /* in bits */
|
unsigned int alg_key_len; /* in bits */
|
||||||
unsigned int alg_trunc_len; /* in bits */
|
unsigned int alg_trunc_len; /* in bits */
|
||||||
char alg_key[0];
|
char alg_key[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xfrm_algo_aead {
|
struct xfrm_algo_aead {
|
||||||
char alg_name[64];
|
char alg_name[64];
|
||||||
unsigned int alg_key_len; /* in bits */
|
unsigned int alg_key_len; /* in bits */
|
||||||
unsigned int alg_icv_len; /* in bits */
|
unsigned int alg_icv_len; /* in bits */
|
||||||
char alg_key[0];
|
char alg_key[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xfrm_stats {
|
struct xfrm_stats {
|
||||||
@@ -137,6 +137,11 @@ enum {
|
|||||||
XFRM_POLICY_MAX = 3
|
XFRM_POLICY_MAX = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xfrm_sa_dir {
|
||||||
|
XFRM_SA_DIR_IN = 1,
|
||||||
|
XFRM_SA_DIR_OUT = 2
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
XFRM_SHARE_ANY, /* No limitations */
|
XFRM_SHARE_ANY, /* No limitations */
|
||||||
XFRM_SHARE_SESSION, /* For this session only */
|
XFRM_SHARE_SESSION, /* For this session only */
|
||||||
@@ -212,6 +217,11 @@ enum {
|
|||||||
|
|
||||||
XFRM_MSG_MAPPING,
|
XFRM_MSG_MAPPING,
|
||||||
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
|
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
|
||||||
|
|
||||||
|
XFRM_MSG_SETDEFAULT,
|
||||||
|
#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT
|
||||||
|
XFRM_MSG_GETDEFAULT,
|
||||||
|
#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT
|
||||||
__XFRM_MSG_MAX
|
__XFRM_MSG_MAX
|
||||||
};
|
};
|
||||||
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
|
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
|
||||||
@@ -288,7 +298,7 @@ enum xfrm_attr_type_t {
|
|||||||
XFRMA_ETIMER_THRESH,
|
XFRMA_ETIMER_THRESH,
|
||||||
XFRMA_SRCADDR, /* xfrm_address_t */
|
XFRMA_SRCADDR, /* xfrm_address_t */
|
||||||
XFRMA_COADDR, /* xfrm_address_t */
|
XFRMA_COADDR, /* xfrm_address_t */
|
||||||
XFRMA_LASTUSED, /* __u64 */
|
XFRMA_LASTUSED, /* __u64 */
|
||||||
XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
|
XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
|
||||||
XFRMA_MIGRATE,
|
XFRMA_MIGRATE,
|
||||||
XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */
|
XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */
|
||||||
@@ -301,10 +311,12 @@ enum xfrm_attr_type_t {
|
|||||||
XFRMA_PROTO, /* __u8 */
|
XFRMA_PROTO, /* __u8 */
|
||||||
XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
|
XFRMA_ADDRESS_FILTER, /* struct xfrm_address_filter */
|
||||||
XFRMA_PAD,
|
XFRMA_PAD,
|
||||||
XFRMA_OFFLOAD_DEV, /* struct xfrm_state_offload */
|
XFRMA_OFFLOAD_DEV, /* struct xfrm_user_offload */
|
||||||
XFRMA_SET_MARK, /* __u32 */
|
XFRMA_SET_MARK, /* __u32 */
|
||||||
XFRMA_SET_MARK_MASK, /* __u32 */
|
XFRMA_SET_MARK_MASK, /* __u32 */
|
||||||
XFRMA_IF_ID, /* __u32 */
|
XFRMA_IF_ID, /* __u32 */
|
||||||
|
XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */
|
||||||
|
XFRMA_SA_DIR, /* __u8 */
|
||||||
__XFRMA_MAX
|
__XFRMA_MAX
|
||||||
|
|
||||||
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
|
#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */
|
||||||
@@ -384,6 +396,7 @@ struct xfrm_usersa_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
|
#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
|
||||||
|
#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
|
||||||
|
|
||||||
struct xfrm_usersa_id {
|
struct xfrm_usersa_id {
|
||||||
xfrm_address_t daddr;
|
xfrm_address_t daddr;
|
||||||
@@ -501,10 +514,30 @@ struct xfrm_user_offload {
|
|||||||
int ifindex;
|
int ifindex;
|
||||||
__u8 flags;
|
__u8 flags;
|
||||||
};
|
};
|
||||||
|
/* This flag was exposed without any kernel code that supports it.
|
||||||
|
* Unfortunately, strongswan has the code that sets this flag,
|
||||||
|
* which makes it impossible to reuse this bit.
|
||||||
|
*
|
||||||
|
* So leave it here to make sure that it won't be reused by mistake.
|
||||||
|
*/
|
||||||
#define XFRM_OFFLOAD_IPV6 1
|
#define XFRM_OFFLOAD_IPV6 1
|
||||||
#define XFRM_OFFLOAD_INBOUND 2
|
#define XFRM_OFFLOAD_INBOUND 2
|
||||||
|
/* Two bits above are relevant for state path only, while
|
||||||
|
* offload is used for both policy and state flows.
|
||||||
|
*
|
||||||
|
* In policy offload mode, they are free and can be safely reused.
|
||||||
|
*/
|
||||||
#define XFRM_OFFLOAD_PACKET 4
|
#define XFRM_OFFLOAD_PACKET 4
|
||||||
|
|
||||||
|
struct xfrm_userpolicy_default {
|
||||||
|
#define XFRM_USERPOLICY_UNSPEC 0
|
||||||
|
#define XFRM_USERPOLICY_BLOCK 1
|
||||||
|
#define XFRM_USERPOLICY_ACCEPT 2
|
||||||
|
__u8 in;
|
||||||
|
__u8 fwd;
|
||||||
|
__u8 out;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
/* backwards compatibility for userspace */
|
/* backwards compatibility for userspace */
|
||||||
#define XFRMGRP_ACQUIRE 1
|
#define XFRMGRP_ACQUIRE 1
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ struct kernel_algorithm_t {
|
|||||||
const char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
|
ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, __XFRM_MSG_MAX,
|
||||||
"XFRM_MSG_NEWSA",
|
"XFRM_MSG_NEWSA",
|
||||||
"XFRM_MSG_DELSA",
|
"XFRM_MSG_DELSA",
|
||||||
"XFRM_MSG_GETSA",
|
"XFRM_MSG_GETSA",
|
||||||
@@ -162,10 +162,13 @@ ENUM(xfrm_msg_names, XFRM_MSG_NEWSA, XFRM_MSG_MAPPING,
|
|||||||
"XFRM_MSG_GETSADINFO",
|
"XFRM_MSG_GETSADINFO",
|
||||||
"XFRM_MSG_NEWSPDINFO",
|
"XFRM_MSG_NEWSPDINFO",
|
||||||
"XFRM_MSG_GETSPDINFO",
|
"XFRM_MSG_GETSPDINFO",
|
||||||
"XFRM_MSG_MAPPING"
|
"XFRM_MSG_MAPPING",
|
||||||
|
"XFRM_MSG_SETDEFAULT",
|
||||||
|
"XFRM_MSG_GETDEFAULT",
|
||||||
|
"XFRM_MSG_MAX",
|
||||||
);
|
);
|
||||||
|
|
||||||
ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_OFFLOAD_DEV,
|
ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, __XFRMA_MAX,
|
||||||
"XFRMA_UNSPEC",
|
"XFRMA_UNSPEC",
|
||||||
"XFRMA_ALG_AUTH",
|
"XFRMA_ALG_AUTH",
|
||||||
"XFRMA_ALG_CRYPT",
|
"XFRMA_ALG_CRYPT",
|
||||||
@@ -195,6 +198,12 @@ ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_OFFLOAD_DEV,
|
|||||||
"XFRMA_ADDRESS_FILTER",
|
"XFRMA_ADDRESS_FILTER",
|
||||||
"XFRMA_PAD",
|
"XFRMA_PAD",
|
||||||
"XFRMA_OFFLOAD_DEV",
|
"XFRMA_OFFLOAD_DEV",
|
||||||
|
"XFRMA_SET_MARK",
|
||||||
|
"XFRMA_SET_MARK_MASK",
|
||||||
|
"XFRMA_IF_ID",
|
||||||
|
"XFRMA_MTIMER_THRESH",
|
||||||
|
"XFRMA_SA_DIR",
|
||||||
|
"XFRMA_MAX",
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -353,6 +362,11 @@ struct private_kernel_netlink_ipsec_t {
|
|||||||
*/
|
*/
|
||||||
bool sa_lastused;
|
bool sa_lastused;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the kernel supports setting the SA direction
|
||||||
|
*/
|
||||||
|
bool sa_dir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to install routes along policies
|
* Whether to install routes along policies
|
||||||
*/
|
*/
|
||||||
@@ -1178,114 +1192,6 @@ METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
|||||||
(this->sa_lastused ? KERNEL_SA_USE_TIME : 0);
|
(this->sa_lastused ? KERNEL_SA_USE_TIME : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an SPI for a specific protocol from the kernel.
|
|
||||||
*/
|
|
||||||
static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
|
|
||||||
host_t *src, host_t *dst, uint8_t proto, uint32_t min, uint32_t max,
|
|
||||||
uint32_t *spi)
|
|
||||||
{
|
|
||||||
netlink_buf_t request;
|
|
||||||
struct nlmsghdr *hdr, *out;
|
|
||||||
struct xfrm_userspi_info *userspi;
|
|
||||||
uint32_t received_spi = 0;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
memset(&request, 0, sizeof(request));
|
|
||||||
|
|
||||||
hdr = &request.hdr;
|
|
||||||
hdr->nlmsg_flags = NLM_F_REQUEST;
|
|
||||||
hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
|
|
||||||
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
|
|
||||||
|
|
||||||
userspi = NLMSG_DATA(hdr);
|
|
||||||
host2xfrm(src, &userspi->info.saddr);
|
|
||||||
host2xfrm(dst, &userspi->info.id.daddr);
|
|
||||||
userspi->info.id.proto = proto;
|
|
||||||
userspi->info.mode = XFRM_MODE_TUNNEL;
|
|
||||||
userspi->info.family = src->get_family(src);
|
|
||||||
userspi->min = min;
|
|
||||||
userspi->max = max;
|
|
||||||
|
|
||||||
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
|
||||||
{
|
|
||||||
hdr = out;
|
|
||||||
while (NLMSG_OK(hdr, len))
|
|
||||||
{
|
|
||||||
switch (hdr->nlmsg_type)
|
|
||||||
{
|
|
||||||
case XFRM_MSG_NEWSA:
|
|
||||||
{
|
|
||||||
struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr);
|
|
||||||
received_spi = usersa->id.spi;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NLMSG_ERROR:
|
|
||||||
{
|
|
||||||
netlink_log_error(hdr, "allocating SPI failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
hdr = NLMSG_NEXT(hdr, len);
|
|
||||||
continue;
|
|
||||||
case NLMSG_DONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (received_spi == 0)
|
|
||||||
{
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*spi = received_spi;
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_spi, status_t,
|
|
||||||
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
|
||||||
uint8_t protocol, uint32_t *spi)
|
|
||||||
{
|
|
||||||
uint32_t spi_min, spi_max;
|
|
||||||
|
|
||||||
spi_min = lib->settings->get_int(lib->settings, "%s.spi_min",
|
|
||||||
KERNEL_SPI_MIN, lib->ns);
|
|
||||||
spi_max = lib->settings->get_int(lib->settings, "%s.spi_max",
|
|
||||||
KERNEL_SPI_MAX, lib->ns);
|
|
||||||
|
|
||||||
if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max),
|
|
||||||
max(spi_min, spi_max), spi) != SUCCESS)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "unable to get SPI");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
METHOD(kernel_ipsec_t, get_cpi, status_t,
|
|
||||||
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
|
||||||
uint16_t *cpi)
|
|
||||||
{
|
|
||||||
uint32_t received_spi = 0;
|
|
||||||
|
|
||||||
if (get_spi_internal(this, src, dst, IPPROTO_COMP,
|
|
||||||
0x100, 0xEFFF, &received_spi) != SUCCESS)
|
|
||||||
{
|
|
||||||
DBG1(DBG_KNL, "unable to get CPI");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*cpi = htons((uint16_t)ntohl(received_spi));
|
|
||||||
|
|
||||||
DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format the mark for debug messages
|
* Format the mark for debug messages
|
||||||
*/
|
*/
|
||||||
@@ -1375,6 +1281,137 @@ static bool add_uint32(struct nlmsghdr *hdr, int buflen,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a uint8 attribute to message
|
||||||
|
*/
|
||||||
|
static bool add_uint8(struct nlmsghdr *hdr, int buflen,
|
||||||
|
enum xfrm_attr_type_t type, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t *xvalue;
|
||||||
|
|
||||||
|
xvalue = netlink_reserve(hdr, buflen, type, sizeof(*xvalue));
|
||||||
|
if (!xvalue)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*xvalue = value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an SPI for a specific protocol from the kernel.
|
||||||
|
*/
|
||||||
|
static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
|
||||||
|
host_t *src, host_t *dst, uint8_t proto, uint32_t min, uint32_t max,
|
||||||
|
uint32_t *spi)
|
||||||
|
{
|
||||||
|
netlink_buf_t request;
|
||||||
|
struct nlmsghdr *hdr, *out;
|
||||||
|
struct xfrm_userspi_info *userspi;
|
||||||
|
uint32_t received_spi = 0;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
|
||||||
|
hdr = &request.hdr;
|
||||||
|
hdr->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
hdr->nlmsg_type = XFRM_MSG_ALLOCSPI;
|
||||||
|
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userspi_info));
|
||||||
|
|
||||||
|
userspi = NLMSG_DATA(hdr);
|
||||||
|
host2xfrm(src, &userspi->info.saddr);
|
||||||
|
host2xfrm(dst, &userspi->info.id.daddr);
|
||||||
|
userspi->info.id.proto = proto;
|
||||||
|
userspi->info.mode = XFRM_MODE_TUNNEL;
|
||||||
|
userspi->info.family = src->get_family(src);
|
||||||
|
userspi->min = min;
|
||||||
|
userspi->max = max;
|
||||||
|
|
||||||
|
if (this->sa_dir &&
|
||||||
|
!add_uint8(hdr, sizeof(request), XFRMA_SA_DIR, XFRM_SA_DIR_IN))
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
|
||||||
|
{
|
||||||
|
hdr = out;
|
||||||
|
while (NLMSG_OK(hdr, len))
|
||||||
|
{
|
||||||
|
switch (hdr->nlmsg_type)
|
||||||
|
{
|
||||||
|
case XFRM_MSG_NEWSA:
|
||||||
|
{
|
||||||
|
struct xfrm_usersa_info* usersa = NLMSG_DATA(hdr);
|
||||||
|
received_spi = usersa->id.spi;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NLMSG_ERROR:
|
||||||
|
{
|
||||||
|
netlink_log_error(hdr, "allocating SPI failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
hdr = NLMSG_NEXT(hdr, len);
|
||||||
|
continue;
|
||||||
|
case NLMSG_DONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (received_spi == 0)
|
||||||
|
{
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*spi = received_spi;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_ipsec_t, get_spi, status_t,
|
||||||
|
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
|
uint8_t protocol, uint32_t *spi)
|
||||||
|
{
|
||||||
|
uint32_t spi_min, spi_max;
|
||||||
|
|
||||||
|
spi_min = lib->settings->get_int(lib->settings, "%s.spi_min",
|
||||||
|
KERNEL_SPI_MIN, lib->ns);
|
||||||
|
spi_max = lib->settings->get_int(lib->settings, "%s.spi_max",
|
||||||
|
KERNEL_SPI_MAX, lib->ns);
|
||||||
|
|
||||||
|
if (get_spi_internal(this, src, dst, protocol, min(spi_min, spi_max),
|
||||||
|
max(spi_min, spi_max), spi) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to get SPI");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi));
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(kernel_ipsec_t, get_cpi, status_t,
|
||||||
|
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
|
||||||
|
uint16_t *cpi)
|
||||||
|
{
|
||||||
|
uint32_t received_spi = 0;
|
||||||
|
|
||||||
|
if (get_spi_internal(this, src, dst, IPPROTO_COMP,
|
||||||
|
0x100, 0xEFFF, &received_spi) != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_KNL, "unable to get CPI");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cpi = htons((uint16_t)ntohl(received_spi));
|
||||||
|
|
||||||
|
DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi));
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* ETHTOOL_GSSET_INFO is available since 2.6.34 and ETH_SS_FEATURES (enum) and
|
/* ETHTOOL_GSSET_INFO is available since 2.6.34 and ETH_SS_FEATURES (enum) and
|
||||||
* ETHTOOL_GFEATURES since 2.6.39, so check for the latter */
|
* ETHTOOL_GFEATURES since 2.6.39, so check for the latter */
|
||||||
#ifdef ETHTOOL_GFEATURES
|
#ifdef ETHTOOL_GFEATURES
|
||||||
@@ -1715,11 +1752,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
sa->family = id->src->get_family(id->src);
|
sa->family = id->src->get_family(id->src);
|
||||||
sa->mode = mode2kernel(mode);
|
sa->mode = mode2kernel(mode);
|
||||||
|
|
||||||
if (!data->copy_df)
|
|
||||||
{
|
|
||||||
sa->flags |= XFRM_STATE_NOPMTUDISC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data->copy_ecn)
|
if (!data->copy_ecn)
|
||||||
{
|
{
|
||||||
sa->flags |= XFRM_STATE_NOECN;
|
sa->flags |= XFRM_STATE_NOECN;
|
||||||
@@ -1739,6 +1771,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!data->copy_df)
|
||||||
|
{
|
||||||
|
sa->flags |= XFRM_STATE_NOPMTUDISC;
|
||||||
|
}
|
||||||
switch (data->copy_dscp)
|
switch (data->copy_dscp)
|
||||||
{
|
{
|
||||||
case DSCP_COPY_IN_ONLY:
|
case DSCP_COPY_IN_ONLY:
|
||||||
@@ -2038,13 +2074,21 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->sa_dir &&
|
||||||
|
!add_uint8(hdr, sizeof(request), XFRMA_SA_DIR,
|
||||||
|
data->inbound ? XFRM_SA_DIR_IN : XFRM_SA_DIR_OUT))
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
if (id->proto != IPPROTO_COMP)
|
if (id->proto != IPPROTO_COMP)
|
||||||
{
|
{
|
||||||
/* generally, we don't need a replay window for outbound SAs, however,
|
/* we don't need a replay window for outbound SAs, however, older
|
||||||
* when using ESN the kernel rejects the attribute if it is 0 */
|
* kernels reject the attribute if it is 0 when using ESN, while
|
||||||
|
* newer kernels reject it if > 0 if the SA's direction is set */
|
||||||
if (!data->inbound && data->replay_window)
|
if (!data->inbound && data->replay_window)
|
||||||
{
|
{
|
||||||
data->replay_window = data->esn ? 1 : 0;
|
data->replay_window = (data->esn && !this->sa_dir) ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (data->esn || data->replay_window > 32)
|
if (data->esn || data->replay_window > 32)
|
||||||
{
|
{
|
||||||
@@ -4125,6 +4169,9 @@ static void check_kernel_features(private_kernel_netlink_ipsec_t *this)
|
|||||||
/* before 6.2 the kernel only provided the last used time for
|
/* before 6.2 the kernel only provided the last used time for
|
||||||
* specific outbound IPv6 SAs */
|
* specific outbound IPv6 SAs */
|
||||||
this->sa_lastused = a > 6 || (a == 6 && b >= 2);
|
this->sa_lastused = a > 6 || (a == 6 && b >= 2);
|
||||||
|
/* 6.10 added support for SA direction and enforces certain
|
||||||
|
* flags e.g. 0 replay window for outbound SAs */
|
||||||
|
this->sa_dir = a > 6 || (a == 6 && b >= 10);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user