static_always_inline u16
ikev2_get_port (ikev2_sa_t * sa)
{
- return sa->natt ? IKEV2_PORT_NATT : IKEV2_PORT;
+ return ikev2_natt_active (sa) ? IKEV2_PORT_NATT : IKEV2_PORT;
}
static_always_inline int
sa->profile_index = sai->profile_index;
sa->tun_itf = sai->tun_itf;
sa->is_tun_itf_set = sai->is_tun_itf_set;
+ sa->natt_state = sai->natt_state;
sa->i_id.data = _(sai->i_id.data);
sa->r_id.data = _(sai->r_id.data);
sa->i_auth.method = sai->i_auth.method;
clib_memcpy_fast (&buf[8], &rspi, sizeof (rspi));
clib_memcpy_fast (&buf[8 + 8], ip_addr_bytes (ia), ip_address_size (ia));
clib_memcpy_fast (&buf[8 + 8 + ip_address_size (ia)], &port, sizeof (port));
- SHA1 (buf, sizeof (buf), res);
+ SHA1 (buf, 2 * sizeof (ispi) + sizeof (port) + ip_address_size (ia), res);
return res;
}
udp->src_port);
if (clib_memcmp (src_sha, n->data, vec_len (src_sha)))
{
- sa->natt = 1;
+ if (sa->natt_state == IKEV2_NATT_ENABLED)
+ sa->natt_state = IKEV2_NATT_ACTIVE;
ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx initiator"
" behind NAT", sa->ispi);
}
udp->dst_port);
if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha)))
{
- sa->natt = 1;
+ if (sa->natt_state == IKEV2_NATT_ENABLED)
+ sa->natt_state = IKEV2_NATT_ACTIVE;
ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx responder"
" (self) behind NAT", sa->ispi);
}
udp->dst_port);
if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha)))
{
- sa->natt = 1;
+ if (sa->natt_state == IKEV2_NATT_ENABLED)
+ sa->natt_state = IKEV2_NATT_ACTIVE;
ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx initiator"
" (self) behind NAT", sa->ispi);
}
rekey->tsi = tsi;
rekey->tsr = tsr;
/* update Ni */
- vec_free (sa->i_nonce);
+ vec_reset_length (sa->i_nonce);
vec_add (sa->i_nonce, nonce, IKEV2_NONCE_SIZE);
/* generate new Nr */
vec_validate (sa->r_nonce, IKEV2_NONCE_SIZE - 1);
RAND_bytes ((u8 *) sa->r_nonce, IKEV2_NONCE_SIZE);
- vec_free (n);
}
+ else
+ goto cleanup_and_exit;
+ vec_free (n);
return 1;
cleanup_and_exit:
vec_free (n);
+ vec_free (proposal);
+ vec_free (tsr);
+ vec_free (tsi);
return 0;
}
IPSEC_PROTOCOL_ESP, a->encr_type,
&a->loc_ckey, a->integ_type, &a->loc_ikey,
a->flags, 0, a->salt_local, &zero_addr,
- &zero_addr, NULL, a->src_port, a->dst_port);
+ &zero_addr, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+ IP_DSCP_CS0, NULL, a->src_port, a->dst_port);
+
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, &zero_addr,
- &zero_addr, NULL, a->ipsec_over_udp_port,
+ &zero_addr, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+ IP_DSCP_CS0, NULL,
+ a->ipsec_over_udp_port,
a->ipsec_over_udp_port);
rv |= ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in);
a.flags |= IPSEC_SA_FLAG_IS_TUNNEL;
a.flags |= IPSEC_SA_FLAG_UDP_ENCAP;
}
- if (sa->natt)
+ if (ikev2_natt_active (sa))
a.flags |= IPSEC_SA_FLAG_UDP_ENCAP;
a.is_rekey = is_rekey;
a.salt_remote = child->salt_ei;
a.salt_local = child->salt_er;
}
- a.dst_port = sa->natt ? sa->dst_port : sa->ipsec_over_udp_port;
+ a.dst_port =
+ ikev2_natt_active (sa) ? sa->dst_port : sa->ipsec_over_udp_port;
a.src_port = sa->ipsec_over_udp_port;
}
{
if (sa->del[0].protocol_id == IKEV2_PROTOCOL_IKE)
{
- if (sa->is_initiator)
+ if (ike_hdr_is_request (ike))
ikev2_payload_add_delete (chain, sa->del);
/* The response to a request that deletes the IKE SA is an empty
ike->version = IKE_VERSION_2;
ike->nextpayload = IKEV2_PAYLOAD_SK;
tlen = sizeof (*ike);
+
if (sa->is_initiator)
+ ike->flags |= IKEV2_HDR_FLAG_INITIATOR;
+
+ if (ike_hdr_is_request (ike))
{
- ike->flags = IKEV2_HDR_FLAG_INITIATOR;
sa->last_init_msg_id = clib_net_to_host_u32 (ike->msgid);
}
- else
- {
- ike->flags = IKEV2_HDR_FLAG_RESPONSE;
- }
-
if (ike->exchange == IKEV2_EXCHANGE_SA_INIT)
{
static u32
ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike)
{
+ if (ike_hdr_is_response (ike))
+ return 0;
+
u32 msg_id = clib_net_to_host_u32 (ike->msgid);
/* new req */
}
static_always_inline void
-ikev2_set_ip_address (ikev2_sa_t * sa, const void *src,
- const void *dst, const int af, const int is_initiator)
+ikev2_set_ip_address (ikev2_sa_t * sa, const void *iaddr,
+ const void *raddr, const int af)
{
- const void *raddr = is_initiator ? src : dst;
- const void *iaddr = is_initiator ? dst : src;
ip_address_set (&sa->raddr, raddr, af);
ip_address_set (&sa->iaddr, iaddr, af);
}
sa0 = &sa;
clib_memset (sa0, 0, sizeof (*sa0));
- u8 is_initiator = ike0->flags & IKEV2_HDR_FLAG_INITIATOR;
- if (is_initiator)
+ if (ike_hdr_is_initiator (ike0))
{
if (ike0->rspi == 0)
{
if (is_ip4)
- ikev2_set_ip_address (sa0, &ip40->dst_address,
- &ip40->src_address, AF_IP4,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip40->src_address,
+ &ip40->dst_address, AF_IP4);
else
- ikev2_set_ip_address (sa0, &ip60->dst_address,
- &ip60->src_address, AF_IP6,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip60->src_address,
+ &ip60->dst_address, AF_IP6);
sa0->dst_port = clib_net_to_host_u16 (udp0->src_port);
if (sa0->state == IKEV2_STATE_SA_INIT
|| sa0->state == IKEV2_STATE_NOTIFY_AND_DELETE)
{
+ ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
else //received sa_init without initiator flag
{
if (is_ip4)
- ikev2_set_ip_address (sa0, &ip40->src_address,
- &ip40->dst_address, AF_IP4,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip40->dst_address,
+ &ip40->src_address, AF_IP4);
else
- ikev2_set_ip_address (sa0, &ip60->src_address,
- &ip60->dst_address, AF_IP6,
- is_initiator);
+ ikev2_set_ip_address (sa0, &ip60->dst_address,
+ &ip60->src_address, AF_IP6);
ikev2_process_sa_init_resp (vm, sa0, ike0, udp0, rlen);
ikev2_complete_sa_data (sa0, sai);
ikev2_calc_keys (sa0);
ikev2_sa_auth_init (sa0);
+ ike0->flags = IKEV2_HDR_FLAG_INITIATOR;
slen =
ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
}
}
}
- if (!(ike0->flags & IKEV2_HDR_FLAG_RESPONSE))
+ if (ike_hdr_is_request (ike0))
{
- ike0->flags |= IKEV2_HDR_FLAG_RESPONSE;
+ ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
ikev2_create_tunnel_interface (vm, sa0, child, p[0],
child - sa0->childs, 1);
}
- if (sa0->is_initiator)
+ if (ike_hdr_is_response (ike0))
{
vec_free (sa0->rekey);
}
else
{
+ ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
clib_net_to_host_u16 (ikev2_get_port (sa0));
if (udp0->dst_port == clib_net_to_host_u16 (IKEV2_PORT_NATT)
- && sa0->natt)
+ && ikev2_natt_active (sa0))
{
if (!has_non_esp_marker)
slen = ikev2_insert_non_esp_marker (ike0, slen);
ike0->exchange = IKEV2_EXCHANGE_INFORMATIONAL;
ike0->ispi = clib_host_to_net_u64 (sa->ispi);
ike0->rspi = clib_host_to_net_u64 (sa->rspi);
-
+ ike0->flags = 0;
ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id + 1);
sa->last_init_msg_id = clib_net_to_host_u32 (ike0->msgid);
len = ikev2_generate_message (b0, sa, ike0, 0, 0);
if (~0 == len)
return;
- if (sa->natt)
+ if (ikev2_natt_active (sa))
len = ikev2_insert_non_esp_marker (ike0, len);
if (sa->is_initiator)
sa.state = IKEV2_STATE_SA_INIT;
sa.tun_itf = p->tun_itf;
sa.udp_encap = p->udp_encap;
+ if (p->natt_disabled)
+ sa.natt_state = IKEV2_NATT_DISABLED;
sa.ipsec_over_udp_port = p->ipsec_over_udp_port;
sa.is_tun_itf_set = 1;
sa.initial_contact = 1;
ike0->exchange = IKEV2_EXCHANGE_INFORMATIONAL;
ike0->ispi = clib_host_to_net_u64 (sa->ispi);
ike0->rspi = clib_host_to_net_u64 (sa->rspi);
+ ike0->flags = 0;
vec_resize (sa->del, 1);
sa->del->protocol_id = IKEV2_PROTOCOL_ESP;
sa->del->spi = csa->i_proposals->spi;
if (~0 == len)
return;
- if (sa->natt)
+ if (ikev2_natt_active (sa))
len = ikev2_insert_non_esp_marker (ike0, len);
ikev2_send_ike (vm, &sa->iaddr, &sa->raddr, bi0, len,
ikev2_get_port (sa), sa->dst_port, sa->sw_if_index);
if (~0 == len)
return;
- if (sa->natt)
+ if (ikev2_natt_active (sa))
len = ikev2_insert_non_esp_marker (ike0, len);
ikev2_send_ike (vm, &sa->iaddr, &sa->raddr, bi0, len,
ikev2_get_port (sa), ikev2_get_port (sa), sa->sw_if_index);
return 0;
}
+clib_error_t *
+ikev2_profile_natt_disable (u8 * name)
+{
+ ikev2_profile_t *p = ikev2_profile_index_by_name (name);
+ if (!p)
+ return clib_error_return (0, "unknown profile %v", name);
+
+ p->natt_disabled = 1;
+ return 0;
+}
+
static void
ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
{
}
}
-static ike_payload_header_t *
-ikev2_find_ike_payload (ike_header_t * ike, u32 payload_type)
-{
- int p = 0;
- ike_payload_header_t *ikep;
- u32 payload = ike->nextpayload;
-
- while (payload != IKEV2_PAYLOAD_NONE)
- {
- ikep = (ike_payload_header_t *) & ike->payload[p];
- if (payload == payload_type)
- return ikep;
-
- u16 plen = clib_net_to_host_u16 (ikep->length);
- payload = ikep->nextpayload;
- p += plen;
- }
- return 0;
-}
-
static void
ikev2_process_pending_sa_init_one (ikev2_main_t * km, ikev2_sa_t * sa)
{
ikev2_profile_t *p;
u32 bi0;
- u8 *nat_sha;
- ike_payload_header_t *ph;
+ u8 *nat_sha, *np;
if (ip_address_is_zero (&sa->iaddr))
{
return;
/* update NAT detection payload */
- ph =
- ikev2_find_ike_payload ((ike_header_t *)
- sa->last_sa_init_req_packet_data,
- IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP);
- if (!ph)
- return;
-
- nat_sha =
- ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi),
- clib_host_to_net_u64 (sa->rspi),
- &sa->iaddr,
- clib_host_to_net_u16 (IKEV2_PORT));
- clib_memcpy_fast (ph->payload, nat_sha, vec_len (nat_sha));
- vec_free (nat_sha);
+ np =
+ ikev2_find_ike_notify_payload
+ ((ike_header_t *) sa->last_sa_init_req_packet_data,
+ IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP);
+ if (np)
+ {
+ nat_sha =
+ ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi),
+ clib_host_to_net_u64 (sa->rspi),
+ &sa->iaddr,
+ clib_host_to_net_u16 (IKEV2_PORT));
+ clib_memcpy_fast (np, nat_sha, vec_len (nat_sha));
+ vec_free (nat_sha);
+ }
}
if (vlib_buffer_alloc (km->vlib_main, &bi0, 1) != 1)
ike0->ispi = clib_host_to_net_u64 (sa->ispi);
ike0->rspi = clib_host_to_net_u64 (sa->rspi);
ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id + 1);
+ ike0->flags = 0;
sa->last_init_msg_id = clib_net_to_host_u32 (ike0->msgid);
len = ikev2_generate_message (b0, sa, ike0, 0, 0);
if (~0 == len)
return;
- if (sa->natt)
+ if (ikev2_natt_active (sa))
len = ikev2_insert_non_esp_marker (ike0, len);
if (sa->is_initiator)
sa->sw_if_index);
}
+void
+ikev2_disable_dpd (void)
+{
+ ikev2_main_t *km = &ikev2_main;
+ km->dpd_disabled = 1;
+}
+
static_always_inline int
ikev2_mngr_process_responder_sas (ikev2_sa_t * sa)
{
while (1)
{
- u8 req_sent = 0;
- vlib_process_wait_for_event_or_clock (vm, 1);
+ vlib_process_wait_for_event_or_clock (vm, 2);
vlib_process_get_events (vm, NULL);
/* process ike child sas */
sa->old_id_expiration -= 1;
vec_foreach (c, sa->childs)
- {
- req_sent |= ikev2_mngr_process_child_sa(sa, c, del_old_ids);
- }
+ ikev2_mngr_process_child_sa(sa, c, del_old_ids);
- if (ikev2_mngr_process_responder_sas (sa))
+ if (!km->dpd_disabled && ikev2_mngr_process_responder_sas (sa))
vec_add1 (to_be_deleted, sa - tkm->sas);
}));
/* *INDENT-ON* */
/* *INDENT-ON* */
ikev2_process_pending_sa_init (km);
-
- if (req_sent)
- {
- vlib_process_wait_for_event_or_clock (vm, 5);
- vlib_process_get_events (vm, NULL);
- req_sent = 0;
- }
-
}
return 0;
}