support of xfrm marks for IKEv2

This commit is contained in:
Andreas Steffen
2010-07-02 23:46:09 +02:00
parent 02571374c4
commit ee26c537d7
24 changed files with 530 additions and 150 deletions
+36 -2
View File
@@ -114,10 +114,19 @@ struct private_child_cfg_t {
u_int32_t inactivity; u_int32_t inactivity;
/** /**
* Reqid to install CHIL_SA with * Reqid to install CHILD_SA with
*/ */
u_int32_t reqid; 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 * 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; 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. * 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, char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action, ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp, 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); 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.use_ipcomp = (bool (*) (child_cfg_t *))use_ipcomp;
this->public.get_inactivity = (u_int32_t (*) (child_cfg_t *))get_inactivity; 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_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.use_proxy_mode = (bool (*) (child_cfg_t *))use_proxy_mode;
this->public.install_policy = (bool (*) (child_cfg_t *))install_policy; this->public.install_policy = (bool (*) (child_cfg_t *))install_policy;
this->public.get_ref = (child_cfg_t* (*) (child_cfg_t*))get_ref; 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->use_ipcomp = ipcomp;
this->inactivity = inactivity; this->inactivity = inactivity;
this->reqid = reqid; 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->proxy_mode = FALSE;
this->install_policy = TRUE; this->install_policy = TRUE;
this->refcount = 1; this->refcount = 1;
+22 -1
View File
@@ -26,6 +26,7 @@
typedef enum action_t action_t; typedef enum action_t action_t;
typedef enum ipcomp_transform_t ipcomp_transform_t; typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct lifetime_cfg_t lifetime_cfg_t; typedef struct lifetime_cfg_t lifetime_cfg_t;
typedef struct mark_t mark_t;
typedef struct child_cfg_t child_cfg_t; typedef struct child_cfg_t child_cfg_t;
#include <library.h> #include <library.h>
@@ -82,6 +83,16 @@ struct lifetime_cfg_t {
} time, bytes, packets; } 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. * 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); 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 * 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 ipcomp use IPComp, if peer supports it
* @param inactivity inactivity timeout in s before closing a CHILD_SA * @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 reqid specific reqid to use for CHILD_SA, 0 for auto assign
* @param mark optional mark (can be NULL)
* @return child_cfg_t object * @return child_cfg_t object
*/ */
child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime, child_cfg_t *child_cfg_create(char *name, lifetime_cfg_t *lifetime,
char *updown, bool hostaccess, char *updown, bool hostaccess,
ipsec_mode_t mode, action_t dpd_action, ipsec_mode_t mode, action_t dpd_action,
action_t close_action, bool ipcomp, 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_ @}*/ #endif /** CHILD_CFG_H_ @}*/
+19 -17
View File
@@ -67,8 +67,8 @@ METHOD(kernel_interface_t, get_cpi, status_t,
METHOD(kernel_interface_t, add_sa, status_t, METHOD(kernel_interface_t, add_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, private_kernel_interface_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,
lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, 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 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, u_int16_t cpi, bool encap, bool inbound, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts) traffic_selector_t *dst_ts)
{ {
@@ -77,82 +77,84 @@ METHOD(kernel_interface_t, add_sa, status_t,
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid, return this->ipsec->add_sa(this->ipsec, src, dst, spi, protocol, reqid,
lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp, cpi, mark, lifetime, enc_alg, enc_key, int_alg, int_key, mode, ipcomp,
encap, inbound, src_ts, dst_ts); cpi, encap, inbound, src_ts, dst_ts);
} }
METHOD(kernel_interface_t, update_sa, status_t, METHOD(kernel_interface_t, update_sa, status_t,
private_kernel_interface_t *this, u_int32_t spi, protocol_id_t protocol, 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, 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) if (!this->ipsec)
{ {
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
return this->ipsec->update_sa(this->ipsec, spi, protocol, cpi, src, dst, 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, METHOD(kernel_interface_t, query_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, 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) if (!this->ipsec)
{ {
return NOT_SUPPORTED; 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, METHOD(kernel_interface_t, del_sa, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, u_int32_t spi, 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) if (!this->ipsec)
{ {
return NOT_SUPPORTED; 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, METHOD(kernel_interface_t, add_policy, status_t,
private_kernel_interface_t *this, host_t *src, host_t *dst, private_kernel_interface_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts, traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, 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, u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
bool routed) u_int16_t cpi, bool routed)
{ {
if (!this->ipsec) if (!this->ipsec)
{ {
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
return this->ipsec->add_policy(this->ipsec, src, dst, src_ts, dst_ts, 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, METHOD(kernel_interface_t, query_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts, 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) if (!this->ipsec)
{ {
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
return this->ipsec->query_policy(this->ipsec, src_ts, dst_ts, 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, METHOD(kernel_interface_t, del_policy, status_t,
private_kernel_interface_t *this, traffic_selector_t *src_ts, 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) if (!this->ipsec)
{ {
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
return this->ipsec->del_policy(this->ipsec, src_ts, dst_ts, 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*, METHOD(kernel_interface_t, get_source_addr, host_t*,
+18 -8
View File
@@ -90,6 +90,7 @@ struct kernel_interface_t {
* @param spi SPI allocated by us or remote peer * @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA * @param reqid unique ID for this SA
* @param mark optional mark for this SA
* @param lifetime lifetime_cfg_t for this SA * @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption * @param enc_key key to use for encryption
@@ -106,7 +107,7 @@ struct kernel_interface_t {
*/ */
status_t (*add_sa) (kernel_interface_t *this, status_t (*add_sa) (kernel_interface_t *this,
host_t *src, host_t *dst, u_int32_t spi, 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, lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_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 new_dst new destination address
* @param encap current use of UDP encapsulation * @param encap current use of UDP encapsulation
* @param new_encap new 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 * @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA * 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, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst, host_t *src, host_t *dst,
host_t *new_src, host_t *new_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. * 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 dst destination address for this SA
* @param spi SPI allocated by us or remote peer * @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @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 * @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*query_sa) (kernel_interface_t *this, host_t *src, host_t *dst, 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. * 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 spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0 * @param cpi CPI for IPComp or 0
* @param mark optional mark for this SA
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*del_sa) (kernel_interface_t *this, host_t *src, host_t *dst, 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. * Add a policy to the SPD.
@@ -180,6 +186,7 @@ struct kernel_interface_t {
* @param spi SPI of SA * @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP) * @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy * @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 mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used * @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp * @param cpi CPI for IPComp
@@ -192,8 +199,8 @@ struct kernel_interface_t {
traffic_selector_t *dst_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
bool routed); u_int16_t cpi, bool routed);
/** /**
* Query the use time of a policy. * 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 src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest * @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD * @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 * @param[out] use_time the time of this SA's last use
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*query_policy) (kernel_interface_t *this, status_t (*query_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts, traffic_selector_t *src_ts,
traffic_selector_t *dst_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. * Remove a policy from the SPD.
@@ -223,13 +232,14 @@ struct kernel_interface_t {
* @param src_ts traffic selector to match traffic source * @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest * @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD * @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 * @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*del_policy) (kernel_interface_t *this, status_t (*del_policy) (kernel_interface_t *this,
traffic_selector_t *src_ts, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, policy_dir_t direction, mark_t mark,
bool unrouted); bool unrouted);
/** /**
+18 -8
View File
@@ -121,6 +121,7 @@ struct kernel_ipsec_t {
* @param spi SPI allocated by us or remote peer * @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @param protocol protocol for this SA (ESP/AH)
* @param reqid unique ID for this SA * @param reqid unique ID for this SA
* @param mark mark for this SA
* @param lifetime lifetime_cfg_t for this SA * @param lifetime lifetime_cfg_t for this SA
* @param enc_alg Algorithm to use for encryption (ESP only) * @param enc_alg Algorithm to use for encryption (ESP only)
* @param enc_key key to use for encryption * @param enc_key key to use for encryption
@@ -138,7 +139,7 @@ struct kernel_ipsec_t {
status_t (*add_sa) (kernel_ipsec_t *this, status_t (*add_sa) (kernel_ipsec_t *this,
host_t *src, host_t *dst, u_int32_t spi, 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,
lifetime_cfg_t *lifetime, mark_t mark, lifetime_cfg_t *lifetime,
u_int16_t enc_alg, chunk_t enc_key, u_int16_t enc_alg, chunk_t enc_key,
u_int16_t int_alg, chunk_t int_key, u_int16_t int_alg, chunk_t int_key,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, 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 new_dst new destination address
* @param encap current use of UDP encapsulation * @param encap current use of UDP encapsulation
* @param new_encap new 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 * @return SUCCESS if operation completed, NOT_SUPPORTED if
* the kernel interface can't update the SA * 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, u_int32_t spi, protocol_id_t protocol, u_int16_t cpi,
host_t *src, host_t *dst, host_t *src, host_t *dst,
host_t *new_src, host_t *new_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. * 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 dst destination address for this SA
* @param spi SPI allocated by us or remote peer * @param spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @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 * @param[out] bytes the number of bytes processed by SA
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*query_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, 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. * 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 spi SPI allocated by us or remote peer
* @param protocol protocol for this SA (ESP/AH) * @param protocol protocol for this SA (ESP/AH)
* @param cpi CPI for IPComp or 0 * @param cpi CPI for IPComp or 0
* @param mark optional mark for this SA
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*del_sa) (kernel_ipsec_t *this, host_t *src, host_t *dst, 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. * Add a policy to the SPD.
@@ -211,6 +217,7 @@ struct kernel_ipsec_t {
* @param spi SPI of SA * @param spi SPI of SA
* @param protocol protocol to use to protect traffic (AH/ESP) * @param protocol protocol to use to protect traffic (AH/ESP)
* @param reqid unique ID of an SA to use to enforce policy * @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 mode mode of SA (tunnel, transport)
* @param ipcomp the IPComp transform used * @param ipcomp the IPComp transform used
* @param cpi CPI for IPComp * @param cpi CPI for IPComp
@@ -223,8 +230,8 @@ struct kernel_ipsec_t {
traffic_selector_t *dst_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, policy_dir_t direction, u_int32_t spi,
protocol_id_t protocol, u_int32_t reqid, protocol_id_t protocol, u_int32_t reqid,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, mark_t mark, ipsec_mode_t mode,
bool routed); u_int16_t ipcomp, u_int16_t cpi, bool routed);
/** /**
* Query the use time of a policy. * 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 src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest * @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD * @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 * @param[out] use_time the monotonic timestamp of this SA's last use
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*query_policy) (kernel_ipsec_t *this, status_t (*query_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts, traffic_selector_t *src_ts,
traffic_selector_t *dst_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. * Remove a policy from the SPD.
@@ -255,13 +264,14 @@ struct kernel_ipsec_t {
* @param src_ts traffic selector to match traffic source * @param src_ts traffic selector to match traffic source
* @param dst_ts traffic selector to match traffic dest * @param dst_ts traffic selector to match traffic dest
* @param direction direction of traffic, POLICY_IN, POLICY_OUT, POLICY_FWD * @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 * @param unrouted TRUE, if this policy is unrouted from the kernel
* @return SUCCESS if operation completed * @return SUCCESS if operation completed
*/ */
status_t (*del_policy) (kernel_ipsec_t *this, status_t (*del_policy) (kernel_ipsec_t *this,
traffic_selector_t *src_ts, traffic_selector_t *src_ts,
traffic_selector_t *dst_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, policy_dir_t direction, mark_t mark,
bool unrouted); bool unrouted);
/** /**
@@ -291,7 +291,7 @@ static job_requeue_t initiate(private_android_service_t *this)
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL, 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)); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535); ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts); child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+2 -2
View File
@@ -233,8 +233,8 @@ static void setup_tunnel(private_ha_tunnel_t *this,
identification_create_from_string(remote)); identification_create_from_string(remote));
peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE);
child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, child_cfg = child_cfg_create("ha", &lifetime, NULL, TRUE, MODE_TRANSPORT,
MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE, 0, 0); ACTION_NONE, ACTION_NONE, FALSE, 0, 0, NULL);
ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT); ts = traffic_selector_create_dynamic(IPPROTO_UDP, HA_PORT, HA_PORT);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts); child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535); ts = traffic_selector_create_dynamic(IPPROTO_ICMP, 0, 65535);
@@ -1690,10 +1690,11 @@ static status_t group_ipip_sa(private_kernel_klips_ipsec_t *this,
METHOD(kernel_ipsec_t, add_sa, status_t, METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, 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, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_klips_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, 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, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, 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 */ return NOT_SUPPORTED; /* TODO */
} }
METHOD(kernel_ipsec_t, del_sa, status_t, METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, private_kernel_klips_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts, traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, 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, u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
bool routed) u_int16_t cpi, bool routed)
{ {
unsigned char request[PFKEY_BUFFER_SIZE]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts, 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=" #define IDLE_PREFIX "idle="
static const char *path_eroute = "/proc/net/ipsec_eroute"; 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, METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_klips_ipsec_t *this, traffic_selector_t *src_ts, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg = (struct sadb_msg*)request, *out; struct sadb_msg *msg = (struct sadb_msg*)request, *out;
@@ -2574,7 +2577,7 @@ METHOD(kernel_ipsec_t, destroy, void,
{ {
close(this->socket); close(this->socket);
} }
if (this->socket_evnets > 0) if (this->socket_events > 0)
{ {
close(this->socket_events); close(this->socket_events);
} }
@@ -280,6 +280,9 @@ struct policy_entry_t {
/** parameters of installed policy */ /** parameters of installed policy */
struct xfrm_selector sel; struct xfrm_selector sel;
/** optional mark */
u_int32_t mark;
/** associated route installed for this policy */ /** associated route installed for this policy */
route_entry_t *route; route_entry_t *route;
@@ -292,7 +295,8 @@ struct policy_entry_t {
*/ */
static u_int policy_hash(policy_entry_t *key) 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); 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) 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; 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, METHOD(kernel_ipsec_t, add_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, 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, 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 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, u_int16_t cpi, bool encap, bool inbound,
traffic_selector_t* dst_ts) traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{ {
netlink_buf_t request; netlink_buf_t request;
char *alg_name; char *alg_name;
@@ -934,8 +939,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (ipcomp != IPCOMP_NONE && cpi != 0) if (ipcomp != IPCOMP_NONE && cpi != 0)
{ {
lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,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, add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark,
ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty,
mode, ipcomp, 0, FALSE, inbound, NULL, NULL); mode, ipcomp, 0, FALSE, inbound, NULL, NULL);
ipcomp = IPCOMP_NONE; ipcomp = IPCOMP_NONE;
/* use transport mode ESP SA, IPComp uses tunnel mode */ /* 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)); memset(&request, 0, sizeof(request));
DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", if (mark.value)
ntohl(spi), reqid); {
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 = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; hdr->nlmsg_type = inbound ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA;
@@ -1151,6 +1163,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
if (encap) if (encap)
{ {
struct xfrm_encap_tmpl *tmpl;
rthdr->rta_type = XFRMA_ENCAP; rthdr->rta_type = XFRMA_ENCAP;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
@@ -1160,7 +1174,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
return FAILED; 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_type = UDP_ENCAP_ESPINUDP;
tmpl->encap_sport = htons(src->get_port(src)); tmpl->encap_sport = htons(src->get_port(src));
tmpl->encap_dport = htons(dst->get_port(dst)); 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); 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) 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 FAILED;
} }
return SUCCESS; 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, METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, 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; netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr; struct nlmsghdr *out = NULL, *hdr;
@@ -1285,8 +1326,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
memset(&request, 0, sizeof(request)); 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 = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETSA; 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->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst); 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) if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
{ {
hdr = out; hdr = out;
@@ -1313,8 +1379,20 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
case NLMSG_ERROR: case NLMSG_ERROR:
{ {
struct nlmsgerr *err = NLMSG_DATA(hdr); 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; break;
} }
default: default:
@@ -1341,7 +1419,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
METHOD(kernel_ipsec_t, del_sa, status_t, METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, 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; netlink_buf_t request;
struct nlmsghdr *hdr; 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 IPComp was used, we first delete the additional IPComp SA */
if (cpi) 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)); 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 = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_DELSA; 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->proto = proto_ike2kernel(protocol);
sa_id->family = dst->get_family(dst); 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) 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; 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; return SUCCESS;
} }
METHOD(kernel_ipsec_t, update_sa, status_t, METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_netlink_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, 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, 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; netlink_buf_t request;
u_char *pos; u_char *pos;
@@ -1398,7 +1517,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
if (cpi) if (cpi)
{ {
update_sa(this, htonl(ntohs(cpi)), IPPROTO_COMP, 0, 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)); 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) */ /* 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)); DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi));
free(out); 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, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts, traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, 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, u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
bool routed) u_int16_t cpi, bool routed)
{ {
policy_entry_t *current, *policy; policy_entry_t *current, *policy;
bool found = FALSE; bool found = FALSE;
@@ -1571,6 +1690,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy = malloc_thing(policy_entry_t); policy = malloc_thing(policy_entry_t);
memset(policy, 0, sizeof(policy_entry_t)); memset(policy, 0, sizeof(policy_entry_t));
policy->sel = ts2selector(src_ts, dst_ts); policy->sel = ts2selector(src_ts, dst_ts);
policy->mark = mark.value & mark.mask;
policy->direction = direction; policy->direction = direction;
/* find the policy, which matches EXACTLY */ /* find the policy, which matches EXACTLY */
@@ -1580,9 +1700,19 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
{ {
/* use existing policy */ /* use existing policy */
current->refcount++; current->refcount++;
DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " if (mark.value)
"refcount", src_ts, dst_ts, {
policy_dir_names, direction); 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); free(policy);
policy = current; policy = current;
found = TRUE; found = TRUE;
@@ -1593,8 +1723,17 @@ METHOD(kernel_ipsec_t, add_policy, status_t,
policy->refcount = 1; policy->refcount = 1;
} }
DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts, if (mark.value)
policy_dir_names, direction); {
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)); memset(&request, 0, sizeof(request));
hdr = (struct nlmsghdr*)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->aalgos = tmpl->ealgos = tmpl->calgos = ~0;
tmpl->mode = mode2kernel(mode); tmpl->mode = mode2kernel(mode);
tmpl->family = src->get_family(src); 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) 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, METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts, 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; netlink_buf_t request;
struct nlmsghdr *out = NULL, *hdr; struct nlmsghdr *out = NULL, *hdr;
@@ -1751,9 +1910,17 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
memset(&request, 0, sizeof(request)); memset(&request, 0, sizeof(request));
DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts, if (mark.value)
policy_dir_names, direction); {
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 = (struct nlmsghdr*)request;
hdr->nlmsg_flags = NLM_F_REQUEST; hdr->nlmsg_flags = NLM_F_REQUEST;
hdr->nlmsg_type = XFRM_MSG_GETPOLICY; 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->sel = ts2selector(src_ts, dst_ts);
policy_id->dir = direction; 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) if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
{ {
hdr = out; hdr = out;
@@ -1816,7 +2002,8 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
METHOD(kernel_ipsec_t, del_policy, status_t, METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_netlink_ipsec_t *this, traffic_selector_t *src_ts, 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; policy_entry_t *current, policy, *to_delete = NULL;
route_entry_t *route; route_entry_t *route;
@@ -1824,12 +2011,22 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
struct nlmsghdr *hdr; struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id; struct xfrm_userpolicy_id *policy_id;
DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts, if (mark.value)
policy_dir_names, direction); {
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 */ /* create a policy */
memset(&policy, 0, sizeof(policy_entry_t)); memset(&policy, 0, sizeof(policy_entry_t));
policy.sel = ts2selector(src_ts, dst_ts); policy.sel = ts2selector(src_ts, dst_ts);
policy.mark = mark.value & mark.mask;
policy.direction = direction; policy.direction = direction;
/* find the policy */ /* find the policy */
@@ -1851,8 +2048,17 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);
if (!to_delete) if (!to_delete)
{ {
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts, if (mark.value)
dst_ts, policy_dir_names, direction); {
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; return NOT_FOUND;
} }
@@ -1867,13 +2073,40 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
policy_id->sel = to_delete->sel; policy_id->sel = to_delete->sel;
policy_id->dir = direction; 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; route = to_delete->route;
free(to_delete); free(to_delete);
if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) 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, if (mark.value)
policy_dir_names, direction); {
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; return FAILED;
} }
@@ -1245,10 +1245,11 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
METHOD(kernel_ipsec_t, add_sa, 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, 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, protocol_id_t protocol, u_int32_t reqid, mark_t mark,
u_int16_t enc_alg, chunk_t enc_key, u_int16_t int_alg, chunk_t int_key, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, bool encap, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode,
bool inbound, traffic_selector_t *src_ts, traffic_selector_t *dst_ts) 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, update_sa, status_t,
private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, 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, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, query_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, del_sa, status_t,
private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst,
traffic_selector_t *src_ts, traffic_selector_t *dst_ts, traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, 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, u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp,
bool routed) u_int16_t cpi, bool routed)
{ {
unsigned char request[PFKEY_BUFFER_SIZE]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, query_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; 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, METHOD(kernel_ipsec_t, del_policy, status_t,
private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, 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]; unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out; struct sadb_msg *msg, *out;
@@ -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, 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"); proposal = proposal_create_from_string(PROTO_ESP, "aes128-sha1");
child_cfg->add_proposal(child_cfg, proposal); child_cfg->add_proposal(child_cfg, proposal);
ts = traffic_selector_create_dynamic(0, 0, 65535); ts = traffic_selector_create_dynamic(0, 0, 65535);
+3 -3
View File
@@ -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)); identification_create_from_encoding(ID_KEY_ID, other));
peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL,
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_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, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_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); this->current->add_auth_cfg(this->current, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, 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_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, TRUE, ts_from_string(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, ts_from_string(remote_net));
+1 -1
View File
@@ -444,7 +444,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
child_cfg = child_cfg_create(priv->name, &lifetime, child_cfg = child_cfg_create(priv->name, &lifetime,
NULL, TRUE, MODE_TUNNEL, /* updown, hostaccess */ 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)); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
ts = traffic_selector_create_dynamic(0, 0, 65535); ts = traffic_selector_create_dynamic(0, 0, 65535);
child_cfg->add_traffic_selector(child_cfg, TRUE, ts); child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
+1 -1
View File
@@ -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 } .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
}; };
child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode, 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 */ /* TODO: read proposal from db */
child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
add_traffic_selectors(this, child_cfg, id); add_traffic_selectors(this, child_cfg, id);
+5 -1
View File
@@ -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 .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) switch (msg->add_conn.dpd.action)
{ /* map startes magic values to our action type */ { /* 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.name, &lifetime,
msg->add_conn.me.updown, msg->add_conn.me.hostaccess, msg->add_conn.me.updown, msg->add_conn.me.hostaccess,
msg->add_conn.mode, dpd, dpd, msg->add_conn.ipcomp, 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, child_cfg->set_mipv6_options(child_cfg, msg->add_conn.proxy_mode,
msg->add_conn.install_policy); msg->add_conn.install_policy);
add_ts(this, &msg->add_conn.me, child_cfg, TRUE); add_ts(this, &msg->add_conn.me, child_cfg, TRUE);
+1 -1
View File
@@ -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); this->peer_cfg->add_auth_cfg(this->peer_cfg, auth, FALSE);
child_cfg = child_cfg_create(name, &lifetime, NULL, TRUE, MODE_TUNNEL, 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_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, TRUE, create_ts(local_net));
child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net)); child_cfg->add_traffic_selector(child_cfg, FALSE, create_ts(remote_net));
+48 -34
View File
@@ -97,6 +97,16 @@ struct private_child_sa_t {
*/ */
u_int32_t reqid; 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 * 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) if (this->my_spi)
{ {
status = charon->kernel_interface->query_sa( status = charon->kernel_interface->query_sa(charon->kernel_interface,
charon->kernel_interface,
this->other_addr, this->my_addr, 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 (status == SUCCESS)
{ {
if (bytes > this->my_usebytes) 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) if (this->other_spi)
{ {
status = charon->kernel_interface->query_sa( status = charon->kernel_interface->query_sa(charon->kernel_interface,
charon->kernel_interface,
this->my_addr, this->other_addr, 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 (status == SUCCESS)
{ {
if (bytes > this->other_usebytes) if (bytes > this->other_usebytes)
@@ -485,14 +495,14 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
if (inbound) if (inbound)
{ {
if (charon->kernel_interface->query_policy(charon->kernel_interface, 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); last_use = max(last_use, in);
} }
if (this->mode != MODE_TRANSPORT) if (this->mode != MODE_TRANSPORT)
{ {
if (charon->kernel_interface->query_policy(charon->kernel_interface, 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); last_use = max(last_use, fwd);
} }
@@ -501,7 +511,7 @@ static void update_usetime(private_child_sa_t *this, bool inbound)
else else
{ {
if (charon->kernel_interface->query_policy(charon->kernel_interface, 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); 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, status = charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, spi, this->protocol, this->reqid, lifetime, src, dst, spi, this->protocol, this->reqid,
enc_alg, encr, int_alg, integ, this->mode, this->ipcomp, cpi, inbound ? this->mark_in : this->mark_out,
this->encap, update, src_ts, dst_ts); lifetime, enc_alg, encr, int_alg, integ, this->mode,
this->ipcomp, cpi, this->encap, update, src_ts, dst_ts);
free(lifetime); free(lifetime);
@@ -708,19 +719,19 @@ static status_t add_policies(private_child_sa_t *this,
/* install 3 policies: out, in and forward */ /* install 3 policies: out, in and forward */
status |= charon->kernel_interface->add_policy(charon->kernel_interface, status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT, this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT,
this->other_spi, this->protocol, this->reqid, this->mode, this->other_spi, this->protocol, this->reqid, this->mark_out,
this->ipcomp, this->other_cpi, routed); this->mode, this->ipcomp, this->other_cpi, routed);
status |= charon->kernel_interface->add_policy(charon->kernel_interface, status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN, this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
this->my_spi, this->protocol, this->reqid, this->mode, this->my_spi, this->protocol, this->reqid, this->mark_in,
this->ipcomp, this->my_cpi, routed); this->mode, this->ipcomp, this->my_cpi, routed);
if (this->mode != MODE_TRANSPORT) if (this->mode != MODE_TRANSPORT)
{ {
status |= charon->kernel_interface->add_policy(charon->kernel_interface, status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD, this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD,
this->my_spi, this->protocol, this->reqid, this->mode, this->my_spi, this->protocol, this->reqid, this->mark_in,
this->ipcomp, this->my_cpi, routed); this->mode, this->ipcomp, this->my_cpi, routed);
} }
if (status != SUCCESS) 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->my_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0, this->ipcomp != IPCOMP_NONE ? this->my_cpi : 0,
this->other_addr, this->my_addr, other, me, this->other_addr, this->my_addr, other, me,
this->encap, encap) == NOT_SUPPORTED) this->encap, encap, this->mark_in) == NOT_SUPPORTED)
{ {
return 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->other_spi, this->protocol,
this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0, this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
this->my_addr, this->other_addr, me, other, this->my_addr, this->other_addr, me, other,
this->encap, encap) == NOT_SUPPORTED) this->encap, encap, this->mark_out) == NOT_SUPPORTED)
{ {
return 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 */ /* remove old policies first */
charon->kernel_interface->del_policy(charon->kernel_interface, 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, 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) if (this->mode != MODE_TRANSPORT)
{ {
charon->kernel_interface->del_policy(charon->kernel_interface, 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 */ /* 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 */ /* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface, charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->other_spi, me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
this->protocol, this->reqid, this->mode, this->ipcomp, this->protocol, this->reqid, this->mark_out, this->mode,
this->other_cpi, FALSE); this->ipcomp, this->other_cpi, FALSE);
charon->kernel_interface->add_policy(charon->kernel_interface, charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_IN, this->my_spi, other, me, other_ts, my_ts, POLICY_IN, this->my_spi,
this->protocol, this->reqid, this->mode, this->ipcomp, this->protocol, this->reqid, this->mark_in, this->mode,
this->my_cpi, FALSE); this->ipcomp, this->my_cpi, FALSE);
if (this->mode != MODE_TRANSPORT) if (this->mode != MODE_TRANSPORT)
{ {
charon->kernel_interface->add_policy(charon->kernel_interface, charon->kernel_interface->add_policy(charon->kernel_interface,
other, me, other_ts, my_ts, POLICY_FWD, this->my_spi, other, me, other_ts, my_ts, POLICY_FWD, this->my_spi,
this->protocol, this->reqid, this->mode, this->ipcomp, this->protocol, this->reqid, this->mark_in, this->mode,
this->my_cpi, FALSE); this->ipcomp, this->my_cpi, FALSE);
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
@@ -896,13 +907,13 @@ static void destroy(private_child_sa_t *this)
} }
charon->kernel_interface->del_sa(charon->kernel_interface, charon->kernel_interface->del_sa(charon->kernel_interface,
this->other_addr, this->my_addr, this->my_spi, 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) if (this->other_spi)
{ {
charon->kernel_interface->del_sa(charon->kernel_interface, charon->kernel_interface->del_sa(charon->kernel_interface,
this->my_addr, this->other_addr, this->other_spi, 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)) 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)) while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
{ {
charon->kernel_interface->del_policy(charon->kernel_interface, 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, 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) if (this->mode != MODE_TRANSPORT)
{ {
charon->kernel_interface->del_policy(charon->kernel_interface, 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); enumerator->destroy(enumerator);
@@ -1000,6 +1011,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->config = config; this->config = config;
config->get_ref(config); config->get_ref(config);
this->reqid = config->get_reqid(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) if (!this->reqid)
{ {
/* reuse old reqid if we are rekeying an existing CHILD_SA */ /* reuse old reqid if we are rekeying an existing CHILD_SA */
+1
View File
@@ -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_mediated_by), NULL },
{ ARG_STR, offsetof(starter_conn_t, me_peerid), NULL }, { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL },
{ ARG_UINT, offsetof(starter_conn_t, reqid), NULL }, { ARG_UINT, offsetof(starter_conn_t, reqid), NULL },
{ ARG_MISC, 0, NULL /* KW_MARK */ },
/* ca section keywords */ /* ca section keywords */
{ ARG_STR, offsetof(starter_ca_t, name), NULL }, { ARG_STR, offsetof(starter_ca_t, name), NULL },
+35
View File
@@ -671,6 +671,41 @@ static void load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg
} }
break; 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: case KW_KEYINGTRIES:
if (streq(kw->value, "%forever")) if (streq(kw->value, "%forever"))
{ {
+2
View File
@@ -122,6 +122,8 @@ struct starter_conn {
unsigned long sa_keying_tries; unsigned long sa_keying_tries;
unsigned long sa_rekey_fuzz; unsigned long sa_rekey_fuzz;
u_int32_t reqid; u_int32_t reqid;
u_int32_t mark_value;
u_int32_t mark_mask;
sa_family_t addr_family; sa_family_t addr_family;
sa_family_t tunnel_addr_family; sa_family_t tunnel_addr_family;
bool install_policy; bool install_policy;
+2 -1
View File
@@ -98,9 +98,10 @@ typedef enum {
KW_MEDIATED_BY, KW_MEDIATED_BY,
KW_ME_PEERID, KW_ME_PEERID,
KW_REQID, KW_REQID,
KW_MARK,
#define KW_CONN_FIRST KW_CONN_SETUP #define KW_CONN_FIRST KW_CONN_SETUP
#define KW_CONN_LAST KW_REQID #define KW_CONN_LAST KW_MARK
/* ca section keywords */ /* ca section keywords */
KW_CA_NAME, KW_CA_NAME,
+1
View File
@@ -89,6 +89,7 @@ mediation, KW_MEDIATION
mediated_by, KW_MEDIATED_BY mediated_by, KW_MEDIATED_BY
me_peerid, KW_ME_PEERID me_peerid, KW_ME_PEERID
reqid, KW_REQID reqid, KW_REQID
mark, KW_MARK
cacert, KW_CACERT cacert, KW_CACERT
ldaphost, KW_LDAPHOST ldaphost, KW_LDAPHOST
ldapbase, KW_LDAPBASE ldapbase, KW_LDAPBASE
+2
View File
@@ -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.mediated_by = push_string(&msg, conn->me_mediated_by);
msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid); msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid);
msg.add_conn.reqid = conn->reqid; 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.me, &conn->left);
starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right); starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
+4
View File
@@ -256,6 +256,10 @@ struct stroke_msg_t {
char *mediated_by; char *mediated_by;
char *peerid; char *peerid;
} ikeme; } ikeme;
struct {
u_int32_t value;
u_int32_t mask;
} mark;
stroke_end_t me, other; stroke_end_t me, other;
} add_conn; } add_conn;