support of xfrm marks for IKEv2

This commit is contained in:
Andreas Steffen 2010-07-02 23:45:57 +02:00
parent 02571374c4
commit ee26c537d7
24 changed files with 530 additions and 150 deletions

View File

@ -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;

View File

@ -26,6 +26,7 @@
typedef enum action_t action_t;
typedef enum ipcomp_transform_t ipcomp_transform_t;
typedef struct lifetime_cfg_t lifetime_cfg_t;
typedef struct mark_t mark_t;
typedef struct child_cfg_t child_cfg_t;
#include <library.h>
@ -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_ @}*/

View File

@ -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*,

View File

@ -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);
/**

View File

@ -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);
/**

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

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));
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));

View File

@ -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);

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 }
};
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);

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
}
};
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);

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);
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));

View File

@ -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 */

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_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 },

View File

@ -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"))
{

View File

@ -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;

View File

@ -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,

View File

@ -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

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.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);

View File

@ -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;