#include <plugins/ikev2/ikev2_priv.h>
#include <openssl/sha.h>
#include <vnet/ipsec/ipsec_punt.h>
+#include <plugins/ikev2/ikev2.api_enum.h>
#define IKEV2_LIVENESS_RETRIES 3
#define IKEV2_LIVENESS_PERIOD_CHECK 30
ikev2_sa_t * sa,
ikev2_child_sa_t * child);
-#define ikev2_set_state(sa, v) do { \
+#define ikev2_set_state(sa, v, ...) do { \
(sa)->state = v; \
- ikev2_elog_sa_state("ispi %lx SA state changed to " #v, sa->ispi); \
+ ikev2_elog_sa_state("ispi %lx SA state changed to " #v __VA_ARGS__, sa->ispi); \
} while(0);
typedef struct
u32 sw_if_index;
} ikev2_trace_t;
+typedef struct
+{
+ u16 n_keepalives;
+ u16 n_rekey_req;
+ u16 n_exchange_sa_req;
+ u16 n_ike_auth_req;
+} ikev2_stats_t;
+
static u8 *
format_ikev2_trace (u8 * s, va_list * args)
{
return s;
}
-#define foreach_ikev2_error \
-_(PROCESSED, "IKEv2 packets processed") \
-_(IKE_SA_INIT_RETRANSMIT, "IKE_SA_INIT retransmit ") \
-_(IKE_SA_INIT_IGNORE, "IKE_SA_INIT ignore (IKE SA already auth)") \
-_(IKE_REQ_RETRANSMIT, "IKE request retransmit") \
-_(IKE_REQ_IGNORE, "IKE request ignore (old msgid)") \
-_(NOT_IKEV2, "Non IKEv2 packets received") \
-_(BAD_LENGTH, "Bad packet length") \
-_(MALFORMED_PACKET, "Malformed packet") \
-_(NO_BUFF_SPACE, "No buffer space")
+#define IKEV2_GENERATE_SA_INIT_OK_str ""
+#define IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR \
+ "no DH group configured for IKE proposals!"
+#define IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR \
+ "DH group not supported!"
typedef enum
{
-#define _(sym,str) IKEV2_ERROR_##sym,
- foreach_ikev2_error
-#undef _
- IKEV2_N_ERROR,
-} ikev2_error_t;
+ IKEV2_GENERATE_SA_INIT_OK,
+ IKEV2_GENERATE_SA_INIT_ERR_NO_DH,
+ IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH,
+} ikev2_generate_sa_error_t;
-static char *ikev2_error_strings[] = {
-#define _(sym,string) string,
- foreach_ikev2_error
-#undef _
-};
+static u8 *
+format_ikev2_gen_sa_error (u8 * s, va_list * args)
+{
+ ikev2_generate_sa_error_t e = va_arg (*args, ikev2_generate_sa_error_t);
+ switch (e)
+ {
+ case IKEV2_GENERATE_SA_INIT_OK:
+ break;
+ case IKEV2_GENERATE_SA_INIT_ERR_NO_DH:
+ s = format (s, IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR);
+ break;
+ case IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH:
+ s = format (s, IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR);
+ break;
+ }
+ return s;
+}
typedef enum
{
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
}
}
-static void
+static ikev2_generate_sa_error_t
ikev2_generate_sa_init_data (ikev2_sa_t * sa)
{
ikev2_sa_transform_t *t = 0, *t2;
ikev2_main_t *km = &ikev2_main;
if (sa->dh_group == IKEV2_TRANSFORM_DH_TYPE_NONE)
- {
- return;
- }
+ return IKEV2_GENERATE_SA_INIT_ERR_NO_DH;
/* check if received DH group is on our list of supported groups */
vec_foreach (t2, km->supported_transforms)
if (!t)
{
sa->dh_group = IKEV2_TRANSFORM_DH_TYPE_NONE;
- return;
+ return IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH;
}
if (sa->is_initiator)
/* generate dh keys */
ikev2_generate_dh (sa, t);
+ return IKEV2_GENERATE_SA_INIT_OK;
}
static void
sa->profile_index = sai->profile_index;
sa->tun_itf = sai->tun_itf;
sa->is_tun_itf_set = sai->is_tun_itf_set;
+ if (sai->natt_state == IKEV2_NATT_DISABLED)
+ sa->natt_state = IKEV2_NATT_DISABLED;
sa->i_id.data = _(sai->i_id.data);
sa->r_id.data = _(sai->r_id.data);
sa->i_auth.method = sai->i_auth.method;
sa->i_auth.data = _(sai->i_auth.data);
sa->i_auth.key = _(sai->i_auth.key);
sa->last_sa_init_req_packet_data = _(sai->last_sa_init_req_packet_data);
+ sa->last_init_msg_id = sai->last_init_msg_id;
sa->childs = _(sai->childs);
sa->udp_encap = sai->udp_encap;
sa->ipsec_over_udp_port = sai->ipsec_over_udp_port;
}
static int
-ikev2_process_sa_init_req (vlib_main_t * vm,
- ikev2_sa_t * sa, ike_header_t * ike,
- udp_header_t * udp, u32 len)
+ikev2_process_sa_init_req (vlib_main_t *vm, ikev2_sa_t *sa, ike_header_t *ike,
+ udp_header_t *udp, u32 len, u32 sw_if_index)
{
u8 nonce[IKEV2_NONCE_SIZE];
int p = 0;
ip_addr_version (&sa->iaddr) == AF_IP4);
sa->ispi = clib_net_to_host_u64 (ike->ispi);
+ sa->sw_if_index = sw_if_index;
/* store whole IKE payload - needed for PSK auth */
vec_reset_length (sa->last_sa_init_req_packet_data);
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);
}
/* find old IKE SAs with the same authenticated identity */
/* *INDENT-OFF* */
- pool_foreach (tmp, ptd->sas, ({
+ 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 - ptd->sas);
- }));
+ }
/* *INDENT-ON* */
for (i = 0; i < vec_len (delete); i++)
return 1;
malformed:
- ikev2_set_state (sa, IKEV2_STATE_DELETED);
+ ikev2_set_state (sa, IKEV2_STATE_DELETED, ": malformed IKE_AUTH");
return 0;
}
p += plen;
}
- if (sa->is_initiator && proposal->protocol_id == IKEV2_PROTOCOL_ESP)
+ if (sa->is_initiator && proposal
+ && proposal->protocol_id == IKEV2_PROTOCOL_ESP)
{
- ikev2_rekey_t *rekey = &sa->rekey[0];
+ ikev2_rekey_t *rekey = sa->rekey;
+ if (vec_len (rekey) == 0)
+ goto cleanup_and_exit;
rekey->protocol_id = proposal->protocol_id;
rekey->i_proposal =
ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
ikev2_id_t *id_rem, *id_loc;
/* *INDENT-OFF* */
- pool_foreach (p, km->profiles, ({
+ pool_foreach (p, km->profiles) {
if (sa->is_initiator)
{
}
break;
- }));
+ }
/* *INDENT-ON* */
if (tsi && tsr)
}
/* *INDENT-OFF* */
- pool_foreach (p, km->profiles, ({
+ pool_foreach (p, km->profiles) {
/* check id */
if (!ikev2_is_id_equal (&p->rem_id, id_rem)
vec_free(auth);
vec_free(psk);
- }));
+ }
/* *INDENT-ON* */
if (sel_p)
ikev2_main_t *km = &ikev2_main;
u32 sw_if_index;
int rv = 0;
- ip46_address_t zero_addr = ip46_address_initializer;
if (~0 == a->sw_if_index)
{
vec_add1 (sas_in, a->old_remote_sa_id);
}
- 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, &zero_addr,
- &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, 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);
+ 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, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+ IP_DSCP_CS0, NULL, a->src_port, a->dst_port);
+ if (rv)
+ goto err0;
+
+ 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, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+ IP_DSCP_CS0, NULL,
+ a->ipsec_over_udp_port, a->ipsec_over_udp_port);
+ if (rv)
+ goto err1;
+
+ rv = ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in);
+ if (rv)
+ goto err2;
+
+ return;
+
+err2:
+ ipsec_sa_unlock_id (a->remote_sa_id);
+err1:
+ ipsec_sa_unlock_id (a->local_sa_id);
+err0:
+ vec_free (sas_in);
}
static int
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;
}
}
static u32
-ikev2_generate_message (vlib_buffer_t * b, ikev2_sa_t * sa,
- ike_header_t * ike, void *user, udp_header_t * udp)
+ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
+ void *user, udp_header_t *udp, ikev2_stats_t *stats)
{
ikev2_main_t *km = &ikev2_main;
u16 buffer_data_size = vlib_buffer_get_default_data_size (km->vlib_main);
}
else
{
- ikev2_set_state (sa, IKEV2_STATE_DELETED);
+ ikev2_set_state (sa, IKEV2_STATE_DELETED, ": unexpected IKE_AUTH");
goto done;
}
}
/* received N(AUTHENTICATION_FAILED) */
else if (sa->state == IKEV2_STATE_AUTH_FAILED)
{
- ikev2_set_state (sa, IKEV2_STATE_DELETED);
+ ikev2_set_state (sa, IKEV2_STATE_DELETED, ": auth failed");
goto done;
}
/* received unsupported critical payload */
vec_free (data);
sa->unsupported_cp = 0;
}
- /* else send empty response */
+ else
+ /* else send empty response */
+ {
+ if (ike_hdr_is_response (ike))
+ {
+ ASSERT (stats != 0);
+ stats->n_keepalives++;
+ }
+ }
}
else if (ike->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
{
if (sa->is_initiator)
ike->flags |= IKEV2_HDR_FLAG_INITIATOR;
- if (ike_hdr_is_request (ike))
- {
- sa->last_init_msg_id = clib_net_to_host_u32 (ike->msgid);
- }
-
if (ike->exchange == IKEV2_EXCHANGE_SA_INIT)
{
tlen += vec_len (chain->data);
ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data ();
/* *INDENT-OFF* */
- pool_foreach (sa, ptd->sas, ({
+ pool_foreach (sa, ptd->sas) {
res = ikev2_retransmit_sa_init_one (sa, ike, iaddr, raddr, rlen);
if (res)
return res;
- }));
+ }
/* *INDENT-ON* */
/* req is not retransmit */
exchange, src, dst);
}
+static void
+ikev2_generate_sa_init_data_and_log (ikev2_sa_t * sa)
+{
+ ikev2_generate_sa_error_t rc = ikev2_generate_sa_init_data (sa);
+
+ if (PREDICT_TRUE (rc == IKEV2_GENERATE_SA_INIT_OK))
+ return;
+
+ if (rc == IKEV2_GENERATE_SA_INIT_ERR_NO_DH)
+ ikev2_elog_error (IKEV2_GENERATE_SA_INIT_OK_ERR_NO_DH_STR);
+ else if (rc == IKEV2_GENERATE_SA_INIT_ERR_UNSUPPORTED_DH)
+ ikev2_elog_error (IKEV2_GENERATE_SA_INIT_OK_ERR_UNSUPP_STR);
+}
+
+static void
+ikev2_update_stats (vlib_main_t *vm, u32 node_index, ikev2_stats_t *s)
+{
+ vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_KEEPALIVE,
+ s->n_keepalives);
+ vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_REKEY_REQ,
+ s->n_rekey_req);
+ vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_EXCHANGE_SA_REQ,
+ s->n_exchange_sa_req);
+ vlib_node_increment_counter (vm, node_index, IKEV2_ERROR_IKE_AUTH_REQ,
+ s->n_ike_auth_req);
+}
+
static_always_inline uword
-ikev2_node_internal (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame,
- u8 is_ip4)
+ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame, u8 is_ip4, u8 natt)
{
u32 n_left = frame->n_vectors, *from;
ikev2_main_t *km = &ikev2_main;
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 ();
+ ikev2_stats_t _stats, *stats = &_stats;
int res;
+ clib_memset_u16 (stats, 0, sizeof (stats[0]) / sizeof (u16));
from = vlib_frame_vector_args (frame);
vlib_get_buffers (vm, from, bufs, n_left);
b = bufs;
ikev2_sa_t sa; /* temporary store for SA */
u32 rlen, slen = 0;
int ip_hdr_sz = 0;
- int is_req = 0, has_non_esp_marker = 0;
+ int is_req = 0;
- if (b0->punt_reason == ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0])
+ if (natt)
{
u8 *ptr = vlib_buffer_get_current (b0);
ip40 = (ip4_header_t *) ptr;
rlen = b0->current_length - ip_hdr_sz - sizeof (*udp0);
/* check for non-esp marker */
- if (*((u32 *) ike0) == 0)
+ if (natt)
{
+ ASSERT (*((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)
if (ike_hdr_is_initiator (ike0))
{
+ stats->n_exchange_sa_req++;
if (ike0->rspi == 0)
{
if (is_ip4)
goto dispatch0;
}
- res = ikev2_process_sa_init_req (vm, sa0, ike0, udp0, rlen);
+ res = ikev2_process_sa_init_req (
+ vm, sa0, ike0, udp0, rlen,
+ vnet_buffer (b0)->sw_if_index[VLIB_RX]);
if (!res)
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_MALFORMED_PACKET,
sa0->r_proposals =
ikev2_select_proposal (sa0->i_proposals,
IKEV2_PROTOCOL_IKE);
- ikev2_generate_sa_init_data (sa0);
+ ikev2_generate_sa_init_data_and_log (sa0);
}
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);
+ slen =
+ ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_NO_BUFF_SPACE,
ikev2_calc_keys (sa0);
ikev2_sa_auth_init (sa0);
ike0->flags = IKEV2_HDR_FLAG_INITIATOR;
- slen =
- ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ ike0->msgid =
+ clib_net_to_host_u32 (sai->last_init_msg_id);
+ sa0->last_init_msg_id = sai->last_init_msg_id + 1;
+ slen = ikev2_generate_message (b0, sa0, ike0, 0,
+ udp0, stats);
if (~0 == slen)
vlib_node_increment_counter (vm,
node->node_index,
}
else
{
- slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ stats->n_ike_auth_req++;
+ ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
+ slen =
+ ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_NO_BUFF_SPACE,
if (ike_hdr_is_request (ike0))
{
ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
- slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ slen =
+ ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_NO_BUFF_SPACE,
}
else
{
+ stats->n_rekey_req++;
ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
- slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0);
+ slen =
+ ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
if (~0 == slen)
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_NO_BUFF_SPACE,
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)
+ if (!natt)
slen = ikev2_insert_non_esp_marker (ike0, slen);
}
}
else
{
- if (has_non_esp_marker)
+ if (natt)
slen += sizeof (ikev2_non_esp_marker);
u16 tp = udp0->dst_port;
b += 1;
}
+ ikev2_update_stats (vm, node->node_index, stats);
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_PROCESSED, frame->n_vectors);
vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
static uword
ikev2_ip4 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- return ikev2_node_internal (vm, node, frame, 1 /* is_ip4 */ );
+ return ikev2_node_internal (vm, node, frame, 1 /* is_ip4 */, 0);
+}
+
+static uword
+ikev2_ip4_natt (vlib_main_t *vm, vlib_node_runtime_t *node,
+ vlib_frame_t *frame)
+{
+ return ikev2_node_internal (vm, node, frame, 1 /* is_ip4 */, 1 /* natt */);
}
static uword
ikev2_ip6 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- return ikev2_node_internal (vm, node, frame, 0 /* is_ip4 */ );
+ return ikev2_node_internal (vm, node, frame, 0 /* is_ip4 */, 0);
}
/* *INDENT-OFF* */
.format_trace = format_ikev2_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(ikev2_error_strings),
- .error_strings = ikev2_error_strings,
+ .n_errors = IKEV2_N_ERROR,
+ .error_counters = ikev2_error_counters,
+
+ .n_next_nodes = IKEV2_IP4_N_NEXT,
+ .next_nodes = {
+ [IKEV2_NEXT_IP4_LOOKUP] = "ip4-lookup",
+ [IKEV2_NEXT_IP4_ERROR_DROP] = "error-drop",
+ },
+};
+
+VLIB_REGISTER_NODE (ikev2_node_ip4_natt,static) = {
+ .function = ikev2_ip4_natt,
+ .name = "ikev2-ip4-natt",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ikev2_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+
+ .n_errors = IKEV2_N_ERROR,
+ .error_counters = ikev2_error_counters,
.n_next_nodes = IKEV2_IP4_N_NEXT,
.next_nodes = {
.format_trace = format_ikev2_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(ikev2_error_strings),
- .error_strings = ikev2_error_strings,
+ .n_errors = IKEV2_N_ERROR,
+ .error_counters = ikev2_error_counters,
.n_next_nodes = IKEV2_IP6_N_NEXT,
.next_nodes = {
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);
+ ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
+ sa->last_init_msg_id += 1;
+ len = ikev2_generate_message (b0, sa, ike0, 0, 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)
u32 *del_sai = 0;
/* *INDENT-OFF* */
- pool_foreach(sa, km->sais, ({
+ pool_foreach (sa, km->sais) {
if (pi == sa->profile_index)
vec_add1 (del_sai, sa - km->sais);
- }));
+ }
/* *INDENT-ON* */
vec_foreach (sai, del_sai)
vec_foreach (tkm, km->per_thread_data)
{
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
if (sa->profile_index != ~0 && pi == sa->profile_index)
vec_add1 (del_sai, sa - tkm->sas);
- }));
+ }
/* *INDENT-ON* */
vec_foreach (sai, del_sai)
valid_ip = 1;
}
- bi0 = ikev2_get_new_ike_header_buff (vm, &b0);
- if (!bi0)
- {
- char *errmsg = "buffer alloc failure";
- ikev2_log_error (errmsg);
- return clib_error_return (0, errmsg);
- }
- ike0 = vlib_buffer_get_current (b0);
-
/* Prepare the SA and the IKE payload */
ikev2_sa_t sa;
clib_memset (&sa, 0, sizeof (ikev2_sa_t));
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;
sa.dst_port = IKEV2_PORT;
- ikev2_generate_sa_init_data (&sa);
+
+ ikev2_generate_sa_error_t rc = ikev2_generate_sa_init_data (&sa);
+ if (rc != IKEV2_GENERATE_SA_INIT_OK)
+ {
+ ikev2_sa_free_all_vec (&sa);
+ ikev2_payload_destroy_chain (chain);
+ return clib_error_return (0, "%U", format_ikev2_gen_sa_error, rc);
+ }
+
ikev2_payload_add_ke (chain, sa.dh_group, sa.i_dh_data);
ikev2_payload_add_nonce (chain, sa.i_nonce);
sig_hash_algo);
vec_free (sig_hash_algo);
+ bi0 = ikev2_get_new_ike_header_buff (vm, &b0);
+ if (!bi0)
+ {
+ ikev2_sa_free_all_vec (&sa);
+ ikev2_payload_destroy_chain (chain);
+ char *errmsg = "buffer alloc failure";
+ ikev2_log_error (errmsg);
+ return clib_error_return (0, errmsg);
+ }
+ ike0 = vlib_buffer_get_current (b0);
+
/* Buffer update and boilerplate */
len += vec_len (chain->data);
ike0->nextpayload = chain->first_payload_type;
ike0->ispi = clib_host_to_net_u64 (sa.ispi);
ike0->rspi = 0;
ike0->msgid = 0;
+ sa.last_init_msg_id += 1;
/* store whole IKE payload - needed for PSK auth */
vec_reset_length (sa.last_sa_init_req_packet_data);
vec_resize (sa->del, 1);
sa->del->protocol_id = IKEV2_PROTOCOL_ESP;
sa->del->spi = csa->i_proposals->spi;
- 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);
+ ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
+ sa->last_init_msg_id += 1;
+ len = ikev2_generate_message (b0, sa, ike0, 0, 0, 0);
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 (fchild)
break;
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ispi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
{
fsa = sa;
break;
}
- }));
+ }
/* *INDENT-ON* */
}
if (fsa)
break;
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
if (sa->ispi == ispi)
{
fsa = sa;
ftkm = tkm;
break;
}
- }));
+ }
/* *INDENT-ON* */
}
ike0->exchange = IKEV2_EXCHANGE_CREATE_CHILD_SA;
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);
- sa->last_init_msg_id = clib_net_to_host_u32 (ike0->msgid);
+ ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
+ sa->last_init_msg_id += 1;
ikev2_rekey_t *rekey;
+ vec_reset_length (sa->rekey);
vec_add2 (sa->rekey, rekey, 1);
ikev2_sa_proposal_t *proposals = vec_dup (csa->i_proposals);
RAND_bytes ((u8 *) & proposals[0].spi, sizeof (proposals[0].spi));
rekey->spi = proposals[0].spi;
rekey->ispi = csa->i_proposals->spi;
- len = ikev2_generate_message (b0, sa, ike0, proposals, 0);
+ len = ikev2_generate_message (b0, sa, ike0, proposals, 0, 0);
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);
if (fchild)
break;
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ispi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
{
fsa = sa;
break;
}
- }));
+ }
/* *INDENT-ON* */
}
vec_foreach (tkm, km->per_thread_data)
{
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
if (ikev2_sa_sw_if_match (sa, sw_if_index))
vec_add1 (sa_vec, sa);
- }));
+ }
/* *INDENT-ON* */
vec_foreach (sap, sa_vec)
vec_free (sa_vec);
/* *INDENT-OFF* */
- pool_foreach (sa, km->sais, ({
+ pool_foreach (sa, km->sais) {
if (ikev2_sa_sw_if_match (sa, sw_if_index))
vec_add1 (ispi_vec, sa->ispi);
- }));
+ }
/* *INDENT-ON* */
vec_foreach (ispi, ispi_vec)
return 0;
/* *INDENT-OFF* */
- pool_foreach (p, km->profiles, ({
+ pool_foreach (p, km->profiles) {
if (p->responder.sw_if_index == sw_if_index)
ikev2_sa_del (p, sw_if_index);
- }));
+ }
/* *INDENT-ON* */
return 0;
udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip4.index, 1);
udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node_ip6.index, 0);
- vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("ikev2-ip4");
+ vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("ikev2-ip4-natt");
vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
- "ikev2-ip4");
+ "ikev2-ip4-natt");
ikev2_cli_reference ();
km->log_level = IKEV2_LOG_ERROR;
u32 *sas_in = NULL;
vec_add1 (sas_in, csa->remote_sa_id);
vlib_worker_thread_barrier_sync (vm);
- ipsec_tun_protect_update (sw_if_index, NULL, csa->local_sa_id, sas_in);
+ int rv = ipsec_tun_protect_update (sw_if_index, NULL,
+ csa->local_sa_id, sas_in);
+ if (rv)
+ vec_free (sas_in);
ipsec_sa_unlock_id (ikev2_flip_alternate_sa_bit (csa->remote_sa_id));
vlib_worker_thread_barrier_release (vm);
}
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)
{
if (fchild)
break;
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ipsec_sa->spi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
{
fsa = sa;
break;
}
- }));
+ }
/* *INDENT-ON* */
}
vlib_get_combined_counter (&ipsec_sa_counters,
ike0->exchange = IKEV2_EXCHANGE_INFORMATIONAL;
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->msgid = clib_host_to_net_u32 (sa->last_init_msg_id);
ike0->flags = 0;
- sa->last_init_msg_id = clib_net_to_host_u32 (ike0->msgid);
- len = ikev2_generate_message (b0, sa, ike0, 0, 0);
+ sa->last_init_msg_id += 1;
+ len = ikev2_generate_message (b0, sa, ike0, 0, 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)
u32 *to_be_deleted = 0;
/* *INDENT-OFF* */
- pool_foreach (sa, tkm->sas, ({
+ pool_foreach (sa, tkm->sas) {
ikev2_child_sa_t *c;
u8 del_old_ids = 0;
if (!km->dpd_disabled && ikev2_mngr_process_responder_sas (sa))
vec_add1 (to_be_deleted, sa - tkm->sas);
- }));
+ }
/* *INDENT-ON* */
vec_foreach (sai, to_be_deleted)
p = pool_elt_at_index (km->profiles, sa->profile_index);
if (p)
{
- ikev2_initiate_sa_init (vm, p->name);
+ clib_error_t *e = ikev2_initiate_sa_init (vm, p->name);
+ if (e)
+ {
+ ikev2_log_error ("%U", format_clib_error, e);
+ clib_error_free (e);
+ }
}
}
}
/* process ipsec sas */
ipsec_sa_t *sa;
/* *INDENT-OFF* */
- pool_foreach (sa, im->sad, ({
+ pool_foreach (sa, im->sad) {
ikev2_mngr_process_ipsec_sa(sa);
- }));
+ }
/* *INDENT-ON* */
ikev2_process_pending_sa_init (km);