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.c766
1 files changed, 359 insertions, 407 deletions
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index 5103d9832fb..593d616593d 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -1840,11 +1840,11 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
static int
ikev2_create_tunnel_interface (vlib_main_t * vm,
- u32 thread_index,
ikev2_sa_t * sa,
ikev2_child_sa_t * child, u32 sa_index,
u32 child_index, u8 is_rekey)
{
+ u32 thread_index = vlib_get_thread_index ();
ikev2_main_t *km = &ikev2_main;
ipsec_crypto_alg_t encr_type;
ipsec_integ_alg_t integ_type;
@@ -2662,264 +2662,117 @@ static uword
ikev2_node_fn (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- u32 n_left_from, *from, *to_next;
- ikev2_next_t next_index;
+ u32 n_left = frame->n_vectors, *from;
ikev2_main_t *km = &ikev2_main;
- u32 thread_index = vlib_get_thread_index ();
+ vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
+ u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
+ ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data ();
int res;
from = vlib_frame_vector_args (frame);
- n_left_from = frame->n_vectors;
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from > 0 && n_left_to_next > 0)
+ vlib_get_buffers (vm, from, bufs, n_left);
+ b = bufs;
+
+ while (n_left > 0)
+ {
+ vlib_buffer_t *b0 = b[0];
+ next[0] = IKEV2_NEXT_ERROR_DROP;
+ ip4_header_t *ip40;
+ udp_header_t *udp0;
+ ike_header_t *ike0;
+ ikev2_sa_t *sa0 = 0;
+ ikev2_sa_t sa; /* temporary store for SA */
+ u32 rlen, slen = 0;
+ int is_req = 0, has_non_esp_marker = 0;
+
+ if (b0->punt_reason == ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0])
{
- u32 bi0;
- vlib_buffer_t *b0;
- u32 next0 = IKEV2_NEXT_ERROR_DROP;
- ip4_header_t *ip40;
- udp_header_t *udp0;
- ike_header_t *ike0;
- ikev2_sa_t *sa0 = 0;
- ikev2_sa_t sa; /* temporary store for SA */
- u32 rlen, slen = 0;
- int is_req = 0, has_non_esp_marker = 0;
-
- /* speculatively enqueue b0 to the current next frame */
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
-
- b0 = vlib_get_buffer (vm, bi0);
-
- if (b0->punt_reason == ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0])
- {
- u8 *ptr = vlib_buffer_get_current (b0);
- ip40 = (ip4_header_t *) ptr;
- ptr += sizeof (*ip40);
- udp0 = (udp_header_t *) ptr;
- ptr += sizeof (*udp0);
- ike0 = (ike_header_t *) ptr;
- }
- else
- {
- ike0 = vlib_buffer_get_current (b0);
- vlib_buffer_advance (b0, -sizeof (*udp0));
- udp0 = vlib_buffer_get_current (b0);
- vlib_buffer_advance (b0, -sizeof (*ip40));
- ip40 = vlib_buffer_get_current (b0);
- }
-
- rlen = b0->current_length - sizeof (*ip40) - sizeof (*udp0);
-
- /* check for non-esp marker */
- if (*((u32 *) ike0) == 0)
- {
- ike0 =
- (ike_header_t *) ((u8 *) ike0 +
- sizeof (ikev2_non_esp_marker));
- rlen -= sizeof (ikev2_non_esp_marker);
- has_non_esp_marker = 1;
- }
-
- if (clib_net_to_host_u32 (ike0->length) != rlen)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_BAD_LENGTH, 1);
- goto dispatch0;
- }
-
- if (ike0->version != IKE_VERSION_2)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_NOT_IKEV2, 1);
- goto dispatch0;
- }
-
- if (ike0->exchange == IKEV2_EXCHANGE_SA_INIT)
- {
- sa0 = &sa;
- clib_memset (sa0, 0, sizeof (*sa0));
-
- if (ike0->flags & IKEV2_HDR_FLAG_INITIATOR)
- {
- if (ike0->rspi == 0)
- {
- sa0->raddr.as_u32 = ip40->dst_address.as_u32;
- sa0->iaddr.as_u32 = ip40->src_address.as_u32;
- sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
-
- slen =
- ikev2_retransmit_sa_init (ike0, sa0->iaddr,
- sa0->raddr, rlen);
- if (slen)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- ~0 ==
- slen ?
- IKEV2_ERROR_IKE_SA_INIT_IGNORE
- :
- IKEV2_ERROR_IKE_SA_INIT_RETRANSMIT,
- 1);
- goto dispatch0;
- }
+ u8 *ptr = vlib_buffer_get_current (b0);
+ ip40 = (ip4_header_t *) ptr;
+ ptr += sizeof (*ip40);
+ udp0 = (udp_header_t *) ptr;
+ ptr += sizeof (*udp0);
+ ike0 = (ike_header_t *) ptr;
+ }
+ else
+ {
+ ike0 = vlib_buffer_get_current (b0);
+ vlib_buffer_advance (b0, -sizeof (*udp0));
+ udp0 = vlib_buffer_get_current (b0);
+ vlib_buffer_advance (b0, -sizeof (*ip40));
+ ip40 = vlib_buffer_get_current (b0);
+ }
- res = ikev2_process_sa_init_req (vm, sa0,
- ike0, udp0, rlen);
- if (!res)
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_MALFORMED_PACKET,
- 1);
+ rlen = b0->current_length - sizeof (*ip40) - sizeof (*udp0);
- if (sa0->state == IKEV2_STATE_SA_INIT)
- {
- ikev2_sa_free_proposal_vector (&sa0->r_proposals);
- sa0->r_proposals =
- ikev2_select_proposal (sa0->i_proposals,
- IKEV2_PROTOCOL_IKE);
- ikev2_generate_sa_init_data (sa0);
- }
+ /* check for non-esp marker */
+ if (*((u32 *) ike0) == 0)
+ {
+ ike0 =
+ (ike_header_t *) ((u8 *) ike0 + sizeof (ikev2_non_esp_marker));
+ rlen -= sizeof (ikev2_non_esp_marker);
+ has_non_esp_marker = 1;
+ }
- if (sa0->state == IKEV2_STATE_SA_INIT
- || sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE)
- {
- slen =
- ikev2_generate_message (b0, sa0, ike0, 0, udp0);
- if (~0 == slen)
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_NO_BUFF_SPACE,
- 1);
- }
+ if (clib_net_to_host_u32 (ike0->length) != rlen)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_BAD_LENGTH, 1);
+ goto dispatch0;
+ }
- if (sa0->state == IKEV2_STATE_SA_INIT)
- {
- /* add SA to the pool */
- pool_get (km->per_thread_data[thread_index].sas,
- sa0);
- clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
- ikev2_init_sa (vm, sa0);
- hash_set (km->
- per_thread_data[thread_index].sa_by_rspi,
- sa0->rspi,
- sa0 -
- km->per_thread_data[thread_index].sas);
- }
- else
- {
- ikev2_sa_free_all_vec (sa0);
- }
- }
- }
- else //received sa_init without initiator flag
- {
- sa0->raddr.as_u32 = ip40->src_address.as_u32;
- sa0->iaddr.as_u32 = ip40->dst_address.as_u32;
- ikev2_process_sa_init_resp (vm, sa0, ike0, udp0, rlen);
+ if (ike0->version != IKE_VERSION_2)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_NOT_IKEV2, 1);
+ goto dispatch0;
+ }
- if (sa0->state == IKEV2_STATE_SA_INIT)
- {
- is_req = 1;
- ike0->exchange = IKEV2_EXCHANGE_IKE_AUTH;
- uword *p = hash_get (km->sa_by_ispi, sa0->ispi);
- if (p)
- {
- ikev2_sa_t *sai =
- pool_elt_at_index (km->sais, p[0]);
-
- if (clib_atomic_bool_cmp_and_swap
- (&sai->init_response_received, 0, 1))
- {
- ikev2_complete_sa_data (sa0, sai);
- ikev2_calc_keys (sa0);
- ikev2_sa_auth_init (sa0);
- slen =
- ikev2_generate_message (b0, sa0, ike0, 0,
- udp0);
- if (~0 == slen)
- vlib_node_increment_counter (vm,
- ikev2_node.index,
- IKEV2_ERROR_NO_BUFF_SPACE,
- 1);
- }
- else
- {
- /* we've already processed sa-init response */
- sa0->state = IKEV2_STATE_UNKNOWN;
- }
- }
- }
+ if (ike0->exchange == IKEV2_EXCHANGE_SA_INIT)
+ {
+ sa0 = &sa;
+ clib_memset (sa0, 0, sizeof (*sa0));
- if (sa0->state == IKEV2_STATE_SA_INIT)
- {
- /* add SA to the pool */
- pool_get (km->per_thread_data[thread_index].sas, sa0);
- clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
- hash_set (km->per_thread_data[thread_index].sa_by_rspi,
- sa0->rspi,
- sa0 - km->per_thread_data[thread_index].sas);
- }
- else
- {
- ikev2_sa_free_all_vec (sa0);
- }
- }
- }
- else if (ike0->exchange == IKEV2_EXCHANGE_IKE_AUTH)
+ if (ike0->flags & IKEV2_HDR_FLAG_INITIATOR)
{
- uword *p;
- p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
- clib_net_to_host_u64 (ike0->rspi));
- if (p)
+ if (ike0->rspi == 0)
{
- sa0 =
- pool_elt_at_index (km->per_thread_data[thread_index].sas,
- p[0]);
+ sa0->raddr.as_u32 = ip40->dst_address.as_u32;
+ sa0->iaddr.as_u32 = ip40->src_address.as_u32;
+ sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
- slen = ikev2_retransmit_resp (sa0, ike0);
+ slen =
+ ikev2_retransmit_sa_init (ike0, sa0->iaddr,
+ sa0->raddr, rlen);
if (slen)
{
vlib_node_increment_counter (vm, ikev2_node.index,
~0 ==
slen ?
- IKEV2_ERROR_IKE_REQ_IGNORE
+ IKEV2_ERROR_IKE_SA_INIT_IGNORE
:
- IKEV2_ERROR_IKE_REQ_RETRANSMIT,
+ IKEV2_ERROR_IKE_SA_INIT_RETRANSMIT,
1);
goto dispatch0;
}
- sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
- res = ikev2_process_auth_req (vm, sa0, ike0, rlen);
- if (res)
- ikev2_sa_auth (sa0);
- else
+ res = ikev2_process_sa_init_req (vm, sa0, ike0, udp0, rlen);
+ if (!res)
vlib_node_increment_counter (vm, ikev2_node.index,
IKEV2_ERROR_MALFORMED_PACKET,
1);
- if (sa0->state == IKEV2_STATE_AUTHENTICATED)
- {
- ikev2_initial_contact_cleanup (sa0);
- ikev2_sa_match_ts (sa0);
- if (sa0->state != IKEV2_STATE_TS_UNACCEPTABLE)
- ikev2_create_tunnel_interface (vm, thread_index, sa0,
- &sa0->childs[0],
- p[0], 0, 0);
- }
- if (sa0->is_initiator)
+ if (sa0->state == IKEV2_STATE_SA_INIT)
{
- ikev2_del_sa_init (sa0->ispi);
+ ikev2_sa_free_proposal_vector (&sa0->r_proposals);
+ sa0->r_proposals =
+ ikev2_select_proposal (sa0->i_proposals,
+ IKEV2_PROTOCOL_IKE);
+ ikev2_generate_sa_init_data (sa0);
}
- else
+
+ if (sa0->state == IKEV2_STATE_SA_INIT
+ || sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE)
{
slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
@@ -2927,237 +2780,336 @@ ikev2_node_fn (vlib_main_t * vm,
IKEV2_ERROR_NO_BUFF_SPACE,
1);
}
- }
- }
- else if (ike0->exchange == IKEV2_EXCHANGE_INFORMATIONAL)
- {
- uword *p;
- p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
- clib_net_to_host_u64 (ike0->rspi));
- if (p)
- {
- sa0 =
- pool_elt_at_index (km->per_thread_data[thread_index].sas,
- p[0]);
-
- slen = ikev2_retransmit_resp (sa0, ike0);
- if (slen)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- ~0 ==
- slen ?
- IKEV2_ERROR_IKE_REQ_IGNORE
- :
- IKEV2_ERROR_IKE_REQ_RETRANSMIT,
- 1);
- goto dispatch0;
- }
- res = ikev2_process_informational_req (vm, sa0, ike0, rlen);
- if (!res)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_MALFORMED_PACKET,
- 1);
- slen = ~0;
- goto dispatch0;
- }
-
- if (sa0->del)
+ if (sa0->state == IKEV2_STATE_SA_INIT)
{
- if (sa0->del[0].protocol_id != IKEV2_PROTOCOL_IKE)
- {
- ikev2_delete_t *d, *tmp, *resp = 0;
- vec_foreach (d, sa0->del)
- {
- ikev2_child_sa_t *ch_sa;
- ch_sa = ikev2_sa_get_child (sa0, d->spi,
- d->protocol_id,
- !sa0->is_initiator);
- if (ch_sa)
- {
- ikev2_delete_tunnel_interface (km->vnet_main,
- sa0, ch_sa);
- if (!sa0->is_initiator)
- {
- vec_add2 (resp, tmp, 1);
- tmp->protocol_id = d->protocol_id;
- tmp->spi = ch_sa->r_proposals[0].spi;
- }
- ikev2_sa_del_child_sa (sa0, ch_sa);
- }
- }
- if (!sa0->is_initiator)
- {
- vec_free (sa0->del);
- sa0->del = resp;
- }
- }
+ /* add SA to the pool */
+ pool_get (ptd->sas, sa0);
+ clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
+ ikev2_init_sa (vm, sa0);
+ hash_set (ptd->sa_by_rspi, sa0->rspi, sa0 - ptd->sas);
}
- if (!(ike0->flags & IKEV2_HDR_FLAG_RESPONSE))
+ else
{
- ike0->flags |= IKEV2_HDR_FLAG_RESPONSE;
- slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
- if (~0 == slen)
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_NO_BUFF_SPACE,
- 1);
+ ikev2_sa_free_all_vec (sa0);
}
}
}
- else if (ike0->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
+ else //received sa_init without initiator flag
{
- uword *p;
- p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
- clib_net_to_host_u64 (ike0->rspi));
- if (p)
- {
- sa0 =
- pool_elt_at_index (km->per_thread_data[thread_index].sas,
- p[0]);
+ sa0->raddr.as_u32 = ip40->src_address.as_u32;
+ sa0->iaddr.as_u32 = ip40->dst_address.as_u32;
+ ikev2_process_sa_init_resp (vm, sa0, ike0, udp0, rlen);
- slen = ikev2_retransmit_resp (sa0, ike0);
- if (slen)
- {
- vlib_node_increment_counter (vm, ikev2_node.index,
- ~0 ==
- slen ?
- IKEV2_ERROR_IKE_REQ_IGNORE
- :
- IKEV2_ERROR_IKE_REQ_RETRANSMIT,
- 1);
- goto dispatch0;
- }
-
- res = ikev2_process_create_child_sa_req (vm, sa0,
- ike0, rlen);
- if (!res)
+ if (sa0->state == IKEV2_STATE_SA_INIT)
+ {
+ is_req = 1;
+ ike0->exchange = IKEV2_EXCHANGE_IKE_AUTH;
+ uword *p = hash_get (km->sa_by_ispi, sa0->ispi);
+ if (p)
{
- vlib_node_increment_counter (vm, ikev2_node.index,
- IKEV2_ERROR_MALFORMED_PACKET,
- 1);
- slen = ~0;
- goto dispatch0;
- }
+ ikev2_sa_t *sai = pool_elt_at_index (km->sais, p[0]);
- if (sa0->rekey)
- {
- if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
- {
- if (sa0->childs)
- ikev2_sa_free_all_child_sa (&sa0->childs);
- ikev2_child_sa_t *child;
- vec_add2 (sa0->childs, child, 1);
- clib_memset (child, 0, sizeof (*child));
- child->r_proposals = sa0->rekey[0].r_proposal;
- child->i_proposals = sa0->rekey[0].i_proposal;
- child->tsi = sa0->rekey[0].tsi;
- child->tsr = sa0->rekey[0].tsr;
- ikev2_create_tunnel_interface (vm, thread_index,
- sa0, child, p[0],
- child - sa0->childs,
- 1);
- }
- if (sa0->is_initiator)
- {
- vec_free (sa0->rekey);
- }
- else
+ if (clib_atomic_bool_cmp_and_swap
+ (&sai->init_response_received, 0, 1))
{
+ ikev2_complete_sa_data (sa0, sai);
+ ikev2_calc_keys (sa0);
+ ikev2_sa_auth_init (sa0);
slen =
ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
- vlib_node_increment_counter (vm, ikev2_node.index,
+ vlib_node_increment_counter (vm,
+ ikev2_node.index,
IKEV2_ERROR_NO_BUFF_SPACE,
1);
}
+ else
+ {
+ /* we've already processed sa-init response */
+ sa0->state = IKEV2_STATE_UNKNOWN;
+ }
}
}
+
+ if (sa0->state == IKEV2_STATE_SA_INIT)
+ {
+ /* add SA to the pool */
+ pool_get (ptd->sas, sa0);
+ clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
+ hash_set (ptd->sa_by_rspi, sa0->rspi, sa0 - ptd->sas);
+ }
+ else
+ {
+ ikev2_sa_free_all_vec (sa0);
+ }
}
- else
+ }
+ else if (ike0->exchange == IKEV2_EXCHANGE_IKE_AUTH)
+ {
+ uword *p;
+ p = hash_get (ptd->sa_by_rspi, clib_net_to_host_u64 (ike0->rspi));
+ if (p)
{
- ikev2_elog_uint_peers (IKEV2_LOG_WARNING, "IKEv2 exchange %d "
- "received from %d.%d.%d.%d to %d.%d.%d.%d",
- ike0->exchange,
- ip40->src_address.as_u32,
- ip40->dst_address.as_u32);
- }
+ sa0 = pool_elt_at_index (ptd->sas, p[0]);
+ slen = ikev2_retransmit_resp (sa0, ike0);
+ if (slen)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ ~0 ==
+ slen ?
+ IKEV2_ERROR_IKE_REQ_IGNORE
+ :
+ IKEV2_ERROR_IKE_REQ_RETRANSMIT,
+ 1);
+ goto dispatch0;
+ }
+
+ sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
+ res = ikev2_process_auth_req (vm, sa0, ike0, rlen);
+ if (res)
+ ikev2_sa_auth (sa0);
+ else
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_MALFORMED_PACKET, 1);
+ if (sa0->state == IKEV2_STATE_AUTHENTICATED)
+ {
+ ikev2_initial_contact_cleanup (sa0);
+ ikev2_sa_match_ts (sa0);
+ if (sa0->state != IKEV2_STATE_TS_UNACCEPTABLE)
+ ikev2_create_tunnel_interface (vm, sa0,
+ &sa0->childs[0],
+ p[0], 0, 0);
+ }
- dispatch0:
- /* if we are sending packet back, rewrite headers */
- if (slen && ~0 != slen)
- {
- next0 = IKEV2_NEXT_IP4_LOOKUP;
if (sa0->is_initiator)
{
- ip40->dst_address.as_u32 = sa0->raddr.as_u32;
- ip40->src_address.as_u32 = sa0->iaddr.as_u32;
+ ikev2_del_sa_init (sa0->ispi);
}
else
{
- ip40->dst_address.as_u32 = sa0->iaddr.as_u32;
- ip40->src_address.as_u32 = sa0->raddr.as_u32;
+ slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ if (~0 == slen)
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_NO_BUFF_SPACE,
+ 1);
+ }
+ }
+ }
+ else if (ike0->exchange == IKEV2_EXCHANGE_INFORMATIONAL)
+ {
+ uword *p;
+ p = hash_get (ptd->sa_by_rspi, clib_net_to_host_u64 (ike0->rspi));
+ if (p)
+ {
+ sa0 = pool_elt_at_index (ptd->sas, p[0]);
+ slen = ikev2_retransmit_resp (sa0, ike0);
+ if (slen)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ ~0 ==
+ slen ?
+ IKEV2_ERROR_IKE_REQ_IGNORE
+ :
+ IKEV2_ERROR_IKE_REQ_RETRANSMIT,
+ 1);
+ goto dispatch0;
}
- if (is_req)
+ res = ikev2_process_informational_req (vm, sa0, ike0, rlen);
+ if (!res)
{
- udp0->dst_port = udp0->src_port =
- clib_net_to_host_u16 (ikev2_get_port (sa0));
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_MALFORMED_PACKET,
+ 1);
+ slen = ~0;
+ goto dispatch0;
+ }
- if (udp0->dst_port == clib_net_to_host_u16 (IKEV2_PORT_NATT)
- && sa0->natt)
+ if (sa0->del)
+ {
+ if (sa0->del[0].protocol_id != IKEV2_PROTOCOL_IKE)
{
- if (!has_non_esp_marker)
- slen = ikev2_insert_non_esp_marker (ike0, slen);
+ ikev2_delete_t *d, *tmp, *resp = 0;
+ vec_foreach (d, sa0->del)
+ {
+ ikev2_child_sa_t *ch_sa;
+ ch_sa = ikev2_sa_get_child (sa0, d->spi,
+ d->protocol_id,
+ !sa0->is_initiator);
+ if (ch_sa)
+ {
+ ikev2_delete_tunnel_interface (km->vnet_main,
+ sa0, ch_sa);
+ if (!sa0->is_initiator)
+ {
+ vec_add2 (resp, tmp, 1);
+ tmp->protocol_id = d->protocol_id;
+ tmp->spi = ch_sa->r_proposals[0].spi;
+ }
+ ikev2_sa_del_child_sa (sa0, ch_sa);
+ }
+ }
+ if (!sa0->is_initiator)
+ {
+ vec_free (sa0->del);
+ sa0->del = resp;
+ }
}
}
- else
+ if (!(ike0->flags & IKEV2_HDR_FLAG_RESPONSE))
{
- if (has_non_esp_marker)
- slen += sizeof (ikev2_non_esp_marker);
+ ike0->flags |= IKEV2_HDR_FLAG_RESPONSE;
+ slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ if (~0 == slen)
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_NO_BUFF_SPACE,
+ 1);
+ }
+ }
+ }
+ else if (ike0->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
+ {
+ uword *p;
+ p = hash_get (ptd->sa_by_rspi, clib_net_to_host_u64 (ike0->rspi));
+ if (p)
+ {
+ sa0 = pool_elt_at_index (ptd->sas, p[0]);
+ slen = ikev2_retransmit_resp (sa0, ike0);
+ if (slen)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ ~0 ==
+ slen ?
+ IKEV2_ERROR_IKE_REQ_IGNORE
+ :
+ IKEV2_ERROR_IKE_REQ_RETRANSMIT,
+ 1);
+ goto dispatch0;
+ }
- u16 tp = udp0->dst_port;
- udp0->dst_port = udp0->src_port;
- udp0->src_port = tp;
+ res = ikev2_process_create_child_sa_req (vm, sa0, ike0, rlen);
+ if (!res)
+ {
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_MALFORMED_PACKET,
+ 1);
+ slen = ~0;
+ goto dispatch0;
}
- udp0->length =
- clib_host_to_net_u16 (slen + sizeof (udp_header_t));
- udp0->checksum = 0;
- b0->current_length =
- slen + sizeof (ip4_header_t) + sizeof (udp_header_t);
- ip40->length = clib_host_to_net_u16 (b0->current_length);
- ip40->checksum = ip4_header_checksum (ip40);
+ if (sa0->rekey)
+ {
+ if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
+ {
+ if (sa0->childs)
+ ikev2_sa_free_all_child_sa (&sa0->childs);
+ ikev2_child_sa_t *child;
+ vec_add2 (sa0->childs, child, 1);
+ clib_memset (child, 0, sizeof (*child));
+ child->r_proposals = sa0->rekey[0].r_proposal;
+ child->i_proposals = sa0->rekey[0].i_proposal;
+ child->tsi = sa0->rekey[0].tsi;
+ child->tsr = sa0->rekey[0].tsr;
+ ikev2_create_tunnel_interface (vm, sa0, child, p[0],
+ child - sa0->childs, 1);
+ }
+ if (sa0->is_initiator)
+ {
+ vec_free (sa0->rekey);
+ }
+ else
+ {
+ slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ if (~0 == slen)
+ vlib_node_increment_counter (vm, ikev2_node.index,
+ IKEV2_ERROR_NO_BUFF_SPACE,
+ 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ ikev2_elog_uint_peers (IKEV2_LOG_WARNING, "IKEv2 exchange %d "
+ "received from %d.%d.%d.%d to %d.%d.%d.%d",
+ ike0->exchange,
+ ip40->src_address.as_u32,
+ ip40->dst_address.as_u32);
+ }
+
+ dispatch0:
+ /* if we are sending packet back, rewrite headers */
+ if (slen && ~0 != slen)
+ {
+ next[0] = IKEV2_NEXT_IP4_LOOKUP;
+ if (sa0->is_initiator)
+ {
+ ip40->dst_address.as_u32 = sa0->raddr.as_u32;
+ ip40->src_address.as_u32 = sa0->iaddr.as_u32;
}
- /* delete sa */
- if (sa0 && (sa0->state == IKEV2_STATE_DELETED ||
- sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE))
+ else
{
- ikev2_child_sa_t *c;
+ ip40->dst_address.as_u32 = sa0->iaddr.as_u32;
+ ip40->src_address.as_u32 = sa0->raddr.as_u32;
+ }
- vec_foreach (c, sa0->childs)
- ikev2_delete_tunnel_interface (km->vnet_main, sa0, c);
+ if (is_req)
+ {
+ udp0->dst_port = udp0->src_port =
+ clib_net_to_host_u16 (ikev2_get_port (sa0));
- ikev2_delete_sa (sa0);
+ if (udp0->dst_port == clib_net_to_host_u16 (IKEV2_PORT_NATT)
+ && sa0->natt)
+ {
+ if (!has_non_esp_marker)
+ slen = ikev2_insert_non_esp_marker (ike0, slen);
+ }
}
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ else
{
+ if (has_non_esp_marker)
+ slen += sizeof (ikev2_non_esp_marker);
- ikev2_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
- t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
- t->next_index = next0;
+ u16 tp = udp0->dst_port;
+ udp0->dst_port = udp0->src_port;
+ udp0->src_port = tp;
}
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
+ udp0->length = clib_host_to_net_u16 (slen + sizeof (udp_header_t));
+ udp0->checksum = 0;
+ b0->current_length =
+ slen + sizeof (ip4_header_t) + sizeof (udp_header_t);
+ ip40->length = clib_host_to_net_u16 (b0->current_length);
+ ip40->checksum = ip4_header_checksum (ip40);
}
+ /* delete sa */
+ if (sa0 && (sa0->state == IKEV2_STATE_DELETED ||
+ sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE))
+ {
+ ikev2_child_sa_t *c;
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ vec_foreach (c, sa0->childs)
+ ikev2_delete_tunnel_interface (km->vnet_main, sa0, c);
+
+ ikev2_delete_sa (sa0);
+ }
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
+ && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+
+ ikev2_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ t->next_index = next[0];
+ }
+ n_left -= 1;
+ next += 1;
+ b += 1;
}
vlib_node_increment_counter (vm, ikev2_node.index,
IKEV2_ERROR_PROCESSED, frame->n_vectors);
+ vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
return frame->n_vectors;
}
@@ -3176,7 +3128,7 @@ VLIB_REGISTER_NODE (ikev2_node,static) = {
.next_nodes = {
[IKEV2_NEXT_IP4_LOOKUP] = "ip4-lookup",
- [IKEV2_NEXT_ERROR_DROP] = "error-drop",
+ [IKEV2_NEXT_ERROR_DROP] = "error-drop",
},
};
/* *INDENT-ON* */