* 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*,
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)
{
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);
}
.get_ref = _get_ref,
.destroy = _destroy,
.get_hw_offload = _get_hw_offload,
+ .get_copy_dscp = _get_copy_dscp,
},
.name = strdup(name),
.options = data->options,
.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;
*/
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.
*
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;
};
/**
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 */
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:
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);
}
/**
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
*/
{ "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,
.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,
"auto",
);
+ENUM(dscp_copy_names, DSCP_COPY_OUT_ONLY, DSCP_COPY_NO,
+ "out",
+ "in",
+ "yes",
+ "no",
+);
+
/*
* See header
*/
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;
*/
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.
*/
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_).