summaryrefslogtreecommitdiffstats
path: root/src/plugins/ikev2/ikev2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ikev2/ikev2.c')
-rw-r--r--src/plugins/ikev2/ikev2.c210
1 files changed, 122 insertions, 88 deletions
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index 62a77f9c6d8..463be3ae19c 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -343,19 +343,17 @@ ikev2_sa_free_all_vec (ikev2_sa_t * sa)
}
static void
-ikev2_delete_sa (ikev2_sa_t * sa)
+ikev2_delete_sa (ikev2_main_per_thread_data_t * ptd, ikev2_sa_t * sa)
{
- ikev2_main_t *km = &ikev2_main;
- u32 thread_index = vlib_get_thread_index ();
uword *p;
ikev2_sa_free_all_vec (sa);
- p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
+ p = hash_get (ptd->sa_by_rspi, sa->rspi);
if (p)
{
- hash_unset (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
- pool_put (km->per_thread_data[thread_index].sas, sa);
+ hash_unset (ptd->sa_by_rspi, sa->rspi);
+ pool_put (ptd->sas, sa);
}
}
@@ -1026,43 +1024,61 @@ ikev2_is_id_equal (ikev2_id_t * i1, ikev2_id_t * i2)
}
static void
-ikev2_initial_contact_cleanup (ikev2_sa_t * sa)
+ikev2_initial_contact_cleanup_internal (ikev2_main_per_thread_data_t * ptd,
+ ikev2_sa_t * sa)
{
ikev2_main_t *km = &ikev2_main;
ikev2_sa_t *tmp;
u32 i, *delete = 0;
ikev2_child_sa_t *c;
- u32 thread_index = vlib_get_thread_index ();
-
- if (!sa->initial_contact)
- return;
/* find old IKE SAs with the same authenticated identity */
/* *INDENT-OFF* */
- pool_foreach (tmp, km->per_thread_data[thread_index].sas, ({
- if (!ikev2_is_id_equal (&tmp->i_id, &sa->i_id)
- || !ikev2_is_id_equal(&tmp->r_id, &sa->r_id))
- continue;
+ pool_foreach (tmp, ptd->sas, ({
+ if (!ikev2_is_id_equal (&tmp->i_id, &sa->i_id)
+ || !ikev2_is_id_equal(&tmp->r_id, &sa->r_id))
+ continue;
- if (sa->rspi != tmp->rspi)
- vec_add1(delete, tmp - km->per_thread_data[thread_index].sas);
+ if (sa->rspi != tmp->rspi)
+ vec_add1(delete, tmp - ptd->sas);
}));
/* *INDENT-ON* */
for (i = 0; i < vec_len (delete); i++)
{
- tmp =
- pool_elt_at_index (km->per_thread_data[thread_index].sas, delete[i]);
- vec_foreach (c,
- tmp->childs) ikev2_delete_tunnel_interface (km->vnet_main,
- tmp, c);
- ikev2_delete_sa (tmp);
+ tmp = pool_elt_at_index (ptd->sas, delete[i]);
+ vec_foreach (c, tmp->childs)
+ {
+ ikev2_delete_tunnel_interface (km->vnet_main, tmp, c);
+ }
+ ikev2_delete_sa (ptd, tmp);
}
vec_free (delete);
sa->initial_contact = 0;
}
+static void
+ikev2_initial_contact_cleanup (ikev2_main_per_thread_data_t * ptd,
+ ikev2_sa_t * sa)
+{
+ ikev2_main_t *km = &ikev2_main;
+
+ if (!sa->initial_contact)
+ return;
+
+ if (ptd)
+ {
+ ikev2_initial_contact_cleanup_internal (ptd, sa);
+ }
+ else
+ {
+ vec_foreach (ptd, km->per_thread_data)
+ ikev2_initial_contact_cleanup_internal (ptd, sa);
+ }
+ sa->initial_contact = 0;
+}
+
static int
ikev2_parse_id_payload (const void *p, u16 rlen, ikev2_id_t * sa_id)
{
@@ -2531,74 +2547,87 @@ done:
}
static u32
+ikev2_retransmit_sa_init_one (ikev2_sa_t * sa, ike_header_t * ike,
+ ip_address_t iaddr, ip_address_t raddr,
+ u32 rlen)
+{
+ int p = 0;
+ ike_header_t *tmp;
+ u8 payload = ike->nextpayload;
+
+ if (sa->ispi != clib_net_to_host_u64 (ike->ispi) ||
+ ip_address_cmp (&sa->iaddr, &iaddr) ||
+ ip_address_cmp (&sa->raddr, &raddr))
+ {
+ return 0;
+ }
+
+ while (p < rlen && payload != IKEV2_PAYLOAD_NONE)
+ {
+ ike_payload_header_t *ikep = (ike_payload_header_t *) & ike->payload[p];
+ u32 plen = clib_net_to_host_u16 (ikep->length);
+
+ if (plen < sizeof (ike_payload_header_t))
+ return ~0;
+
+ if (payload == IKEV2_PAYLOAD_NONCE &&
+ !clib_memcmp (sa->i_nonce, ikep->payload, plen - sizeof (*ikep)))
+ {
+ /* req is retransmit */
+ if (sa->state == IKEV2_STATE_SA_INIT)
+ {
+ tmp = (ike_header_t *) sa->last_sa_init_res_packet_data;
+ u32 slen = clib_net_to_host_u32 (tmp->length);
+ ike->ispi = tmp->ispi;
+ ike->rspi = tmp->rspi;
+ ike->nextpayload = tmp->nextpayload;
+ ike->version = tmp->version;
+ ike->exchange = tmp->exchange;
+ ike->flags = tmp->flags;
+ ike->msgid = tmp->msgid;
+ ike->length = tmp->length;
+ clib_memcpy_fast (ike->payload, tmp->payload,
+ slen - sizeof (*ike));
+ ikev2_elog_uint_peers (IKEV2_LOG_DEBUG,
+ "ispi %lx IKE_SA_INIT retransmit "
+ "from %d.%d.%d.%d to %d.%d.%d.%d",
+ ike->ispi,
+ ip_addr_v4 (&raddr).as_u32,
+ ip_addr_v4 (&iaddr).as_u32);
+ return slen;
+ }
+ /* else ignore req */
+ else
+ {
+ ikev2_elog_uint_peers (IKEV2_LOG_DEBUG,
+ "ispi %lx IKE_SA_INIT ignore "
+ "from %d.%d.%d.%d to %d.%d.%d.%d",
+ ike->ispi,
+ ip_addr_v4 (&raddr).as_u32,
+ ip_addr_v4 (&iaddr).as_u32);
+ return ~0;
+ }
+ }
+ payload = ikep->nextpayload;
+ p += plen;
+ }
+
+ return 0;
+}
+
+static u32
ikev2_retransmit_sa_init (ike_header_t * ike, ip_address_t iaddr,
ip_address_t raddr, u32 rlen)
{
ikev2_sa_t *sa;
+ u32 res;
ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data ();
/* *INDENT-OFF* */
pool_foreach (sa, ptd->sas, ({
- if (sa->ispi == clib_net_to_host_u64(ike->ispi) &&
- !ip_address_cmp(&sa->iaddr, &iaddr) &&
- !ip_address_cmp(&sa->raddr, &raddr))
- {
- int p = 0;
- u8 payload = ike->nextpayload;
-
- while (p < rlen && payload!= IKEV2_PAYLOAD_NONE) {
- ike_payload_header_t * ikep = (ike_payload_header_t *) &ike->payload[p];
- u32 plen = clib_net_to_host_u16 (ikep->length);
- if (plen > p + sizeof (*ike))
- return ~0;
-
- if (plen < sizeof(ike_payload_header_t))
- return ~0;
-
- if (payload == IKEV2_PAYLOAD_NONCE)
- {
- if (!clib_memcmp(sa->i_nonce, ikep->payload,
- plen - sizeof(*ikep)))
- {
- /* req is retransmit */
- if (sa->state == IKEV2_STATE_SA_INIT)
- {
- ike_header_t * tmp = (ike_header_t*)sa->last_sa_init_res_packet_data;
- u32 slen = clib_net_to_host_u32(tmp->length);
- ike->ispi = tmp->ispi;
- ike->rspi = tmp->rspi;
- ike->nextpayload = tmp->nextpayload;
- ike->version = tmp->version;
- ike->exchange = tmp->exchange;
- ike->flags = tmp->flags;
- ike->msgid = tmp->msgid;
- ike->length = tmp->length;
- clib_memcpy_fast(ike->payload, tmp->payload, slen - sizeof(*ike));
- ikev2_elog_uint_peers (IKEV2_LOG_DEBUG,
- "ispi %lx IKE_SA_INIT retransmit "
- "from %d.%d.%d.%d to %d.%d.%d.%d",
- ike->ispi,
- ip_addr_v4(&raddr).as_u32,
- ip_addr_v4 (&iaddr).as_u32);
- return slen;
- }
- /* else ignore req */
- else
- {
- ikev2_elog_uint_peers (IKEV2_LOG_DEBUG,
- "ispi %lx IKE_SA_INIT ignore "
- "from %d.%d.%d.%d to %d.%d.%d.%d",
- ike->ispi,
- ip_addr_v4(&raddr).as_u32,
- ip_addr_v4(&iaddr).as_u32);
- return ~0;
- }
- }
- }
- payload = ikep->nextpayload;
- p+=plen;
- }
- }
+ res = ikev2_retransmit_sa_init_one (sa, ike, iaddr, raddr, rlen);
+ if (res)
+ return res;
}));
/* *INDENT-ON* */
@@ -2981,7 +3010,7 @@ ikev2_node_internal (vlib_main_t * vm,
IKEV2_ERROR_MALFORMED_PACKET, 1);
if (sa0->state == IKEV2_STATE_AUTHENTICATED)
{
- ikev2_initial_contact_cleanup (sa0);
+ ikev2_initial_contact_cleanup (ptd, sa0);
ikev2_sa_match_ts (sa0);
if (sa0->state != IKEV2_STATE_TS_UNACCEPTABLE)
ikev2_create_tunnel_interface (vm, sa0,
@@ -3201,7 +3230,7 @@ ikev2_node_internal (vlib_main_t * vm,
vec_foreach (c, sa0->childs)
ikev2_delete_tunnel_interface (km->vnet_main, sa0, c);
- ikev2_delete_sa (sa0);
+ ikev2_delete_sa (ptd, sa0);
}
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
@@ -3595,6 +3624,9 @@ ikev2_initiate_delete_ike_sa_internal (vlib_main_t * vm,
if (~0 == len)
return;
+ if (sa->natt)
+ len = ikev2_insert_non_esp_marker (ike0, len);
+
if (sa->is_initiator)
{
src = &sa->iaddr;
@@ -4177,7 +4209,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
vec_add (sa.childs[0].tsi, &p->loc_ts, 1);
vec_add (sa.childs[0].tsr, &p->rem_ts, 1);
- ikev2_initial_contact_cleanup (&sa);
+ ikev2_initial_contact_cleanup (0, &sa);
/* add SA to the pool */
ikev2_sa_t *sa0 = 0;
@@ -4661,8 +4693,6 @@ ikev2_process_pending_sa_init (ikev2_main_t * km)
/* *INDENT-ON* */
}
-static vlib_node_registration_t ikev2_mngr_process_node;
-
static void
ikev2_send_informational_request (ikev2_sa_t * sa)
{
@@ -4760,6 +4790,10 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
pool_foreach (sa, tkm->sas, ({
ikev2_child_sa_t *c;
u8 del_old_ids = 0;
+
+ if (sa->state != IKEV2_STATE_AUTHENTICATED)
+ continue;
+
if (sa->old_remote_id_present && 0 > sa->old_id_expiration)
{
sa->old_remote_id_present = 0;