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
*/
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.
*/
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);
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;
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;
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>
} 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.
*
*/
u_int32_t (*get_reqid)(child_cfg_t *this);
+ /**
+ * Optional mark for CHILD_SA
+ *
+ * @param inbound TRUE for inbound, FALSE for outbound
+ * @return mark
+ */
+ mark_t (*get_mark)(child_cfg_t *this, bool inbound);
+
/**
* Sets two options needed for Mobile IPv6 interoperability
*
* @param 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_ @}*/
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)
{
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*,
* @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
*/
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,
* @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
*/
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.
* @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.
* @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.
* @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
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.
* @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.
* @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);
/**
* @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
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,
* @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
*/
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.
* @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.
* @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.
* @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
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.
* @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.
* @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);
/**
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);
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);
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;
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;
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;
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;
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";
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;
{
close(this->socket);
}
- if (this->socket_evnets > 0)
+ if (this->socket_events > 0)
{
close(this->socket_events);
}
/** parameters of installed policy */
struct xfrm_selector sel;
+ /** optional mark */
+ u_int32_t mark;
+
/** associated route installed for this policy */
route_entry_t *route;
*/
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);
}
*/
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;
}
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;
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 */
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;
if (encap)
{
+ struct xfrm_encap_tmpl *tmpl;
+
rthdr->rta_type = XFRMA_ENCAP;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
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));
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;
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;
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;
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;
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:
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;
/* 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;
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;
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));
}
/* 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);
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;
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 */
{
/* 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;
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;
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)
{
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;
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;
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;
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;
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 */
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;
}
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;
}
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;
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;
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;
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;
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;
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;
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;
}
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);
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));
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));
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);
.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);
.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 */
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);
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));
*/
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
*/
{
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)
{
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)
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);
}
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);
}
}
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);
/* 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)
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;
}
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;
}
{
/* 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 */
/* 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);
}
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))
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);
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 */
{ 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 },
}
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"))
{
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;
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,
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
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);
char *mediated_by;
char *peerid;
} ikeme;
+ struct {
+ u_int32_t value;
+ u_int32_t mask;
+ } mark;
stroke_end_t me, other;
} add_conn;