change makes IPcomp tunnel mode connections incompatible with previous
releases; disable compression on such tunnels.
+- Fixed BEET mode connections on recent kernels by installing SAs with
+ appropriate traffic selectors, based on a patch by Michael Rossberg.
+
- The IKEv1 daemon ignores the Juniper SRX notification type 40001, thus
allowing interoperability.
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)
+ bool inbound, traffic_selector_t *src_ts,
+ traffic_selector_t *dst_ts)
{
if (!this->ipsec)
{
}
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);
+ encap, inbound, src_ts, dst_ts);
}
/**
this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.get_cpi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
this->public.update_sa = (status_t(*)(kernel_interface_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
this->public.query_sa = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
* @param cpi CPI for IPComp
* @param encap enable UDP encapsulation for NAT traversal
* @param inbound TRUE if this is an inbound SA
+ * @param src_ts traffic selector with BEET source address
+ * @param dst_ts traffic selector with BEET destination address
* @return SUCCESS if operation completed
*/
status_t (*add_sa) (kernel_interface_t *this,
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);
+ bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
/**
* Update the hosts on an installed SA.
ENUM(ipsec_mode_names, MODE_TRANSPORT, MODE_BEET,
"TRANSPORT",
"TUNNEL",
- "2",
- "3",
"BEET",
);
* @param cpi CPI for IPComp
* @param encap enable UDP encapsulation for NAT traversal
* @param inbound TRUE if this is an inbound SA
+ * @param src_ts traffic selector with BEET source address
+ * @param dst_ts traffic selector with BEET destination address
* @return SUCCESS if operation completed
*/
status_t (*add_sa) (kernel_ipsec_t *this,
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);
+ bool encap, bool inbound,
+ traffic_selector_t *src_ts, traffic_selector_t *dst_ts);
/**
* Update the hosts on an installed SA.
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)
+ 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;
/* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
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)
+ bool encap, bool inbound,
+ traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
{
netlink_buf_t request;
char *alg_name;
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,
- mode, ipcomp, 0, FALSE, inbound);
+ mode, ipcomp, 0, FALSE, inbound, NULL, NULL);
ipcomp = IPCOMP_NONE;
/* use transport mode ESP SA, IPComp uses tunnel mode */
mode = MODE_TRANSPORT;
sa->id.proto = proto_ike2kernel(protocol);
sa->family = src->get_family(src);
sa->mode = mode2kernel(mode);
- if (mode == MODE_TUNNEL)
+ switch (mode)
{
- sa->flags |= XFRM_STATE_AF_UNSPEC;
+ case MODE_TUNNEL:
+ sa->flags |= XFRM_STATE_AF_UNSPEC;
+ break;
+ case MODE_BEET:
+ if(src_ts && dst_ts)
+ {
+ sa->sel = ts2selector(src_ts, dst_ts);
+ }
+ break;
+ default:
+ break;
}
+
sa->replay_window = (protocol == IPPROTO_COMP) ? 0 : 32;
sa->reqid = reqid;
sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey);
/* install a route, if:
* - we are NOT updating a policy
* - this is a forward policy (to just get one for each child)
- * - we are in tunnel mode
+ * - we are in tunnel/BEET mode
* - routing is not disabled via strongswan.conf
*/
if (policy->route == NULL && direction == POLICY_FWD &&
/* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
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)
+ 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;
/* public functions */
this->public.interface.get_spi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi;
this->public.interface.get_cpi = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,u_int16_t*))get_cpi;
- this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool))add_sa;
+ this->public.interface.add_sa = (status_t(*)(kernel_ipsec_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,lifetime_cfg_t*,u_int16_t,chunk_t,u_int16_t,chunk_t,ipsec_mode_t,u_int16_t,u_int16_t,bool,bool,traffic_selector_t*,traffic_selector_t*))add_sa;
this->public.interface.update_sa = (status_t(*)(kernel_ipsec_t*,u_int32_t,protocol_id_t,u_int16_t,host_t*,host_t*,host_t*,host_t*,bool,bool))update_sa;
this->public.interface.query_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int64_t*))query_sa;
this->public.interface.del_sa = (status_t(*)(kernel_ipsec_t*,host_t*,host_t*,u_int32_t,protocol_id_t,u_int16_t))del_sa;
* Implementation of child_sa_t.install
*/
static status_t install(private_child_sa_t *this, chunk_t encr, chunk_t integ,
- u_int32_t spi, u_int16_t cpi, bool inbound)
+ u_int32_t spi, u_int16_t cpi, bool inbound,
+ linked_list_t *my_ts, linked_list_t *other_ts)
{
u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size;
+ traffic_selector_t *src_ts = NULL, *dst_ts = NULL;
time_t now;
lifetime_cfg_t *lifetime;
host_t *src, *dst;
lifetime->time.rekey = 0;
}
+ if (this->mode == MODE_BEET)
+ {
+ /* BEET requires the bound address from the traffic selectors.
+ * TODO: We add just the first traffic selector for now, as the
+ * kernel accepts a single TS per SA only */
+ if (inbound)
+ {
+ my_ts->get_first(my_ts, (void**)&dst_ts);
+ other_ts->get_first(other_ts, (void**)&src_ts);
+ }
+ else
+ {
+ my_ts->get_first(my_ts, (void**)&src_ts);
+ other_ts->get_first(other_ts, (void**)&dst_ts);
+ }
+ }
+
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);
+ this->encap, update, src_ts, dst_ts);
free(lifetime);
this->public.set_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t))set_ipcomp;
this->public.alloc_spi = (u_int32_t(*)(child_sa_t*, protocol_id_t protocol))alloc_spi;
this->public.alloc_cpi = (u_int16_t(*)(child_sa_t*))alloc_cpi;
- this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound))install;
+ this->public.install = (status_t(*)(child_sa_t*, chunk_t encr, chunk_t integ, u_int32_t spi, u_int16_t cpi, bool inbound, linked_list_t *my_ts_list, linked_list_t *other_ts_list))install;
this->public.update = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update;
this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies;
this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
* @param spi SPI to use, allocated for inbound
* @param cpi CPI to use, allocated for outbound
* @param inbound TRUE to install an inbound SA, FALSE for outbound
+ * @param my_ts negotiated local traffic selector list
+ * @param other_ts negotiated remote traffic selector list
* @return SUCCESS or FAILED
*/
status_t (*install)(child_sa_t *this, chunk_t encr, chunk_t integ,
- u_int32_t spi, u_int16_t cpi, bool inbound);
+ u_int32_t spi, u_int16_t cpi, bool inbound,
+ linked_list_t *my_ts, linked_list_t *other_ts);
/**
* Install the policies using some traffic selectors.
*
}
status_i = status_o = FAILED;
if (this->keymat->derive_child_keys(this->keymat, this->proposal,
- this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
+ this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
{
if (this->initiator)
{
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
- this->my_spi, this->my_cpi, TRUE);
+ this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->other_spi, this->other_cpi, FALSE);
+ this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
}
else
{
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->my_spi, this->my_cpi, TRUE);
+ this->my_spi, this->my_cpi, TRUE, my_ts, other_ts);
status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
- this->other_spi, this->other_cpi, FALSE);
+ this->other_spi, this->other_cpi, FALSE, my_ts, other_ts);
}
}
chunk_clear(&integ_i);