aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/ikev2
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/ikev2')
-rw-r--r--src/plugins/ikev2/CMakeLists.txt9
-rw-r--r--src/plugins/ikev2/ikev2.api74
-rw-r--r--src/plugins/ikev2/ikev2.c872
-rw-r--r--src/plugins/ikev2/ikev2.h11
-rw-r--r--src/plugins/ikev2/ikev2_api.c421
-rw-r--r--src/plugins/ikev2/ikev2_cli.c51
-rw-r--r--src/plugins/ikev2/ikev2_crypto.c6
-rw-r--r--src/plugins/ikev2/ikev2_payload.c42
-rw-r--r--src/plugins/ikev2/ikev2_priv.h64
-rw-r--r--src/plugins/ikev2/ikev2_test.c229
-rw-r--r--src/plugins/ikev2/ikev2_types.api76
11 files changed, 1400 insertions, 455 deletions
diff --git a/src/plugins/ikev2/CMakeLists.txt b/src/plugins/ikev2/CMakeLists.txt
index 6f2e5a68153..568271ed7d9 100644
--- a/src/plugins/ikev2/CMakeLists.txt
+++ b/src/plugins/ikev2/CMakeLists.txt
@@ -11,8 +11,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-add_definitions (-DWITH_LIBSSL=1)
+if(NOT OPENSSL_FOUND)
+ message(WARNING "openssl headers not found - ikev2 plugin disabled")
+ return()
+endif()
+
include_directories(${OPENSSL_INCLUDE_DIR})
+add_compile_definitions(OPENSSL_SUPPRESS_DEPRECATED)
add_vpp_plugin(ikev2
SOURCES
@@ -35,5 +40,5 @@ add_vpp_plugin(ikev2
ikev2_priv.h
LINK_LIBRARIES
- ${OPENSSL_LIBRARIES}
+ ${OPENSSL_CRYPTO_LIBRARIES}
)
diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api
index ff9ed72e888..de276e7f3ea 100644
--- a/src/plugins/ikev2/ikev2.api
+++ b/src/plugins/ikev2/ikev2.api
@@ -72,7 +72,26 @@ define ikev2_sa_dump
{
u32 client_index;
u32 context;
+};
+/** \brief Dump all SAs
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define ikev2_sa_v2_dump
+{
+ u32 client_index;
+ u32 context;
+};
+
+/** \brief Dump all SAs
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define ikev2_sa_v3_dump
+{
+ u32 client_index;
+ u32 context;
option status = "in_progress";
};
@@ -87,6 +106,32 @@ define ikev2_sa_details
i32 retval;
vl_api_ikev2_sa_t sa;
+};
+
+/** \brief Details about IKE SA
+ @param context - sender context, to match reply w/ request
+ @param retval - return code
+ @param sa - SA data
+*/
+define ikev2_sa_v2_details
+{
+ u32 context;
+ i32 retval;
+
+ vl_api_ikev2_sa_v2_t sa;
+};
+
+/** \brief Details about IKE SA
+ @param context - sender context, to match reply w/ request
+ @param retval - return code
+ @param sa - SA data
+*/
+define ikev2_sa_v3_details
+{
+ u32 context;
+ i32 retval;
+
+ vl_api_ikev2_sa_v3_t sa;
option status = "in_progress";
};
@@ -102,7 +147,6 @@ define ikev2_child_sa_dump
u32 sa_index;
option vat_help = "sa_index <index>";
- option status = "in_progress";
};
/** \brief Child SA details
@@ -116,6 +160,34 @@ define ikev2_child_sa_details
i32 retval;
vl_api_ikev2_child_sa_t child_sa;
+};
+
+/** \brief Dump child SA of specific SA
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param sa_index - index of specific sa
+*/
+define ikev2_child_sa_v2_dump
+{
+ u32 client_index;
+ u32 context;
+
+ u32 sa_index;
+ option vat_help = "sa_index <index>";
+ option status = "in_progress";
+};
+
+/** \brief Child SA details
+ @param context - sender context, to match reply w/ request
+ @param retval - return code
+ @param child_sa - child SA data
+*/
+define ikev2_child_sa_v2_details
+{
+ u32 context;
+ i32 retval;
+
+ vl_api_ikev2_child_sa_v2_t child_sa;
option status = "in_progress";
};
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index fa653760b1d..9bea2c96d12 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -110,14 +110,14 @@ typedef enum
typedef u32 ikev2_non_esp_marker;
-static_always_inline u16
-ikev2_get_port (ikev2_sa_t * sa)
+static u16
+ikev2_get_port (ikev2_sa_t *sa)
{
return ikev2_natt_active (sa) ? IKEV2_PORT_NATT : IKEV2_PORT;
}
-static_always_inline int
-ikev2_insert_non_esp_marker (ike_header_t * ike, int len)
+static int
+ikev2_insert_non_esp_marker (ike_header_t *ike, int len)
{
memmove ((u8 *) ike + sizeof (ikev2_non_esp_marker), ike, len);
clib_memset (ike, 0, sizeof (ikev2_non_esp_marker));
@@ -211,6 +211,8 @@ ikev2_select_proposal (ikev2_sa_proposal_t * proposals,
rv->proposal_num = proposal->proposal_num;
rv->protocol_id = proposal->protocol_id;
RAND_bytes ((u8 *) & rv->spi, sizeof (rv->spi));
+ if (rv->protocol_id != IKEV2_PROTOCOL_IKE)
+ rv->spi &= 0xffffffff;
goto done;
}
else
@@ -405,8 +407,8 @@ ikev2_generate_sa_init_data (ikev2_sa_t * sa)
RAND_bytes ((u8 *) & sa->rspi, 8);
/* generate nonce */
- sa->r_nonce = vec_new (u8, IKEV2_NONCE_SIZE);
- RAND_bytes ((u8 *) sa->r_nonce, IKEV2_NONCE_SIZE);
+ sa->r_nonce = vec_new (u8, vec_len (sa->i_nonce));
+ RAND_bytes ((u8 *) sa->r_nonce, vec_len (sa->i_nonce));
}
/* generate dh keys */
@@ -480,11 +482,10 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai)
}
static void
-ikev2_calc_keys (ikev2_sa_t * sa)
+ikev2_calc_keys_internal (ikev2_sa_t *sa, u8 *skeyseed)
{
u8 *tmp;
/* calculate SKEYSEED = prf(Ni | Nr, g^ir) */
- u8 *skeyseed = 0;
u8 *s = 0;
u16 integ_key_len = 0, salt_len = 0;
ikev2_sa_transform_t *tr_encr, *tr_prf, *tr_integ;
@@ -502,7 +503,6 @@ ikev2_calc_keys (ikev2_sa_t * sa)
vec_append (s, sa->i_nonce);
vec_append (s, sa->r_nonce);
- skeyseed = ikev2_calc_prf (tr_prf, s, sa->dh_shared_key);
/* Calculate S = Ni | Nr | SPIi | SPIr */
u64 *spi;
@@ -520,7 +520,6 @@ ikev2_calc_keys (ikev2_sa_t * sa)
salt_len * 2;
keymat = ikev2_calc_prfplus (tr_prf, skeyseed, s, len);
- vec_free (skeyseed);
vec_free (s);
int pos = 0;
@@ -568,7 +567,42 @@ ikev2_calc_keys (ikev2_sa_t * sa)
}
static void
-ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child)
+ikev2_calc_keys_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old)
+{
+ u8 *s = 0, *skeyseed = 0;
+ ikev2_sa_transform_t *tr_prf =
+ ikev2_sa_get_td_for_type (sa_old->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+
+ vec_append (s, sa_new->dh_shared_key);
+ vec_append (s, sa_new->i_nonce);
+ vec_append (s, sa_new->r_nonce);
+ skeyseed = ikev2_calc_prf (tr_prf, sa_old->sk_d, s);
+
+ ikev2_calc_keys_internal (sa_new, skeyseed);
+
+ vec_free (skeyseed);
+ vec_free (s);
+}
+
+static void
+ikev2_calc_keys (ikev2_sa_t *sa)
+{
+ u8 *s = 0, *skeyseed = 0;
+ ikev2_sa_transform_t *tr_prf =
+ ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+
+ vec_append (s, sa->i_nonce);
+ vec_append (s, sa->r_nonce);
+ skeyseed = ikev2_calc_prf (tr_prf, s, sa->dh_shared_key);
+
+ ikev2_calc_keys_internal (sa, skeyseed);
+
+ vec_free (skeyseed);
+ vec_free (s);
+}
+
+static void
+ikev2_calc_child_keys (ikev2_sa_t *sa, ikev2_child_sa_t *child, u8 kex)
{
u8 *s = 0;
u16 integ_key_len = 0;
@@ -587,6 +621,8 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child)
else
salt_len = sizeof (u32);
+ if (kex)
+ vec_append (s, sa->dh_shared_key);
vec_append (s, sa->i_nonce);
vec_append (s, sa->r_nonce);
/* calculate PRFplus */
@@ -638,8 +674,8 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child)
vec_free (keymat);
}
-static_always_inline u8 *
-ikev2_compute_nat_sha1 (u64 ispi, u64 rspi, ip_address_t * ia, u16 port)
+static u8 *
+ikev2_compute_nat_sha1 (u64 ispi, u64 rspi, ip_address_t *ia, u16 port)
{
const u32 max_buf_size =
sizeof (ispi) + sizeof (rspi) + sizeof (ip6_address_t) + sizeof (u16);
@@ -662,7 +698,10 @@ ikev2_parse_ke_payload (const void *p, u32 rlen, ikev2_sa_t * sa,
u16 plen = clib_net_to_host_u16 (ke->length);
ASSERT (plen >= sizeof (*ke) && plen <= rlen);
if (sizeof (*ke) > rlen)
- return 0;
+ {
+ ikev2_elog_error ("KE: packet too small");
+ return 0;
+ }
sa->dh_group = clib_net_to_host_u16 (ke->dh_group);
vec_reset_length (ke_data[0]);
@@ -671,13 +710,20 @@ ikev2_parse_ke_payload (const void *p, u32 rlen, ikev2_sa_t * sa,
}
static int
-ikev2_parse_nonce_payload (const void *p, u32 rlen, u8 * nonce)
+ikev2_parse_nonce_payload (const void *p, u32 rlen, const u8 **nonce)
{
const ike_payload_header_t *ikep = p;
u16 plen = clib_net_to_host_u16 (ikep->length);
ASSERT (plen >= sizeof (*ikep) && plen <= rlen);
- clib_memcpy_fast (nonce, ikep->payload, plen - sizeof (*ikep));
- return 1;
+ int len = plen - sizeof (*ikep);
+ ASSERT (len >= 16 && len <= 256);
+ if (PREDICT_FALSE (len < 16 || len > 256))
+ {
+ ikev2_elog_error ("NONCE: bad size");
+ return 0;
+ }
+ *nonce = ikep->payload;
+ return len;
}
static int
@@ -685,10 +731,16 @@ ikev2_check_payload_length (const ike_payload_header_t * ikep, int rlen,
u16 * plen)
{
if (sizeof (*ikep) > rlen)
- return 0;
+ {
+ ikev2_elog_error ("payload: packet too small");
+ return 0;
+ }
*plen = clib_net_to_host_u16 (ikep->length);
if (*plen < sizeof (*ikep) || *plen > rlen)
- return 0;
+ {
+ ikev2_elog_error ("payload: bad size");
+ return 0;
+ }
return 1;
}
@@ -696,7 +748,6 @@ 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, u32 sw_if_index)
{
- u8 nonce[IKEV2_NONCE_SIZE];
int p = 0;
u8 payload = ike->nextpayload;
ike_payload_header_t *ikep;
@@ -716,7 +767,10 @@ ikev2_process_sa_init_req (vlib_main_t *vm, ikev2_sa_t *sa, ike_header_t *ike,
vec_add (sa->last_sa_init_req_packet_data, ike, len);
if (len < sizeof (*ike))
- return 0;
+ {
+ ikev2_elog_error ("IKE_INIT request too small");
+ return 0;
+ }
len -= sizeof (*ike);
while (p < len && payload != IKEV2_PAYLOAD_NONE)
@@ -739,9 +793,13 @@ ikev2_process_sa_init_req (vlib_main_t *vm, ikev2_sa_t *sa, ike_header_t *ike,
}
else if (payload == IKEV2_PAYLOAD_NONCE)
{
+ const u8 *nonce;
+ int nonce_len;
vec_reset_length (sa->i_nonce);
- if (ikev2_parse_nonce_payload (ikep, current_length, nonce))
- vec_add (sa->i_nonce, nonce, plen - sizeof (*ikep));
+ if ((nonce_len = ikev2_parse_nonce_payload (ikep, current_length,
+ &nonce)) <= 0)
+ return 0;
+ vec_add (sa->i_nonce, nonce, nonce_len);
}
else if (payload == IKEV2_PAYLOAD_NOTIFY)
{
@@ -805,7 +863,6 @@ ikev2_process_sa_init_resp (vlib_main_t * vm,
ikev2_sa_t * sa, ike_header_t * ike,
udp_header_t * udp, u32 len)
{
- u8 nonce[IKEV2_NONCE_SIZE];
int p = 0;
u8 payload = ike->nextpayload;
ike_payload_header_t *ikep;
@@ -824,7 +881,10 @@ ikev2_process_sa_init_resp (vlib_main_t * vm,
vec_add (sa->last_sa_init_res_packet_data, ike, len);
if (sizeof (*ike) > len)
- return;
+ {
+ ikev2_elog_error ("IKE_INIT response too small");
+ return;
+ }
len -= sizeof (*ike);
while (p < len && payload != IKEV2_PAYLOAD_NONE)
@@ -853,9 +913,13 @@ ikev2_process_sa_init_resp (vlib_main_t * vm,
}
else if (payload == IKEV2_PAYLOAD_NONCE)
{
+ const u8 *nonce;
+ int nonce_len;
vec_reset_length (sa->r_nonce);
- if (ikev2_parse_nonce_payload (ikep, current_length, nonce))
- vec_add (sa->r_nonce, nonce, plen - sizeof (*ikep));
+ if ((nonce_len = ikev2_parse_nonce_payload (ikep, current_length,
+ &nonce)) <= 0)
+ return;
+ vec_add (sa->r_nonce, nonce, nonce_len);
}
else if (payload == IKEV2_PAYLOAD_NOTIFY)
{
@@ -1021,8 +1085,8 @@ ikev2_decrypt_sk_payload (ikev2_sa_t * sa, ike_header_t * ike,
return plaintext;
}
-static_always_inline int
-ikev2_is_id_equal (ikev2_id_t * i1, ikev2_id_t * i2)
+static int
+ikev2_is_id_equal (const ikev2_id_t *i1, const ikev2_id_t *i2)
{
if (i1->type != i2->type)
return 0;
@@ -1046,7 +1110,6 @@ ikev2_initial_contact_cleanup_internal (ikev2_main_per_thread_data_t * ptd,
ikev2_child_sa_t *c;
/* find old IKE SAs with the same authenticated identity */
- /* *INDENT-OFF* */
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))
@@ -1055,7 +1118,6 @@ ikev2_initial_contact_cleanup_internal (ikev2_main_per_thread_data_t * ptd,
if (sa->rspi != tmp->rspi)
vec_add1(delete, tmp - ptd->sas);
}
- /* *INDENT-ON* */
for (i = 0; i < vec_len (delete); i++)
{
@@ -1332,6 +1394,159 @@ ikev2_process_informational_req (vlib_main_t * vm,
}
static int
+ikev2_process_create_child_sa_rekey (ikev2_sa_t *sa, ikev2_sa_t *sar,
+ ikev2_rekey_t *rekey,
+ ikev2_sa_proposal_t *proposal,
+ ikev2_ts_t *tsi, ikev2_ts_t *tsr,
+ const u8 *nonce, int nonce_len)
+{
+ ikev2_sa_transform_t *tr;
+
+ rekey->i_proposal = proposal;
+ rekey->r_proposal = ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
+
+ if (sar->dh_group)
+ {
+ tr =
+ ikev2_sa_get_td_for_type (rekey->r_proposal, IKEV2_TRANSFORM_TYPE_DH);
+
+ if (!tr || tr->dh_type != sar->dh_group)
+ {
+ rekey->notify_type = IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD;
+ ikev2_sa_free_proposal_vector (&rekey->r_proposal);
+ return 0;
+ }
+
+ vec_free (sa->dh_shared_key);
+ vec_free (sa->dh_private_key);
+ vec_free (sa->i_dh_data);
+ vec_free (sa->r_dh_data);
+
+ sa->dh_group = sar->dh_group;
+ sa->i_dh_data = sar->i_dh_data;
+ sar->i_dh_data = 0;
+
+ ikev2_generate_dh (sa, tr);
+ rekey->kex = 1;
+ }
+
+ vec_reset_length (sa->i_nonce);
+ vec_add (sa->i_nonce, nonce, nonce_len);
+
+ vec_validate (sa->r_nonce, nonce_len - 1);
+ RAND_bytes ((u8 *) sa->r_nonce, nonce_len);
+
+ rekey->tsi = tsi;
+ rekey->tsr = tsr;
+
+ return 1;
+}
+
+static void
+ikev2_complete_sa_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old,
+ ikev2_sa_rekey_t *sa_rekey)
+{
+ sa_new->del = 0;
+ sa_new->rekey = 0;
+ sa_new->new_child = 0;
+ sa_new->sa_rekey = 0;
+ sa_new->last_sa_init_req_packet_data = 0;
+ sa_new->last_sa_init_res_packet_data = 0;
+ sa_new->last_msg_id = ~0;
+ sa_new->last_res_packet_data = 0;
+ sa_new->last_init_msg_id = 0;
+ clib_memset (&sa_new->stats, 0, sizeof (sa_new->stats));
+
+ sa_new->ispi = sa_rekey->ispi;
+ sa_new->rspi = sa_rekey->rspi;
+ sa_new->i_nonce = sa_rekey->i_nonce;
+ sa_new->r_nonce = sa_rekey->r_nonce;
+ sa_new->dh_group = sa_rekey->dh_group;
+ sa_new->dh_shared_key = sa_rekey->dh_shared_key;
+ sa_new->dh_private_key = sa_rekey->dh_private_key;
+ sa_new->i_dh_data = sa_rekey->i_dh_data;
+ sa_new->r_dh_data = sa_rekey->r_dh_data;
+ sa_new->i_proposals = sa_rekey->i_proposals;
+ sa_new->r_proposals = sa_rekey->r_proposals;
+
+ sa_new->sk_d = 0;
+ sa_new->sk_ai = 0;
+ sa_new->sk_ar = 0;
+ sa_new->sk_ei = 0;
+ sa_new->sk_er = 0;
+ sa_new->sk_pi = 0;
+ sa_new->sk_pr = 0;
+ ikev2_calc_keys_rekey (sa_new, sa_old);
+
+ sa_new->i_auth.data = vec_dup (sa_old->i_auth.data);
+ sa_new->i_auth.key = sa_old->i_auth.key;
+ if (sa_new->i_auth.key)
+ EVP_PKEY_up_ref (sa_new->i_auth.key);
+
+ sa_new->r_auth.data = vec_dup (sa_old->r_auth.data);
+ sa_new->r_auth.key = sa_old->r_auth.key;
+ if (sa_new->r_auth.key)
+ EVP_PKEY_up_ref (sa_new->r_auth.key);
+
+ sa_new->i_id.data = vec_dup (sa_old->i_id.data);
+ sa_new->r_id.data = vec_dup (sa_old->r_id.data);
+
+ sa_old->is_tun_itf_set = 0;
+ sa_old->tun_itf = ~0;
+ sa_old->old_id_expiration = 0;
+ sa_old->current_remote_id_mask = 0;
+ sa_old->old_remote_id = 0;
+ sa_old->old_remote_id_present = 0;
+ sa_old->childs = 0;
+ sa_old->sw_if_index = ~0;
+}
+
+static void
+ikev2_process_sa_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old,
+ ikev2_sa_rekey_t *sa_rekey)
+{
+ ikev2_sa_transform_t *tr;
+
+ if (ikev2_generate_sa_init_data (sa_new) != IKEV2_GENERATE_SA_INIT_OK)
+ {
+ sa_rekey->notify_type = IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD;
+ return;
+ }
+
+ sa_new->r_proposals =
+ ikev2_select_proposal (sa_new->i_proposals, IKEV2_PROTOCOL_IKE);
+
+ tr = ikev2_sa_get_td_for_type (sa_new->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ if (!tr || tr->dh_type != sa_new->dh_group)
+ {
+ sa_rekey->notify_type = IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD;
+ return;
+ }
+
+ sa_rekey->notify_type = 0;
+ sa_rekey->ispi = sa_new->i_proposals[0].spi;
+ sa_rekey->rspi = sa_new->r_proposals[0].spi;
+ sa_rekey->i_nonce = sa_new->i_nonce;
+ sa_rekey->r_nonce = sa_new->r_nonce;
+ sa_rekey->dh_group = sa_new->dh_group;
+ sa_rekey->dh_shared_key = sa_new->dh_shared_key;
+ sa_rekey->dh_private_key = sa_new->dh_private_key;
+ sa_rekey->i_dh_data = sa_new->i_dh_data;
+ sa_rekey->r_dh_data = sa_new->r_dh_data;
+ sa_rekey->i_proposals = sa_new->i_proposals;
+ sa_rekey->r_proposals = sa_new->r_proposals;
+
+ sa_new->i_nonce = 0;
+ sa_new->r_nonce = 0;
+ sa_new->dh_shared_key = 0;
+ sa_new->dh_private_key = 0;
+ sa_new->i_dh_data = 0;
+ sa_new->r_dh_data = 0;
+ sa_new->i_proposals = 0;
+ sa_new->r_proposals = 0;
+}
+
+static int
ikev2_process_create_child_sa_req (vlib_main_t * vm,
ikev2_sa_t * sa, ike_header_t * ike,
u32 len)
@@ -1339,8 +1554,6 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
int p = 0;
u8 payload = ike->nextpayload;
u8 *plaintext = 0;
- u8 rekeying = 0;
- u8 nonce[IKEV2_NONCE_SIZE];
ikev2_rekey_t *rekey;
ike_payload_header_t *ikep;
ikev2_notify_t *n = 0;
@@ -1350,6 +1563,11 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
ikev2_child_sa_t *child_sa;
u32 dlen = 0, src;
u16 plen;
+ const u8 *nonce = 0;
+ int nonce_len = 0;
+ ikev2_sa_t sar;
+
+ clib_memset (&sar, 0, sizeof (sar));
if (sa->is_initiator)
src = ip_addr_v4 (&sa->raddr).as_u32;
@@ -1379,13 +1597,23 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
{
proposal = ikev2_parse_sa_payload (ikep, current_length);
}
+ else if (payload == IKEV2_PAYLOAD_KE)
+ {
+ if (!ikev2_parse_ke_payload (ikep, current_length, &sar,
+ &sar.i_dh_data))
+ goto cleanup_and_exit;
+ }
else if (payload == IKEV2_PAYLOAD_NOTIFY)
{
- n = ikev2_parse_notify_payload (ikep, current_length);
- if (n->msg_type == IKEV2_NOTIFY_MSG_REKEY_SA)
+ ikev2_notify_t *n0;
+ n0 = ikev2_parse_notify_payload (ikep, current_length);
+ if (n0->msg_type == IKEV2_NOTIFY_MSG_REKEY_SA)
{
- rekeying = 1;
+ vec_free (n);
+ n = n0;
}
+ else
+ vec_free (n0);
}
else if (payload == IKEV2_PAYLOAD_DELETE)
{
@@ -1397,7 +1625,9 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
}
else if (payload == IKEV2_PAYLOAD_NONCE)
{
- ikev2_parse_nonce_payload (ikep, current_length, nonce);
+ nonce_len = ikev2_parse_nonce_payload (ikep, current_length, &nonce);
+ if (nonce_len <= 0)
+ goto cleanup_and_exit;
}
else if (payload == IKEV2_PAYLOAD_TSI)
{
@@ -1421,7 +1651,9 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
p += plen;
}
- if (!proposal || proposal->protocol_id != IKEV2_PROTOCOL_ESP)
+ if (!proposal || !nonce ||
+ (proposal->protocol_id != IKEV2_PROTOCOL_ESP &&
+ proposal->protocol_id != IKEV2_PROTOCOL_IKE))
goto cleanup_and_exit;
if (sa->is_initiator)
@@ -1429,6 +1661,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
rekey = sa->rekey;
if (vec_len (rekey) == 0)
goto cleanup_and_exit;
+ rekey->notify_type = 0;
rekey->protocol_id = proposal->protocol_id;
rekey->i_proposal =
ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
@@ -1438,7 +1671,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
rekey->tsr = tsr;
/* update Nr */
vec_reset_length (sa->r_nonce);
- vec_add (sa->r_nonce, nonce, IKEV2_NONCE_SIZE);
+ vec_add (sa->r_nonce, nonce, nonce_len);
child_sa = ikev2_sa_get_child (sa, rekey->ispi, IKEV2_PROTOCOL_ESP, 1);
if (child_sa)
{
@@ -1447,7 +1680,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
}
else
{
- if (rekeying)
+ if (n)
{
child_sa = ikev2_sa_get_child (sa, n->spi, n->protocol_id, 1);
if (!child_sa)
@@ -1457,36 +1690,52 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm,
goto cleanup_and_exit;
}
vec_add2 (sa->rekey, rekey, 1);
+ rekey->notify_type = 0;
+ rekey->kex = 0;
rekey->protocol_id = n->protocol_id;
rekey->spi = n->spi;
- rekey->i_proposal = proposal;
- rekey->r_proposal =
- ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
- /* update Ni */
- 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);
+ if (sa->old_remote_id_present)
+ {
+ rekey->notify_type = IKEV2_NOTIFY_MSG_TEMPORARY_FAILURE;
+ vec_free (proposal);
+ vec_free (tsr);
+ vec_free (tsi);
+ }
+ else if (!ikev2_process_create_child_sa_rekey (
+ sa, &sar, rekey, proposal, tsi, tsr, nonce, nonce_len))
+ {
+ vec_free (proposal);
+ vec_free (tsr);
+ vec_free (tsi);
+ }
+ }
+ else if (proposal[0].protocol_id == IKEV2_PROTOCOL_IKE)
+ {
+ ikev2_sa_rekey_t *sa_rekey;
+ if (tsi || tsr)
+ goto cleanup_and_exit;
+ sar.i_proposals = proposal;
+ vec_add (sar.i_nonce, nonce, nonce_len);
+ vec_add2 (sa->sa_rekey, sa_rekey, 1);
+ ikev2_process_sa_rekey (&sar, sa, sa_rekey);
}
else
{
/* create new child SA */
vec_add2 (sa->new_child, rekey, 1);
- rekey->i_proposal = proposal;
- rekey->r_proposal =
- ikev2_select_proposal (proposal, IKEV2_PROTOCOL_ESP);
- /* update Ni */
- 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);
+ rekey->notify_type = 0;
+ rekey->kex = 0;
+ if (!ikev2_process_create_child_sa_rekey (
+ sa, &sar, rekey, proposal, tsi, tsr, nonce, nonce_len))
+ {
+ vec_free (proposal);
+ vec_free (tsr);
+ vec_free (tsi);
+ }
}
- rekey->tsi = tsi;
- rekey->tsr = tsr;
}
vec_free (n);
+ ikev2_sa_free_all_vec (&sar);
return 1;
cleanup_and_exit:
@@ -1494,6 +1743,7 @@ cleanup_and_exit:
vec_free (proposal);
vec_free (tsr);
vec_free (tsi);
+ ikev2_sa_free_all_vec (&sar);
return 0;
}
@@ -1541,6 +1791,25 @@ ikev2_sa_generate_authmsg (ikev2_sa_t * sa, int is_responder)
}
static int
+ikev2_match_profile (const ikev2_profile_t *p, const ikev2_id_t *id_loc,
+ const ikev2_id_t *id_rem, int is_initiator)
+{
+ /* on the initiator, IDi is always present and must match
+ * however on the responder, IDr (which is our local id) is optional */
+ if ((is_initiator || id_loc->type != 0) &&
+ !ikev2_is_id_equal (&p->loc_id, id_loc))
+ return 0;
+
+ /* on the initiator, we might not have configured a specific remote id
+ * however on the responder, the remote id should always be configured */
+ if ((!is_initiator || p->rem_id.type != 0) &&
+ !ikev2_is_id_equal (&p->rem_id, id_rem))
+ return 0;
+
+ return 1;
+}
+
+static int
ikev2_ts_cmp (ikev2_ts_t * ts1, ikev2_ts_t * ts2)
{
if (ts1->ts_type == ts2->ts_type && ts1->protocol_id == ts2->protocol_id &&
@@ -1560,7 +1829,6 @@ ikev2_sa_match_ts (ikev2_sa_t * sa)
ikev2_ts_t *ts, *p_tsi, *p_tsr, *tsi = 0, *tsr = 0;
ikev2_id_t *id_rem, *id_loc;
- /* *INDENT-OFF* */
pool_foreach (p, km->profiles) {
if (sa->is_initiator)
@@ -1578,9 +1846,7 @@ ikev2_sa_match_ts (ikev2_sa_t * sa)
id_loc = &sa->r_id;
}
- /* check id */
- if (!ikev2_is_id_equal (&p->rem_id, id_rem)
- || !ikev2_is_id_equal (&p->loc_id, id_loc))
+ if (!ikev2_match_profile (p, id_loc, id_rem, sa->is_initiator))
continue;
sa->profile_index = p - km->profiles;
@@ -1605,7 +1871,6 @@ ikev2_sa_match_ts (ikev2_sa_t * sa)
break;
}
- /* *INDENT-ON* */
if (tsi && tsr)
{
@@ -1623,7 +1888,7 @@ ikev2_sa_match_ts (ikev2_sa_t * sa)
}
static ikev2_profile_t *
-ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa,
+ikev2_select_profile (vlib_main_t *vm, ikev2_main_t *km, ikev2_sa_t *sa,
ikev2_sa_transform_t *tr_prf, u8 *key_pad)
{
ikev2_profile_t *ret = 0, *p;
@@ -1648,9 +1913,7 @@ ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa,
pool_foreach (p, km->profiles)
{
- /* check id */
- if (!ikev2_is_id_equal (&p->rem_id, id_rem) ||
- !ikev2_is_id_equal (&p->loc_id, id_loc))
+ if (!ikev2_match_profile (p, id_loc, id_rem, sa->is_initiator))
continue;
if (sa_auth->method == IKEV2_AUTH_METHOD_SHARED_KEY_MIC)
@@ -1665,6 +1928,7 @@ ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa,
if (!clib_memcmp (auth, sa_auth->data, vec_len (sa_auth->data)))
{
ikev2_set_state (sa, IKEV2_STATE_AUTHENTICATED);
+ sa->auth_timestamp = vlib_time_now (vm);
vec_free (auth);
ret = p;
break;
@@ -1683,6 +1947,7 @@ ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa,
if (ikev2_verify_sign (p->auth.key, sa_auth->data, authmsg) == 1)
{
ikev2_set_state (sa, IKEV2_STATE_AUTHENTICATED);
+ sa->auth_timestamp = vlib_time_now (vm);
ret = p;
break;
}
@@ -1698,7 +1963,7 @@ ikev2_select_profile (ikev2_main_t *km, ikev2_sa_t *sa,
}
static void
-ikev2_sa_auth (ikev2_sa_t *sa)
+ikev2_sa_auth (ikev2_sa_t *sa, vlib_main_t *vm)
{
ikev2_main_t *km = &ikev2_main;
ikev2_profile_t *sel_p = 0;
@@ -1719,7 +1984,7 @@ ikev2_sa_auth (ikev2_sa_t *sa)
}
key_pad = format (0, "%s", IKEV2_KEY_PAD);
- sel_p = ikev2_select_profile (km, sa, tr_prf, key_pad);
+ sel_p = ikev2_select_profile (vm, km, sa, tr_prf, key_pad);
if (sel_p)
{
@@ -1864,8 +2129,8 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
.t_mode = TUNNEL_MODE_P2P,
.t_table_id = 0,
.t_hop_limit = 255,
- .t_src = a->local_ip,
- .t_dst = a->remote_ip,
+ .t_src = a->remote_ip,
+ .t_dst = a->local_ip,
};
tunnel_t tun_out = {
.t_flags = TUNNEL_FLAG_NONE,
@@ -1874,8 +2139,8 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
.t_mode = TUNNEL_MODE_P2P,
.t_table_id = 0,
.t_hop_limit = 255,
- .t_src = a->remote_ip,
- .t_dst = a->local_ip,
+ .t_src = a->local_ip,
+ .t_dst = a->remote_ip,
};
if (~0 == a->sw_if_index)
@@ -1924,7 +2189,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
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, a->salt_local,
- a->src_port, a->dst_port, &tun_out, NULL);
+ a->src_port, a->dst_port, 0, &tun_out, NULL);
if (rv)
goto err0;
@@ -1932,7 +2197,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
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), a->salt_remote,
- a->ipsec_over_udp_port, a->ipsec_over_udp_port, &tun_in, NULL);
+ a->ipsec_over_udp_port, a->ipsec_over_udp_port, 0, &tun_in, NULL);
if (rv)
goto err1;
@@ -1951,10 +2216,9 @@ err0:
}
static int
-ikev2_create_tunnel_interface (vlib_main_t * vm,
- ikev2_sa_t * sa,
- ikev2_child_sa_t * child, u32 sa_index,
- u32 child_index, u8 is_rekey)
+ikev2_create_tunnel_interface (vlib_main_t *vm, ikev2_sa_t *sa,
+ ikev2_child_sa_t *child, u32 sa_index,
+ u32 child_index, u8 is_rekey, u8 kex)
{
u32 thread_index = vlib_get_thread_index ();
ikev2_main_t *km = &ikev2_main;
@@ -1968,6 +2232,8 @@ ikev2_create_tunnel_interface (vlib_main_t * vm,
clib_memset (&a, 0, sizeof (a));
+ child->timestamp = vlib_time_now (vm);
+
if (!child->r_proposals)
{
ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN);
@@ -2097,7 +2363,7 @@ ikev2_create_tunnel_interface (vlib_main_t * vm,
}
a.integ_type = integ_type;
- ikev2_calc_child_keys (sa, child);
+ ikev2_calc_child_keys (sa, child, kex);
if (sa->is_initiator)
{
@@ -2202,7 +2468,7 @@ typedef struct
u32 sw_if_index;
} ikev2_del_ipsec_tunnel_args_t;
-static_always_inline u32
+static u32
ikev2_flip_alternate_sa_bit (u32 id)
{
u32 mask = 0x800;
@@ -2220,14 +2486,12 @@ ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a)
if (~0 == a->sw_if_index)
{
- /* *INDENT-OFF* */
ipip_tunnel_key_t key = {
.src = a->local_ip,
.dst = a->remote_ip,
.transport = IPIP_TRANSPORT_IP4,
.fib_index = 0,
};
- /* *INDENT-ON* */
ipip = ipip_tunnel_db_find (&key);
@@ -2284,6 +2548,47 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
return 0;
}
+static void
+ikev2_add_invalid_ke_payload (ikev2_sa_t *sa, ikev2_payload_chain_t *chain)
+{
+ u8 *data = vec_new (u8, 2);
+ ikev2_sa_transform_t *tr_dh =
+ ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ ASSERT (tr_dh && tr_dh->dh_type);
+ data[0] = (tr_dh->dh_type >> 8) & 0xff;
+ data[1] = (tr_dh->dh_type) & 0xff;
+ ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD, data);
+ vec_free (data);
+}
+
+static void
+ikev2_add_notify_payload (ikev2_sa_t *sa, ikev2_payload_chain_t *chain,
+ u16 notify_type)
+{
+ if (notify_type == IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD)
+ ikev2_add_invalid_ke_payload (sa, chain);
+ else
+ ikev2_payload_add_notify (chain, notify_type, 0);
+}
+
+static void
+ikev2_add_create_child_resp (ikev2_sa_t *sa, ikev2_rekey_t *rekey,
+ ikev2_payload_chain_t *chain)
+{
+ if (rekey->notify_type)
+ {
+ ikev2_add_notify_payload (sa, chain, rekey->notify_type);
+ return;
+ }
+
+ ikev2_payload_add_sa (chain, rekey->r_proposal, 0);
+ ikev2_payload_add_nonce (chain, sa->r_nonce);
+ if (rekey->kex)
+ ikev2_payload_add_ke (chain, sa->dh_group, sa->r_dh_data);
+ ikev2_payload_add_ts (chain, rekey->tsi, IKEV2_PAYLOAD_TSI);
+ ikev2_payload_add_ts (chain, rekey->tsr, IKEV2_PAYLOAD_TSR);
+}
+
static u32
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)
@@ -2314,20 +2619,7 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
}
else if (sa->dh_group == IKEV2_TRANSFORM_DH_TYPE_NONE)
{
- u8 *data = vec_new (u8, 2);
- ikev2_sa_transform_t *tr_dh;
- tr_dh =
- ikev2_sa_get_td_for_type (sa->r_proposals,
- IKEV2_TRANSFORM_TYPE_DH);
- ASSERT (tr_dh && tr_dh->dh_type);
-
- data[0] = (tr_dh->dh_type >> 8) & 0xff;
- data[1] = (tr_dh->dh_type) & 0xff;
-
- ikev2_payload_add_notify (chain,
- IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD,
- data);
- vec_free (data);
+ ikev2_add_invalid_ke_payload (sa, chain);
ikev2_set_state (sa, IKEV2_STATE_NOTIFY_AND_DELETE);
}
else if (sa->state == IKEV2_STATE_NOTIFY_AND_DELETE)
@@ -2345,7 +2637,7 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
ASSERT (udp);
ike->rspi = clib_host_to_net_u64 (sa->rspi);
- ikev2_payload_add_sa (chain, sa->r_proposals);
+ ikev2_payload_add_sa (chain, sa->r_proposals, 0);
ikev2_payload_add_ke (chain, sa->dh_group, sa->r_dh_data);
ikev2_payload_add_nonce (chain, sa->r_nonce);
@@ -2372,9 +2664,8 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
if (sa->state == IKEV2_STATE_AUTHENTICATED)
{
ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR);
- ikev2_payload_add_id (chain, &sa->i_id, IKEV2_PAYLOAD_IDI);
ikev2_payload_add_auth (chain, &sa->r_auth);
- ikev2_payload_add_sa (chain, sa->childs[0].r_proposals);
+ ikev2_payload_add_sa (chain, sa->childs[0].r_proposals, 0);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
}
@@ -2414,9 +2705,12 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
else if (sa->state == IKEV2_STATE_SA_INIT)
{
ikev2_payload_add_id (chain, &sa->i_id, IKEV2_PAYLOAD_IDI);
- ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR);
+ /* IDr is optional when sending INIT from the initiator */
+ ASSERT (sa->r_id.type != 0 || sa->is_initiator);
+ if (sa->r_id.type != 0)
+ ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR);
ikev2_payload_add_auth (chain, &sa->i_auth);
- ikev2_payload_add_sa (chain, sa->childs[0].i_proposals);
+ ikev2_payload_add_sa (chain, sa->childs[0].i_proposals, 0);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_INITIAL_CONTACT,
@@ -2493,7 +2787,7 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
notify.spi = sa->childs[0].i_proposals->spi;
*(u32 *) data = clib_host_to_net_u32 (notify.spi);
- ikev2_payload_add_sa (chain, proposals);
+ ikev2_payload_add_sa (chain, proposals, 0);
ikev2_payload_add_nonce (chain, sa->i_nonce);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
@@ -2504,22 +2798,27 @@ ikev2_generate_message (vlib_buffer_t *b, ikev2_sa_t *sa, ike_header_t *ike,
}
else if (vec_len (sa->rekey) > 0)
{
- ikev2_payload_add_sa (chain, sa->rekey[0].r_proposal);
- ikev2_payload_add_nonce (chain, sa->r_nonce);
- ikev2_payload_add_ts (chain, sa->rekey[0].tsi, IKEV2_PAYLOAD_TSI);
- ikev2_payload_add_ts (chain, sa->rekey[0].tsr, IKEV2_PAYLOAD_TSR);
+ ikev2_add_create_child_resp (sa, &sa->rekey[0], chain);
vec_del1 (sa->rekey, 0);
}
else if (vec_len (sa->new_child) > 0)
{
- ikev2_payload_add_sa (chain, sa->new_child[0].r_proposal);
- ikev2_payload_add_nonce (chain, sa->r_nonce);
- ikev2_payload_add_ts (chain, sa->new_child[0].tsi,
- IKEV2_PAYLOAD_TSI);
- ikev2_payload_add_ts (chain, sa->new_child[0].tsr,
- IKEV2_PAYLOAD_TSR);
+ ikev2_add_create_child_resp (sa, &sa->new_child[0], chain);
vec_del1 (sa->new_child, 0);
}
+ else if (vec_len (sa->sa_rekey) > 0)
+ {
+ if (sa->sa_rekey[0].notify_type)
+ ikev2_add_notify_payload (sa, chain, sa->sa_rekey[0].notify_type);
+ else
+ {
+ ikev2_payload_add_sa (chain, sa->sa_rekey[0].r_proposals, 1);
+ ikev2_payload_add_nonce (chain, sa->sa_rekey[0].r_nonce);
+ ikev2_payload_add_ke (chain, sa->sa_rekey[0].dh_group,
+ sa->sa_rekey[0].r_dh_data);
+ }
+ vec_del1 (sa->sa_rekey, 0);
+ }
else if (sa->unsupported_cp)
{
u8 *data = vec_new (u8, 1);
@@ -2712,13 +3011,11 @@ ikev2_retransmit_sa_init (ike_header_t * ike, ip_address_t iaddr,
u32 res;
ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data ();
- /* *INDENT-OFF* */
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 */
return 0;
@@ -2796,8 +3093,8 @@ ikev2_del_sa_init (u64 ispi)
sizeof (ispi));
}
-static_always_inline void
-ikev2_rewrite_v6_addrs (ikev2_sa_t * sa, ip6_header_t * ih)
+static void
+ikev2_rewrite_v6_addrs (ikev2_sa_t *sa, ip6_header_t *ih)
{
if (sa->is_initiator)
{
@@ -2811,8 +3108,8 @@ ikev2_rewrite_v6_addrs (ikev2_sa_t * sa, ip6_header_t * ih)
}
}
-static_always_inline void
-ikev2_rewrite_v4_addrs (ikev2_sa_t * sa, ip4_header_t * ih)
+static void
+ikev2_rewrite_v4_addrs (ikev2_sa_t *sa, ip4_header_t *ih)
{
if (sa->is_initiator)
{
@@ -2826,7 +3123,7 @@ ikev2_rewrite_v4_addrs (ikev2_sa_t * sa, ip4_header_t * ih)
}
}
-static_always_inline void
+static void
ikev2_set_ip_address (ikev2_sa_t *sa, const void *iaddr, const void *raddr,
const ip_address_family_t af)
{
@@ -2881,7 +3178,7 @@ ikev2_update_stats (vlib_main_t *vm, u32 node_index, ikev2_stats_t *s)
s->n_sa_auth_req);
}
-static_always_inline uword
+static uword
ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
vlib_frame_t *frame, u8 is_ip4, u8 natt)
{
@@ -3131,18 +3428,19 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
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);
+ ikev2_sa_auth (sa0, vm);
else
vlib_node_increment_counter (vm, node->node_index,
IKEV2_ERROR_MALFORMED_PACKET, 1);
if (sa0->state == IKEV2_STATE_AUTHENTICATED)
{
ikev2_initial_contact_cleanup (ptd, sa0);
+ p = hash_get (ptd->sa_by_rspi,
+ clib_net_to_host_u64 (ike0->rspi));
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);
+ ikev2_create_tunnel_interface (vm, sa0, &sa0->childs[0],
+ p[0], 0, 0, 0);
}
if (sa0->is_initiator)
@@ -3267,11 +3565,12 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
goto dispatch0;
}
- if (sa0->rekey)
+ if (vec_len (sa0->rekey) > 0)
{
- if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
+ if (!sa0->rekey[0].notify_type &&
+ sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE)
{
- if (sa0->childs)
+ if (vec_len (sa0->childs) > 0)
ikev2_sa_free_all_child_sa (&sa0->childs);
ikev2_child_sa_t *child;
vec_add2 (sa0->childs, child, 1);
@@ -3281,7 +3580,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
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);
+ child - sa0->childs, 1,
+ sa0->rekey[0].kex);
}
if (ike_hdr_is_response (ike0))
{
@@ -3300,7 +3600,7 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
1);
}
}
- else if (sa0->new_child)
+ else if (vec_len (sa0->new_child) > 0)
{
ikev2_child_sa_t *c;
vec_add2 (sa0->childs, c, 1);
@@ -3310,7 +3610,8 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
c->tsi = sa0->new_child[0].tsi;
c->tsr = sa0->new_child[0].tsr;
ikev2_create_tunnel_interface (vm, sa0, c, p[0],
- c - sa0->childs, 0);
+ c - sa0->childs, 0,
+ sa0->new_child[0].kex);
if (ike_hdr_is_request (ike0))
{
ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
@@ -3321,6 +3622,38 @@ ikev2_node_internal (vlib_main_t *vm, vlib_node_runtime_t *node,
vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1);
}
}
+ else if (vec_len (sa0->sa_rekey) > 0)
+ {
+ if (!sa0->sa_rekey[0].notify_type)
+ {
+ ikev2_sa_t *sar, *tmp = 0;
+ pool_get (ptd->sas, tmp);
+ sa0 = pool_elt_at_index (ptd->sas, p[0]);
+ /* swap old/new SAs to keep index and inherit IPsec SA */
+ clib_memcpy_fast (tmp, sa0, sizeof (*tmp));
+ sar = sa0;
+ sa0 = tmp;
+ hash_set (ptd->sa_by_rspi, sa0->rspi, sa0 - ptd->sas);
+ p = hash_get (ptd->sa_by_rspi, sa0->rspi);
+ ikev2_complete_sa_rekey (sar, sa0, &sa0->sa_rekey[0]);
+ hash_set (ptd->sa_by_rspi, sar->rspi, sar - ptd->sas);
+ }
+ if (ike_hdr_is_response (ike0))
+ {
+ vec_free (sa0->sa_rekey);
+ }
+ else
+ {
+ stats->n_rekey_req++;
+ sa0->stats.n_rekey_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, 1);
+ }
+ }
}
}
else
@@ -3429,7 +3762,6 @@ 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 */, 0);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ikev2_node_ip4,static) = {
.function = ikev2_ip4,
.name = "ikev2-ip4",
@@ -3480,7 +3812,6 @@ VLIB_REGISTER_NODE (ikev2_node_ip6,static) = {
[IKEV2_NEXT_IP6_ERROR_DROP] = "error-drop",
},
};
-/* *INDENT-ON* */
// set ikev2 proposals when vpp is used as initiator
static clib_error_t *
@@ -3721,21 +4052,23 @@ ikev2_set_local_key (vlib_main_t * vm, u8 * file)
return 0;
}
-static_always_inline vnet_api_error_t
-ikev2_register_udp_port (ikev2_profile_t * p, u16 port)
+static vnet_api_error_t
+ikev2_register_udp_port (ikev2_profile_t *p, u16 port)
{
- ipsec_register_udp_port (port);
+ ipsec_register_udp_port (port, 0 /* is_ip4 */);
+ ipsec_register_udp_port (port, 1 /* is_ip4 */);
p->ipsec_over_udp_port = port;
return 0;
}
-static_always_inline void
-ikev2_unregister_udp_port (ikev2_profile_t * p)
+static void
+ikev2_unregister_udp_port (ikev2_profile_t *p)
{
if (p->ipsec_over_udp_port == IPSEC_UDP_PORT_NONE)
return;
- ipsec_unregister_udp_port (p->ipsec_over_udp_port);
+ ipsec_unregister_udp_port (p->ipsec_over_udp_port, 0 /* is_ip4 */);
+ ipsec_unregister_udp_port (p->ipsec_over_udp_port, 1 /* is_ip4 */);
p->ipsec_over_udp_port = IPSEC_UDP_PORT_NONE;
}
@@ -3820,12 +4153,10 @@ ikev2_cleanup_profile_sessions (ikev2_main_t * km, ikev2_profile_t * p)
u32 *sai;
u32 *del_sai = 0;
- /* *INDENT-OFF* */
pool_foreach (sa, km->sais) {
if (pi == sa->profile_index)
vec_add1 (del_sai, sa - km->sais);
}
- /* *INDENT-ON* */
vec_foreach (sai, del_sai)
{
@@ -3838,12 +4169,10 @@ ikev2_cleanup_profile_sessions (ikev2_main_t * km, ikev2_profile_t * p)
vec_foreach (tkm, km->per_thread_data)
{
- /* *INDENT-OFF* */
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)
{
@@ -3878,12 +4207,51 @@ ikev2_profile_free (ikev2_profile_t * p)
vec_free (p->rem_id.data);
}
+static void
+ikev2_bind (vlib_main_t *vm, ikev2_main_t *km)
+{
+ if (0 == km->bind_refcount)
+ {
+ udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip4.index, 1);
+ udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip6.index, 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_register (km->punt_hdl,
+ ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
+ "ikev2-ip4-natt");
+ }
+
+ km->bind_refcount++;
+}
+
+static void
+ikev2_unbind (vlib_main_t *vm, ikev2_main_t *km)
+{
+ km->bind_refcount--;
+ if (0 == km->bind_refcount)
+ {
+ vlib_punt_unregister (km->punt_hdl,
+ ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
+ "ikev2-ip4-natt");
+
+ udp_unregister_dst_port (vm, IKEV2_PORT_NATT, 0);
+ udp_unregister_dst_port (vm, IKEV2_PORT_NATT, 1);
+ udp_unregister_dst_port (vm, IKEV2_PORT, 0);
+ udp_unregister_dst_port (vm, IKEV2_PORT, 1);
+ }
+}
+
+static void ikev2_lazy_init (ikev2_main_t *km);
+
clib_error_t *
ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
{
ikev2_main_t *km = &ikev2_main;
ikev2_profile_t *p;
+ ikev2_lazy_init (km);
+
if (is_add)
{
if (ikev2_profile_index_by_name (name))
@@ -3897,6 +4265,8 @@ ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
p->tun_itf = ~0;
uword index = p - km->profiles;
mhash_set_mem (&km->profile_index_by_name, name, &index, 0);
+
+ ikev2_bind (vm, km);
}
else
{
@@ -3904,6 +4274,8 @@ ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
if (!p)
return clib_error_return (0, "policy %v does not exists", name);
+ ikev2_unbind (vm, km);
+
ikev2_unregister_udp_port (p);
ikev2_cleanup_profile_sessions (km, p);
@@ -3995,8 +4367,8 @@ ikev2_set_profile_id (vlib_main_t * vm, u8 * name, u8 id_type, u8 * data,
return 0;
}
-static_always_inline void
-ikev2_set_ts_type (ikev2_ts_t * ts, const ip_address_t * addr)
+static void
+ikev2_set_ts_type (ikev2_ts_t *ts, const ip_address_t *addr)
{
if (ip_addr_version (addr) == AF_IP4)
ts->ts_type = TS_IPV4_ADDR_RANGE;
@@ -4004,9 +4376,9 @@ ikev2_set_ts_type (ikev2_ts_t * ts, const ip_address_t * addr)
ts->ts_type = TS_IPV6_ADDR_RANGE;
}
-static_always_inline void
-ikev2_set_ts_addrs (ikev2_ts_t * ts, const ip_address_t * start,
- const ip_address_t * end)
+static void
+ikev2_set_ts_addrs (ikev2_ts_t *ts, const ip_address_t *start,
+ const ip_address_t *end)
{
ip_address_copy (&ts->start_addr, start);
ip_address_copy (&ts->end_addr, end);
@@ -4103,15 +4475,15 @@ ikev2_set_profile_ike_transforms (vlib_main_t * vm, u8 * name,
u32 crypto_key_size)
{
ikev2_profile_t *p;
- clib_error_t *r;
p = ikev2_profile_index_by_name (name);
-
if (!p)
- {
- r = clib_error_return (0, "unknown profile %v", name);
- return r;
- }
+ return clib_error_return (0, "unknown profile %v", name);
+
+ if ((IKEV2_TRANSFORM_INTEG_TYPE_NONE != integ_alg) +
+ (IKEV2_TRANSFORM_ENCR_TYPE_AES_GCM_16 == crypto_alg) !=
+ 1)
+ return clib_error_return (0, "invalid cipher + integrity algorithm");
p->ike_ts.crypto_alg = crypto_alg;
p->ike_ts.integ_alg = integ_alg;
@@ -4264,13 +4636,20 @@ ikev2_resolve_responder_hostname (vlib_main_t *vm, ikev2_responder_t *r)
dns_cache_entry_t *ep = 0;
dns_pending_request_t _t0, *t0 = &_t0;
dns_resolve_name_t _rn, *rn = &_rn;
+ u8 *name;
int rv;
- if (!km->dns_resolve_name)
+ if (!km->dns_resolve_name_ptr)
return clib_error_return (0, "cannot load symbols from dns plugin");
t0->request_type = DNS_API_PENDING_NAME_TO_IP;
- rv = km->dns_resolve_name (r->hostname, &ep, t0, rn);
+ /* VPP main curse: IKEv2 uses only non-NULL terminated vectors internally
+ * whereas DNS resolver expects a NULL-terminated C-string */
+ name = vec_dup (r->hostname);
+ vec_terminate_c_string (name);
+ rv = ((__typeof__ (dns_resolve_name) *) km->dns_resolve_name_ptr) (name, &ep,
+ t0, rn);
+ vec_free (name);
if (rv < 0)
return clib_error_return (0, "dns lookup failure");
@@ -4339,7 +4718,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
proposals[0].protocol_id = IKEV2_PROTOCOL_IKE;
/* Add and then cleanup proposal data */
- ikev2_payload_add_sa (chain, proposals);
+ ikev2_payload_add_sa (chain, proposals, 0);
ikev2_sa_free_proposal_vector (&proposals);
sa.is_initiator = 1;
@@ -4373,6 +4752,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
sa.childs[0].i_proposals[0].protocol_id = IKEV2_PROTOCOL_ESP;
RAND_bytes ((u8 *) & sa.childs[0].i_proposals[0].spi,
sizeof (sa.childs[0].i_proposals[0].spi));
+ sa.childs[0].i_proposals[0].spi &= 0xffffffff;
/* Add NAT detection notification messages (mandatory) */
u8 *nat_detection_sha1 = ikev2_compute_nat_sha1 (
@@ -4524,7 +4904,6 @@ ikev2_initiate_delete_child_sa (vlib_main_t * vm, u32 ispi)
ikev2_sa_t *sa;
if (fchild)
break;
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ispi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
@@ -4533,7 +4912,6 @@ ikev2_initiate_delete_child_sa (vlib_main_t * vm, u32 ispi)
break;
}
}
- /* *INDENT-ON* */
}
if (!fchild || !fsa)
@@ -4564,7 +4942,6 @@ ikev2_initiate_delete_ike_sa (vlib_main_t * vm, u64 ispi)
ikev2_sa_t *sa;
if (fsa)
break;
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
if (sa->ispi == ispi)
{
@@ -4573,7 +4950,6 @@ ikev2_initiate_delete_ike_sa (vlib_main_t * vm, u64 ispi)
break;
}
}
- /* *INDENT-ON* */
}
if (!fsa)
@@ -4615,10 +4991,12 @@ ikev2_rekey_child_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa,
ikev2_rekey_t *rekey;
vec_reset_length (sa->rekey);
vec_add2 (sa->rekey, rekey, 1);
+ rekey->kex = 0;
ikev2_sa_proposal_t *proposals = vec_dup (csa->i_proposals);
/*need new ispi */
RAND_bytes ((u8 *) & proposals[0].spi, sizeof (proposals[0].spi));
+ proposals[0].spi &= 0xffffffff;
rekey->spi = proposals[0].spi;
rekey->ispi = csa->i_proposals->spi;
len = ikev2_generate_message (b0, sa, ike0, proposals, 0, 0);
@@ -4647,7 +5025,6 @@ ikev2_initiate_rekey_child_sa (vlib_main_t * vm, u32 ispi)
ikev2_sa_t *sa;
if (fchild)
break;
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ispi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
@@ -4656,7 +5033,6 @@ ikev2_initiate_rekey_child_sa (vlib_main_t * vm, u32 ispi)
break;
}
}
- /* *INDENT-ON* */
}
if (!fchild || !fsa)
@@ -4689,12 +5065,10 @@ ikev2_sa_del (ikev2_profile_t * p, u32 sw_if_index)
vec_foreach (tkm, km->per_thread_data)
{
- /* *INDENT-OFF* */
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)
{
@@ -4704,12 +5078,10 @@ ikev2_sa_del (ikev2_profile_t * p, u32 sw_if_index)
}
vec_free (sa_vec);
- /* *INDENT-OFF* */
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)
{
@@ -4728,12 +5100,10 @@ ikev2_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
if (is_add)
return 0;
- /* *INDENT-OFF* */
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;
}
@@ -4744,67 +5114,24 @@ clib_error_t *
ikev2_init (vlib_main_t * vm)
{
ikev2_main_t *km = &ikev2_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
- int thread_id;
clib_memset (km, 0, sizeof (ikev2_main_t));
+
+ km->log_level = IKEV2_LOG_ERROR;
+ km->log_class = vlib_log_register_class ("ikev2", 0);
+
km->vnet_main = vnet_get_main ();
km->vlib_main = vm;
km->liveness_period = IKEV2_LIVENESS_PERIOD_CHECK;
km->liveness_max_retries = IKEV2_LIVENESS_RETRIES;
- ikev2_crypto_init (km);
-
- mhash_init_vec_string (&km->profile_index_by_name, sizeof (uword));
-
- vec_validate_aligned (km->per_thread_data, tm->n_vlib_mains - 1,
- CLIB_CACHE_LINE_BYTES);
- for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++)
- {
- ikev2_main_per_thread_data_t *ptd =
- vec_elt_at_index (km->per_thread_data, thread_id);
- ptd->sa_by_rspi = hash_create (0, sizeof (uword));
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- ptd->evp_ctx = EVP_CIPHER_CTX_new ();
- ptd->hmac_ctx = HMAC_CTX_new ();
-#else
- EVP_CIPHER_CTX_init (&ptd->_evp_ctx);
- ptd->evp_ctx = &ptd->_evp_ctx;
- HMAC_CTX_init (&(ptd->_hmac_ctx));
- ptd->hmac_ctx = &ptd->_hmac_ctx;
-#endif
- }
-
- km->sa_by_ispi = hash_create (0, sizeof (uword));
- km->sw_if_indices = hash_create (0, 0);
-
- udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip4.index, 1);
- udp_register_dst_port (vm, IKEV2_PORT, ikev2_node_ip6.index, 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-natt");
- vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0],
- "ikev2-ip4-natt");
- ikev2_cli_reference ();
-
- km->dns_resolve_name =
- vlib_get_plugin_symbol ("dns_plugin.so", "dns_resolve_name");
- if (!km->dns_resolve_name)
- ikev2_log_error ("cannot load symbols from dns plugin");
-
- km->log_level = IKEV2_LOG_ERROR;
- km->log_class = vlib_log_register_class ("ikev2", 0);
return 0;
}
-/* *INDENT-OFF* */
VLIB_INIT_FUNCTION (ikev2_init) = {
- .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init", "dns_init"),
+ .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init"),
};
-/* *INDENT-ON* */
static u8
ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa,
@@ -4875,14 +5202,12 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa,
ip_addr_bytes (&sa->iaddr));
}
- /* *INDENT-OFF* */
ipip_tunnel_key_t key = {
.src = local_ip,
.dst = remote_ip,
.transport = IPIP_TRANSPORT_IP4,
.fib_index = 0,
};
- /* *INDENT-ON* */
ipip = ipip_tunnel_db_find (&key);
@@ -4963,7 +5288,6 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
ikev2_sa_t *sa;
if (fchild)
break;
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
fchild = ikev2_sa_get_child(sa, ipsec_sa->spi, IKEV2_PROTOCOL_ESP, 1);
if (fchild)
@@ -4972,7 +5296,6 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
break;
}
}
- /* *INDENT-ON* */
}
vlib_get_combined_counter (&ipsec_sa_counters,
ipsec_sa->stat_index, &counts);
@@ -5070,7 +5393,6 @@ ikev2_process_pending_sa_init (vlib_main_t *vm, ikev2_main_t *km)
u64 ispi;
ikev2_sa_t *sa;
- /* *INDENT-OFF* */
hash_foreach (ispi, sai, km->sa_by_ispi,
({
sa = pool_elt_at_index (km->sais, sai);
@@ -5079,7 +5401,6 @@ ikev2_process_pending_sa_init (vlib_main_t *vm, ikev2_main_t *km)
ikev2_process_pending_sa_init_one (vm, km, sa);
}));
- /* *INDENT-ON* */
}
static void
@@ -5137,8 +5458,8 @@ ikev2_disable_dpd (void)
km->dpd_disabled = 1;
}
-static_always_inline int
-ikev2_mngr_process_responder_sas (ikev2_sa_t * sa)
+static int
+ikev2_mngr_process_responder_sas (ikev2_sa_t *sa)
{
ikev2_main_t *km = &ikev2_main;
vlib_main_t *vm = km->vlib_main;
@@ -5169,6 +5490,9 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
ikev2_child_sa_t *c;
u32 *sai;
+ /* lazy init will wake it up */
+ vlib_process_wait_for_event (vm);
+
while (1)
{
vlib_process_wait_for_event_or_clock (vm, 2);
@@ -5181,34 +5505,38 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
ikev2_sa_t *sa;
u32 *to_be_deleted = 0;
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
ikev2_child_sa_t *c;
u8 del_old_ids = 0;
- if (sa->state != IKEV2_STATE_AUTHENTICATED)
- continue;
+ if (sa->state == IKEV2_STATE_SA_INIT)
+ {
+ if (vec_len (sa->childs) > 0)
+ vec_add1 (to_be_deleted, sa - tkm->sas);
+ }
+ else if (sa->state != IKEV2_STATE_AUTHENTICATED)
+ continue;
- if (sa->old_remote_id_present && 0 > sa->old_id_expiration)
- {
- sa->old_remote_id_present = 0;
- del_old_ids = 1;
- }
- else
- sa->old_id_expiration -= 1;
+ if (sa->old_remote_id_present && 0 > sa->old_id_expiration)
+ {
+ sa->old_remote_id_present = 0;
+ del_old_ids = 1;
+ }
+ else
+ sa->old_id_expiration -= 1;
- vec_foreach (c, sa->childs)
- ikev2_mngr_process_child_sa(sa, c, del_old_ids);
+ vec_foreach (c, sa->childs)
+ ikev2_mngr_process_child_sa (sa, c, del_old_ids);
- if (!km->dpd_disabled && ikev2_mngr_process_responder_sas (sa))
- vec_add1 (to_be_deleted, sa - tkm->sas);
- }
- /* *INDENT-ON* */
+ if (!km->dpd_disabled && ikev2_mngr_process_responder_sas (sa))
+ vec_add1 (to_be_deleted, sa - tkm->sas);
+ }
vec_foreach (sai, to_be_deleted)
{
sa = pool_elt_at_index (tkm->sas, sai[0]);
- u8 reinitiate = (sa->is_initiator && sa->profile_index != ~0);
+ const u32 profile_index = sa->profile_index;
+ const int reinitiate = (sa->is_initiator && profile_index != ~0);
vec_foreach (c, sa->childs)
{
ikev2_delete_tunnel_interface (km->vnet_main, sa, c);
@@ -5220,7 +5548,7 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
if (reinitiate)
{
- p = pool_elt_at_index (km->profiles, sa->profile_index);
+ p = pool_elt_at_index (km->profiles, profile_index);
if (p)
{
clib_error_t *e = ikev2_initiate_sa_init (vm, p->name);
@@ -5237,19 +5565,16 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
/* process ipsec sas */
ipsec_sa_t *sa;
- /* *INDENT-OFF* */
pool_foreach (sa, ipsec_sa_pool)
{
ikev2_mngr_process_ipsec_sa (sa);
}
- /* *INDENT-ON* */
ikev2_process_pending_sa_init (vm, km);
}
return 0;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ikev2_mngr_process_node, static) = {
.function = ikev2_mngr_process_fn,
.type = VLIB_NODE_TYPE_PROCESS,
@@ -5257,11 +5582,60 @@ VLIB_REGISTER_NODE (ikev2_mngr_process_node, static) = {
"ikev2-manager-process",
};
+static void
+ikev2_lazy_init (ikev2_main_t *km)
+{
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
+ int thread_id;
+
+ if (km->lazy_init_done)
+ return;
+
+ ikev2_crypto_init (km);
+
+ mhash_init_vec_string (&km->profile_index_by_name, sizeof (uword));
+
+ vec_validate_aligned (km->per_thread_data, tm->n_vlib_mains - 1,
+ CLIB_CACHE_LINE_BYTES);
+ for (thread_id = 0; thread_id < tm->n_vlib_mains; thread_id++)
+ {
+ ikev2_main_per_thread_data_t *ptd =
+ vec_elt_at_index (km->per_thread_data, thread_id);
+
+ ptd->sa_by_rspi = hash_create (0, sizeof (uword));
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ ptd->evp_ctx = EVP_CIPHER_CTX_new ();
+ ptd->hmac_ctx = HMAC_CTX_new ();
+#else
+ EVP_CIPHER_CTX_init (&ptd->_evp_ctx);
+ ptd->evp_ctx = &ptd->_evp_ctx;
+ HMAC_CTX_init (&(ptd->_hmac_ctx));
+ ptd->hmac_ctx = &ptd->_hmac_ctx;
+#endif
+ }
+
+ km->sa_by_ispi = hash_create (0, sizeof (uword));
+ km->sw_if_indices = hash_create (0, 0);
+
+ km->punt_hdl = vlib_punt_client_register ("ikev2");
+
+ km->dns_resolve_name_ptr =
+ vlib_get_plugin_symbol ("dns_plugin.so", "dns_resolve_name");
+ if (!km->dns_resolve_name_ptr)
+ ikev2_log_error ("cannot load symbols from dns plugin");
+
+ /* wake up ikev2 process */
+ vlib_process_signal_event (vlib_get_first_main (),
+ ikev2_mngr_process_node.index, 0, 0);
+
+ km->lazy_init_done = 1;
+}
+
VLIB_PLUGIN_REGISTER () = {
.version = VPP_BUILD_VER,
.description = "Internet Key Exchange (IKEv2) Protocol",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/ikev2/ikev2.h b/src/plugins/ikev2/ikev2.h
index 308ffe52ba4..9ed0ecc494c 100644
--- a/src/plugins/ikev2/ikev2.h
+++ b/src/plugins/ikev2/ikev2.h
@@ -32,7 +32,6 @@
typedef u8 v8;
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u64 ispi;
u64 rspi;
@@ -42,14 +41,12 @@ typedef CLIB_PACKED (struct {
u8 flags;
u32 msgid; u32 length; u8 payload[0];
}) ike_header_t;
-/* *INDENT-ON* */
#define ike_hdr_is_response(_h) ((_h)->flags & IKEV2_HDR_FLAG_RESPONSE)
#define ike_hdr_is_request(_h) (!ike_hdr_is_response(_h))
#define ike_hdr_is_initiator(_h) ((_h)->flags & IKEV2_HDR_FLAG_INITIATOR)
#define ike_hdr_is_responder(_h) (!(ike_hdr_is_initiator(_h)))
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -58,17 +55,13 @@ typedef CLIB_PACKED (struct {
u8 reserved[2];
u8 payload[0];
}) ike_ke_payload_header_t;
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
u16 length; u8 payload[0];
}) ike_payload_header_t;
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -77,9 +70,7 @@ typedef CLIB_PACKED (struct {
u8 reserved[3];
u8 payload[0];
}) ike_auth_payload_header_t;
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -87,7 +78,6 @@ typedef CLIB_PACKED (struct {
u8 id_type;
u8 reserved[3]; u8 payload[0];
}) ike_id_payload_header_t;
-/* *INDENT-ON* */
#define IKE_VERSION_2 0x20
@@ -451,7 +441,6 @@ uword unformat_ikev2_transform_dh_type (unformat_input_t * input,
va_list * args);
uword unformat_ikev2_transform_esn_type (unformat_input_t * input,
va_list * args);
-void ikev2_cli_reference (void);
clib_error_t *ikev2_set_liveness_params (u32 period, u32 max_retries);
diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c
index d104e54579a..c9608aa660b 100644
--- a/src/plugins/ikev2/ikev2_api.c
+++ b/src/plugins/ikev2/ikev2_api.c
@@ -173,7 +173,7 @@ send_profile (ikev2_profile_t * profile, vl_api_registration_t * reg,
rmp->profile.lifetime_jitter = profile->lifetime_jitter;
rmp->profile.handover = profile->handover;
- vl_api_ikev2_profile_t_endian (&rmp->profile);
+ vl_api_ikev2_profile_t_endian (&rmp->profile, 1 /* to network */);
vl_api_send_msg (reg, (u8 *) rmp);
}
@@ -188,12 +188,10 @@ vl_api_ikev2_profile_dump_t_handler (vl_api_ikev2_profile_dump_t * mp)
if (!reg)
return;
- /* *INDENT-OFF* */
pool_foreach (profile, im->profiles)
{
send_profile (profile, reg, mp->context);
}
- /* *INDENT-ON* */
}
static void
@@ -207,6 +205,32 @@ ikev2_copy_stats (vl_api_ikev2_sa_stats_t *dst, const ikev2_stats_t *src)
dst->n_sa_auth_req = src->n_sa_auth_req;
}
+static vl_api_ikev2_state_t
+ikev2_state_encode (ikev2_state_t state)
+{
+ switch (state)
+ {
+ case IKEV2_STATE_UNKNOWN:
+ return UNKNOWN;
+ case IKEV2_STATE_SA_INIT:
+ return SA_INIT;
+ case IKEV2_STATE_DELETED:
+ return DELETED;
+ case IKEV2_STATE_AUTH_FAILED:
+ return AUTH_FAILED;
+ case IKEV2_STATE_AUTHENTICATED:
+ return AUTHENTICATED;
+ case IKEV2_STATE_NOTIFY_AND_DELETE:
+ return NOTIFY_AND_DELETE;
+ case IKEV2_STATE_TS_UNACCEPTABLE:
+ return TS_UNACCEPTABLE;
+ case IKEV2_STATE_NO_PROPOSAL_CHOSEN:
+ return NO_PROPOSAL_CHOSEN;
+ }
+
+ return UNKNOWN;
+}
+
static void
send_sa (ikev2_sa_t * sa, vl_api_ikev2_sa_dump_t * mp, u32 api_sa_index)
{
@@ -214,7 +238,6 @@ send_sa (ikev2_sa_t * sa, vl_api_ikev2_sa_dump_t * mp, u32 api_sa_index)
int rv = 0;
ikev2_sa_transform_t *tr;
- /* *INDENT-OFF* */
REPLY_MACRO2_ZERO (VL_API_IKEV2_SA_DETAILS,
{
vl_api_ikev2_sa_t *rsa = &rmp->sa;
@@ -268,9 +291,8 @@ send_sa (ikev2_sa_t * sa, vl_api_ikev2_sa_dump_t * mp, u32 api_sa_index)
ikev2_copy_stats (&rsa->stats, &sa->stats);
- vl_api_ikev2_sa_t_endian(rsa);
+ vl_api_ikev2_sa_t_endian (rsa, 1 /* to network */);
});
- /* *INDENT-ON* */
}
static void
@@ -282,17 +304,199 @@ vl_api_ikev2_sa_dump_t_handler (vl_api_ikev2_sa_dump_t * mp)
vec_foreach (tkm, km->per_thread_data)
{
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas)
{
u32 api_sa_index = ikev2_encode_sa_index (sa - tkm->sas,
tkm - km->per_thread_data);
send_sa (sa, mp, api_sa_index);
}
- /* *INDENT-ON* */
}
}
+static void
+send_sa_v2 (ikev2_sa_t *sa, vl_api_ikev2_sa_v2_dump_t *mp, u32 api_sa_index)
+{
+ ikev2_main_t *km = &ikev2_main;
+ vl_api_ikev2_sa_v2_details_t *rmp = 0;
+ int rv = 0;
+ ikev2_sa_transform_t *tr;
+ ikev2_profile_t *p;
+ p = pool_elt_at_index (km->profiles, sa->profile_index);
+
+ REPLY_MACRO2_ZERO (VL_API_IKEV2_SA_V2_DETAILS, {
+ vl_api_ikev2_sa_v2_t *rsa = &rmp->sa;
+ vl_api_ikev2_keys_t *k = &rsa->keys;
+
+ int size_data = sizeof (rsa->profile_name) - 1;
+ if (vec_len (p->name) < size_data)
+ size_data = vec_len (p->name);
+ clib_memcpy (rsa->profile_name, p->name, size_data);
+
+ rsa->state = ikev2_state_encode (sa->state);
+
+ rsa->sa_index = api_sa_index;
+ ip_address_encode2 (&sa->iaddr, &rsa->iaddr);
+ ip_address_encode2 (&sa->raddr, &rsa->raddr);
+ rsa->ispi = sa->ispi;
+ rsa->rspi = sa->rspi;
+ cp_id (&rsa->i_id, &sa->i_id);
+ cp_id (&rsa->r_id, &sa->r_id);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
+ if (tr)
+ cp_sa_transform (&rsa->encryption, tr);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+ if (tr)
+ cp_sa_transform (&rsa->prf, tr);
+
+ tr =
+ ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
+ if (tr)
+ cp_sa_transform (&rsa->integrity, tr);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ if (tr)
+ cp_sa_transform (&rsa->dh, tr);
+
+ k->sk_d_len = vec_len (sa->sk_d);
+ clib_memcpy (&k->sk_d, sa->sk_d, k->sk_d_len);
+
+ k->sk_ai_len = vec_len (sa->sk_ai);
+ clib_memcpy (&k->sk_ai, sa->sk_ai, k->sk_ai_len);
+
+ k->sk_ar_len = vec_len (sa->sk_ar);
+ clib_memcpy (&k->sk_ar, sa->sk_ar, k->sk_ar_len);
+
+ k->sk_ei_len = vec_len (sa->sk_ei);
+ clib_memcpy (&k->sk_ei, sa->sk_ei, k->sk_ei_len);
+
+ k->sk_er_len = vec_len (sa->sk_er);
+ clib_memcpy (&k->sk_er, sa->sk_er, k->sk_er_len);
+
+ k->sk_pi_len = vec_len (sa->sk_pi);
+ clib_memcpy (&k->sk_pi, sa->sk_pi, k->sk_pi_len);
+
+ k->sk_pr_len = vec_len (sa->sk_pr);
+ clib_memcpy (&k->sk_pr, sa->sk_pr, k->sk_pr_len);
+
+ ikev2_copy_stats (&rsa->stats, &sa->stats);
+
+ vl_api_ikev2_sa_v2_t_endian (rsa, 1 /* to network */);
+ });
+}
+
+static void
+vl_api_ikev2_sa_v2_dump_t_handler (vl_api_ikev2_sa_v2_dump_t *mp)
+{
+ ikev2_main_t *km = &ikev2_main;
+ ikev2_main_per_thread_data_t *tkm;
+ ikev2_sa_t *sa;
+
+ vec_foreach (tkm, km->per_thread_data)
+ {
+ pool_foreach (sa, tkm->sas)
+ {
+ u32 api_sa_index =
+ ikev2_encode_sa_index (sa - tkm->sas, tkm - km->per_thread_data);
+ send_sa_v2 (sa, mp, api_sa_index);
+ }
+ }
+}
+
+static void
+send_sa_v3 (ikev2_sa_t *sa, vl_api_ikev2_sa_v3_dump_t *mp, u32 api_sa_index)
+{
+ ikev2_main_t *km = &ikev2_main;
+ vl_api_ikev2_sa_v3_details_t *rmp = 0;
+ int rv = 0;
+ ikev2_sa_transform_t *tr;
+ ikev2_profile_t *p;
+ p = pool_elt_at_index (km->profiles, sa->profile_index);
+ vlib_main_t *vm = vlib_get_main ();
+
+ REPLY_MACRO2_ZERO (VL_API_IKEV2_SA_V3_DETAILS, {
+ vl_api_ikev2_sa_v3_t *rsa = &rmp->sa;
+ vl_api_ikev2_keys_t *k = &rsa->keys;
+
+ int size_data = sizeof (rsa->profile_name) - 1;
+ if (vec_len (p->name) < size_data)
+ size_data = vec_len (p->name);
+ clib_memcpy (rsa->profile_name, p->name, size_data);
+
+ rsa->state = ikev2_state_encode (sa->state);
+
+ rsa->uptime = vlib_time_now (vm) - sa->auth_timestamp;
+
+ rsa->sa_index = api_sa_index;
+ ip_address_encode2 (&sa->iaddr, &rsa->iaddr);
+ ip_address_encode2 (&sa->raddr, &rsa->raddr);
+ rsa->ispi = sa->ispi;
+ rsa->rspi = sa->rspi;
+ cp_id (&rsa->i_id, &sa->i_id);
+ cp_id (&rsa->r_id, &sa->r_id);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
+ if (tr)
+ cp_sa_transform (&rsa->encryption, tr);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+ if (tr)
+ cp_sa_transform (&rsa->prf, tr);
+
+ tr =
+ ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG);
+ if (tr)
+ cp_sa_transform (&rsa->integrity, tr);
+
+ tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ if (tr)
+ cp_sa_transform (&rsa->dh, tr);
+
+ k->sk_d_len = vec_len (sa->sk_d);
+ clib_memcpy (&k->sk_d, sa->sk_d, k->sk_d_len);
+
+ k->sk_ai_len = vec_len (sa->sk_ai);
+ clib_memcpy (&k->sk_ai, sa->sk_ai, k->sk_ai_len);
+
+ k->sk_ar_len = vec_len (sa->sk_ar);
+ clib_memcpy (&k->sk_ar, sa->sk_ar, k->sk_ar_len);
+
+ k->sk_ei_len = vec_len (sa->sk_ei);
+ clib_memcpy (&k->sk_ei, sa->sk_ei, k->sk_ei_len);
+
+ k->sk_er_len = vec_len (sa->sk_er);
+ clib_memcpy (&k->sk_er, sa->sk_er, k->sk_er_len);
+
+ k->sk_pi_len = vec_len (sa->sk_pi);
+ clib_memcpy (&k->sk_pi, sa->sk_pi, k->sk_pi_len);
+
+ k->sk_pr_len = vec_len (sa->sk_pr);
+ clib_memcpy (&k->sk_pr, sa->sk_pr, k->sk_pr_len);
+
+ ikev2_copy_stats (&rsa->stats, &sa->stats);
+
+ vl_api_ikev2_sa_v3_t_endian (rsa, 1 /* to network */);
+ });
+}
+
+static void
+vl_api_ikev2_sa_v3_dump_t_handler (vl_api_ikev2_sa_v3_dump_t *mp)
+{
+ ikev2_main_t *km = &ikev2_main;
+ ikev2_main_per_thread_data_t *tkm;
+ ikev2_sa_t *sa;
+
+ vec_foreach (tkm, km->per_thread_data)
+ {
+ pool_foreach (sa, tkm->sas)
+ {
+ u32 api_sa_index =
+ ikev2_encode_sa_index (sa - tkm->sas, tkm - km->per_thread_data);
+ send_sa_v3 (sa, mp, api_sa_index);
+ }
+ }
+}
static void
send_child_sa (ikev2_child_sa_t * child,
@@ -303,7 +507,6 @@ send_child_sa (ikev2_child_sa_t * child,
int rv = 0;
ikev2_sa_transform_t *tr;
- /* *INDENT-OFF* */
REPLY_MACRO2_ZERO (VL_API_IKEV2_CHILD_SA_DETAILS,
{
vl_api_ikev2_keys_t *k = &rmp->child_sa.keys;
@@ -346,9 +549,8 @@ send_child_sa (ikev2_child_sa_t * child,
k->sk_ar_len);
}
- vl_api_ikev2_child_sa_t_endian (&rmp->child_sa);
+ vl_api_ikev2_child_sa_t_endian (&rmp->child_sa, 1 /* to network */);
});
- /* *INDENT-ON* */
}
static void
@@ -380,6 +582,85 @@ vl_api_ikev2_child_sa_dump_t_handler (vl_api_ikev2_child_sa_dump_t * mp)
}
static void
+send_child_sa_v2 (ikev2_child_sa_t *child, vl_api_ikev2_child_sa_v2_dump_t *mp,
+ u32 child_sa_index, u32 sa_index)
+{
+ vl_api_ikev2_child_sa_v2_details_t *rmp = 0;
+ int rv = 0;
+ ikev2_sa_transform_t *tr;
+ vlib_main_t *vm = vlib_get_main ();
+
+ REPLY_MACRO2_ZERO (VL_API_IKEV2_CHILD_SA_V2_DETAILS, {
+ vl_api_ikev2_keys_t *k = &rmp->child_sa.keys;
+ rmp->child_sa.child_sa_index = child_sa_index;
+ rmp->child_sa.uptime = vlib_time_now (vm) - child->timestamp;
+ rmp->child_sa.sa_index = sa_index;
+ rmp->child_sa.i_spi = child->i_proposals ? child->i_proposals[0].spi : 0;
+ rmp->child_sa.r_spi = child->r_proposals ? child->r_proposals[0].spi : 0;
+
+ tr =
+ ikev2_sa_get_td_for_type (child->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR);
+ if (tr)
+ cp_sa_transform (&rmp->child_sa.encryption, tr);
+
+ tr = ikev2_sa_get_td_for_type (child->r_proposals,
+ IKEV2_TRANSFORM_TYPE_INTEG);
+ if (tr)
+ cp_sa_transform (&rmp->child_sa.integrity, tr);
+
+ tr =
+ ikev2_sa_get_td_for_type (child->r_proposals, IKEV2_TRANSFORM_TYPE_ESN);
+ if (tr)
+ cp_sa_transform (&rmp->child_sa.esn, tr);
+
+ k->sk_ei_len = vec_len (child->sk_ei);
+ clib_memcpy (&k->sk_ei, child->sk_ei, k->sk_ei_len);
+
+ k->sk_er_len = vec_len (child->sk_er);
+ clib_memcpy (&k->sk_er, child->sk_er, k->sk_er_len);
+
+ if (vec_len (child->sk_ai))
+ {
+ k->sk_ai_len = vec_len (child->sk_ai);
+ clib_memcpy (&k->sk_ai, child->sk_ai, k->sk_ai_len);
+
+ k->sk_ar_len = vec_len (child->sk_ar);
+ clib_memcpy (&k->sk_ar, child->sk_ar, k->sk_ar_len);
+ }
+
+ vl_api_ikev2_child_sa_v2_t_endian (&rmp->child_sa, 1 /* to network */);
+ });
+}
+
+static void
+vl_api_ikev2_child_sa_v2_dump_t_handler (vl_api_ikev2_child_sa_v2_dump_t *mp)
+{
+ ikev2_main_t *im = &ikev2_main;
+ ikev2_main_per_thread_data_t *tkm;
+ ikev2_sa_t *sa;
+ ikev2_child_sa_t *child;
+ u32 sai = ~0, ti = ~0;
+
+ ikev2_decode_sa_index (clib_net_to_host_u32 (mp->sa_index), &sai, &ti);
+
+ if (vec_len (im->per_thread_data) <= ti)
+ return;
+
+ tkm = vec_elt_at_index (im->per_thread_data, ti);
+
+ if (pool_len (tkm->sas) <= sai || pool_is_free_index (tkm->sas, sai))
+ return;
+
+ sa = pool_elt_at_index (tkm->sas, sai);
+
+ vec_foreach (child, sa->childs)
+ {
+ u32 child_sa_index = child - sa->childs;
+ send_child_sa_v2 (child, mp, child_sa_index, sai);
+ }
+}
+
+static void
vl_api_ikev2_traffic_selector_dump_t_handler
(vl_api_ikev2_traffic_selector_dump_t * mp)
{
@@ -414,15 +695,13 @@ static void
vl_api_ikev2_traffic_selector_details_t *rmp = 0;
int rv = 0;
- /* *INDENT-OFF* */
REPLY_MACRO2_ZERO (VL_API_IKEV2_TRAFFIC_SELECTOR_DETAILS,
{
rmp->ts.sa_index = api_sa_index;
rmp->ts.child_sa_index = child_sa_index;
cp_ts (&rmp->ts, ts, mp->is_initiator);
- vl_api_ikev2_ts_t_endian (&rmp->ts);
+ vl_api_ikev2_ts_t_endian (&rmp->ts, 1 /* to network */);
});
- /* *INDENT-ON* */
}
}
@@ -451,13 +730,11 @@ vl_api_ikev2_nonce_get_t_handler (vl_api_ikev2_nonce_get_t * mp)
int data_len = vec_len (nonce);
int rv = 0;
- /* *INDENT-OFF* */
REPLY_MACRO3_ZERO (VL_API_IKEV2_NONCE_GET_REPLY, data_len,
{
rmp->data_len = clib_host_to_net_u32 (data_len);
clib_memcpy (rmp->nonce, nonce, data_len);
});
- /* *INDENT-ON* */
}
static void
@@ -490,8 +767,6 @@ static void
{
vl_api_ikev2_profile_set_liveness_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
clib_error_t *error;
error = ikev2_set_liveness_params (clib_net_to_host_u32 (mp->period),
clib_net_to_host_u32 (mp->max_retries));
@@ -501,10 +776,6 @@ static void
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_LIVENESS_REPLY);
}
@@ -513,8 +784,6 @@ vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
{
vl_api_ikev2_profile_add_del_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
u8 *tmp = format (0, "%s", mp->name);
@@ -526,10 +795,6 @@ vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_ADD_DEL_REPLY);
}
@@ -539,8 +804,6 @@ static void
{
vl_api_ikev2_profile_set_auth_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
int data_len = ntohl (mp->data_len);
@@ -562,10 +825,6 @@ static void
}
else
rv = VNET_API_ERROR_INVALID_VALUE;
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_AUTH_REPLY);
}
@@ -574,8 +833,6 @@ vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
{
vl_api_ikev2_profile_set_id_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
u8 *tmp = format (0, "%s", mp->name);
@@ -596,9 +853,6 @@ vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp)
}
else
rv = VNET_API_ERROR_INVALID_VALUE;
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_ID_REPLY);
}
@@ -609,8 +863,6 @@ static void
{
vl_api_ikev2_profile_set_udp_encap_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
u8 *tmp = format (0, "%s", mp->name);
@@ -622,10 +874,6 @@ static void
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_UDP_ENCAP_REPLY);
}
@@ -634,8 +882,6 @@ vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
{
vl_api_ikev2_profile_set_ts_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
u8 *tmp = format (0, "%s", mp->name);
@@ -654,10 +900,6 @@ vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_TS_REPLY);
}
@@ -666,8 +908,6 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
{
vl_api_ikev2_set_local_key_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -678,10 +918,6 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
}
@@ -691,8 +927,6 @@ vl_api_ikev2_set_responder_hostname_t_handler (
{
vl_api_ikev2_set_responder_hostname_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -710,10 +944,6 @@ vl_api_ikev2_set_responder_hostname_t_handler (
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_RESPONDER_HOSTNAME_REPLY);
}
@@ -722,8 +952,6 @@ vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
{
vl_api_ikev2_set_responder_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -740,10 +968,6 @@ vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_RESPONDER_REPLY);
}
@@ -753,8 +977,6 @@ vl_api_ikev2_set_ike_transforms_t_handler (vl_api_ikev2_set_ike_transforms_t *
{
vl_api_ikev2_set_ike_transforms_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -772,10 +994,6 @@ vl_api_ikev2_set_ike_transforms_t_handler (vl_api_ikev2_set_ike_transforms_t *
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_IKE_TRANSFORMS_REPLY);
}
@@ -785,8 +1003,6 @@ vl_api_ikev2_set_esp_transforms_t_handler (vl_api_ikev2_set_esp_transforms_t *
{
vl_api_ikev2_set_esp_transforms_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -803,10 +1019,6 @@ vl_api_ikev2_set_esp_transforms_t_handler (vl_api_ikev2_set_esp_transforms_t *
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_ESP_TRANSFORMS_REPLY);
}
@@ -815,8 +1027,6 @@ vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp)
{
vl_api_ikev2_set_sa_lifetime_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -836,10 +1046,6 @@ vl_api_ikev2_set_sa_lifetime_t_handler (vl_api_ikev2_set_sa_lifetime_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_SET_SA_LIFETIME_REPLY);
}
@@ -849,8 +1055,6 @@ static void
{
vl_api_ikev2_profile_set_ipsec_udp_port_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
u8 *tmp = format (0, "%s", mp->name);
@@ -860,10 +1064,6 @@ static void
clib_net_to_host_u16 (mp->port),
mp->is_set);
vec_free (tmp);
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_SET_IPSEC_UDP_PORT_REPLY);
}
@@ -876,7 +1076,6 @@ static void
VALIDATE_SW_IF_INDEX (mp);
-#if WITH_LIBSSL > 0
u8 *tmp = format (0, "%s", mp->name);
clib_error_t *error;
@@ -890,10 +1089,6 @@ static void
rv = VNET_API_ERROR_UNSPECIFIED;
}
vec_free (tmp);
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_IKEV2_SET_TUNNEL_INTERFACE_REPLY);
}
@@ -903,8 +1098,6 @@ vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp)
{
vl_api_ikev2_initiate_sa_init_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -918,10 +1111,6 @@ vl_api_ikev2_initiate_sa_init_t_handler (vl_api_ikev2_initiate_sa_init_t * mp)
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_INITIATE_SA_INIT_REPLY);
}
@@ -931,8 +1120,6 @@ vl_api_ikev2_initiate_del_ike_sa_t_handler (vl_api_ikev2_initiate_del_ike_sa_t
{
vl_api_ikev2_initiate_del_ike_sa_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -943,10 +1130,6 @@ vl_api_ikev2_initiate_del_ike_sa_t_handler (vl_api_ikev2_initiate_del_ike_sa_t
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_IKE_SA_REPLY);
}
@@ -956,8 +1139,6 @@ static void
{
vl_api_ikev2_initiate_del_child_sa_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -968,10 +1149,6 @@ static void
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_INITIATE_DEL_CHILD_SA_REPLY);
}
@@ -981,8 +1158,6 @@ static void
{
vl_api_ikev2_profile_disable_natt_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
clib_error_t *error;
u8 *tmp = format (0, "%s", mp->name);
@@ -994,10 +1169,6 @@ static void
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_PROFILE_DISABLE_NATT_REPLY);
}
@@ -1007,8 +1178,6 @@ static void
{
vl_api_ikev2_initiate_rekey_child_sa_reply_t *rmp;
int rv = 0;
-
-#if WITH_LIBSSL > 0
vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
@@ -1019,10 +1188,6 @@ static void
clib_error_free (error);
rv = VNET_API_ERROR_UNSPECIFIED;
}
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
REPLY_MACRO (VL_API_IKEV2_INITIATE_REKEY_CHILD_SA_REPLY);
}
diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c
index 3523ce079b6..975774c48d5 100644
--- a/src/plugins/ikev2/ikev2_cli.c
+++ b/src/plugins/ikev2/ikev2_cli.c
@@ -74,12 +74,16 @@ format_ikev2_child_sa (u8 * s, va_list * va)
ikev2_ts_t *ts;
ikev2_sa_transform_t *tr;
u8 *c = 0;
+ vlib_main_t *vm = vlib_get_main ();
u32 indent = format_get_indent (s);
indent += 1;
s = format (s, "child sa %u:", index);
+ s = format (s, "\n uptime: %f (s)\n ",
+ vlib_time_now (vm) - child->timestamp);
+
tr = ikev2_sa_get_td_for_type (child->r_proposals,
IKEV2_TRANSFORM_TYPE_ENCR);
c = format (c, "%U ", format_ikev2_sa_transform, tr);
@@ -121,6 +125,12 @@ format_ikev2_child_sa (u8 * s, va_list * va)
return s;
}
+static char *stateNames[] = {
+#define _(v, f, s) s,
+ foreach_ikev2_state
+#undef _
+};
+
static u8 *
format_ikev2_sa (u8 * s, va_list * va)
{
@@ -129,6 +139,12 @@ format_ikev2_sa (u8 * s, va_list * va)
ikev2_sa_transform_t *tr;
ikev2_child_sa_t *child;
u32 indent = 1;
+ vlib_main_t *vm = vlib_get_main ();
+
+ ikev2_main_t *km = &ikev2_main;
+ ikev2_profile_t *p;
+
+ p = pool_elt_at_index (km->profiles, sa->profile_index);
s = format (s, "iip %U ispi %lx rip %U rspi %lx",
format_ip_address, &sa->iaddr, sa->ispi,
@@ -150,6 +166,16 @@ format_ikev2_sa (u8 * s, va_list * va)
tr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
s = format (s, "%U", format_ikev2_sa_transform, tr);
+ s = format (s, "\n profile: %v", p->name);
+
+ if (sa->state <= IKEV2_STATE_NO_PROPOSAL_CHOSEN)
+ {
+ s = format (s, "\n state: %s", stateNames[sa->state]);
+ }
+
+ s =
+ format (s, "\n uptime: %f (s)\n", vlib_time_now (vm) - sa->auth_timestamp);
+
s = format (s, "\n%U", format_white_space, indent);
s = format (s, "nonce i:%U\n%Ur:%U\n",
@@ -232,7 +258,6 @@ show_ikev2_sa_command_fn (vlib_main_t * vm,
vec_foreach (tkm, km->per_thread_data)
{
- /* *INDENT-OFF* */
pool_foreach (sa, tkm->sas) {
if (show_one)
{
@@ -245,7 +270,6 @@ show_ikev2_sa_command_fn (vlib_main_t * vm,
else
s = format (s, "%U\n", format_ikev2_sa, sa, details);
}
- /* *INDENT-ON* */
}
vlib_cli_output (vm, "%v", s);
@@ -253,13 +277,11 @@ show_ikev2_sa_command_fn (vlib_main_t * vm,
return 0;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_ikev2_sa_command, static) = {
.path = "show ikev2 sa",
.short_help = "show ikev2 sa [rspi <rspi>] [details]",
.function = show_ikev2_sa_command_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
ikev2_disable_dpd_command_fn (vlib_main_t * vm,
@@ -270,13 +292,11 @@ ikev2_disable_dpd_command_fn (vlib_main_t * vm,
return 0;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ikev2_cli_disable_dpd_command, static) = {
.path = "ikev2 dpd disable",
.short_help = "ikev2 dpd disable",
.function = ikev2_disable_dpd_command_fn,
};
-/* *INDENT-ON* */
static uword
unformat_ikev2_token (unformat_input_t * input, va_list * va)
@@ -553,7 +573,6 @@ done:
return r;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = {
.path = "ikev2 profile",
.short_help =
@@ -574,7 +593,6 @@ VLIB_CLI_COMMAND (ikev2_profile_add_del_command, static) = {
"ikev2 profile set <id> disable natt\n",
.function = ikev2_profile_add_del_command_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
show_ikev2_profile_command_fn (vlib_main_t * vm,
@@ -584,7 +602,6 @@ show_ikev2_profile_command_fn (vlib_main_t * vm,
ikev2_main_t *km = &ikev2_main;
ikev2_profile_t *p;
- /* *INDENT-OFF* */
pool_foreach (p, km->profiles) {
vlib_cli_output(vm, "profile %v", p->name);
@@ -651,18 +668,15 @@ show_ikev2_profile_command_fn (vlib_main_t * vm,
vlib_cli_output(vm, " lifetime %d jitter %d handover %d maxdata %d",
p->lifetime, p->lifetime_jitter, p->handover, p->lifetime_maxdata);
}
- /* *INDENT-ON* */
return 0;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_ikev2_profile_command, static) = {
.path = "show ikev2 profile",
.short_help = "show ikev2 profile",
.function = show_ikev2_profile_command_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
set_ikev2_liveness_period_fn (vlib_main_t * vm,
@@ -695,13 +709,11 @@ done:
return r;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_ikev2_liveness_command, static) = {
.path = "ikev2 set liveness",
.short_help = "ikev2 set liveness <period> <max-retires>",
.function = set_ikev2_liveness_period_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
set_ikev2_local_key_command_fn (vlib_main_t * vm,
@@ -735,14 +747,12 @@ done:
return r;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_ikev2_local_key_command, static) = {
.path = "set ikev2 local key",
.short_help =
"set ikev2 local key <file>",
.function = set_ikev2_local_key_command_fn,
};
-/* *INDENT-ON* */
static clib_error_t *
@@ -793,7 +803,6 @@ done:
return r;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
.path = "ikev2 initiate",
.short_help =
@@ -803,12 +812,6 @@ VLIB_CLI_COMMAND (ikev2_initiate_command, static) = {
"ikev2 initiate rekey-child-sa <child sa ispi>\n",
.function = ikev2_initiate_command_fn,
};
-/* *INDENT-ON* */
-
-void
-ikev2_cli_reference (void)
-{
-}
static clib_error_t *
ikev2_set_log_level_command_fn (vlib_main_t * vm,
@@ -838,13 +841,11 @@ done:
return error;
}
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (ikev2_set_log_level_command, static) = {
.path = "ikev2 set logging level",
.function = ikev2_set_log_level_command_fn,
.short_help = "ikev2 set logging level <0-5>",
};
-/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/ikev2/ikev2_crypto.c b/src/plugins/ikev2/ikev2_crypto.c
index a9ab1bc8067..3d4ad0a28ed 100644
--- a/src/plugins/ikev2/ikev2_crypto.c
+++ b/src/plugins/ikev2/ikev2_crypto.c
@@ -488,7 +488,7 @@ BN_bn2binpad (const BIGNUM * a, unsigned char *to, int tolen)
{
vec_insert (to, pad, 0);
clib_memset (to, 0, pad);
- _vec_len (to) -= pad;
+ vec_dec_len (to, pad);
}
return tolen;
}
@@ -553,7 +553,7 @@ ikev2_generate_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
{
vec_insert (sa->dh_shared_key, pad, 0);
clib_memset (sa->dh_shared_key, 0, pad);
- _vec_len (sa->dh_shared_key) -= pad;
+ vec_dec_len (sa->dh_shared_key, pad);
}
BN_clear_free (ex);
}
@@ -679,7 +679,7 @@ ikev2_complete_dh (ikev2_sa_t * sa, ikev2_sa_transform_t * t)
{
vec_insert (sa->dh_shared_key, pad, 0);
clib_memset (sa->dh_shared_key, 0, pad);
- _vec_len (sa->dh_shared_key) -= pad;
+ vec_dec_len (sa->dh_shared_key, pad);
}
BN_clear_free (ex);
DH_free (dh);
diff --git a/src/plugins/ikev2/ikev2_payload.c b/src/plugins/ikev2/ikev2_payload.c
index 294864d8c43..5801a1b3e87 100644
--- a/src/plugins/ikev2/ikev2_payload.c
+++ b/src/plugins/ikev2/ikev2_payload.c
@@ -24,7 +24,6 @@
#include <plugins/ikev2/ikev2.h>
#include <plugins/ikev2/ikev2_priv.h>
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -34,9 +33,7 @@ typedef CLIB_PACKED (struct {
u16 msg_type;
u8 payload[0];
}) ike_notify_payload_header_t;
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
ip4_address_t start_addr;
ip4_address_t end_addr;
@@ -55,9 +52,7 @@ typedef CLIB_PACKED (struct {
u16 end_port;
u8 addr_pair[0];
}) ikev2_ts_payload_entry_t;
-/* *INDENT-OFF* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -66,9 +61,7 @@ typedef CLIB_PACKED (struct {
u8 reserved[3];
ikev2_ts_payload_entry_t ts[0];
}) ike_ts_payload_header_t;
-/* *INDENT-OFF* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 last_or_more;
u8 reserved;
@@ -78,9 +71,7 @@ typedef CLIB_PACKED (struct {
u8 spi_size;
u8 num_transforms; u32 spi[0];
}) ike_sa_proposal_data_t;
-/* *INDENT-OFF* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 last_or_more;
u8 reserved;
@@ -90,9 +81,7 @@ typedef CLIB_PACKED (struct {
u16 transform_id;
u8 attributes[0];
}) ike_sa_transform_data_t;
-/* *INDENT-OFF* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
u8 nextpayload;
u8 flags;
@@ -102,7 +91,6 @@ typedef CLIB_PACKED (struct {
u16 num_of_spi;
u32 spi[0];
}) ike_delete_payload_header_t;
-/* *INDENT-OFF* */
static ike_payload_header_t *
ikev2_payload_add_hdr (ikev2_payload_chain_t * c, u8 payload_type, int len)
@@ -167,8 +155,8 @@ ikev2_payload_add_notify_2 (ikev2_payload_chain_t * c, u16 msg_type,
}
void
-ikev2_payload_add_sa (ikev2_payload_chain_t * c,
- ikev2_sa_proposal_t * proposals)
+ikev2_payload_add_sa (ikev2_payload_chain_t *c, ikev2_sa_proposal_t *proposals,
+ u8 force_spi)
{
ike_payload_header_t *ph;
ike_sa_proposal_data_t *prop;
@@ -184,7 +172,13 @@ ikev2_payload_add_sa (ikev2_payload_chain_t * c,
vec_foreach (p, proposals)
{
- int spi_size = (p->protocol_id == IKEV2_PROTOCOL_ESP) ? 4 : 0;
+ int spi_size = 0;
+
+ if (p->protocol_id == IKEV2_PROTOCOL_ESP)
+ spi_size = 4;
+ else if (force_spi && p->protocol_id == IKEV2_PROTOCOL_IKE)
+ spi_size = 8;
+
pr_data = vec_new (u8, sizeof (ike_sa_proposal_data_t) + spi_size);
prop = (ike_sa_proposal_data_t *) pr_data;
prop->last_or_more = proposals - p + 1 < vec_len (proposals) ? 2 : 0;
@@ -193,8 +187,13 @@ ikev2_payload_add_sa (ikev2_payload_chain_t * c,
prop->spi_size = spi_size;
prop->num_transforms = vec_len (p->transforms);
- if (spi_size)
+ if (spi_size == 4)
prop->spi[0] = clib_host_to_net_u32 (p->spi);
+ else if (spi_size == 8)
+ {
+ u64 s = clib_host_to_net_u64 (p->spi);
+ clib_memcpy_fast (prop->spi, &s, sizeof (s));
+ }
vec_foreach (t, p->transforms)
{
@@ -384,8 +383,9 @@ ikev2_parse_sa_payload (ike_payload_header_t * ikep, u32 rlen)
sap = (ike_sa_proposal_data_t *) & ikep->payload[proposal_ptr];
int i, transform_ptr;
- /* IKE proposal should not have SPI */
- if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
+ /* IKE proposal should have 8 bytes or no SPI */
+ if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0 &&
+ sap->spi_size != 8)
goto data_corrupted;
/* IKE proposal should not have SPI */
@@ -404,6 +404,12 @@ ikev2_parse_sa_payload (ike_payload_header_t * ikep, u32 rlen)
{
proposal->spi = clib_net_to_host_u32 (sap->spi[0]);
}
+ else if (sap->spi_size == 8)
+ {
+ u64 s;
+ clib_memcpy_fast (&s, &sap->spi[0], sizeof (s));
+ proposal->spi = clib_net_to_host_u64 (s);
+ }
for (i = 0; i < sap->num_transforms; i++)
{
diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h
index 4c56b980f1c..0639809e9b1 100644
--- a/src/plugins/ikev2/ikev2_priv.h
+++ b/src/plugins/ikev2/ikev2_priv.h
@@ -184,16 +184,21 @@ do { \
#define ikev2_log_debug(...) \
vlib_log(VLIB_LOG_LEVEL_DEBUG, ikev2_main.log_class, __VA_ARGS__)
+#define foreach_ikev2_state \
+ _ (0, UNKNOWN, "UNKNOWN") \
+ _ (1, SA_INIT, "SA_INIT") \
+ _ (2, DELETED, "DELETED") \
+ _ (3, AUTH_FAILED, "AUTH_FAILED") \
+ _ (4, AUTHENTICATED, "AUTHENTICATED") \
+ _ (5, NOTIFY_AND_DELETE, "NOTIFY_AND_DELETE") \
+ _ (6, TS_UNACCEPTABLE, "TS_UNACCEPTABLE") \
+ _ (7, NO_PROPOSAL_CHOSEN, "NO_PROPOSAL_CHOSEN")
+
typedef enum
{
- IKEV2_STATE_UNKNOWN,
- IKEV2_STATE_SA_INIT,
- IKEV2_STATE_DELETED,
- IKEV2_STATE_AUTH_FAILED,
- IKEV2_STATE_AUTHENTICATED,
- IKEV2_STATE_NOTIFY_AND_DELETE,
- IKEV2_STATE_TS_UNACCEPTABLE,
- IKEV2_STATE_NO_PROPOSAL_CHOSEN,
+#define _(v, f, s) IKEV2_STATE_##f = v,
+ foreach_ikev2_state
+#undef _
} ikev2_state_t;
typedef struct
@@ -238,7 +243,7 @@ typedef struct
{
u8 proposal_num;
ikev2_protocol_id_t protocol_id:8;
- u32 spi;
+ u64 spi;
ikev2_sa_transform_t *transforms;
} ikev2_sa_proposal_t;
@@ -302,6 +307,8 @@ typedef struct
f64 time_to_expiration;
u8 is_expired;
i8 rekey_retries;
+
+ f64 timestamp;
} ikev2_child_sa_t;
typedef struct
@@ -312,6 +319,8 @@ typedef struct
typedef struct
{
+ u16 notify_type;
+ u8 kex;
u8 protocol_id;
u32 spi;
u32 ispi;
@@ -323,6 +332,22 @@ typedef struct
typedef struct
{
+ u16 notify_type;
+ u16 dh_group;
+ u64 ispi;
+ u64 rspi;
+ u8 *i_nonce;
+ u8 *r_nonce;
+ u8 *dh_shared_key;
+ u8 *dh_private_key;
+ u8 *i_dh_data;
+ u8 *r_dh_data;
+ ikev2_sa_proposal_t *i_proposals;
+ ikev2_sa_proposal_t *r_proposals;
+} ikev2_sa_rekey_t;
+
+typedef struct
+{
u16 msg_type;
u8 protocol_id;
u32 spi;
@@ -425,6 +450,9 @@ typedef struct
ikev2_rekey_t *new_child;
+ /* pending sa rekeyings */
+ ikev2_sa_rekey_t *sa_rekey;
+
/* packet data */
u8 *last_sa_init_req_packet_data;
u8 *last_sa_init_res_packet_data;
@@ -462,6 +490,8 @@ typedef struct
u8 keys_generated;
ikev2_stats_t stats;
+
+ f64 auth_timestamp;
} ikev2_sa_t;
@@ -530,7 +560,17 @@ typedef struct
u8 dpd_disabled;
/* pointer to name resolver function in dns plugin */
- int (*dns_resolve_name) ();
+ void *dns_resolve_name_ptr;
+
+ /* flag indicating whether lazy init is done or not */
+ int lazy_init_done;
+
+ /* refcount for IKEv2 udp ports and IPsec NATT punt registration */
+ int bind_refcount;
+
+ /* punt handle for IPsec NATT IPSEC_PUNT_IP4_SPI_UDP_0 reason */
+ vlib_punt_hdl_t punt_hdl;
+
} ikev2_main_t;
extern ikev2_main_t ikev2_main;
@@ -584,8 +624,8 @@ void ikev2_payload_add_notify (ikev2_payload_chain_t * c, u16 msg_type,
u8 * data);
void ikev2_payload_add_notify_2 (ikev2_payload_chain_t * c, u16 msg_type,
u8 * data, ikev2_notify_t * notify);
-void ikev2_payload_add_sa (ikev2_payload_chain_t * c,
- ikev2_sa_proposal_t * proposals);
+void ikev2_payload_add_sa (ikev2_payload_chain_t *c,
+ ikev2_sa_proposal_t *proposals, u8 force_spi);
void ikev2_payload_add_ke (ikev2_payload_chain_t * c, u16 dh_group,
u8 * dh_data);
void ikev2_payload_add_nonce (ikev2_payload_chain_t * c, u8 * nonce);
diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c
index b63778ed103..93683a5b5dc 100644
--- a/src/plugins/ikev2/ikev2_test.c
+++ b/src/plugins/ikev2/ikev2_test.c
@@ -32,7 +32,7 @@
#include <vnet/format_fns.h>
#include <ikev2/ikev2.api_enum.h>
#include <ikev2/ikev2.api_types.h>
-#include <vpp/api/vpe.api_types.h>
+#include <vlibmemory/vlib.api_types.h>
#define vl_endianfun /* define message structures */
#include <plugins/ikev2/ikev2.api.h>
@@ -391,13 +391,83 @@ vl_api_ikev2_sa_details_t_handler (vl_api_ikev2_sa_details_t * mp)
ip_address_t iaddr;
ip_address_t raddr;
vl_api_ikev2_keys_t *k = &sa->keys;
- vl_api_ikev2_sa_t_endian (sa);
+ vl_api_ikev2_sa_t_endian (sa, 0 /* from network */);
ip_address_decode2 (&sa->iaddr, &iaddr);
ip_address_decode2 (&sa->raddr, &raddr);
- fformat (vam->ofp, "profile index %d sa index: %d\n",
- mp->sa.profile_index, mp->sa.sa_index);
+ fformat (vam->ofp, "profile index %u sa index: %d\n", mp->sa.profile_index,
+ mp->sa.sa_index);
+ fformat (vam->ofp, " iip %U ispi %lx rip %U rspi %lx\n", format_ip_address,
+ &iaddr, sa->ispi, format_ip_address, &raddr, sa->rspi);
+ fformat (vam->ofp, " %U ", format_ikev2_sa_transform, &sa->encryption);
+ fformat (vam->ofp, "%U ", format_ikev2_sa_transform, &sa->prf);
+ fformat (vam->ofp, "%U ", format_ikev2_sa_transform, &sa->integrity);
+ fformat (vam->ofp, "%U \n", format_ikev2_sa_transform, &sa->dh);
+
+ fformat (vam->ofp, " SK_d %U\n", format_hex_bytes, k->sk_d, k->sk_d_len);
+
+ fformat (vam->ofp, " SK_a i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ai, k->sk_ai_len, format_hex_bytes, k->sk_ar, k->sk_ar_len);
+
+ fformat (vam->ofp, " SK_e i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ei, k->sk_ei_len, format_hex_bytes, k->sk_er, k->sk_er_len);
+
+ fformat (vam->ofp, " SK_p i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_pi, k->sk_pi_len, format_hex_bytes, k->sk_pr, k->sk_pr_len);
+
+ fformat (vam->ofp, " identifier (i) %U\n", format_ikev2_id_type_and_data,
+ &sa->i_id);
+ fformat (vam->ofp, " identifier (r) %U\n", format_ikev2_id_type_and_data,
+ &sa->r_id);
+
+ vam->result_ready = 1;
+}
+
+static int
+api_ikev2_sa_v2_dump (vat_main_t *vam)
+{
+ ikev2_test_main_t *im = &ikev2_test_main;
+ vl_api_ikev2_sa_v2_dump_t *mp;
+ vl_api_control_ping_t *mp_ping;
+ int ret;
+
+ /* Construct the API message */
+ M (IKEV2_SA_V2_DUMP, mp);
+
+ /* send it... */
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ if (!im->ping_id)
+ im->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
+ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
+ mp_ping->_vl_msg_id = htons (im->ping_id);
+ mp_ping->client_index = vam->my_client_index;
+ vam->result_ready = 0;
+
+ S (mp_ping);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static void
+vl_api_ikev2_sa_v2_details_t_handler (vl_api_ikev2_sa_v2_details_t *mp)
+{
+ vat_main_t *vam = ikev2_test_main.vat_main;
+ vl_api_ikev2_sa_v2_t *sa = &mp->sa;
+ ip_address_t iaddr;
+ ip_address_t raddr;
+ vl_api_ikev2_keys_t *k = &sa->keys;
+ vl_api_ikev2_sa_v2_t_endian (sa, 0 /* from network */);
+
+ ip_address_decode2 (&sa->iaddr, &iaddr);
+ ip_address_decode2 (&sa->raddr, &raddr);
+
+ fformat (vam->ofp, "profile name %s sa index: %d\n", mp->sa.profile_name,
+ mp->sa.sa_index);
fformat (vam->ofp, " iip %U ispi %lx rip %U rspi %lx\n", format_ip_address,
&iaddr, sa->ispi, format_ip_address, &raddr, sa->rspi);
fformat (vam->ofp, " %U ", format_ikev2_sa_transform, &sa->encryption);
@@ -427,6 +497,76 @@ vl_api_ikev2_sa_details_t_handler (vl_api_ikev2_sa_details_t * mp)
}
static int
+api_ikev2_sa_v3_dump (vat_main_t *vam)
+{
+ ikev2_test_main_t *im = &ikev2_test_main;
+ vl_api_ikev2_sa_v3_dump_t *mp;
+ vl_api_control_ping_t *mp_ping;
+ int ret;
+
+ /* Construct the API message */
+ M (IKEV2_SA_V3_DUMP, mp);
+
+ /* send it... */
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ if (!im->ping_id)
+ im->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
+ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
+ mp_ping->_vl_msg_id = htons (im->ping_id);
+ mp_ping->client_index = vam->my_client_index;
+ vam->result_ready = 0;
+
+ S (mp_ping);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static void
+vl_api_ikev2_sa_v3_details_t_handler (vl_api_ikev2_sa_v3_details_t *mp)
+{
+ vat_main_t *vam = ikev2_test_main.vat_main;
+ vl_api_ikev2_sa_v3_t *sa = &mp->sa;
+ ip_address_t iaddr;
+ ip_address_t raddr;
+ vl_api_ikev2_keys_t *k = &sa->keys;
+ vl_api_ikev2_sa_v3_t_endian (sa, 0 /* from network */);
+
+ ip_address_decode2 (&sa->iaddr, &iaddr);
+ ip_address_decode2 (&sa->raddr, &raddr);
+
+ fformat (vam->ofp, "profile name %s sa index: %d\n", mp->sa.profile_name,
+ mp->sa.sa_index);
+ fformat (vam->ofp, " iip %U ispi %lx rip %U rspi %lx\n", format_ip_address,
+ &iaddr, sa->ispi, format_ip_address, &raddr, sa->rspi);
+ fformat (vam->ofp, " %U ", format_ikev2_sa_transform, &sa->encryption);
+ fformat (vam->ofp, "%U ", format_ikev2_sa_transform, &sa->prf);
+ fformat (vam->ofp, "%U ", format_ikev2_sa_transform, &sa->integrity);
+ fformat (vam->ofp, "%U \n", format_ikev2_sa_transform, &sa->dh);
+
+ fformat (vam->ofp, " SK_d %U\n", format_hex_bytes, k->sk_d, k->sk_d_len);
+
+ fformat (vam->ofp, " SK_a i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ai, k->sk_ai_len, format_hex_bytes, k->sk_ar, k->sk_ar_len);
+
+ fformat (vam->ofp, " SK_e i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ei, k->sk_ei_len, format_hex_bytes, k->sk_er, k->sk_er_len);
+
+ fformat (vam->ofp, " SK_p i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_pi, k->sk_pi_len, format_hex_bytes, k->sk_pr, k->sk_pr_len);
+
+ fformat (vam->ofp, " identifier (i) %U\n", format_ikev2_id_type_and_data,
+ &sa->i_id);
+ fformat (vam->ofp, " identifier (r) %U\n", format_ikev2_id_type_and_data,
+ &sa->r_id);
+
+ vam->result_ready = 1;
+}
+
+static int
api_ikev2_child_sa_dump (vat_main_t * vam)
{
unformat_input_t *i = vam->input;
@@ -479,7 +619,84 @@ vl_api_ikev2_child_sa_details_t_handler (vl_api_ikev2_child_sa_details_t * mp)
vat_main_t *vam = ikev2_test_main.vat_main;
vl_api_ikev2_child_sa_t *child_sa = &mp->child_sa;
vl_api_ikev2_keys_t *k = &child_sa->keys;
- vl_api_ikev2_child_sa_t_endian (child_sa);
+ vl_api_ikev2_child_sa_t_endian (child_sa, 0 /* from network */);
+
+ fformat (vam->ofp, " child sa %u:\n", child_sa->child_sa_index);
+
+ fformat (vam->ofp, " %U ", format_ikev2_sa_transform,
+ &child_sa->encryption);
+ fformat (vam->ofp, "%U ", format_ikev2_sa_transform, &child_sa->integrity);
+ fformat (vam->ofp, "%U \n", format_ikev2_sa_transform, &child_sa->esn);
+
+ fformat (vam->ofp, " spi(i) %lx spi(r) %lx\n", child_sa->i_spi,
+ child_sa->r_spi);
+
+ fformat (vam->ofp, " SK_e i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ei, k->sk_ei_len, format_hex_bytes, k->sk_er, k->sk_er_len);
+ if (k->sk_ai_len)
+ {
+ fformat (vam->ofp, " SK_a i:%U\n r:%U\n", format_hex_bytes,
+ k->sk_ai, k->sk_ai_len, format_hex_bytes, k->sk_ar,
+ k->sk_ar_len);
+ }
+ vam->result_ready = 1;
+}
+
+static int
+api_ikev2_child_sa_v2_dump (vat_main_t *vam)
+{
+ unformat_input_t *i = vam->input;
+ ikev2_test_main_t *im = &ikev2_test_main;
+ vl_api_ikev2_child_sa_dump_t *mp;
+ vl_api_control_ping_t *mp_ping;
+ int ret;
+ u32 sa_index = ~0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "sa_index %d", &sa_index))
+ ;
+ else
+ {
+ errmsg ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (sa_index == ~0)
+ return -99;
+
+ /* Construct the API message */
+ M (IKEV2_CHILD_SA_DUMP, mp);
+
+ mp->sa_index = clib_net_to_host_u32 (sa_index);
+
+ /* send it... */
+ S (mp);
+
+ /* Use a control ping for synchronization */
+ if (!im->ping_id)
+ im->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC));
+ mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping));
+ mp_ping->_vl_msg_id = htons (im->ping_id);
+ mp_ping->client_index = vam->my_client_index;
+ vam->result_ready = 0;
+
+ S (mp_ping);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
+static void
+vl_api_ikev2_child_sa_v2_details_t_handler (
+ vl_api_ikev2_child_sa_details_t *mp)
+{
+ vat_main_t *vam = ikev2_test_main.vat_main;
+ vl_api_ikev2_child_sa_t *child_sa = &mp->child_sa;
+ vl_api_ikev2_keys_t *k = &child_sa->keys;
+ vl_api_ikev2_child_sa_t_endian (child_sa, 0 /* from network */);
fformat (vam->ofp, " child sa %u:\n", child_sa->child_sa_index);
@@ -567,7 +784,7 @@ static void
vat_main_t *vam = ikev2_test_main.vat_main;
vl_api_ikev2_ts_t *ts = &mp->ts;
ip_address_t start_addr, end_addr;
- vl_api_ikev2_ts_t_endian (ts);
+ vl_api_ikev2_ts_t_endian (ts, 0 /* from network */);
ip_address_decode2 (&ts->start_addr, &start_addr);
ip_address_decode2 (&ts->end_addr, &end_addr);
diff --git a/src/plugins/ikev2/ikev2_types.api b/src/plugins/ikev2/ikev2_types.api
index b279026c2b9..2492611703d 100644
--- a/src/plugins/ikev2/ikev2_types.api
+++ b/src/plugins/ikev2/ikev2_types.api
@@ -128,6 +128,19 @@ typedef ikev2_child_sa
vl_api_ikev2_sa_transform_t esn;
};
+typedef ikev2_child_sa_v2
+{
+ u32 sa_index;
+ u32 child_sa_index;
+ u32 i_spi;
+ u32 r_spi;
+ vl_api_ikev2_keys_t keys;
+ vl_api_ikev2_sa_transform_t encryption;
+ vl_api_ikev2_sa_transform_t integrity;
+ vl_api_ikev2_sa_transform_t esn;
+ f64 uptime;
+};
+
typedef ikev2_sa_stats
{
u16 n_keepalives;
@@ -138,6 +151,18 @@ typedef ikev2_sa_stats
u16 n_init_sa_retransmit;
};
+enum ikev2_state
+{
+ UNKNOWN,
+ SA_INIT,
+ DELETED,
+ AUTH_FAILED,
+ AUTHENTICATED,
+ NOTIFY_AND_DELETE,
+ TS_UNACCEPTABLE,
+ NO_PROPOSAL_CHOSEN,
+};
+
typedef ikev2_sa
{
u32 sa_index;
@@ -161,3 +186,54 @@ typedef ikev2_sa
vl_api_ikev2_sa_stats_t stats;
};
+
+typedef ikev2_sa_v2
+{
+ u32 sa_index;
+ string profile_name[64];
+ vl_api_ikev2_state_t state;
+
+ u64 ispi;
+ u64 rspi;
+ vl_api_address_t iaddr;
+ vl_api_address_t raddr;
+
+ vl_api_ikev2_keys_t keys;
+
+ /* ID */
+ vl_api_ikev2_id_t i_id;
+ vl_api_ikev2_id_t r_id;
+
+ vl_api_ikev2_sa_transform_t encryption;
+ vl_api_ikev2_sa_transform_t integrity;
+ vl_api_ikev2_sa_transform_t prf;
+ vl_api_ikev2_sa_transform_t dh;
+
+ vl_api_ikev2_sa_stats_t stats;
+};
+
+typedef ikev2_sa_v3
+{
+ u32 sa_index;
+ string profile_name[64];
+ vl_api_ikev2_state_t state;
+
+ u64 ispi;
+ u64 rspi;
+ vl_api_address_t iaddr;
+ vl_api_address_t raddr;
+
+ vl_api_ikev2_keys_t keys;
+
+ /* ID */
+ vl_api_ikev2_id_t i_id;
+ vl_api_ikev2_id_t r_id;
+
+ vl_api_ikev2_sa_transform_t encryption;
+ vl_api_ikev2_sa_transform_t integrity;
+ vl_api_ikev2_sa_transform_t prf;
+ vl_api_ikev2_sa_transform_t dh;
+
+ vl_api_ikev2_sa_stats_t stats;
+ f64 uptime;
+}; \ No newline at end of file