mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-06 00:00:47 -04:00
kernel: Add option to control DS field behavior
This commit is contained in:
parent
dc8b015d78
commit
c993eaf9d1
@ -147,6 +147,11 @@ struct private_child_cfg_t {
|
||||
* HW offload mode
|
||||
*/
|
||||
hw_offload_t hw_offload;
|
||||
|
||||
/**
|
||||
* DS header field copy mode
|
||||
*/
|
||||
dscp_copy_t copy_dscp;
|
||||
};
|
||||
|
||||
METHOD(child_cfg_t, get_name, char*,
|
||||
@ -487,6 +492,12 @@ METHOD(child_cfg_t, get_hw_offload, hw_offload_t,
|
||||
return this->hw_offload;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_copy_dscp, dscp_copy_t,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
return this->copy_dscp;
|
||||
}
|
||||
|
||||
METHOD(child_cfg_t, get_dpd_action, action_t,
|
||||
private_child_cfg_t *this)
|
||||
{
|
||||
@ -612,6 +623,8 @@ METHOD(child_cfg_t, equals, bool,
|
||||
this->tfc == other->tfc &&
|
||||
this->manual_prio == other->manual_prio &&
|
||||
this->replay_window == other->replay_window &&
|
||||
this->hw_offload == other->hw_offload &&
|
||||
this->copy_dscp == other->copy_dscp &&
|
||||
streq(this->updown, other->updown) &&
|
||||
streq(this->interface, other->interface);
|
||||
}
|
||||
@ -673,6 +686,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
.get_hw_offload = _get_hw_offload,
|
||||
.get_copy_dscp = _get_copy_dscp,
|
||||
},
|
||||
.name = strdup(name),
|
||||
.options = data->options,
|
||||
@ -696,6 +710,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
|
||||
.replay_window = lib->settings->get_int(lib->settings,
|
||||
"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
|
||||
.hw_offload = data->hw_offload,
|
||||
.copy_dscp = data->copy_dscp,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
|
@ -191,6 +191,13 @@ struct child_cfg_t {
|
||||
*/
|
||||
hw_offload_t (*get_hw_offload) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Get the copy mode for the DS header field to use for the CHILD_SA.
|
||||
*
|
||||
* @return IP header copy mode
|
||||
*/
|
||||
dscp_copy_t (*get_copy_dscp) (child_cfg_t *this);
|
||||
|
||||
/**
|
||||
* Action to take if CHILD_SA gets closed.
|
||||
*
|
||||
@ -361,6 +368,8 @@ struct child_cfg_create_t {
|
||||
char *updown;
|
||||
/** HW offload mode */
|
||||
hw_offload_t hw_offload;
|
||||
/** How to handle the DS header field in tunnel mode */
|
||||
dscp_copy_t copy_dscp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -99,6 +99,8 @@ struct kernel_ipsec_add_sa_t {
|
||||
bool copy_df;
|
||||
/** TRUE to copy the ECN header field to/from the outer header */
|
||||
bool copy_ecn;
|
||||
/** Whether to copy the DSCP header field to/from the outer header */
|
||||
dscp_copy_t copy_dscp;
|
||||
/** TRUE if initiator of the exchange creating the SA */
|
||||
bool initiator;
|
||||
/** TRUE if this is an inbound SA */
|
||||
|
@ -1597,6 +1597,42 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
|
||||
sa->flags |= XFRM_STATE_NOECN;
|
||||
}
|
||||
|
||||
if (data->inbound)
|
||||
{
|
||||
switch (data->copy_dscp)
|
||||
{
|
||||
case DSCP_COPY_YES:
|
||||
case DSCP_COPY_IN_ONLY:
|
||||
sa->flags |= XFRM_STATE_DECAP_DSCP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (data->copy_dscp)
|
||||
{
|
||||
case DSCP_COPY_IN_ONLY:
|
||||
case DSCP_COPY_NO:
|
||||
{
|
||||
uint32_t *xflags;
|
||||
|
||||
xflags = netlink_reserve(hdr, sizeof(request),
|
||||
XFRMA_SA_EXTRA_FLAGS, sizeof(*xflags));
|
||||
if (!xflags)
|
||||
{
|
||||
goto failed;
|
||||
}
|
||||
/* currently the only extra flag */
|
||||
*xflags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE_TUNNEL:
|
||||
|
@ -536,6 +536,7 @@ static void log_child_data(child_data_t *data, char *name)
|
||||
DBG2(DBG_CFG, " sha256_96 = %u", has_opt(OPT_SHA256_96));
|
||||
DBG2(DBG_CFG, " copy_df = %u", !has_opt(OPT_NO_COPY_DF));
|
||||
DBG2(DBG_CFG, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN));
|
||||
DBG2(DBG_CFG, " copy_dscp = %N", dscp_copy_names, cfg->copy_dscp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -939,6 +940,28 @@ CALLBACK(parse_opt_copy_ecn, bool,
|
||||
return parse_option(out, OPT_NO_COPY_ECN, v, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a dscp_copy_t
|
||||
*/
|
||||
CALLBACK(parse_copy_dscp, bool,
|
||||
dscp_copy_t *out, chunk_t v)
|
||||
{
|
||||
enum_map_t map[] = {
|
||||
{ "no", DSCP_COPY_NO },
|
||||
{ "in", DSCP_COPY_IN_ONLY },
|
||||
{ "out", DSCP_COPY_OUT_ONLY },
|
||||
{ "yes", DSCP_COPY_YES },
|
||||
};
|
||||
int d;
|
||||
|
||||
if (parse_map(map, countof(map), &d, v))
|
||||
{
|
||||
*out = d;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an action_t
|
||||
*/
|
||||
@ -1623,6 +1646,7 @@ CALLBACK(child_kv, bool,
|
||||
{ "sha256_96", parse_opt_sha256_96,&child->cfg.options },
|
||||
{ "copy_df", parse_opt_copy_df, &child->cfg.options },
|
||||
{ "copy_ecn", parse_opt_copy_ecn, &child->cfg.options },
|
||||
{ "copy_dscp", parse_copy_dscp, &child->cfg.copy_dscp },
|
||||
};
|
||||
|
||||
return parse_rules(rules, countof(rules), name, value,
|
||||
|
@ -893,6 +893,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
|
||||
.esn = esn,
|
||||
.copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
|
||||
.copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
|
||||
.copy_dscp = this->config->get_copy_dscp(this->config),
|
||||
.initiator = initiator,
|
||||
.inbound = inbound,
|
||||
.update = update,
|
||||
|
@ -43,6 +43,13 @@ ENUM(hw_offload_names, HW_OFFLOAD_NO, HW_OFFLOAD_AUTO,
|
||||
"auto",
|
||||
);
|
||||
|
||||
ENUM(dscp_copy_names, DSCP_COPY_OUT_ONLY, DSCP_COPY_NO,
|
||||
"out",
|
||||
"in",
|
||||
"yes",
|
||||
"no",
|
||||
);
|
||||
|
||||
/*
|
||||
* See header
|
||||
*/
|
||||
|
@ -27,6 +27,7 @@ typedef enum policy_type_t policy_type_t;
|
||||
typedef enum policy_priority_t policy_priority_t;
|
||||
typedef enum ipcomp_transform_t ipcomp_transform_t;
|
||||
typedef enum hw_offload_t hw_offload_t;
|
||||
typedef enum dscp_copy_t dscp_copy_t;
|
||||
typedef struct ipsec_sa_cfg_t ipsec_sa_cfg_t;
|
||||
typedef struct lifetime_cfg_t lifetime_cfg_t;
|
||||
typedef struct mark_t mark_t;
|
||||
@ -131,6 +132,22 @@ enum hw_offload_t {
|
||||
*/
|
||||
extern enum_name_t *hw_offload_names;
|
||||
|
||||
/**
|
||||
* DSCP header field copy behavior (the default is not to copy from outer
|
||||
* to inner header)
|
||||
*/
|
||||
enum dscp_copy_t {
|
||||
DSCP_COPY_OUT_ONLY,
|
||||
DSCP_COPY_IN_ONLY,
|
||||
DSCP_COPY_YES,
|
||||
DSCP_COPY_NO,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum strings for dscp_copy_t.
|
||||
*/
|
||||
extern enum_name_t *dscp_copy_names;
|
||||
|
||||
/**
|
||||
* This struct contains details about IPsec SA(s) tied to a policy.
|
||||
*/
|
||||
|
@ -941,16 +941,30 @@ connections.<conn>.children.<child>.copy_df = yes
|
||||
Whether to copy the DF bit to the outer IPv4 header in tunnel mode.
|
||||
|
||||
Whether to copy the DF bit to the outer IPv4 header in tunnel mode. This
|
||||
effectively disables Path MTU discovery (PMTUD). Disabling this is not
|
||||
supported by all kernel interfaces.
|
||||
effectively disables Path MTU discovery (PMTUD). Controlling this behavior
|
||||
is not supported by all kernel interfaces.
|
||||
|
||||
connections.<conn>.children.<child>.copy_ecn = yes
|
||||
Whether to copy the ECN header field to/from the outer IP header in tunnel
|
||||
mode.
|
||||
|
||||
Whether to copy the ECN (Explicit Congestion Notification) header field
|
||||
to/from the outer IP header in tunnel mode. Disabling this is not supported
|
||||
by all kernel interfaces.
|
||||
to/from the outer IP header in tunnel mode. Controlling this behavior is not
|
||||
supported by all kernel interfaces.
|
||||
|
||||
connections.<conn>.children.<child>.copy_dscp = out
|
||||
Whether to copy the DSCP header field to/from the outer IP header in tunnel
|
||||
mode.
|
||||
|
||||
Whether to copy the DSCP (Differentiated Services Field Codepoint) header
|
||||
field to/from the outer IP header in tunnel mode. The value _out_ only
|
||||
copies the field from the inner to the outer header, the value _in_ does the
|
||||
opposite and only copies the field from the outer to the inner header when
|
||||
decapsulating, the value _yes_ copies the field in both directions, and the
|
||||
value _no_ disables copying the field altogether. Setting this to _yes_ or
|
||||
_in_ could allow an attacker to adversely affect other traffic at the
|
||||
receiver, which is why the default is _out_. Controlling this behavior is
|
||||
not supported by all kernel interfaces.
|
||||
|
||||
connections.<conn>.children.<child>.start_action = none
|
||||
Action to perform after loading the configuration (_none_, _trap_, _start_).
|
||||
|
Loading…
x
Reference in New Issue
Block a user