From ee26c537d7f78e16a1c94bcb933aca853f96bd3d Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Fri, 2 Jul 2010 23:45:57 +0200 Subject: [PATCH] support of xfrm marks for IKEv2 --- src/libcharon/config/child_cfg.c | 38 ++- src/libcharon/config/child_cfg.h | 23 +- src/libcharon/kernel/kernel_interface.c | 36 +- src/libcharon/kernel/kernel_interface.h | 26 +- src/libcharon/kernel/kernel_ipsec.h | 26 +- .../plugins/android/android_service.c | 2 +- src/libcharon/plugins/ha/ha_tunnel.c | 4 +- .../plugins/kernel_klips/kernel_klips_ipsec.c | 27 +- .../kernel_netlink/kernel_netlink_ipsec.c | 323 +++++++++++++++--- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 25 +- .../plugins/load_tester/load_tester_config.c | 2 +- src/libcharon/plugins/medcli/medcli_config.c | 6 +- src/libcharon/plugins/nm/nm_service.c | 2 +- src/libcharon/plugins/sql/sql_config.c | 2 +- src/libcharon/plugins/stroke/stroke_config.c | 6 +- src/libcharon/plugins/uci/uci_config.c | 2 +- src/libcharon/sa/child_sa.c | 82 +++-- src/starter/args.c | 1 + src/starter/confread.c | 35 ++ src/starter/confread.h | 2 + src/starter/keywords.h | 3 +- src/starter/keywords.txt | 1 + src/starter/starterstroke.c | 2 + src/stroke/stroke_msg.h | 4 + 24 files changed, 530 insertions(+), 150 deletions(-) diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index a33502eff7..d3f688a5d4 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -114,10 +114,19 @@ 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 */ @@ -460,6 +469,14 @@ static u_int32_t get_reqid(private_child_cfg_t *this) return this->reqid; } +/** + * 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. */ @@ -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 db86cd6aad..a401918294 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 @@ -82,6 +83,16 @@ struct lifetime_cfg_t { } time, bytes, packets; }; +/** + * 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. * @@ -245,6 +256,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 * @@ -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 64a43a7fca..837e628bca 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 4a62e76b85..92d85f9c90 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 300464cf66..d09265cc93 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 c60aa861da..80d068c1f2 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 faa3b2c5bb..e2807c08ff 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 01df4f71a5..6b5aeb3420 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 1b8c1b879e..019ec93f86 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 04abf9f4a3..a64c27f6f3 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 b9a6f0561a..528c9a31b2 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 7b9b5aa408..e574910444 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 d9badec770..20e6c15291 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 8893beaad6..d9964cea87 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 c86d1457a5..41bf5d1a1a 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 00d05c4017..ba93d87345 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 fb1ed34077..bd41cba56f 100644 --- a/src/libcharon/sa/child_sa.c +++ b/src/libcharon/sa/child_sa.c @@ -97,6 +97,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 */ @@ -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 26f3aaef44..4fe9c9d27b 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 e9b9028d5c..6ebdaf58b0 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 5d845c2b96..ada155d7a1 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 85b8472305..ea702fdbc7 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 894e1e94fa..a9d2af42a5 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 6a50007610..475f07c745 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 b20dd22e31..e33737bbc1 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; -- 2.39.5