diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/ikev2/ikev2.c | 220 | ||||
-rw-r--r-- | src/plugins/ikev2/ikev2_priv.h | 5 |
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; |