X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fikev2%2Fikev2.c;h=ee0b11ea4b072f9923ac742425fa6b4920a16e42;hb=8ebcb7a99d7b73a1ee5874780b4efdc69d32c82f;hp=2340137bb9cc17df7daa44db74a45794b9d212a5;hpb=1d1985de91833a5483a6b7ee96ef4090d530a7a6;p=vpp.git diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index 2340137bb9c..ee0b11ea4b0 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -34,7 +37,7 @@ static int ikev2_delete_tunnel_interface (vnet_main_t * vnm, #define ikev2_set_state(sa, v) do { \ (sa)->state = v; \ - clib_warning("sa state changed to " #v); \ + ikev2_elog_sa_state("ispi %lx SA state changed to " #v, sa->ispi); \ } while(0); typedef struct @@ -168,9 +171,6 @@ ikev2_select_proposal (ikev2_sa_proposal_t * proposals, } } - clib_warning ("bitmap is %x mandatory is %x optional is %x", - bitmap, mandatory_bitmap, optional_bitmap); - if ((bitmap & mandatory_bitmap) == mandatory_bitmap && (bitmap & ~optional_bitmap) == 0) { @@ -243,19 +243,24 @@ ikev2_sa_free_proposal_vector (ikev2_sa_proposal_t ** v) vec_free (*v); }; +static void +ikev2_sa_free_child_sa (ikev2_child_sa_t * c) +{ + ikev2_sa_free_proposal_vector (&c->r_proposals); + ikev2_sa_free_proposal_vector (&c->i_proposals); + vec_free (c->sk_ai); + vec_free (c->sk_ar); + vec_free (c->sk_ei); + vec_free (c->sk_er); + vec_free (c->tsi); + vec_free (c->tsr); +} + static void ikev2_sa_free_all_child_sa (ikev2_child_sa_t ** childs) { ikev2_child_sa_t *c; - vec_foreach (c, *childs) - { - ikev2_sa_free_proposal_vector (&c->r_proposals); - ikev2_sa_free_proposal_vector (&c->i_proposals); - vec_free (c->sk_ai); - vec_free (c->sk_ar); - vec_free (c->sk_ei); - vec_free (c->sk_er); - } + vec_foreach (c, *childs) ikev2_sa_free_child_sa (c); vec_free (*childs); } @@ -263,13 +268,7 @@ ikev2_sa_free_all_child_sa (ikev2_child_sa_t ** childs) static void ikev2_sa_del_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * child) { - ikev2_sa_free_proposal_vector (&child->r_proposals); - ikev2_sa_free_proposal_vector (&child->i_proposals); - vec_free (child->sk_ai); - vec_free (child->sk_ar); - vec_free (child->sk_ei); - vec_free (child->sk_er); - + ikev2_sa_free_child_sa (child); vec_del1 (sa->childs, child - sa->childs); } @@ -344,8 +343,6 @@ ikev2_generate_sa_init_data (ikev2_sa_t * sa) if (!t) { - clib_warning ("unknown dh data group %u (data len %u)", sa->dh_group, - vec_len (sa->i_dh_data)); sa->dh_group = IKEV2_TRANSFORM_DH_TYPE_NONE; return; } @@ -389,8 +386,9 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai) sa->iaddr.as_u32 = sai->iaddr.as_u32; sa->raddr.as_u32 = sai->raddr.as_u32; sa->is_initiator = sai->is_initiator; - sa->profile = sai->profile; sa->i_id.type = sai->i_id.type; + sa->profile_index = sai->profile_index; + sa->is_profile_index_set = sai->is_profile_index_set; sa->i_id.data = _(sai->i_id.data); sa->i_auth.method = sai->i_auth.method; sa->i_auth.hex = sai->i_auth.hex; @@ -418,8 +416,6 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai) if (!t) { - clib_warning ("unknown dh data group %u (data len %u)", sa->dh_group, - vec_len (sa->i_dh_data)); sa->dh_group = IKEV2_TRANSFORM_DH_TYPE_NONE; return; } @@ -437,6 +433,7 @@ ikev2_calc_keys (ikev2_sa_t * sa) /* calculate SKEYSEED = prf(Ni | Nr, g^ir) */ u8 *skeyseed = 0; u8 *s = 0; + u16 integ_key_len = 0; ikev2_sa_transform_t *tr_encr, *tr_prf, *tr_integ; tr_encr = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_ENCR); @@ -445,6 +442,9 @@ ikev2_calc_keys (ikev2_sa_t * sa) tr_integ = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG); + if (tr_integ) + integ_key_len = tr_integ->key_len; + vec_append (s, sa->i_nonce); vec_append (s, sa->r_nonce); skeyseed = ikev2_calc_prf (tr_prf, s, sa->dh_shared_key); @@ -459,7 +459,7 @@ ikev2_calc_keys (ikev2_sa_t * sa) /* calculate PRFplus */ u8 *keymat; int len = tr_prf->key_trunc + /* SK_d */ - tr_integ->key_len * 2 + /* SK_ai, SK_ar */ + integ_key_len * 2 + /* SK_ai, SK_ar */ tr_encr->key_len * 2 + /* SK_ei, SK_er */ tr_prf->key_len * 2; /* SK_pi, SK_pr */ @@ -474,15 +474,18 @@ ikev2_calc_keys (ikev2_sa_t * sa) clib_memcpy_fast (sa->sk_d, keymat + pos, tr_prf->key_trunc); pos += tr_prf->key_trunc; - /* SK_ai */ - sa->sk_ai = vec_new (u8, tr_integ->key_len); - clib_memcpy_fast (sa->sk_ai, keymat + pos, tr_integ->key_len); - pos += tr_integ->key_len; + if (integ_key_len) + { + /* SK_ai */ + sa->sk_ai = vec_new (u8, integ_key_len); + clib_memcpy_fast (sa->sk_ai, keymat + pos, integ_key_len); + pos += integ_key_len; - /* SK_ar */ - sa->sk_ar = vec_new (u8, tr_integ->key_len); - clib_memcpy_fast (sa->sk_ar, keymat + pos, tr_integ->key_len); - pos += tr_integ->key_len; + /* SK_ar */ + sa->sk_ar = vec_new (u8, integ_key_len); + clib_memcpy_fast (sa->sk_ar, keymat + pos, integ_key_len); + pos += integ_key_len; + } /* SK_ei */ sa->sk_ei = vec_new (u8, tr_encr->key_len); @@ -511,6 +514,9 @@ static void ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child) { u8 *s = 0; + u16 integ_key_len = 0; + u8 salt_len = 0; + ikev2_sa_transform_t *tr_prf, *ctr_encr, *ctr_integ; tr_prf = ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF); @@ -519,11 +525,16 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child) ctr_integ = ikev2_sa_get_td_for_type (child->r_proposals, IKEV2_TRANSFORM_TYPE_INTEG); + if (ctr_integ) + integ_key_len = ctr_integ->key_len; + else + salt_len = sizeof (u32); + vec_append (s, sa->i_nonce); vec_append (s, sa->r_nonce); /* calculate PRFplus */ u8 *keymat; - int len = ctr_encr->key_len * 2 + ctr_integ->key_len * 2; + int len = ctr_encr->key_len * 2 + integ_key_len * 2 + salt_len * 2; keymat = ikev2_calc_prfplus (tr_prf, sa->sk_d, s, len); @@ -534,20 +545,36 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child) clib_memcpy_fast (child->sk_ei, keymat + pos, ctr_encr->key_len); pos += ctr_encr->key_len; - /* SK_ai */ - child->sk_ai = vec_new (u8, ctr_integ->key_len); - clib_memcpy_fast (child->sk_ai, keymat + pos, ctr_integ->key_len); - pos += ctr_integ->key_len; + if (ctr_integ) + { + /* SK_ai */ + child->sk_ai = vec_new (u8, ctr_integ->key_len); + clib_memcpy_fast (child->sk_ai, keymat + pos, ctr_integ->key_len); + pos += ctr_integ->key_len; + } + else + { + clib_memcpy (&child->salt_ei, keymat + pos, salt_len); + pos += salt_len; + } /* SK_er */ child->sk_er = vec_new (u8, ctr_encr->key_len); clib_memcpy_fast (child->sk_er, keymat + pos, ctr_encr->key_len); pos += ctr_encr->key_len; - /* SK_ar */ - child->sk_ar = vec_new (u8, ctr_integ->key_len); - clib_memcpy_fast (child->sk_ar, keymat + pos, ctr_integ->key_len); - pos += ctr_integ->key_len; + if (ctr_integ) + { + /* SK_ar */ + child->sk_ar = vec_new (u8, integ_key_len); + clib_memcpy_fast (child->sk_ar, keymat + pos, integ_key_len); + pos += integ_key_len; + } + else + { + clib_memcpy (&child->salt_er, keymat + pos, salt_len); + pos += salt_len; + } ASSERT (pos == len); @@ -562,13 +589,10 @@ ikev2_process_sa_init_req (vlib_main_t * vm, ikev2_sa_t * sa, u32 len = clib_net_to_host_u32 (ike->length); u8 payload = ike->nextpayload; - clib_warning ("ispi %lx rspi %lx nextpayload %x version %x " - "exchange %x flags %x msgid %x length %u", - clib_net_to_host_u64 (ike->ispi), - clib_net_to_host_u64 (ike->rspi), - payload, ike->version, - ike->exchange, ike->flags, - clib_net_to_host_u32 (ike->msgid), len); + ikev2_elog_exchange ("ispi %lx rspi %lx IKE_INIT request received " + "from %d.%d.%d.%d", + clib_net_to_host_u64 (ike->ispi), + clib_net_to_host_u64 (ike->rspi), sa->iaddr.as_u32); sa->ispi = clib_net_to_host_u64 (ike->ispi); @@ -612,8 +636,8 @@ ikev2_process_sa_init_req (vlib_main_t * vm, ikev2_sa_t * sa, } else { - clib_warning ("unknown payload %u flags %x length %u", payload, - ikep->flags, plen); + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { ikev2_set_state (sa, IKEV2_STATE_NOTIFY_AND_DELETE); @@ -637,17 +661,13 @@ ikev2_process_sa_init_resp (vlib_main_t * vm, ikev2_sa_t * sa, u32 len = clib_net_to_host_u32 (ike->length); u8 payload = ike->nextpayload; - clib_warning ("ispi %lx rspi %lx nextpayload %x version %x " - "exchange %x flags %x msgid %x length %u", - clib_net_to_host_u64 (ike->ispi), - clib_net_to_host_u64 (ike->rspi), - payload, ike->version, - ike->exchange, ike->flags, - clib_net_to_host_u32 (ike->msgid), len); - sa->ispi = clib_net_to_host_u64 (ike->ispi); sa->rspi = clib_net_to_host_u64 (ike->rspi); + ikev2_elog_exchange ("ispi %lx rspi %lx IKE_INIT response received " + "from %d.%d.%d.%d", sa->ispi, sa->rspi, + sa->raddr.as_u32); + /* store whole IKE payload - needed for PSK auth */ vec_free (sa->last_sa_init_res_packet_data); vec_add (sa->last_sa_init_res_packet_data, ike, len); @@ -694,8 +714,8 @@ ikev2_process_sa_init_resp (vlib_main_t * vm, ikev2_sa_t * sa, } else { - clib_warning ("unknown payload %u flags %x length %u", payload, - ikep->flags, plen); + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { ikev2_set_state (sa, IKEV2_STATE_NOTIFY_AND_DELETE); @@ -733,13 +753,12 @@ ikev2_decrypt_sk_payload (ikev2_sa_t * sa, ike_header_t * ike, u8 * payload) if (*payload == IKEV2_PAYLOAD_SK) { - clib_warning ("received IKEv2 payload SK, len %u", plen - 4); last_payload = *payload; } else { - clib_warning ("unknown payload %u flags %x length %u", payload, - ikep->flags, plen); + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + *payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { sa->unsupported_cp = *payload; @@ -753,7 +772,7 @@ ikev2_decrypt_sk_payload (ikev2_sa_t * sa, ike_header_t * ike, u8 * payload) if (last_payload != IKEV2_PAYLOAD_SK) { - clib_warning ("Last payload must be SK"); + ikev2_elog_error ("Last payload must be SK"); return 0; } @@ -765,7 +784,7 @@ ikev2_decrypt_sk_payload (ikev2_sa_t * sa, ike_header_t * ike, u8 * payload) if (memcmp (hmac, &ikep->payload[plen], tr_integ->key_trunc)) { - clib_warning ("message integrity check failed"); + ikev2_elog_error ("message integrity check failed"); vec_free (hmac); return 0; } @@ -811,6 +830,9 @@ ikev2_initial_contact_cleanup (ikev2_sa_t * sa) vec_free (delete); sa->initial_contact = 0; + + km->log_level = IKEV2_LOG_ERROR; + km->log_class = vlib_log_register_class ("ikev2", 0); } static void @@ -818,20 +840,16 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) { ikev2_child_sa_t *first_child_sa; int p = 0; - u32 len = clib_net_to_host_u32 (ike->length); u8 payload = ike->nextpayload; u8 *plaintext = 0; - ike_payload_header_t *ikep; u32 plen; - clib_warning ("ispi %lx rspi %lx nextpayload %x version %x " - "exchange %x flags %x msgid %x length %u", - clib_net_to_host_u64 (ike->ispi), - clib_net_to_host_u64 (ike->rspi), - payload, ike->version, - ike->exchange, ike->flags, - clib_net_to_host_u32 (ike->msgid), len); + ikev2_elog_exchange ("ispi %lx rspi %lx EXCHANGE_IKE_AUTH received " + "from %d.%d.%d.%d", clib_host_to_net_u64 (ike->ispi), + clib_host_to_net_u64 (ike->rspi), + sa->is_initiator ? sa->raddr.as_u32 : sa-> + iaddr.as_u32); ikev2_calc_keys (sa); @@ -868,7 +886,6 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) if (payload == IKEV2_PAYLOAD_SA) /* 33 */ { - clib_warning ("received payload SA, len %u", plen - sizeof (*ikep)); if (sa->is_initiator) { ikev2_sa_free_proposal_vector (&first_child_sa->r_proposals); @@ -887,9 +904,6 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) sa->i_id.type = id->id_type; vec_free (sa->i_id.data); vec_add (sa->i_id.data, id->payload, plen - sizeof (*id)); - - clib_warning ("received payload IDi, len %u id_type %u", - plen - sizeof (*id), id->id_type); } else if (payload == IKEV2_PAYLOAD_IDR) /* 36 */ { @@ -898,9 +912,6 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) sa->r_id.type = id->id_type; vec_free (sa->r_id.data); vec_add (sa->r_id.data, id->payload, plen - sizeof (*id)); - - clib_warning ("received payload IDr len %u id_type %u", - plen - sizeof (*id), id->id_type); } else if (payload == IKEV2_PAYLOAD_AUTH) /* 39 */ { @@ -918,9 +929,6 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) vec_free (sa->i_auth.data); vec_add (sa->i_auth.data, a->payload, plen - sizeof (*a)); } - - clib_warning ("received payload AUTH, len %u auth_type %u", - plen - sizeof (*a), a->auth_method); } else if (payload == IKEV2_PAYLOAD_NOTIFY) /* 41 */ { @@ -937,25 +945,18 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) } else if (payload == IKEV2_PAYLOAD_TSI) /* 44 */ { - clib_warning ("received payload TSi, len %u", - plen - sizeof (*ikep)); - vec_free (first_child_sa->tsi); first_child_sa->tsi = ikev2_parse_ts_payload (ikep); } else if (payload == IKEV2_PAYLOAD_TSR) /* 45 */ { - clib_warning ("received payload TSr, len %u", - plen - sizeof (*ikep)); - vec_free (first_child_sa->tsr); first_child_sa->tsr = ikev2_parse_ts_payload (ikep); } else { - clib_warning ("unknown payload %u flags %x length %u data %u", - payload, ikep->flags, plen - 4, - format_hex_bytes, ikep->payload, plen - 4); + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { @@ -978,20 +979,14 @@ ikev2_process_informational_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) { int p = 0; - u32 len = clib_net_to_host_u32 (ike->length); u8 payload = ike->nextpayload; u8 *plaintext = 0; - ike_payload_header_t *ikep; u32 plen; - clib_warning ("ispi %lx rspi %lx nextpayload %x version %x " - "exchange %x flags %x msgid %x length %u", - clib_net_to_host_u64 (ike->ispi), - clib_net_to_host_u64 (ike->rspi), - payload, ike->version, - ike->exchange, ike->flags, - clib_net_to_host_u32 (ike->msgid), len); + ikev2_elog_exchange ("ispi %lx rspi %lx INFORMATIONAL received " + "from %d.%d.%d.%d", clib_host_to_net_u64 (ike->ispi), + clib_host_to_net_u64 (ike->rspi), sa->iaddr.as_u32); plaintext = ikev2_decrypt_sk_payload (sa, ike, &payload); @@ -1025,10 +1020,8 @@ ikev2_process_informational_req (vlib_main_t * vm, ikev2_sa_t * sa, } else { - clib_warning ("unknown payload %u flags %x length %u data %u", - payload, ikep->flags, plen - 4, - format_hex_bytes, ikep->payload, plen - 4); - + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { sa->unsupported_cp = payload; @@ -1049,7 +1042,6 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) { int p = 0; - u32 len = clib_net_to_host_u32 (ike->length); u8 payload = ike->nextpayload; u8 *plaintext = 0; u8 rekeying = 0; @@ -1063,13 +1055,9 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, ikev2_sa_t * sa, ikev2_sa_proposal_t *proposal = 0; ikev2_child_sa_t *child_sa; - clib_warning ("ispi %lx rspi %lx nextpayload %x version %x " - "exchange %x flags %x msgid %x length %u", - clib_net_to_host_u64 (ike->ispi), - clib_net_to_host_u64 (ike->rspi), - payload, ike->version, - ike->exchange, ike->flags, - clib_net_to_host_u32 (ike->msgid), len); + ikev2_elog_exchange ("ispi %lx rspi %lx CREATE_CHILD_SA received " + "from %d.%d.%d.%d", clib_host_to_net_u64 (ike->ispi), + clib_host_to_net_u64 (ike->rspi), sa->raddr.as_u32); plaintext = ikev2_decrypt_sk_payload (sa, ike, &payload); @@ -1120,10 +1108,8 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, ikev2_sa_t * sa, } else { - clib_warning ("unknown payload %u flags %x length %u data %u", - payload, ikep->flags, plen - 4, - format_hex_bytes, ikep->payload, plen - 4); - + ikev2_elog_uint (IKEV2_LOG_ERROR, "Unknown payload! type=%d", + payload); if (ikep->flags & IKEV2_PAYLOAD_FLAG_CRITICAL) { sa->unsupported_cp = payload; @@ -1160,7 +1146,8 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, ikev2_sa_t * sa, child_sa = ikev2_sa_get_child (sa, n->spi, n->protocol_id, 1); if (!child_sa) { - clib_warning ("child SA spi %lx not found", n->spi); + ikev2_elog_uint (IKEV2_LOG_ERROR, "child SA spi %lx not found", + n->spi); goto cleanup_and_exit; } vec_add2 (sa->rekey, rekey, 1); @@ -1274,7 +1261,7 @@ ikev2_sa_match_ts (ikev2_sa_t * sa) { if (ikev2_ts_cmp(p_tsi, ts)) { - tsi = vec_dup(ts); + vec_add1 (tsi, ts[0]); break; } } @@ -1283,7 +1270,7 @@ ikev2_sa_match_ts (ikev2_sa_t * sa) { if (ikev2_ts_cmp(p_tsr, ts)) { - tsr = vec_dup(ts); + vec_add1 (tsr, ts[0]); break; } } @@ -1322,8 +1309,9 @@ ikev2_sa_auth (ikev2_sa_t * sa) if (!(sa->i_auth.method == IKEV2_AUTH_METHOD_SHARED_KEY_MIC || sa->i_auth.method == IKEV2_AUTH_METHOD_RSA_SIG)) { - clib_warning ("unsupported authentication method %u", - sa->i_auth.method); + ikev2_elog_uint (IKEV2_LOG_ERROR, + "unsupported authentication method %u", + sa->i_auth.method); ikev2_set_state (sa, IKEV2_STATE_AUTH_FAILED); return; } @@ -1423,6 +1411,8 @@ ikev2_sa_auth (ikev2_sa_t * sa) } else { + ikev2_elog_uint (IKEV2_LOG_ERROR, "authentication failed, no matching " + "profile found! ispi %lx", sa->ispi); ikev2_set_state (sa, IKEV2_STATE_AUTH_FAILED); } vec_free (psk); @@ -1444,8 +1434,9 @@ ikev2_sa_auth_init (ikev2_sa_t * sa) if (!(sa->i_auth.method == IKEV2_AUTH_METHOD_SHARED_KEY_MIC || sa->i_auth.method == IKEV2_AUTH_METHOD_RSA_SIG)) { - clib_warning ("unsupported authentication method %u", - sa->i_auth.method); + ikev2_elog_uint (IKEV2_LOG_ERROR, + "unsupported authentication method %u", + sa->i_auth.method); ikev2_set_state (sa, IKEV2_STATE_AUTH_FAILED); return; } @@ -1473,16 +1464,99 @@ ikev2_sa_auth_init (ikev2_sa_t * sa) vec_free (authmsg); } +static u32 +ikev2_mk_local_sa_id (u32 sai, u32 ci, u32 ti) +{ + return (0x80000000 | (ti << 24) | (sai << 12) | ci); +} + +static u32 +ikev2_mk_remote_sa_id (u32 sai, u32 ci, u32 ti) +{ + return (0xc0000000 | (ti << 24) | (sai << 12) | ci); +} + +typedef struct +{ + u32 salt_local; + u32 salt_remote; + u32 local_sa_id; + u32 remote_sa_id; + ipsec_sa_flags_t flags; + u32 local_spi; + u32 remote_spi; + ipsec_crypto_alg_t encr_type; + ipsec_integ_alg_t integ_type; + ip46_address_t local_ip; + ip46_address_t remote_ip; + ipsec_key_t loc_ckey, rem_ckey, loc_ikey, rem_ikey; +} ikev2_add_ipsec_tunnel_args_t; + +static void +ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a) +{ + ikev2_main_t *km = &ikev2_main; + u32 sw_if_index; + int rv; + uword *p = 0; + + rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0, + &a->local_ip, &a->remote_ip, 0, + TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0, + TUNNEL_MODE_P2P, &sw_if_index); + + if (rv == VNET_API_ERROR_IF_ALREADY_EXISTS) + { + p = hash_get (km->sw_if_indices, sw_if_index); + if (p) + /* interface is managed by IKE; proceed with updating SAs */ + rv = 0; + } + + if (rv) + { + ikev2_elog_peers (IKEV2_LOG_ERROR, "installing ipip tunnel failed! " + "loc:%d.%d.%d.%d rem:%d.%d.%d.%d", + a->local_ip.ip4.as_u32, a->remote_ip.ip4.as_u32); + return; + } + + rv |= ipsec_sa_add_and_lock (a->local_sa_id, + a->local_spi, + IPSEC_PROTOCOL_ESP, a->encr_type, + &a->loc_ckey, a->integ_type, &a->loc_ikey, + a->flags, 0, a->salt_local, &a->local_ip, + &a->remote_ip, NULL); + rv |= ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi, + IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey, + a->integ_type, &a->rem_ikey, + (a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0, + a->salt_remote, &a->remote_ip, + &a->local_ip, NULL); + + u32 *sas_in = NULL; + vec_add1 (sas_in, a->remote_sa_id); + rv |= ipsec_tun_protect_update (sw_if_index, a->local_sa_id, sas_in); + hash_set1 (km->sw_if_indices, sw_if_index); +} static int -ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, - ikev2_child_sa_t * child) +ikev2_create_tunnel_interface (vnet_main_t * vnm, + u32 thread_index, + ikev2_sa_t * sa, + ikev2_child_sa_t * child, u32 sa_index, + u32 child_index) { - ipsec_add_del_tunnel_args_t a; + ikev2_main_t *km = &ikev2_main; + ipsec_crypto_alg_t encr_type; + ipsec_integ_alg_t integ_type; + ikev2_profile_t *p = 0; ikev2_sa_transform_t *tr; ikev2_sa_proposal_t *proposals; - u8 encr_type = 0; - u8 integ_type = 0; + u8 is_aead = 0; + ikev2_add_ipsec_tunnel_args_t a; + + clib_memset (&a, 0, sizeof (a)); if (!child->r_proposals) { @@ -1490,31 +1564,28 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, return 1; } - clib_memset (&a, 0, sizeof (a)); - a.is_add = 1; if (sa->is_initiator) { - a.local_ip.ip4.as_u32 = sa->iaddr.as_u32; - a.remote_ip.ip4.as_u32 = sa->raddr.as_u32; + ip46_address_set_ip4 (&a.local_ip, &sa->iaddr); + ip46_address_set_ip4 (&a.remote_ip, &sa->raddr); proposals = child->i_proposals; a.local_spi = child->r_proposals[0].spi; a.remote_spi = child->i_proposals[0].spi; } else { - a.local_ip.ip4.as_u32 = sa->raddr.as_u32; - a.remote_ip.ip4.as_u32 = sa->iaddr.as_u32; + ip46_address_set_ip4 (&a.local_ip, &sa->raddr); + ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr); proposals = child->r_proposals; a.local_spi = child->i_proposals[0].spi; a.remote_spi = child->r_proposals[0].spi; } - a.anti_replay = 1; + + a.flags = IPSEC_SA_FLAG_USE_ANTI_REPLAY; tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_ESN); - if (tr) - a.esn = tr->esn_type; - else - a.esn = 0; + if (tr && tr->esn_type) + a.flags |= IPSEC_SA_FLAG_USE_ESN; tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_ENCR); if (tr) @@ -1538,6 +1609,27 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, break; } } + else if (tr->encr_type == IKEV2_TRANSFORM_ENCR_TYPE_AES_GCM_16 + && tr->key_len) + { + switch (tr->key_len) + { + case 16: + encr_type = IPSEC_CRYPTO_ALG_AES_GCM_128; + break; + case 24: + encr_type = IPSEC_CRYPTO_ALG_AES_GCM_192; + break; + case 32: + encr_type = IPSEC_CRYPTO_ALG_AES_GCM_256; + break; + default: + ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); + return 1; + break; + } + is_aead = 1; + } else { ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); @@ -1549,70 +1641,79 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); return 1; } + a.encr_type = encr_type; - tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_INTEG); - if (tr) + if (!is_aead) { - switch (tr->integ_type) - { - case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128: - integ_type = IPSEC_INTEG_ALG_SHA_256_128; - break; - case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192: - integ_type = IPSEC_INTEG_ALG_SHA_384_192; - break; - case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256: - integ_type = IPSEC_INTEG_ALG_SHA_512_256; - break; - case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96: - integ_type = IPSEC_INTEG_ALG_SHA1_96; - break; - default: + tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_INTEG); + if (tr) + { + switch (tr->integ_type) + { + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128: + integ_type = IPSEC_INTEG_ALG_SHA_256_128; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192: + integ_type = IPSEC_INTEG_ALG_SHA_384_192; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256: + integ_type = IPSEC_INTEG_ALG_SHA_512_256; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96: + integ_type = IPSEC_INTEG_ALG_SHA1_96; + break; + default: + ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); + return 1; + } + } + else + { ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); return 1; } } else { - ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); - return 1; + integ_type = IPSEC_INTEG_ALG_NONE; } + a.integ_type = integ_type; ikev2_calc_child_keys (sa, child); - u8 *loc_ckey, *rem_ckey, *loc_ikey, *rem_ikey; if (sa->is_initiator) { - loc_ikey = child->sk_ai; - rem_ikey = child->sk_ar; - loc_ckey = child->sk_ei; - rem_ckey = child->sk_er; + ipsec_mk_key (&a.loc_ikey, child->sk_ai, vec_len (child->sk_ai)); + ipsec_mk_key (&a.rem_ikey, child->sk_ar, vec_len (child->sk_ar)); + ipsec_mk_key (&a.loc_ckey, child->sk_ei, vec_len (child->sk_ei)); + ipsec_mk_key (&a.rem_ckey, child->sk_er, vec_len (child->sk_er)); + if (is_aead) + { + a.salt_remote = child->salt_er; + a.salt_local = child->salt_ei; + } } else { - loc_ikey = child->sk_ar; - rem_ikey = child->sk_ai; - loc_ckey = child->sk_er; - rem_ckey = child->sk_ei; + ipsec_mk_key (&a.loc_ikey, child->sk_ar, vec_len (child->sk_ar)); + ipsec_mk_key (&a.rem_ikey, child->sk_ai, vec_len (child->sk_ai)); + ipsec_mk_key (&a.loc_ckey, child->sk_er, vec_len (child->sk_er)); + ipsec_mk_key (&a.rem_ckey, child->sk_ei, vec_len (child->sk_ei)); + if (is_aead) + { + a.salt_remote = child->salt_ei; + a.salt_local = child->salt_er; + } } - a.integ_alg = integ_type; - a.local_integ_key_len = vec_len (loc_ikey); - clib_memcpy_fast (a.local_integ_key, loc_ikey, a.local_integ_key_len); - a.remote_integ_key_len = vec_len (rem_ikey); - clib_memcpy_fast (a.remote_integ_key, rem_ikey, a.remote_integ_key_len); - - a.crypto_alg = encr_type; - a.local_crypto_key_len = vec_len (loc_ckey); - clib_memcpy_fast (a.local_crypto_key, loc_ckey, a.local_crypto_key_len); - a.remote_crypto_key_len = vec_len (rem_ckey); - clib_memcpy_fast (a.remote_crypto_key, rem_ckey, a.remote_crypto_key_len); + if (sa->is_profile_index_set) + p = pool_elt_at_index (km->profiles, sa->profile_index); - if (sa->profile && sa->profile->lifetime) + if (p && p->lifetime) { - child->time_to_expiration = vlib_time_now (vnm->vlib_main) - + sa->profile->lifetime; - if (sa->profile->lifetime_jitter) + child->time_to_expiration = + vlib_time_now (vnm->vlib_main) + p->lifetime; + if (p->lifetime_jitter) { // This is not much better than rand(3), which Coverity warns // is unsuitable for security applications; random_u32 is @@ -1622,46 +1723,86 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, u32 rnd = (u32) (vlib_time_now (vnm->vlib_main) * 1e6); rnd = random_u32 (&rnd); - child->time_to_expiration += - 1 + (rnd % sa->profile->lifetime_jitter); + child->time_to_expiration += 1 + (rnd % p->lifetime_jitter); } } - ipsec_add_del_tunnel_if (&a); + if (thread_index & 0xffffffc0) + ikev2_elog_error ("error: thread index exceeds max range 0x3f!"); + if (child_index & 0xfffff000 || sa_index & 0xfffff000) + ikev2_elog_error ("error: sa/child index exceeds max range 0xfff!"); + + child->local_sa_id = + a.local_sa_id = + ikev2_mk_local_sa_id (sa_index, child_index, thread_index); + child->remote_sa_id = + a.remote_sa_id = + ikev2_mk_remote_sa_id (sa_index, child_index, thread_index); + + vl_api_rpc_call_main_thread (ikev2_add_tunnel_from_main, + (u8 *) & a, sizeof (a)); return 0; } +typedef struct +{ + ip46_address_t local_ip; + ip46_address_t remote_ip; + u32 remote_sa_id; + u32 local_sa_id; +} ikev2_del_ipsec_tunnel_args_t; + +static void +ikev2_del_tunnel_from_main (ikev2_del_ipsec_tunnel_args_t * a) +{ + ikev2_main_t *km = &ikev2_main; + /* *INDENT-OFF* */ + ipip_tunnel_key_t key = { + .src = a->local_ip, + .dst = a->remote_ip, + .transport = IPIP_TRANSPORT_IP4, + .fib_index = 0, + }; + ipip_tunnel_t *ipip; + /* *INDENT-ON* */ + + ipip = ipip_tunnel_db_find (&key); + + if (ipip) + { + hash_unset (km->sw_if_indices, ipip->sw_if_index); + ipsec_tun_protect_del (ipip->sw_if_index); + ipsec_sa_unlock_id (a->remote_sa_id); + ipsec_sa_unlock_id (a->local_sa_id); + ipip_del_tunnel (ipip->sw_if_index); + } +} + static int ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, ikev2_child_sa_t * child) { - ipsec_add_del_tunnel_args_t a; + ikev2_del_ipsec_tunnel_args_t a; + + clib_memset (&a, 0, sizeof (a)); if (sa->is_initiator) { - if (!vec_len (child->i_proposals)) - return 0; - - a.is_add = 0; - a.local_ip.ip4.as_u32 = sa->iaddr.as_u32; - a.remote_ip.ip4.as_u32 = sa->raddr.as_u32; - a.local_spi = child->r_proposals[0].spi; - a.remote_spi = child->i_proposals[0].spi; + ip46_address_set_ip4 (&a.local_ip, &sa->iaddr); + ip46_address_set_ip4 (&a.remote_ip, &sa->raddr); } else { - if (!vec_len (child->r_proposals)) - return 0; - - a.is_add = 0; - a.local_ip.ip4.as_u32 = sa->raddr.as_u32; - a.remote_ip.ip4.as_u32 = sa->iaddr.as_u32; - a.local_spi = child->i_proposals[0].spi; - a.remote_spi = child->r_proposals[0].spi; + ip46_address_set_ip4 (&a.local_ip, &sa->raddr); + ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr); } - ipsec_add_del_tunnel_if (&a); + a.remote_sa_id = child->remote_sa_id; + a.local_sa_id = child->local_sa_id; + + vl_api_rpc_call_main_thread (ikev2_del_tunnel_from_main, (u8 *) & a, + sizeof (a)); return 0; } @@ -1990,17 +2131,21 @@ ikev2_retransmit_sa_init (ike_header_t * ike, ike->length = tmp->length; clib_memcpy_fast(ike->payload, tmp->payload, clib_net_to_host_u32(tmp->length) - sizeof(*ike)); - clib_warning("IKE_SA_INIT retransmit from %U to %U", - format_ip4_address, &raddr, - format_ip4_address, &iaddr); + ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, + "ispi %lx IKE_SA_INIT retransmit " + "from %d.%d.%d.%d to %d.%d.%d.%d", + ike->ispi, + raddr.as_u32, iaddr.as_u32); return 1; } /* else ignore req */ else { - clib_warning("IKE_SA_INIT ignore from %U to %U", - format_ip4_address, &raddr, - format_ip4_address, &iaddr); + ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, + "ispi %lx IKE_SA_INIT ignore " + "from %d.%d.%d.%d to %d.%d.%d.%d", + ike->ispi, + raddr.as_u32, iaddr.as_u32); return -1; } } @@ -2042,21 +2187,17 @@ ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike) ike->length = tmp->length; clib_memcpy_fast (ike->payload, tmp->payload, clib_net_to_host_u32 (tmp->length) - sizeof (*ike)); - clib_warning ("IKE msgid %u retransmit from %U to %U", - msg_id, - format_ip4_address, &sa->raddr, - format_ip4_address, &sa->iaddr); + ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, "IKE retransmit msgid %d", + msg_id, sa->raddr.as_u32, sa->iaddr.as_u32); return 1; } /* old req ignore */ else { - clib_warning ("IKE msgid %u req ignore from %U to %U", - msg_id, - format_ip4_address, &sa->raddr, - format_ip4_address, &sa->iaddr); - return -1; + ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, "IKE req ignore msgid %d", + msg_id, sa->raddr.as_u32, sa->iaddr.as_u32); } + return -1; } @@ -2250,8 +2391,10 @@ ikev2_node_fn (vlib_main_t * vm, ikev2_initial_contact_cleanup (sa0); ikev2_sa_match_ts (sa0); if (sa0->state != IKEV2_STATE_TS_UNACCEPTABLE) - ikev2_create_tunnel_interface (km->vnet_main, sa0, - &sa0->childs[0]); + ikev2_create_tunnel_interface (km->vnet_main, + thread_index, sa0, + &sa0->childs[0], + p[0], 0); } if (sa0->is_initiator) @@ -2371,14 +2514,18 @@ ikev2_node_fn (vlib_main_t * vm, { if (sa0->rekey[0].protocol_id != IKEV2_PROTOCOL_IKE) { + if (sa0->childs) + vec_free (sa0->childs); ikev2_child_sa_t *child; vec_add2 (sa0->childs, child, 1); child->r_proposals = sa0->rekey[0].r_proposal; child->i_proposals = sa0->rekey[0].i_proposal; child->tsi = sa0->rekey[0].tsi; child->tsr = sa0->rekey[0].tsr; - ikev2_create_tunnel_interface (km->vnet_main, sa0, - child); + ikev2_create_tunnel_interface (km->vnet_main, + thread_index, sa0, + child, p[0], + child - sa0->childs); } if (sa0->is_initiator) { @@ -2393,10 +2540,11 @@ ikev2_node_fn (vlib_main_t * vm, } else { - clib_warning ("IKEv2 exchange %u packet received from %U to %U", - ike0->exchange, - format_ip4_address, ip40->src_address.as_u8, - format_ip4_address, ip40->dst_address.as_u8); + ikev2_elog_uint_peers (IKEV2_LOG_WARNING, "IKEv2 exchange %d " + "received from %d.%d.%d.%d to %d.%d.%d.%d", + ike0->exchange, + ip40->src_address.as_u32, + ip40->dst_address.as_u32); } dispatch0: @@ -2527,7 +2675,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, } if (error) { - clib_warning + ikev2_elog_error ("Didn't find any supported algorithm for IKEV2_TRANSFORM_TYPE_INTEG"); r = clib_error_return (0, "Unsupported algorithm"); return r; @@ -2555,24 +2703,27 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, } /* DH */ - error = 1; - vec_foreach (td, km->supported_transforms) - { - if (td->type == IKEV2_TRANSFORM_TYPE_DH && td->dh_type == ts->dh_type) + if (is_ike || ts->dh_type != IKEV2_TRANSFORM_DH_TYPE_NONE) + { + error = 1; + vec_foreach (td, km->supported_transforms) { - vec_add1 (proposal->transforms, *td); - if (is_ike) + if (td->type == IKEV2_TRANSFORM_TYPE_DH && td->dh_type == ts->dh_type) { - sa->dh_group = td->dh_type; + vec_add1 (proposal->transforms, *td); + if (is_ike) + { + sa->dh_group = td->dh_type; + } + error = 0; + break; } - error = 0; - break; } - } - if (error) - { - r = clib_error_return (0, "Unsupported algorithm"); - return r; + if (error) + { + r = clib_error_return (0, "Unsupported algorithm"); + return r; + } } if (!is_ike) @@ -2973,7 +3124,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) ikev2_sa_free_proposal_vector (&proposals); sa.is_initiator = 1; - sa.profile = p; + sa.profile_index = km->profiles - p; + sa.is_profile_index_set = 1; sa.state = IKEV2_STATE_SA_INIT; ikev2_generate_sa_init_data (&sa); ikev2_payload_add_ke (chain, sa.dh_group, sa.i_dh_data); @@ -3036,6 +3188,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) ike0->flags = IKEV2_HDR_FLAG_INITIATOR; ike0->exchange = IKEV2_EXCHANGE_SA_INIT; ike0->ispi = sa.ispi; + ike0->rspi = 0; + ike0->msgid = 0; /* store whole IKE payload - needed for PSK auth */ vec_free (sa.last_sa_init_req_packet_data); @@ -3049,12 +3203,6 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) sa.i_auth.method = p->auth.method; sa.i_auth.hex = p->auth.hex; sa.i_auth.data = vec_dup (p->auth.data); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - clib_memcpy_fast (sa.i_auth.key, p->auth.key, - EVP_PKEY_size (p->auth.key)); -#else - sa.i_auth.key = vec_dup (p->auth.key); -#endif vec_add (sa.childs[0].tsi, &p->loc_ts, 1); vec_add (sa.childs[0].tsr, &p->rem_ts, 1); @@ -3066,6 +3214,9 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) ikev2_send_ike (vm, if_ip, &p->responder.ip4, bi0, len); + ikev2_elog_exchange ("ispi %lx rspi %lx IKEV2_EXCHANGE_SA_INIT sent to " + "%d.%d.%d.%d", clib_host_to_net_u64 (sa0->ispi), 0, + p->responder.ip4.as_u32); } return 0; @@ -3295,13 +3446,9 @@ clib_error_t * ikev2_init (vlib_main_t * vm) { ikev2_main_t *km = &ikev2_main; - clib_error_t *error; vlib_thread_main_t *tm = vlib_get_thread_main (); int thread_id; - if ((error = vlib_call_init_function (vm, ipsec_init))) - return error; - clib_memset (km, 0, sizeof (ikev2_main_t)); km->vnet_main = vnet_get_main (); km->vlib_main = vm; @@ -3318,33 +3465,42 @@ ikev2_init (vlib_main_t * vm) } km->sa_by_ispi = hash_create (0, sizeof (uword)); - - - if ((error = vlib_call_init_function (vm, ikev2_cli_init))) - return error; + km->sw_if_indices = hash_create (0, 0); udp_register_dst_port (vm, 500, ikev2_node.index, 1); + ikev2_cli_reference (); + return 0; } -VLIB_INIT_FUNCTION (ikev2_init); +/* *INDENT-OFF* */ +VLIB_INIT_FUNCTION (ikev2_init) = +{ + .runs_after = VLIB_INITS("ipsec_init"), +}; +/* *INDENT-ON* */ + static u8 ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa) { ikev2_main_t *km = &ikev2_main; + ikev2_profile_t *p = 0; vlib_main_t *vm = km->vlib_main; f64 now = vlib_time_now (vm); u8 res = 0; - if (sa->is_initiator && sa->profile && csa->time_to_expiration + if (sa->is_profile_index_set) + p = pool_elt_at_index (km->profiles, sa->profile_index); + + if (sa->is_initiator && p && csa->time_to_expiration && now > csa->time_to_expiration) { if (!csa->is_expired || csa->rekey_retries > 0) { ikev2_rekey_child_sa_internal (vm, sa, csa); - csa->time_to_expiration = now + sa->profile->handover; + csa->time_to_expiration = now + p->handover; csa->is_expired = 1; if (csa->rekey_retries == 0) { @@ -3353,8 +3509,8 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa) else if (csa->rekey_retries > 0) { csa->rekey_retries--; - clib_warning ("Rekeying Child SA 0x%x, retries left %d", - csa->i_proposals->spi, csa->rekey_retries); + ikev2_log_debug ("Rekeying Child SA 0x%x, retries left %d", + csa->i_proposals->spi, csa->rekey_retries); if (csa->rekey_retries == 0) { csa->rekey_retries = -1; @@ -3373,6 +3529,21 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa) return res; } +int +ikev2_set_log_level (ikev2_log_level_t log_level) +{ + ikev2_main_t *km = &ikev2_main; + + if (log_level >= IKEV2_LOG_MAX) + { + ikev2_log_error ("unknown logging level %d", log_level); + return -1; + } + + km->log_level = log_level; + return 0; +} + static void ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa) { @@ -3380,6 +3551,7 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa) vlib_main_t *vm = km->vlib_main; ikev2_main_per_thread_data_t *tkm; ikev2_sa_t *fsa = 0; + ikev2_profile_t *p = 0; ikev2_child_sa_t *fchild = 0; f64 now = vlib_time_now (vm); vlib_counter_t counts; @@ -3404,10 +3576,12 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa) vlib_get_combined_counter (&ipsec_sa_counters, ipsec_sa->stat_index, &counts); - if (fchild && fsa && fsa->profile && fsa->profile->lifetime_maxdata) + if (fsa && fsa->is_profile_index_set) + p = pool_elt_at_index (km->profiles, fsa->profile_index); + + if (fchild && p && p->lifetime_maxdata) { - if (!fchild->is_expired - && counts.bytes > fsa->profile->lifetime_maxdata) + if (!fchild->is_expired && counts.bytes > p->lifetime_maxdata) { fchild->time_to_expiration = now; }