aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/ikev2/ikev2.c220
-rw-r--r--src/plugins/ikev2/ikev2_priv.h5
2 files changed, 157 insertions, 68 deletions
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index 00b8f8eea29..b6202aeec6a 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -15,6 +15,7 @@
#include <vlib/vlib.h>
#include <vlib/unix/plugin.h>
+#include <vlibmemory/api.h>
#include <vpp/app/version.h>
#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
@@ -1507,34 +1508,77 @@ ikev2_sa_auth_init (ikev2_sa_t * sa)
}
static u32
-ikev2_mk_local_sa_id (u32 ti)
+ikev2_mk_local_sa_id (u32 sai, u32 ci, u32 ti)
{
- return (0x80000000 | ti);
+ return (0x80000000 | (ti << 24) | (sai << 12) | ci);
}
static u32
-ikev2_mk_remote_sa_id (u32 ti)
+ikev2_mk_remote_sa_id (u32 sai, u32 ci, u32 ti)
{
- return (0xc0000000 | ti);
+ return (0xc0000000 | (ti << 24) | (sai << 12) | ci);
+}
+
+typedef struct
+{
+ u32 salt_local;
+ u32 salt_remote;
+ u32 local_sa_id;
+ u32 remote_sa_id;
+ ipsec_sa_flags_t flags;
+ u32 local_spi;
+ u32 remote_spi;
+ ipsec_crypto_alg_t encr_type;
+ ipsec_integ_alg_t integ_type;
+ ip46_address_t local_ip;
+ ip46_address_t remote_ip;
+ ipsec_key_t loc_ckey, rem_ckey, loc_ikey, rem_ikey;
+} ikev2_add_ipsec_tunnel_args_t;
+
+static void
+ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
+{
+ u32 sw_if_index;
+ int rv;
+
+ rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
+ &a->local_ip, &a->remote_ip, 0, 0, &sw_if_index);
+
+ rv |= ipsec_sa_add_and_lock (a->local_sa_id,
+ a->local_spi,
+ IPSEC_PROTOCOL_ESP, a->encr_type,
+ &a->loc_ckey, a->integ_type, &a->loc_ikey,
+ a->flags, 0, a->salt_local, &a->local_ip,
+ &a->remote_ip, NULL);
+ rv |= ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi,
+ IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey,
+ a->integ_type, &a->rem_ikey,
+ (a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0,
+ a->salt_remote, &a->remote_ip,
+ &a->local_ip, NULL);
+
+ u32 *sas_in = NULL;
+ vec_add1 (sas_in, a->remote_sa_id);
+ rv |= ipsec_tun_protect_update (sw_if_index, a->local_sa_id, sas_in);
}
static int
-ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
- ikev2_child_sa_t * child)
+ikev2_create_tunnel_interface (vnet_main_t * vnm,
+ u32 thread_index,
+ ikev2_sa_t * sa,
+ ikev2_child_sa_t * child, u32 sa_index,
+ u32 child_index)
{
ikev2_main_t *km = &ikev2_main;
+ ipsec_crypto_alg_t encr_type;
+ ipsec_integ_alg_t integ_type;
ikev2_profile_t *p = 0;
- ipsec_key_t loc_ckey, rem_ckey, loc_ikey, rem_ikey;
ikev2_sa_transform_t *tr;
ikev2_sa_proposal_t *proposals;
- ipsec_sa_flags_t flags = 0;
- ipsec_crypto_alg_t encr_type;
- ipsec_integ_alg_t integ_type;
- u32 local_spi, remote_spi;
u8 is_aead = 0;
- u32 salt_local = 0, salt_remote = 0;
- ip46_address_t local_ip, remote_ip;
- int rv;
+ ikev2_add_ipsec_tunnel_args_t a;
+
+ clib_memset (&a, 0, sizeof (a));
if (!child->r_proposals)
{
@@ -1544,26 +1588,26 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
if (sa->is_initiator)
{
- ip46_address_set_ip4 (&local_ip, &sa->iaddr);
- ip46_address_set_ip4 (&remote_ip, &sa->raddr);
+ ip46_address_set_ip4 (&a.local_ip, &sa->iaddr);
+ ip46_address_set_ip4 (&a.remote_ip, &sa->raddr);
proposals = child->i_proposals;
- local_spi = child->r_proposals[0].spi;
- remote_spi = child->i_proposals[0].spi;
+ a.local_spi = child->r_proposals[0].spi;
+ a.remote_spi = child->i_proposals[0].spi;
}
else
{
- ip46_address_set_ip4 (&local_ip, &sa->raddr);
- ip46_address_set_ip4 (&remote_ip, &sa->iaddr);
+ ip46_address_set_ip4 (&a.local_ip, &sa->raddr);
+ ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr);
proposals = child->r_proposals;
- local_spi = child->i_proposals[0].spi;
- remote_spi = child->r_proposals[0].spi;
+ a.local_spi = child->i_proposals[0].spi;
+ a.remote_spi = child->r_proposals[0].spi;
}
- flags = IPSEC_SA_FLAG_USE_ANTI_REPLAY;
+ a.flags = IPSEC_SA_FLAG_USE_ANTI_REPLAY;
tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_ESN);
if (tr && tr->esn_type)
- flags |= IPSEC_SA_FLAG_USE_ESN;
+ a.flags |= IPSEC_SA_FLAG_USE_ESN;
tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_ENCR);
if (tr)
@@ -1619,6 +1663,7 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN);
return 1;
}
+ a.encr_type = encr_type;
if (!is_aead)
{
@@ -1655,30 +1700,31 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
integ_type = IPSEC_INTEG_ALG_NONE;
}
+ a.integ_type = integ_type;
ikev2_calc_child_keys (sa, child);
if (sa->is_initiator)
{
- ipsec_mk_key (&loc_ikey, child->sk_ai, vec_len (child->sk_ai));
- ipsec_mk_key (&rem_ikey, child->sk_ar, vec_len (child->sk_ar));
- ipsec_mk_key (&loc_ckey, child->sk_ei, vec_len (child->sk_ei));
- ipsec_mk_key (&rem_ckey, child->sk_er, vec_len (child->sk_er));
+ ipsec_mk_key (&a.loc_ikey, child->sk_ai, vec_len (child->sk_ai));
+ ipsec_mk_key (&a.rem_ikey, child->sk_ar, vec_len (child->sk_ar));
+ ipsec_mk_key (&a.loc_ckey, child->sk_ei, vec_len (child->sk_ei));
+ ipsec_mk_key (&a.rem_ckey, child->sk_er, vec_len (child->sk_er));
if (is_aead)
{
- salt_remote = child->salt_er;
- salt_local = child->salt_ei;
+ a.salt_remote = child->salt_er;
+ a.salt_local = child->salt_ei;
}
}
else
{
- ipsec_mk_key (&loc_ikey, child->sk_ar, vec_len (child->sk_ar));
- ipsec_mk_key (&rem_ikey, child->sk_ai, vec_len (child->sk_ai));
- ipsec_mk_key (&loc_ckey, child->sk_er, vec_len (child->sk_er));
- ipsec_mk_key (&rem_ckey, child->sk_ei, vec_len (child->sk_ei));
+ ipsec_mk_key (&a.loc_ikey, child->sk_ar, vec_len (child->sk_ar));
+ ipsec_mk_key (&a.rem_ikey, child->sk_ai, vec_len (child->sk_ai));
+ ipsec_mk_key (&a.loc_ckey, child->sk_er, vec_len (child->sk_er));
+ ipsec_mk_key (&a.rem_ckey, child->sk_ei, vec_len (child->sk_ei));
if (is_aead)
{
- salt_remote = child->salt_ei;
- salt_local = child->salt_er;
+ a.salt_remote = child->salt_ei;
+ a.salt_local = child->salt_er;
}
}
@@ -1703,40 +1749,80 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
}
}
- rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
- &local_ip, &remote_ip, 0, 0, &child->sw_if_index);
-
- child->local_sa = ikev2_mk_local_sa_id (child->sw_if_index);
- child->remote_sa = ikev2_mk_remote_sa_id (child->sw_if_index);
-
- rv |= ipsec_sa_add_and_lock (child->local_sa,
- local_spi,
- IPSEC_PROTOCOL_ESP, encr_type,
- &loc_ckey, integ_type, &loc_ikey, flags,
- 0, salt_local, &local_ip, &remote_ip, NULL);
- rv |= ipsec_sa_add_and_lock (child->remote_sa,
- remote_spi,
- IPSEC_PROTOCOL_ESP, encr_type,
- &rem_ckey, integ_type, &rem_ikey,
- (flags | IPSEC_SA_FLAG_IS_INBOUND),
- 0, salt_remote, &remote_ip, &local_ip, NULL);
+ if (thread_index & 0xffffffc0)
+ clib_warning ("error: thread index exceeds max range 0x3f!");
- u32 *sas_in = NULL;
- vec_add1 (sas_in, child->remote_sa);
- rv |=
- ipsec_tun_protect_update (child->sw_if_index, child->local_sa, sas_in);
+ if (child_index & 0xfffff000 || sa_index & 0xfffff000)
+ clib_warning ("error: sa/child index exceeds max range 0xfff!");
+
+ child->local_sa_id =
+ a.local_sa_id =
+ ikev2_mk_local_sa_id (sa_index, child_index, thread_index);
+ child->remote_sa_id =
+ a.remote_sa_id =
+ ikev2_mk_remote_sa_id (sa_index, child_index, thread_index);
+ vl_api_rpc_call_main_thread (ikev2_add_tunnel_from_main,
+ (u8 *) & a, sizeof (a));
return 0;
}
+typedef struct
+{
+ ip46_address_t local_ip;
+ ip46_address_t remote_ip;
+ u32 remote_sa_id;
+ u32 local_sa_id;
+} ikev2_del_ipsec_tunnel_args_t;
+
+static void
+ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a)
+{
+ /* *INDENT-OFF* */
+ ipip_tunnel_key_t key = {
+ .src = a->local_ip,
+ .dst = a->remote_ip,
+ .transport = IPIP_TRANSPORT_IP4,
+ .fib_index = 0,
+ };
+ ipip_tunnel_t *ipip;
+ /* *INDENT-ON* */
+
+ ipip = ipip_tunnel_db_find (&key);
+
+ if (ipip)
+ {
+ ipsec_tun_protect_del (ipip->sw_if_index);
+ ipsec_sa_unlock_id (a->remote_sa_id);
+ ipsec_sa_unlock_id (a->local_sa_id);
+ ipip_del_tunnel (ipip->sw_if_index);
+ }
+}
+
static int
ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
ikev2_child_sa_t * child)
{
- ipsec_tun_protect_del (child->sw_if_index);
- ipsec_sa_unlock_id (child->remote_sa);
- ipsec_sa_unlock_id (child->local_sa);
- ipip_del_tunnel (child->sw_if_index);
+ ikev2_del_ipsec_tunnel_args_t a;
+
+ clib_memset (&a, 0, sizeof (a));
+
+ if (sa->is_initiator)
+ {
+ ip46_address_set_ip4 (&a.local_ip, &sa->iaddr);
+ ip46_address_set_ip4 (&a.remote_ip, &sa->raddr);
+ }
+ else
+ {
+ ip46_address_set_ip4 (&a.local_ip, &sa->raddr);
+ ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr);
+ }
+
+ a.remote_sa_id = child->remote_sa_id;
+ a.local_sa_id = child->local_sa_id;
+
+ vl_api_rpc_call_main_thread (ikev2_del_tunnel_from_main, (u8 *) & a,
+ sizeof (a));
return 0;
}
@@ -2325,8 +2411,10 @@ ikev2_node_fn (vlib_main_t * vm,
ikev2_initial_contact_cleanup (sa0);
ikev2_sa_match_ts (sa0);
if (sa0->state != IKEV2_STATE_TS_UNACCEPTABLE)
- ikev2_create_tunnel_interface (km->vnet_main, sa0,
- &sa0->childs[0]);
+ ikev2_create_tunnel_interface (km->vnet_main,
+ thread_index, sa0,
+ &sa0->childs[0],
+ p[0], 0);
}
if (sa0->is_initiator)
@@ -2452,8 +2540,10 @@ ikev2_node_fn (vlib_main_t * vm,
child->i_proposals = sa0->rekey[0].i_proposal;
child->tsi = sa0->rekey[0].tsi;
child->tsr = sa0->rekey[0].tsr;
- ikev2_create_tunnel_interface (km->vnet_main, sa0,
- child);
+ ikev2_create_tunnel_interface (km->vnet_main,
+ thread_index, sa0,
+ child, p[0],
+ child - sa0->childs);
}
if (sa0->is_initiator)
{
diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h
index 65080f0df3f..c1bc41c0e54 100644
--- a/src/plugins/ikev2/ikev2_priv.h
+++ b/src/plugins/ikev2/ikev2_priv.h
@@ -147,9 +147,8 @@ typedef struct
u32 salt_er;
/* installed data */
- u32 sw_if_index;
- u32 local_sa;
- u32 remote_sa;
+ u32 local_sa_id;
+ u32 remote_sa_id;
/* lifetime data */
f64 time_to_expiration;