aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libcharon/config/child_cfg.c38
-rw-r--r--src/libcharon/config/child_cfg.h23
-rw-r--r--src/libcharon/kernel/kernel_interface.c36
-rw-r--r--src/libcharon/kernel/kernel_interface.h26
-rw-r--r--src/libcharon/kernel/kernel_ipsec.h26
-rw-r--r--src/libcharon/plugins/android/android_service.c2
-rw-r--r--src/libcharon/plugins/ha/ha_tunnel.c4
-rw-r--r--src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c27
-rw-r--r--src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c323
-rw-r--r--src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c25
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_config.c2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c6
-rw-r--r--src/libcharon/plugins/nm/nm_service.c2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c6
-rw-r--r--src/libcharon/plugins/uci/uci_config.c2
-rw-r--r--src/libcharon/sa/child_sa.c82
-rw-r--r--src/starter/args.c1
-rw-r--r--src/starter/confread.c35
-rw-r--r--src/starter/confread.h2
-rw-r--r--src/starter/keywords.h3
-rw-r--r--src/starter/keywords.txt1
-rw-r--r--src/starter/starterstroke.c2
-rw-r--r--src/stroke/stroke_msg.h4
24 files changed, 530 insertions, 150 deletions
diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c
index a33502eff..d3f688a5d 100644
--- a/src/libcharon/config/child_cfg.c
+++ b/src/libcharon/config/child_cfg.c
@@ -114,11 +114,20 @@ struct private_child_cfg_t {
u_int32_t inactivity;
/**
- * Reqid to install CHIL_SA with
+ * Reqid to install CHILD_SA with
*/
u_int32_t reqid;
/**
+ * Optional mark to install inbound CHILD_SA with
+ */
+ mark_t mark_in;
+
+ /**
+ * Optional mark to install outbound CHILD_SA with
+ */
+ mark_t mark_out;
+ /**
* set up IPsec transport SA in MIPv6 proxy mode
*/
bool proxy_mode;
@@ -461,6 +470,14 @@ static u_int32_t get_reqid(private_child_cfg_t *this)
}
/**
+ * Implementation of child_cfg_t.get_mark.
+ */
+static mark_t get_mark(private_child_cfg_t *this, bool inbound)
+{
+ return inbound ? this->mark_in : this->mark_out;
+}
+
+/**
* Implementation of child_cfg_t.set_mipv6_options.
*/
static void set_mipv6_options(private_child_cfg_t *this, bool proxy_mode,
@@ -521,7 +538,8 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp,
- u_int32_t inactivity, u_int32_t reqid)
+ u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark)
{
private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
@@ -542,6 +560,7 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
this->public.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity;
this->public.get_reqid = (u_int32_t (*) (child_cfg_t *))get_reqid;
+ this->public.get_mark = (mark_t (*) (child_cfg_t *,bool))get_mark;
this->public.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref;
@@ -556,6 +575,21 @@ child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
this->use_ipcomp = ipcomp;
this->inactivity = inactivity;
this->reqid = reqid;
+
+ /* TODO configure separate inbound and outbound marks */
+ if (mark)
+ {
+ this->mark_in = *mark;
+ this->mark_out = *mark;
+ }
+ else
+ {
+ this->mark_in.value = 0;
+ this->mark_in.mask = 0;
+ this->mark_out.value = 0;
+ this->mark_out.mask = 0;
+ }
+
this->proxy_mode = FALSE;
this->install_policy = TRUE;
this->refcount = 1;
diff --git a/src/libcharon/config/child_cfg.h b/src/libcharon/config/child_cfg.h
index db86cd6aa..a40191829 100644
--- a/src/libcharon/config/child_cfg.h
+++ b/src/libcharon/config/child_cfg.h
@@ -26,6 +26,7 @@
typedef enum action_t action_t;
typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct lifetime_cfg_t lifetime_cfg_t;
+typedef struct mark_t mark_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
@@ -83,6 +84,16 @@ struct lifetime_cfg_t {
};
/**
+ * A mark_t defines an optional mark in a CHILD_SA.
+ */
+struct mark_t {
+ /** Mark value */
+ u_int32_t value;
+ /** Mark mask */
+ u_int32_t mask;
+};
+
+/**
* A child_cfg_t defines the config template for a CHILD_SA.
*
* After creation, proposals and traffic selectors may be added to the config.
@@ -246,6 +257,14 @@ struct child_cfg_t {
u_int32_t (*get_reqid)(child_cfg_t *this);
/**
+ * Optional mark for CHILD_SA
+ *
+ * @param inbound TRUE for inbound, FALSE for outbound
+ * @return mark
+ */
+ mark_t (*get_mark)(child_cfg_t *this, bool inbound);
+
+ /**
* Sets two options needed for Mobile IPv6 interoperability
*
* @param proxy_mode use IPsec transport proxy mode (default FALSE)
@@ -307,12 +326,14 @@ struct child_cfg_t {
* @param ipcomp use IPComp, if peer supports it
* @param inactivity inactivity timeout in s before closing a CHILD_SA
* @param reqid specific reqid to use for CHILD_SA, 0 for auto assign
+ * @param mark optional mark (can be NULL)
* @return child_cfg_t object
*/
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp,
- u_int32_t inactivity, u_int32_t reqid);
+ u_int32_t inactivity, u_int32_t reqid,
+ mark_t *mark);
#endif /** CHILD_CFG_H_ @}*/
diff --git a/src/libcharon/kernel/kernel_interface.c b/src/libcharon/kernel/kernel_interface.c
index 64a43a7fc..837e628bc 100644
--- a/src/libcharon/kernel/kernel_interface.c
+++ b/src/libcharon/kernel/kernel_interface.c
@@ -67,8 +67,8 @@ METHOD(kernel_interface_t, get_cpi, status_t,
METHOD(kernel_interface_t, add_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
- lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ mark_t mark, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts)
{
@@ -77,82 +77,84 @@ METHOD(kernel_interface_t, add_sa, status_t,
return NOT_SUPPORTED;
}
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
- lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi,
- encap, inbound, src_ts, dst_ts);
+ mark, lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp,
+ cpi, encap, inbound, src_ts, dst_ts);
}
METHOD(kernel_interface_t, update_sa, status_t,
private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst,
- new_src, new_dst, encap, new_encap);
+ new_src, new_dst, encap, new_encap, mark);
}
METHOD(kernel_interface_t, query_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
- return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, bytes);
+ return this->ipsec->query_sa(this->ipsec, src, dst, spi, protocol, mark, bytes);
}
METHOD(kernel_interface_t, del_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int16_t cpi)
+ protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
- return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi);
+ return this->ipsec->del_sa(this->ipsec, src, dst, spi, protocol, cpi, mark);
}
METHOD(kernel_interface_t, add_policy, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts,
- direction, spi, protocol, reqid, mode, ipcomp, cpi, routed);
+ direction, spi, protocol, reqid, mark, mode, ipcomp, cpi, routed);
}
METHOD(kernel_interface_t, query_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts,
- direction, use_time);
+ direction, mark, use_time);
}
METHOD(kernel_interface_t, del_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
if (!this->ipsec)
{
return NOT_SUPPORTED;
}
return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts,
- direction, unrouted);
+ direction, mark, unrouted);
}
METHOD(kernel_interface_t, get_source_addr, host_t*,
diff --git a/src/libcharon/kernel/kernel_interface.h b/src/libcharon/kernel/kernel_interface.h
index 4a62e76b8..92d85f9c9 100644
--- a/src/libcharon/kernel/kernel_interface.h
+++ b/src/libcharon/kernel/kernel_interface.h
@@ -90,6 +90,7 @@ struct kernel_interface_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA
+ * @param mark optional mark for this SA
* @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption
@@ -106,7 +107,7 @@ struct kernel_interface_t {
*/
status_t (*add_sa) (kernel_interface_t *this,
host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid,
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key,
@@ -131,6 +132,7 @@ struct kernel_interface_t {
* @param new_dst new destination address
* @param encap current use of UDP encapsulation
* @param new_encap new use of UDP encapsulation
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA
*/
@@ -138,7 +140,7 @@ struct kernel_interface_t {
u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap);
+ bool encap, bool new_encap, mark_t mark);
/**
* Query the number of bytes processed by an SA from the SAD.
@@ -147,11 +149,13 @@ struct kernel_interface_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+ u_int32_t spi, protocol_id_t protocol, mark_t mark,
+ u_int64_t *bytes);
/**
* Delete a previously installed SA from the SAD.
@@ -161,10 +165,12 @@ struct kernel_interface_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ mark_t mark);
/**
* Add a policy to the SPD.
@@ -180,6 +186,7 @@ struct kernel_interface_t {
* @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
+ * @param mark mark for this policy
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp
@@ -192,8 +199,8 @@ struct kernel_interface_t {
traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed);
+ mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed);
/**
* Query the use time of a policy.
@@ -204,13 +211,15 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param[out] use_time the time of this SA's last use
* @return SUCCESS if operation completed
*/
status_t (*query_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t *use_time);
+ policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time);
/**
* Remove a policy from the SPD.
@@ -223,13 +232,14 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction,
+ policy_dir_t direction, mark_t mark,
bool unrouted);
/**
diff --git a/src/libcharon/kernel/kernel_ipsec.h b/src/libcharon/kernel/kernel_ipsec.h
index 300464cf6..d09265cc9 100644
--- a/src/libcharon/kernel/kernel_ipsec.h
+++ b/src/libcharon/kernel/kernel_ipsec.h
@@ -121,6 +121,7 @@ struct kernel_ipsec_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA
+ * @param mark mark for this SA
* @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption
@@ -138,7 +139,7 @@ struct kernel_ipsec_t {
status_t (*add_sa) (kernel_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- lifetime_cfg_t *lifetime,
+ mark_t mark, lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
@@ -162,6 +163,7 @@ struct kernel_ipsec_t {
* @param new_dst new destination address
* @param encap current use of UDP encapsulation
* @param new_encap new use of UDP encapsulation
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA
*/
@@ -169,7 +171,7 @@ struct kernel_ipsec_t {
u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst,
host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap);
+ bool encap, bool new_encap, mark_t mark);
/**
* Query the number of bytes processed by an SA from the SAD.
@@ -178,11 +180,13 @@ struct kernel_ipsec_t {
* @param dst destination address for this SA
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
+ * @param mark optional mark for this SA
* @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed
*/
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes);
+ u_int32_t spi, protocol_id_t protocol, mark_t mark,
+ u_int64_t *bytes);
/**
* Delete a previusly installed SA from the SAD.
@@ -192,10 +196,12 @@ struct kernel_ipsec_t {
* @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0
+ * @param mark optional mark for this SA
* @return SUCCESS if operation completed
*/
status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi);
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
+ mark_t mark);
/**
* Add a policy to the SPD.
@@ -211,6 +217,7 @@ struct kernel_ipsec_t {
* @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy
+ * @param mark mark for this policy
* @param mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp
@@ -223,8 +230,8 @@ struct kernel_ipsec_t {
traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed);
+ mark_t mark, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool routed);
/**
* Query the use time of a policy.
@@ -236,13 +243,15 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param[out] use_time the monotonic timestamp of this SA's last use
* @return SUCCESS if operation completed
*/
status_t (*query_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction, u_int32_t *use_time);
+ policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time);
/**
* Remove a policy from the SPD.
@@ -255,13 +264,14 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD
+ * @param mark optional mark
* @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed
*/
status_t (*del_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts,
traffic_selector_t *dst_ts,
- policy_dir_t direction,
+ policy_dir_t direction, mark_t mark,
bool unrouted);
/**
diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c
index c60aa861d..80d068c1f 100644
--- a/src/libcharon/plugins/android/android_service.c
+++ b/src/libcharon/plugins/android/android_service.c
@@ -291,7 +291,7 @@ static job_requeue_t initiate(private_android_service_t *this)
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c
index faa3b2c5b..e2807c08f 100644
--- a/src/libcharon/plugins/ha/ha_tunnel.c
+++ b/src/libcharon/plugins/ha/ha_tunnel.c
@@ -233,8 +233,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
identification_create_from_string(remote));
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
- child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE,
- MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
diff --git a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
index 01df4f71a..6b5aeb342 100644
--- a/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
+++ b/src/libcharon/plugins/kernel_klips/kernel_klips_ipsec.c
@@ -1690,10 +1690,11 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
- u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
- bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1849,7 +1850,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_klips_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1920,14 +1921,14 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
return NOT_SUPPORTED; /* TODO */
}
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1992,8 +1993,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -2210,7 +2211,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
#define IDLE_PREFIX "idle="
static const char *path_eroute = "/proc/net/ipsec_eroute";
@@ -2365,7 +2367,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg = (struct sadb_msg*)request, *out;
@@ -2574,7 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void,
{
close(this->socket);
}
- if (this->socket_evnets > 0)
+ if (this->socket_events > 0)
{
close(this->socket_events);
}
diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 1b8c1b879..019ec93f8 100644
--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -280,6 +280,9 @@ struct policy_entry_t {
/** parameters of installed policy */
struct xfrm_selector sel;
+ /** optional mark */
+ u_int32_t mark;
+
/** associated route installed for this policy */
route_entry_t *route;
@@ -292,7 +295,8 @@ struct policy_entry_t {
*/
static u_int policy_hash(policy_entry_t *key)
{
- chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+ chunk_t chunk = chunk_create((void*)&key->sel,
+ sizeof(struct xfrm_selector) + sizeof(u_int32_t));
return chunk_hash(chunk);
}
@@ -301,7 +305,8 @@ static u_int policy_hash(policy_entry_t *key)
*/
static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
{
- return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ return memeq(&key->sel, &other_key->sel,
+ sizeof(struct xfrm_selector) + sizeof(u_int32_t)) &&
key->direction == other_key->direction;
}
@@ -917,11 +922,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int32_t reqid,
+ u_int32_t spi, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
- u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
- u_int16_t cpi, bool encap, bool inbound, traffic_selector_t* src_ts,
- traffic_selector_t* dst_ts)
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{
netlink_buf_t request;
char *alg_name;
@@ -934,8 +939,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (ipcomp != IPCOMP_NONE && cpi != 0)
{
lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}};
- add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, &lft,
- ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+ add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
+ &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
mode, ipcomp, 0, FALSE, inbound, NULL, NULL);
ipcomp = IPCOMP_NONE;
/* use transport mode ESP SA, IPComp uses tunnel mode */
@@ -944,9 +949,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
- ntohl(spi), reqid);
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u} "
+ "(mark %u/0x%8x)", ntohl(spi), reqid, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}",
+ ntohl(spi), reqid);
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -1151,6 +1163,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (encap)
{
+ struct xfrm_encap_tmpl *tmpl;
+
rthdr->rta_type = XFRMA_ENCAP;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
@@ -1160,7 +1174,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
return FAILED;
}
- struct xfrm_encap_tmpl* tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr);
+ 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));
@@ -1177,9 +1191,36 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
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 += 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;
+ rthdr = XFRM_RTA_NEXT(rthdr);
+ }
+
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x "
+ "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi));
+ }
return FAILED;
}
return SUCCESS;
@@ -1275,7 +1316,7 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1285,8 +1326,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi));
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA;
@@ -1298,6 +1346,24 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
sa_id->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst);
+ 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 += 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)
{
hdr = out;
@@ -1313,8 +1379,20 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
case NLMSG_ERROR:
{
struct nlmsgerr *err = NLMSG_DATA(hdr);
- DBG1(DBG_KNL, "querying SAD entry with SPI %.8x failed: %s (%d)",
- ntohl(spi), strerror(-err->error), -err->error);
+
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+ "(mark %u/0x%8x) failed: %s (%d)",
+ ntohl(spi), mark.value, mark.mask,
+ strerror(-err->error), -err->error);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "querying SAD entry with SPI %.8x "
+ "failed: %s (%d)", ntohl(spi),
+ strerror(-err->error), -err->error);
+ }
break;
}
default:
@@ -1341,7 +1419,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
netlink_buf_t request;
struct nlmsghdr *hdr;
@@ -1350,13 +1428,20 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
/* if IPComp was used, we first delete the additional IPComp SA */
if (cpi)
{
- del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0);
+ del_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, 0, mark);
}
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi));
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELSA;
@@ -1368,19 +1453,53 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
sa_id->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst);
+ 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 += 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_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x "
+ "(mark %u/0x%8x)", ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi));
+ }
return FAILED;
}
- DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x (mark %u/0x%8x)",
+ ntohl(spi), mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi));
+ }
return SUCCESS;
}
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool old_encap, bool new_encap)
+ bool old_encap, bool new_encap, mark_t mark)
{
netlink_buf_t request;
u_char *pos;
@@ -1398,7 +1517,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
if (cpi)
{
update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0,
- src, dst, new_src, new_dst, FALSE, FALSE);
+ src, dst, new_src, new_dst, FALSE, FALSE, mark);
}
memset(&request, 0, sizeof(request));
@@ -1459,7 +1578,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
}
/* delete the old SA (without affecting the IPComp SA) */
- if (del_sa(this, src, dst, spi, protocol, 0) != SUCCESS)
+ if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS)
{
DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
free(out);
@@ -1558,8 +1677,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
policy_entry_t *current, *policy;
bool found = FALSE;
@@ -1571,6 +1690,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy = malloc_thing(policy_entry_t);
memset(policy, 0, sizeof(policy_entry_t));
policy->sel = ts2selector(src_ts, dst_ts);
+ policy->mark = mark.value & mark.mask;
policy->direction = direction;
/* find the policy, which matches EXACTLY */
@@ -1580,9 +1700,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
{
/* use existing policy */
current->refcount++;
- DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
- "refcount", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "policy %R === %R %N (mark %u/0x%8x) "
+ "already exists, increasing refcount",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "policy %R === %R %N "
+ "already exists, increasing refcount",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
free(policy);
policy = current;
found = TRUE;
@@ -1593,8 +1723,17 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy->refcount = 1;
}
- DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "adding policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "adding policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
memset(&request, 0, sizeof(request));
hdr = (struct nlmsghdr*)request;
@@ -1673,6 +1812,25 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = mode2kernel(mode);
tmpl->family = src->get_family(src);
+ 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 += 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_ack(this->socket_xfrm, hdr) != SUCCESS)
{
@@ -1741,7 +1899,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr;
@@ -1751,9 +1910,17 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
-
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "querying policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts,
+ policy_dir_names, direction);
+ }
hdr = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETPOLICY;
@@ -1763,6 +1930,25 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
policy_id->sel = ts2selector(src_ts, dst_ts);
policy_id->dir = direction;
+ 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 += 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)
{
hdr = out;
@@ -1816,7 +2002,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
policy_entry_t *current, policy, *to_delete = NULL;
route_entry_t *route;
@@ -1824,12 +2011,22 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
- DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG2(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x)",
+ src_ts, dst_ts, policy_dir_names, direction,
+ mark.value, mark.mask);
+ }
+ else
+ {
+ DBG2(DBG_KNL, "deleting policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
/* create a policy */
memset(&policy, 0, sizeof(policy_entry_t));
policy.sel = ts2selector(src_ts, dst_ts);
+ policy.mark = mark.value & mark.mask;
policy.direction = direction;
/* find the policy */
@@ -1851,8 +2048,17 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
this->mutex->unlock(this->mutex);
if (!to_delete)
{
- DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
- dst_ts, policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N (mark %u/0x%8x) "
+ "failed, not found", src_ts, dst_ts, policy_dir_names,
+ direction, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
return NOT_FOUND;
}
@@ -1867,13 +2073,40 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_id->sel = to_delete->sel;
policy_id->dir = direction;
+ 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 += 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;
+ }
+
route = to_delete->route;
free(to_delete);
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
{
- DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts,
- policy_dir_names, direction);
+ if (mark.value)
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N "
+ "(mark %u/0x%8x)", src_ts, dst_ts, policy_dir_names,
+ direction, mark.value, mark.mask);
+ }
+ else
+ {
+ DBG1(DBG_KNL, "unable to delete policy %R === %R %N",
+ src_ts, dst_ts, policy_dir_names, direction);
+ }
return FAILED;
}
diff --git a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 04abf9f4a..a64c27f6f 100644
--- a/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -1245,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi,
- protocol_id_t protocol, u_int32_t reqid, lifetime_cfg_t *lifetime,
- u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key,
- ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap,
- bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
+ protocol_id_t protocol, u_int32_t reqid, mark_t mark,
+ lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
+ u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
+ u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1392,7 +1393,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol,
u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
- bool encap, bool new_encap)
+ bool encap, bool new_encap, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1525,7 +1526,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int64_t *bytes)
+ u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1581,7 +1582,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
- u_int32_t spi, protocol_id_t protocol, u_int16_t cpi)
+ u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1632,8 +1633,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol,
- u_int32_t reqid, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
- bool routed)
+ u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
+ u_int16_t cpi, bool routed)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1834,7 +1835,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t *use_time)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ u_int32_t *use_time)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
@@ -1937,7 +1939,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts,
- traffic_selector_t *dst_ts, policy_dir_t direction, bool unrouted)
+ traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
+ bool unrouted)
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c
index b9a6f0561..528c9a31b 100644
--- a/src/libcharon/plugins/load_tester/load_tester_config.c
+++ b/src/libcharon/plugins/load_tester/load_tester_config.c
@@ -224,7 +224,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num)
}
child_cfg = child_cfg_create("load-test", &lifetime, NULL, TRUE,
- MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal);
ts = traffic_selector_create_dynamic(0, 0, 65535);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 7b9b5aa40..e57491044 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -181,8 +181,8 @@ static peer_cfg_t *get_peer_cfg_by_name(private_medcli_config_t *this, char *nam
identification_create_from_encoding(ID_KEY_ID, other));
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
- child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE,
- MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
@@ -260,7 +260,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->current->add_auth_cfg(this->current, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c
index d9badec77..20e6c1529 100644
--- a/src/libcharon/plugins/nm/nm_service.c
+++ b/src/libcharon/plugins/nm/nm_service.c
@@ -444,7 +444,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg = child_cfg_create(priv->name, &lifetime,
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */
- ACTION_NONE, ACTION_NONE, ipcomp, 0, 0);
+ ACTION_NONE, ACTION_NONE, ipcomp, 0, 0, NULL);
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index 8893beaad..d9964cea8 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -134,7 +134,7 @@ static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
.time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
};
child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
- dpd, close, ipcomp, 0, 0);
+ dpd, close, ipcomp, 0, 0, NULL);
/* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id);
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index c86d1457a..41bf5d1a1 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -769,6 +769,10 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
.jitter = msg->add_conn.rekey.margin_packets * msg->add_conn.rekey.fuzz / 100
}
};
+ mark_t mark = {
+ .value = msg->add_conn.mark.value,
+ .mask = msg->add_conn.mark.mask
+ };
switch (msg->add_conn.dpd.action)
{ /* map startes magic values to our action type */
@@ -787,7 +791,7 @@ static child_cfg_t *build_child_cfg(private_stroke_config_t *this,
msg->add_conn.name, &lifetime,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp,
- msg->add_conn.inactivity, msg->add_conn.reqid);
+ msg->add_conn.inactivity, msg->add_conn.reqid, &mark);
child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c
index 00d05c401..ba93d8734 100644
--- a/src/libcharon/plugins/uci/uci_config.c
+++ b/src/libcharon/plugins/uci/uci_config.c
@@ -196,7 +196,7 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
- ACTION_NONE, ACTION_NONE, FALSE, 0, 0);
+ ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
child_cfg->add_proposal(child_cfg, create_proposal(esp_proposal, PROTO_ESP));
child_cfg->add_traffic_selector(child_cfg, TRUE, create_ts(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index fb1ed3407..bd41cba56 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -98,6 +98,16 @@ struct private_child_sa_t {
u_int32_t reqid;
/**
+ * inbound mark used for this child_sa
+ */
+ mark_t mark_in;
+
+ /**
+ * outbound mark used for this child_sa
+ */
+ mark_t mark_out;
+
+ /**
* absolute time when rekeying is scheduled
*/
time_t rekey_time;
@@ -431,10 +441,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->my_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->other_addr, this->my_addr,
- this->my_spi, this->protocol, &bytes);
+ this->my_spi, this->protocol,
+ this->mark_in, &bytes);
if (status == SUCCESS)
{
if (bytes > this->my_usebytes)
@@ -450,10 +460,10 @@ static status_t update_usebytes(private_child_sa_t *this, bool inbound)
{
if (this->other_spi)
{
- status = charon->kernel_interface->query_sa(
- charon->kernel_interface,
+ status = charon->kernel_interface->query_sa(charon->kernel_interface,
this->my_addr, this->other_addr,
- this->other_spi, this->protocol, &bytes);
+ this->other_spi, this->protocol,
+ this->mark_out, &bytes);
if (status == SUCCESS)
{
if (bytes > this->other_usebytes)
@@ -485,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
if (inbound)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, &in) == SUCCESS)
+ other_ts, my_ts, POLICY_IN, this->mark_in, &in) == SUCCESS)
{
last_use = max(last_use, in);
}
if (this->mode != MODE_TRANSPORT)
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, &fwd) == SUCCESS)
+ other_ts, my_ts, POLICY_FWD, this->mark_in, &fwd) == SUCCESS)
{
last_use = max(last_use, fwd);
}
@@ -501,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
else
{
if (charon->kernel_interface->query_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, &out) == SUCCESS)
+ my_ts, other_ts, POLICY_OUT, this->mark_out, &out) == SUCCESS)
{
last_use = max(last_use, out);
}
@@ -665,9 +675,10 @@ static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
}
status = charon->kernel_interface->add_sa(charon->kernel_interface,
- src, dst, spi, this->protocol, this->reqid, lifetime,
- enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi,
- this->encap, update, src_ts, dst_ts);
+ src, dst, spi, this->protocol, this->reqid,
+ inbound ? this->mark_in : this->mark_out,
+ lifetime, enc_alg, encr, int_alg, integ, this->mode,
+ this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
free(lifetime);
@@ -708,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
- this->other_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->other_cpi, routed);
+ this->other_spi, this->protocol, this->reqid, this->mark_out,
+ this->mode, this->ipcomp, this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
if (this->mode != MODE_TRANSPORT)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
- this->my_spi, this->protocol, this->reqid, this->mode,
- this->ipcomp, this->my_cpi, routed);
+ this->my_spi, this->protocol, this->reqid, this->mark_in,
+ this->mode, this->ipcomp, this->my_cpi, routed);
}
if (status != SUCCESS)
@@ -768,7 +779,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->my_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
this->other_addr, this->my_addr, other, me,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_in) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -781,7 +792,7 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
this->other_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
this->my_addr, this->other_addr, me, other,
- this->encap, encap) == NOT_SUPPORTED)
+ this->encap, encap, this->mark_out) == NOT_SUPPORTED)
{
return NOT_SUPPORTED;
}
@@ -803,13 +814,13 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
{
/* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, FALSE);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, FALSE);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, FALSE);
+ other_ts, my_ts, POLICY_IN, this->mark_in, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, FALSE);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, FALSE);
}
/* check whether we have to update a "dynamic" traffic selector */
@@ -835,18 +846,18 @@ static status_t update(private_child_sa_t *this, host_t *me, host_t *other,
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->other_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_out, this->mode,
+ this->ipcomp, this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
- this->protocol, this->reqid, this->mode, this->ipcomp,
- this->my_cpi, FALSE);
+ this->protocol, this->reqid, this->mark_in, this->mode,
+ this->ipcomp, this->my_cpi, FALSE);
}
}
enumerator->destroy(enumerator);
@@ -896,13 +907,13 @@ static void destroy(private_child_sa_t *this)
}
charon->kernel_interface->del_sa(charon->kernel_interface,
this->other_addr, this->my_addr, this->my_spi,
- this->protocol, this->my_cpi);
+ this->protocol, this->my_cpi, this->mark_in);
}
if (this->other_spi)
{
charon->kernel_interface->del_sa(charon->kernel_interface,
this->my_addr, this->other_addr, this->other_spi,
- this->protocol, this->other_cpi);
+ this->protocol, this->other_cpi, this->mark_out);
}
if (this->config->install_policy(this->config))
@@ -912,13 +923,13 @@ static void destroy(private_child_sa_t *this)
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- my_ts, other_ts, POLICY_OUT, unrouted);
+ my_ts, other_ts, POLICY_OUT, this->mark_out, unrouted);
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_IN, unrouted);
+ other_ts, my_ts, POLICY_IN, this->mark_in, unrouted);
if (this->mode != MODE_TRANSPORT)
{
charon->kernel_interface->del_policy(charon->kernel_interface,
- other_ts, my_ts, POLICY_FWD, unrouted);
+ other_ts, my_ts, POLICY_FWD, this->mark_in, unrouted);
}
}
enumerator->destroy(enumerator);
@@ -1000,6 +1011,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->config = config;
config->get_ref(config);
this->reqid = config->get_reqid(config);
+ this->mark_in = config->get_mark(config, TRUE);
+ this->mark_out = config->get_mark(config, FALSE);
+
if (!this->reqid)
{
/* reuse old reqid if we are rekeying an existing CHILD_SA */
diff --git a/src/starter/args.c b/src/starter/args.c
index 26f3aaef4..4fe9c9d27 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -235,6 +235,7 @@ static const token_info_t token_info[] =
{ ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL },
{ ARG_STR, offsetof(starter_conn_t, me_peerid), NULL },
{ ARG_UINT, offsetof(starter_conn_t, reqid), NULL },
+ { ARG_MISC, 0, NULL /* KW_MARK */ },
/* ca section keywords */
{ ARG_STR, offsetof(starter_ca_t, name), NULL },
diff --git a/src/starter/confread.c b/src/starter/confread.c
index e9b9028d5..6ebdaf58b 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -671,6 +671,41 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
}
break;
}
+ case KW_MARK:
+ {
+ char *pos, *endptr;
+
+ pos = strchr(kw->value, '/');
+ if (pos)
+ {
+ *pos = '\0';
+ conn->mark_mask = strtoul(pos+1, &endptr, 0);
+ if (*endptr != '\0')
+ {
+ plog("# invalid mark mask: %s", pos+1);
+ cfg->err++;
+ break;
+ }
+ }
+ else
+ {
+ conn->mark_mask = 0xffffffff;
+ }
+ if (*kw->value == '\0')
+ {
+ conn->mark_value = 0;
+ }
+ else
+ {
+ conn->mark_value = strtoul(kw->value, &endptr, 0);
+ if (*endptr != '\0')
+ {
+ plog("# invalid mark value: %s", kw->value);
+ cfg->err++;
+ }
+ }
+ break;
+ }
case KW_KEYINGTRIES:
if (streq(kw->value, "%forever"))
{
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 5d845c2b9..ada155d7a 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -122,6 +122,8 @@ struct starter_conn {
unsigned long sa_keying_tries;
unsigned long sa_rekey_fuzz;
u_int32_t reqid;
+ u_int32_t mark_value;
+ u_int32_t mark_mask;
sa_family_t addr_family;
sa_family_t tunnel_addr_family;
bool install_policy;
diff --git a/src/starter/keywords.h b/src/starter/keywords.h
index 85b847230..ea702fdbc 100644
--- a/src/starter/keywords.h
+++ b/src/starter/keywords.h
@@ -98,9 +98,10 @@ typedef enum {
KW_MEDIATED_BY,
KW_ME_PEERID,
KW_REQID,
+ KW_MARK,
#define KW_CONN_FIRST KW_CONN_SETUP
-#define KW_CONN_LAST KW_REQID
+#define KW_CONN_LAST KW_MARK
/* ca section keywords */
KW_CA_NAME,
diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt
index 894e1e94f..a9d2af42a 100644
--- a/src/starter/keywords.txt
+++ b/src/starter/keywords.txt
@@ -89,6 +89,7 @@ mediation, KW_MEDIATION
mediated_by, KW_MEDIATED_BY
me_peerid, KW_ME_PEERID
reqid, KW_REQID
+mark, KW_MARK
cacert, KW_CACERT
ldaphost, KW_LDAPHOST
ldapbase, KW_LDAPBASE
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 6a5000761..475f07c74 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -270,6 +270,8 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
msg.add_conn.ikeme.mediated_by = push_string(&msg, conn->me_mediated_by);
msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid);
msg.add_conn.reqid = conn->reqid;
+ msg.add_conn.mark.value = conn->mark_value;
+ msg.add_conn.mark.mask = conn->mark_mask;
starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left);
starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index b20dd22e3..e33737bbc 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -256,6 +256,10 @@ struct stroke_msg_t {
char *mediated_by;
char *peerid;
} ikeme;
+ struct {
+ u_int32_t value;
+ u_int32_t mask;
+ } mark;
stroke_end_t me, other;
} add_conn;