From 84962d19ba76eafd5c7658aa86ec61c9b81f7702 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Tue, 8 Sep 2020 06:08:05 +0000 Subject: [PATCH] ikev2: support ipv6 traffic selectors & overlay Ticket: VPP-1917 Type: feature Change-Id: Ie9f22e7336aa7807b1967c48de9843df10fb575c Signed-off-by: Filip Tehlar --- src/plugins/ikev2/ikev2.api | 2 +- src/plugins/ikev2/ikev2.c | 528 ++++++++++++++++++++++++----------- src/plugins/ikev2/ikev2.h | 12 +- src/plugins/ikev2/ikev2_api.c | 22 +- src/plugins/ikev2/ikev2_cli.c | 62 ++-- src/plugins/ikev2/ikev2_payload.c | 114 ++++++-- src/plugins/ikev2/ikev2_priv.h | 50 ++-- src/plugins/ikev2/ikev2_test.c | 78 +++--- src/plugins/ikev2/ikev2_types.api | 10 +- src/plugins/ikev2/test/test_ikev2.py | 184 ++++++++---- src/plugins/ikev2/test/vpp_ikev2.py | 13 +- 11 files changed, 695 insertions(+), 380 deletions(-) diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api index 1e1dbf9589d..a7aeff1fa44 100644 --- a/src/plugins/ikev2/ikev2.api +++ b/src/plugins/ikev2/ikev2.api @@ -264,7 +264,7 @@ autoreply define ikev2_profile_set_ts string name[64]; vl_api_ikev2_ts_t ts; - option vat_help = "name protocol start_port end_port start_addr end_addr (local|remote)"; + option vat_help = "name protocol start_port end_port start_addr end_addr (local|remote)"; option status="in_progress"; }; diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c index bc37b7e0035..a266853760f 100644 --- a/src/plugins/ikev2/ikev2.c +++ b/src/plugins/ikev2/ikev2.c @@ -62,8 +62,6 @@ format_ikev2_trace (u8 * s, va_list * args) return s; } -static vlib_node_registration_t ikev2_node; - #define foreach_ikev2_error \ _(PROCESSED, "IKEv2 packets processed") \ _(IKE_SA_INIT_RETRANSMIT, "IKE_SA_INIT retransmit ") \ @@ -92,9 +90,16 @@ static char *ikev2_error_strings[] = { typedef enum { IKEV2_NEXT_IP4_LOOKUP, - IKEV2_NEXT_ERROR_DROP, - IKEV2_N_NEXT, -} ikev2_next_t; + IKEV2_NEXT_IP4_ERROR_DROP, + IKEV2_IP4_N_NEXT, +} ikev2_ip4_next_t; + +typedef enum +{ + IKEV2_NEXT_IP6_LOOKUP, + IKEV2_NEXT_IP6_ERROR_DROP, + IKEV2_IP6_N_NEXT, +} ikev2_ip6_next_t; typedef u32 ikev2_non_esp_marker; @@ -263,7 +268,7 @@ ikev2_sa_free_proposal_vector (ikev2_sa_proposal_t ** v) vec_free (p->transforms); } vec_free (*v); -}; +} static void ikev2_sa_free_child_sa (ikev2_child_sa_t * c) @@ -417,8 +422,8 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai) sa->i_nonce = _(sai->i_nonce); sa->i_dh_data = _(sai->i_dh_data); sa->dh_private_key = _(sai->dh_private_key); - sa->iaddr.as_u32 = sai->iaddr.as_u32; - sa->raddr.as_u32 = sai->raddr.as_u32; + ip_address_copy (&sa->iaddr, &sai->iaddr); + ip_address_copy (&sa->raddr, &sai->raddr); sa->is_initiator = sai->is_initiator; sa->i_id.type = sai->i_id.type; sa->r_id.type = sai->r_id.type; @@ -627,16 +632,17 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child) } static_always_inline u8 * -ikev2_compute_nat_sha1 (u64 ispi, u64 rspi, u32 ip, u16 port) +ikev2_compute_nat_sha1 (u64 ispi, u64 rspi, ip_address_t * ia, u16 port) { - /* ispi, rspi, ip, port */ - u8 buf[8 + 8 + 4 + 2]; + const u32 max_buf_size = + sizeof (ispi) + sizeof (rspi) + sizeof (ip6_address_t) + sizeof (u16); + u8 buf[max_buf_size]; u8 *res = vec_new (u8, 20); clib_memcpy_fast (&buf[0], &ispi, sizeof (ispi)); clib_memcpy_fast (&buf[8], &rspi, sizeof (rspi)); - clib_memcpy_fast (&buf[8 + 8], &ip, sizeof (ip)); - clib_memcpy_fast (&buf[8 + 8 + 4], &port, sizeof (port)); + clib_memcpy_fast (&buf[8 + 8], ip_addr_bytes (ia), ip_address_size (ia)); + clib_memcpy_fast (&buf[8 + 8 + ip_address_size (ia)], &port, sizeof (port)); SHA1 (buf, sizeof (buf), res); return res; } @@ -691,9 +697,10 @@ ikev2_process_sa_init_req (vlib_main_t * vm, u16 plen; 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); + "from ", clib_net_to_host_u64 (ike->ispi), + clib_net_to_host_u64 (ike->rspi), + ip_addr_v4 (&sa->iaddr).as_u32, + ip_addr_version (&sa->iaddr) == AF_IP4); sa->ispi = clib_net_to_host_u64 (ike->ispi); @@ -735,8 +742,7 @@ ikev2_process_sa_init_req (vlib_main_t * vm, ikev2_parse_notify_payload (ikep, current_length); if (n->msg_type == IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP) { - u8 *src_sha = ikev2_compute_nat_sha1 (ike->ispi, 0, - sa->iaddr.as_u32, + u8 *src_sha = ikev2_compute_nat_sha1 (ike->ispi, 0, &sa->iaddr, udp->src_port); if (clib_memcmp (src_sha, n->data, vec_len (src_sha))) { @@ -749,8 +755,7 @@ ikev2_process_sa_init_req (vlib_main_t * vm, else if (n->msg_type == IKEV2_NOTIFY_MSG_NAT_DETECTION_DESTINATION_IP) { - u8 *dst_sha = ikev2_compute_nat_sha1 (ike->ispi, 0, - sa->raddr.as_u32, + u8 *dst_sha = ikev2_compute_nat_sha1 (ike->ispi, 0, &sa->raddr, udp->dst_port); if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha))) { @@ -801,8 +806,9 @@ ikev2_process_sa_init_resp (vlib_main_t * vm, 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); + "from ", sa->ispi, sa->rspi, + ip_addr_v4 (&sa->raddr).as_u32, + ip_addr_version (&sa->raddr) == AF_IP4); /* store whole IKE payload - needed for PSK auth */ vec_reset_length (sa->last_sa_init_res_packet_data); @@ -848,9 +854,8 @@ ikev2_process_sa_init_resp (vlib_main_t * vm, ikev2_parse_notify_payload (ikep, current_length); if (n->msg_type == IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP) { - u8 *src_sha = ikev2_compute_nat_sha1 (ike->ispi, - ike->rspi, - sa->raddr.as_u32, + u8 *src_sha = ikev2_compute_nat_sha1 (ike->ispi, ike->rspi, + &sa->raddr, udp->src_port); if (clib_memcmp (src_sha, n->data, vec_len (src_sha))) { @@ -862,9 +867,8 @@ ikev2_process_sa_init_resp (vlib_main_t * vm, else if (n->msg_type == IKEV2_NOTIFY_MSG_NAT_DETECTION_DESTINATION_IP) { - u8 *dst_sha = ikev2_compute_nat_sha1 (ike->ispi, - ike->rspi, - sa->iaddr.as_u32, + u8 *dst_sha = ikev2_compute_nat_sha1 (ike->ispi, ike->rspi, + &sa->iaddr, udp->dst_port); if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha))) { @@ -1100,10 +1104,12 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, u32 dlen = 0; ikev2_elog_exchange ("ispi %lx rspi %lx EXCHANGE_IKE_AUTH received " - "from %d.%d.%d.%d", clib_host_to_net_u64 (ike->ispi), + "from ", 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); + sa->is_initiator ? + ip_addr_v4 (&sa->raddr).as_u32 : + ip_addr_v4 (&sa->iaddr).as_u32, + ip_addr_version (&sa->raddr) == AF_IP4); ikev2_calc_keys (sa); @@ -1240,8 +1246,10 @@ ikev2_process_informational_req (vlib_main_t * vm, sa->liveness_retries = 0; 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); + "from ", clib_host_to_net_u64 (ike->ispi), + clib_host_to_net_u64 (ike->rspi), + ip_addr_v4 (&sa->iaddr).as_u32, + ip_addr_version (&sa->iaddr) == AF_IP4); plaintext = ikev2_decrypt_sk_payload (sa, ike, &payload, len, &dlen); @@ -1316,8 +1324,10 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, u16 plen; 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); + "from ", clib_host_to_net_u64 (ike->ispi), + clib_host_to_net_u64 (ike->rspi), + ip_addr_v4 (&sa->raddr).as_u32, + ip_addr_version (&sa->raddr) == AF_IP4); plaintext = ikev2_decrypt_sk_payload (sa, ike, &payload, len, &dlen); @@ -1479,8 +1489,8 @@ ikev2_ts_cmp (ikev2_ts_t * ts1, ikev2_ts_t * ts2) { if (ts1->ts_type == ts2->ts_type && ts1->protocol_id == ts2->protocol_id && ts1->start_port == ts2->start_port && ts1->end_port == ts2->end_port && - ts1->start_addr.as_u32 == ts2->start_addr.as_u32 && - ts1->end_addr.as_u32 == ts2->end_addr.as_u32) + !ip_address_cmp (&ts1->start_addr, &ts2->start_addr) && + !ip_address_cmp (&ts1->end_addr, &ts2->end_addr)) return 1; return 0; @@ -1777,6 +1787,7 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a) ikev2_main_t *km = &ikev2_main; u32 sw_if_index; int rv = 0; + ip46_address_t zero_addr = ip46_address_initializer; if (~0 == a->sw_if_index) { @@ -1802,9 +1813,9 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a) 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); + ikev2_elog_uint (IKEV2_LOG_ERROR, + "installing ipip tunnel failed! local spi: %x", + a->local_spi); return; } @@ -1825,14 +1836,14 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a) 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, a->src_port, a->dst_port); + a->flags, 0, a->salt_local, &zero_addr, + &zero_addr, NULL, a->src_port, a->dst_port); rv |= ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi, IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey, a->integ_type, &a->rem_ikey, (a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0, - a->salt_remote, &a->remote_ip, - &a->local_ip, NULL, a->ipsec_over_udp_port, + a->salt_remote, &zero_addr, + &zero_addr, NULL, a->ipsec_over_udp_port, a->ipsec_over_udp_port); rv |= ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in); @@ -1864,16 +1875,16 @@ ikev2_create_tunnel_interface (vlib_main_t * vm, if (sa->is_initiator) { - ip46_address_set_ip4 (&a.local_ip, &sa->iaddr); - ip46_address_set_ip4 (&a.remote_ip, &sa->raddr); + ip_address_to_46 (&sa->iaddr, &a.local_ip); + ip_address_to_46 (&sa->raddr, &a.remote_ip); proposals = child->r_proposals; a.local_spi = child->r_proposals[0].spi; a.remote_spi = child->i_proposals[0].spi; } else { - ip46_address_set_ip4 (&a.local_ip, &sa->raddr); - ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr); + ip_address_to_46 (&sa->raddr, &a.local_ip); + ip_address_to_46 (&sa->iaddr, &a.remote_ip); proposals = child->i_proposals; a.local_spi = child->i_proposals[0].spi; a.remote_spi = child->r_proposals[0].spi; @@ -2153,13 +2164,13 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, if (sa->is_initiator) { - ip46_address_set_ip4 (&a.local_ip, &sa->iaddr); - ip46_address_set_ip4 (&a.remote_ip, &sa->raddr); + ip_address_to_46 (&sa->iaddr, &a.local_ip); + ip_address_to_46 (&sa->raddr, &a.remote_ip); } else { - ip46_address_set_ip4 (&a.local_ip, &sa->raddr); - ip46_address_set_ip4 (&a.remote_ip, &sa->iaddr); + ip_address_to_46 (&sa->raddr, &a.local_ip); + ip_address_to_46 (&sa->iaddr, &a.remote_ip); } a.remote_sa_id = child->remote_sa_id; @@ -2239,8 +2250,7 @@ ikev2_generate_message (vlib_buffer_t * b, ikev2_sa_t * sa, u8 *nat_detection_sha1 = ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi), clib_host_to_net_u64 (sa->rspi), - sa->raddr.as_u32, - udp->dst_port); + &sa->raddr, udp->dst_port); ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP, nat_detection_sha1); @@ -2248,7 +2258,7 @@ ikev2_generate_message (vlib_buffer_t * b, ikev2_sa_t * sa, nat_detection_sha1 = ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa->ispi), clib_host_to_net_u64 (sa->rspi), - sa->iaddr.as_u32, udp->src_port); + &sa->iaddr, udp->src_port); ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_DESTINATION_IP, nat_detection_sha1); @@ -2518,18 +2528,17 @@ done: } static u32 -ikev2_retransmit_sa_init (ike_header_t * ike, ip4_address_t iaddr, - ip4_address_t raddr, u32 rlen) +ikev2_retransmit_sa_init (ike_header_t * ike, ip_address_t iaddr, + ip_address_t raddr, u32 rlen) { - ikev2_main_t *km = &ikev2_main; ikev2_sa_t *sa; - u32 thread_index = vlib_get_thread_index (); + ikev2_main_per_thread_data_t *ptd = ikev2_get_per_thread_data (); /* *INDENT-OFF* */ - pool_foreach (sa, km->per_thread_data[thread_index].sas, ({ + pool_foreach (sa, ptd->sas, ({ if (sa->ispi == clib_net_to_host_u64(ike->ispi) && - sa->iaddr.as_u32 == iaddr.as_u32 && - sa->raddr.as_u32 == raddr.as_u32) + !ip_address_cmp(&sa->iaddr, &iaddr) && + !ip_address_cmp(&sa->raddr, &raddr)) { int p = 0; u8 payload = ike->nextpayload; @@ -2566,7 +2575,8 @@ ikev2_retransmit_sa_init (ike_header_t * ike, ip4_address_t iaddr, "ispi %lx IKE_SA_INIT retransmit " "from %d.%d.%d.%d to %d.%d.%d.%d", ike->ispi, - raddr.as_u32, iaddr.as_u32); + ip_addr_v4(&raddr).as_u32, + ip_addr_v4 (&iaddr).as_u32); return slen; } /* else ignore req */ @@ -2576,7 +2586,8 @@ ikev2_retransmit_sa_init (ike_header_t * ike, ip4_address_t iaddr, "ispi %lx IKE_SA_INIT ignore " "from %d.%d.%d.%d to %d.%d.%d.%d", ike->ispi, - raddr.as_u32, iaddr.as_u32); + ip_addr_v4(&raddr).as_u32, + ip_addr_v4(&iaddr).as_u32); return ~0; } } @@ -2619,13 +2630,15 @@ ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike) ike->length = tmp->length; clib_memcpy_fast (ike->payload, tmp->payload, slen - sizeof (*ike)); ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, "IKE retransmit msgid %d", - msg_id, sa->raddr.as_u32, sa->iaddr.as_u32); + msg_id, ip_addr_v4 (&sa->raddr).as_u32, + ip_addr_v4 (&sa->iaddr).as_u32); return slen; } /* old req ignore */ ikev2_elog_uint_peers (IKEV2_LOG_DEBUG, "IKE req ignore msgid %d", - msg_id, sa->raddr.as_u32, sa->iaddr.as_u32); + msg_id, ip_addr_v4 (&sa->raddr).as_u32, + ip_addr_v4 (&sa->iaddr).as_u32); return ~0; } @@ -2658,9 +2671,50 @@ ikev2_del_sa_init (u64 ispi) sizeof (ispi)); } -static uword -ikev2_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) +static_always_inline void +ikev2_rewrite_v6_addrs (ikev2_sa_t * sa, ip6_header_t * ih) +{ + if (sa->is_initiator) + { + ip_address_copy_addr (&ih->dst_address, &sa->raddr); + ip_address_copy_addr (&ih->src_address, &sa->iaddr); + } + else + { + ip_address_copy_addr (&ih->dst_address, &sa->iaddr); + ip_address_copy_addr (&ih->src_address, &sa->raddr); + } +} + +static_always_inline void +ikev2_rewrite_v4_addrs (ikev2_sa_t * sa, ip4_header_t * ih) +{ + if (sa->is_initiator) + { + ip_address_copy_addr (&ih->dst_address, &sa->raddr); + ip_address_copy_addr (&ih->src_address, &sa->iaddr); + } + else + { + ip_address_copy_addr (&ih->dst_address, &sa->iaddr); + ip_address_copy_addr (&ih->src_address, &sa->raddr); + } +} + +static_always_inline void +ikev2_set_ip_address (ikev2_sa_t * sa, const void *src, + const void *dst, const int af, const int is_initiator) +{ + const void *raddr = is_initiator ? src : dst; + const void *iaddr = is_initiator ? dst : src; + ip_address_set (&sa->raddr, raddr, af); + ip_address_set (&sa->iaddr, iaddr, af); +} + +static_always_inline uword +ikev2_node_internal (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame, + u8 is_ip4) { u32 n_left = frame->n_vectors, *from; ikev2_main_t *km = &ikev2_main; @@ -2676,13 +2730,16 @@ ikev2_node_fn (vlib_main_t * vm, while (n_left > 0) { vlib_buffer_t *b0 = b[0]; - next[0] = IKEV2_NEXT_ERROR_DROP; - ip4_header_t *ip40; + next[0] = is_ip4 ? IKEV2_NEXT_IP4_ERROR_DROP + : IKEV2_NEXT_IP6_ERROR_DROP; + ip4_header_t *ip40 = 0; + ip6_header_t *ip60 = 0; udp_header_t *udp0; ike_header_t *ike0; ikev2_sa_t *sa0 = 0; ikev2_sa_t sa; /* temporary store for SA */ u32 rlen, slen = 0; + int ip_hdr_sz = 0; int is_req = 0, has_non_esp_marker = 0; if (b0->punt_reason == ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0]) @@ -2693,17 +2750,29 @@ ikev2_node_fn (vlib_main_t * vm, udp0 = (udp_header_t *) ptr; ptr += sizeof (*udp0); ike0 = (ike_header_t *) ptr; + ip_hdr_sz = sizeof (*ip40); } else { + u8 *ipx_hdr = b0->data + vnet_buffer (b0)->l3_hdr_offset; ike0 = vlib_buffer_get_current (b0); vlib_buffer_advance (b0, -sizeof (*udp0)); udp0 = vlib_buffer_get_current (b0); - vlib_buffer_advance (b0, -sizeof (*ip40)); - ip40 = vlib_buffer_get_current (b0); + + if (is_ip4) + { + ip40 = (ip4_header_t *) ipx_hdr; + ip_hdr_sz = sizeof (*ip40); + } + else + { + ip60 = (ip6_header_t *) ipx_hdr; + ip_hdr_sz = sizeof (*ip60); + } + vlib_buffer_advance (b0, -ip_hdr_sz); } - rlen = b0->current_length - sizeof (*ip40) - sizeof (*udp0); + rlen = b0->current_length - ip_hdr_sz - sizeof (*udp0); /* check for non-esp marker */ if (*((u32 *) ike0) == 0) @@ -2716,14 +2785,14 @@ ikev2_node_fn (vlib_main_t * vm, if (clib_net_to_host_u32 (ike0->length) != rlen) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_BAD_LENGTH, 1); goto dispatch0; } if (ike0->version != IKE_VERSION_2) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_NOT_IKEV2, 1); goto dispatch0; } @@ -2733,12 +2802,20 @@ ikev2_node_fn (vlib_main_t * vm, sa0 = &sa; clib_memset (sa0, 0, sizeof (*sa0)); - if (ike0->flags & IKEV2_HDR_FLAG_INITIATOR) + u8 is_initiator = ike0->flags & IKEV2_HDR_FLAG_INITIATOR; + if (is_initiator) { if (ike0->rspi == 0) { - sa0->raddr.as_u32 = ip40->dst_address.as_u32; - sa0->iaddr.as_u32 = ip40->src_address.as_u32; + if (is_ip4) + ikev2_set_ip_address (sa0, &ip40->dst_address, + &ip40->src_address, AF_IP4, + is_initiator); + else + ikev2_set_ip_address (sa0, &ip60->dst_address, + &ip60->src_address, AF_IP6, + is_initiator); + sa0->dst_port = clib_net_to_host_u16 (udp0->src_port); slen = @@ -2746,7 +2823,7 @@ ikev2_node_fn (vlib_main_t * vm, sa0->raddr, rlen); if (slen) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, ~0 == slen ? IKEV2_ERROR_IKE_SA_INIT_IGNORE @@ -2758,7 +2835,7 @@ ikev2_node_fn (vlib_main_t * vm, res = ikev2_process_sa_init_req (vm, sa0, ike0, udp0, rlen); if (!res) - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_MALFORMED_PACKET, 1); @@ -2776,7 +2853,7 @@ ikev2_node_fn (vlib_main_t * vm, { slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0); if (~0 == slen) - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1); } @@ -2797,8 +2874,15 @@ ikev2_node_fn (vlib_main_t * vm, } else //received sa_init without initiator flag { - sa0->raddr.as_u32 = ip40->src_address.as_u32; - sa0->iaddr.as_u32 = ip40->dst_address.as_u32; + if (is_ip4) + ikev2_set_ip_address (sa0, &ip40->src_address, + &ip40->dst_address, AF_IP4, + is_initiator); + else + ikev2_set_ip_address (sa0, &ip60->src_address, + &ip60->dst_address, AF_IP6, + is_initiator); + ikev2_process_sa_init_resp (vm, sa0, ike0, udp0, rlen); if (sa0->state == IKEV2_STATE_SA_INIT) @@ -2820,7 +2904,7 @@ ikev2_node_fn (vlib_main_t * vm, ikev2_generate_message (b0, sa0, ike0, 0, udp0); if (~0 == slen) vlib_node_increment_counter (vm, - ikev2_node.index, + node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1); } @@ -2855,7 +2939,7 @@ ikev2_node_fn (vlib_main_t * vm, slen = ikev2_retransmit_resp (sa0, ike0); if (slen) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, ~0 == slen ? IKEV2_ERROR_IKE_REQ_IGNORE @@ -2870,7 +2954,7 @@ ikev2_node_fn (vlib_main_t * vm, if (res) ikev2_sa_auth (sa0); else - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_MALFORMED_PACKET, 1); if (sa0->state == IKEV2_STATE_AUTHENTICATED) { @@ -2890,7 +2974,7 @@ ikev2_node_fn (vlib_main_t * vm, { slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0); if (~0 == slen) - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1); } @@ -2906,7 +2990,7 @@ ikev2_node_fn (vlib_main_t * vm, slen = ikev2_retransmit_resp (sa0, ike0); if (slen) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, ~0 == slen ? IKEV2_ERROR_IKE_REQ_IGNORE @@ -2919,7 +3003,7 @@ ikev2_node_fn (vlib_main_t * vm, res = ikev2_process_informational_req (vm, sa0, ike0, rlen); if (!res) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_MALFORMED_PACKET, 1); slen = ~0; @@ -2962,7 +3046,7 @@ ikev2_node_fn (vlib_main_t * vm, ike0->flags |= IKEV2_HDR_FLAG_RESPONSE; slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0); if (~0 == slen) - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1); } @@ -2978,7 +3062,7 @@ ikev2_node_fn (vlib_main_t * vm, slen = ikev2_retransmit_resp (sa0, ike0); if (slen) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, ~0 == slen ? IKEV2_ERROR_IKE_REQ_IGNORE @@ -2991,7 +3075,7 @@ ikev2_node_fn (vlib_main_t * vm, res = ikev2_process_create_child_sa_req (vm, sa0, ike0, rlen); if (!res) { - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_MALFORMED_PACKET, 1); slen = ~0; @@ -3022,7 +3106,7 @@ ikev2_node_fn (vlib_main_t * vm, { slen = ikev2_generate_message (b0, sa0, ike0, 0, udp0); if (~0 == slen) - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1); } @@ -3042,16 +3126,15 @@ ikev2_node_fn (vlib_main_t * vm, /* if we are sending packet back, rewrite headers */ if (slen && ~0 != slen) { - next[0] = IKEV2_NEXT_IP4_LOOKUP; - if (sa0->is_initiator) + if (is_ip4) { - ip40->dst_address.as_u32 = sa0->raddr.as_u32; - ip40->src_address.as_u32 = sa0->iaddr.as_u32; + next[0] = IKEV2_NEXT_IP4_LOOKUP; + ikev2_rewrite_v4_addrs (sa0, ip40); } else { - ip40->dst_address.as_u32 = sa0->iaddr.as_u32; - ip40->src_address.as_u32 = sa0->raddr.as_u32; + next[0] = IKEV2_NEXT_IP6_LOOKUP; + ikev2_rewrite_v6_addrs (sa0, ip60); } if (is_req) @@ -3078,10 +3161,17 @@ ikev2_node_fn (vlib_main_t * vm, udp0->length = clib_host_to_net_u16 (slen + sizeof (udp_header_t)); udp0->checksum = 0; - b0->current_length = - slen + sizeof (ip4_header_t) + sizeof (udp_header_t); - ip40->length = clib_host_to_net_u16 (b0->current_length); - ip40->checksum = ip4_header_checksum (ip40); + b0->current_length = slen + ip_hdr_sz + sizeof (udp_header_t); + if (is_ip4) + { + ip40->length = clib_host_to_net_u16 (b0->current_length); + ip40->checksum = ip4_header_checksum (ip40); + } + else + { + ip60->payload_length = + clib_host_to_net_u16 (b0->current_length - sizeof (*ip60)); + } } /* delete sa */ if (sa0 && (sa0->state == IKEV2_STATE_DELETED || @@ -3107,16 +3197,28 @@ ikev2_node_fn (vlib_main_t * vm, b += 1; } - vlib_node_increment_counter (vm, ikev2_node.index, + vlib_node_increment_counter (vm, node->node_index, IKEV2_ERROR_PROCESSED, frame->n_vectors); vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); return frame->n_vectors; } +static uword +ikev2_ip4 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + return ikev2_node_internal (vm, node, frame, 1 /* is_ip4 */ ); +} + +static uword +ikev2_ip6 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + return ikev2_node_internal (vm, node, frame, 0 /* is_ip4 */ ); +} + /* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ikev2_node,static) = { - .function = ikev2_node_fn, - .name = "ikev2", +VLIB_REGISTER_NODE (ikev2_node_ip4,static) = { + .function = ikev2_ip4, + .name = "ikev2-ip4", .vector_size = sizeof (u32), .format_trace = format_ikev2_trace, .type = VLIB_NODE_TYPE_INTERNAL, @@ -3124,11 +3226,27 @@ VLIB_REGISTER_NODE (ikev2_node,static) = { .n_errors = ARRAY_LEN(ikev2_error_strings), .error_strings = ikev2_error_strings, - .n_next_nodes = IKEV2_N_NEXT, - + .n_next_nodes = IKEV2_IP4_N_NEXT, .next_nodes = { [IKEV2_NEXT_IP4_LOOKUP] = "ip4-lookup", - [IKEV2_NEXT_ERROR_DROP] = "error-drop", + [IKEV2_NEXT_IP4_ERROR_DROP] = "error-drop", + }, +}; + +VLIB_REGISTER_NODE (ikev2_node_ip6,static) = { + .function = ikev2_ip6, + .name = "ikev2-ip6", + .vector_size = sizeof (u32), + .format_trace = format_ikev2_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(ikev2_error_strings), + .error_strings = ikev2_error_strings, + + .n_next_nodes = IKEV2_IP6_N_NEXT, + .next_nodes = { + [IKEV2_NEXT_IP6_LOOKUP] = "ip6-lookup", + [IKEV2_NEXT_IP6_ERROR_DROP] = "error-drop", }, }; /* *INDENT-ON* */ @@ -3276,10 +3394,11 @@ ikev2_profile_index_by_name (u8 * name) static void -ikev2_send_ike (vlib_main_t * vm, ip4_address_t * src, ip4_address_t * dst, +ikev2_send_ike (vlib_main_t * vm, ip_address_t * src, ip_address_t * dst, u32 bi0, u32 len, u16 src_port, u16 dst_port, u32 sw_if_index) { ip4_header_t *ip40; + ip6_header_t *ip60; udp_header_t *udp0; vlib_buffer_t *b0; vlib_frame_t *f; @@ -3288,35 +3407,59 @@ ikev2_send_ike (vlib_main_t * vm, ip4_address_t * src, ip4_address_t * dst, b0 = vlib_get_buffer (vm, bi0); vlib_buffer_advance (b0, -sizeof (udp_header_t)); udp0 = vlib_buffer_get_current (b0); - vlib_buffer_advance (b0, -sizeof (ip4_header_t)); - ip40 = vlib_buffer_get_current (b0); - - - ip40->ip_version_and_header_length = 0x45; - ip40->tos = 0; - ip40->fragment_id = 0; - ip40->flags_and_fragment_offset = 0; - ip40->ttl = 0xff; - ip40->protocol = IP_PROTOCOL_UDP; - ip40->dst_address.as_u32 = dst->as_u32; - ip40->src_address.as_u32 = src->as_u32; udp0->dst_port = clib_host_to_net_u16 (dst_port); udp0->src_port = clib_host_to_net_u16 (src_port); udp0->length = clib_host_to_net_u16 (len + sizeof (udp_header_t)); udp0->checksum = 0; - b0->current_length = len + sizeof (ip4_header_t) + sizeof (udp_header_t); - ip40->length = clib_host_to_net_u16 (b0->current_length); - ip40->checksum = ip4_header_checksum (ip40); + if (ip_addr_version (dst) == AF_IP4) + { + vlib_buffer_advance (b0, -sizeof (ip4_header_t)); + ip40 = vlib_buffer_get_current (b0); + ip40->ip_version_and_header_length = 0x45; + ip40->tos = 0; + ip40->fragment_id = 0; + ip40->flags_and_fragment_offset = 0; + ip40->ttl = 0xff; + ip40->protocol = IP_PROTOCOL_UDP; + ip40->dst_address.as_u32 = ip_addr_v4 (dst).as_u32; + ip40->src_address.as_u32 = ip_addr_v4 (src).as_u32; + b0->current_length = + len + sizeof (ip4_header_t) + sizeof (udp_header_t); + ip40->length = clib_host_to_net_u16 (b0->current_length); + ip40->checksum = ip4_header_checksum (ip40); + } + else + { + vlib_buffer_advance (b0, -sizeof (ip6_header_t)); + ip60 = vlib_buffer_get_current (b0); + + b0->current_length = len + sizeof (*ip60) + sizeof (udp_header_t); + ip60->ip_version_traffic_class_and_flow_label = + clib_host_to_net_u32 (0x6 << 28); + ip60->payload_length = + clib_host_to_net_u16 (b0->current_length - sizeof (*ip60)); + ip60->protocol = IP_PROTOCOL_UDP; + ip60->hop_limit = 0xff; + clib_memcpy_fast (ip60->src_address.as_u8, ip_addr_v6 (src).as_u8, + sizeof (ip60->src_address)); + clib_memcpy_fast (ip60->dst_address.as_u8, ip_addr_v6 (dst).as_u8, + sizeof (ip60->src_address)); + } + + b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED; vnet_buffer (b0)->sw_if_index[VLIB_RX] = sw_if_index; vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + u32 next_index = (ip_addr_version (dst) == AF_IP4) ? + ip4_lookup_node.index : ip6_lookup_node.index; + /* send the request */ - f = vlib_get_frame_to_node (vm, ip4_lookup_node.index); + f = vlib_get_frame_to_node (vm, next_index); to_next = vlib_frame_vector_args (f); to_next[0] = bi0; f->n_vectors = 1; - vlib_put_frame_to_node (vm, ip4_lookup_node.index, f); + vlib_put_frame_to_node (vm, next_index, f); } @@ -3405,7 +3548,7 @@ ikev2_initiate_delete_ike_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa) { ikev2_main_t *km = &ikev2_main; - ip4_address_t *src, *dst; + ip_address_t *src, *dst; vlib_buffer_t *b0; /* Create the Initiator notification for IKE SA removal */ @@ -3591,6 +3734,15 @@ ikev2_set_profile_auth (vlib_main_t * vm, u8 * name, u8 auth_method, return 0; } +static int +ikev2_is_id_supported (u8 id_type) +{ + return (id_type == IKEV2_ID_TYPE_ID_IPV4_ADDR || + id_type == IKEV2_ID_TYPE_ID_IPV6_ADDR || + id_type == IKEV2_ID_TYPE_ID_RFC822_ADDR || + id_type == IKEV2_ID_TYPE_ID_FQDN); +} + clib_error_t * ikev2_set_profile_id (vlib_main_t * vm, u8 * name, u8 id_type, u8 * data, int is_local) @@ -3598,8 +3750,7 @@ ikev2_set_profile_id (vlib_main_t * vm, u8 * name, u8 id_type, u8 * data, ikev2_profile_t *p; clib_error_t *r; - if (id_type > IKEV2_ID_TYPE_ID_RFC822_ADDR - && id_type < IKEV2_ID_TYPE_ID_KEY_ID) + if (!ikev2_is_id_supported (id_type)) { r = clib_error_return (0, "unsupported identity type %U", format_ikev2_id_type, id_type); @@ -3630,10 +3781,27 @@ 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) +{ + if (ip_addr_version (addr) == AF_IP4) + ts->ts_type = TS_IPV4_ADDR_RANGE; + else + 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) +{ + ip_address_copy (&ts->start_addr, start); + ip_address_copy (&ts->end_addr, end); +} + clib_error_t * ikev2_set_profile_ts (vlib_main_t * vm, u8 * name, u8 protocol_id, - u16 start_port, u16 end_port, ip4_address_t start_addr, - ip4_address_t end_addr, int is_local) + u16 start_port, u16 end_port, ip_address_t start_addr, + ip_address_t end_addr, int is_local) { ikev2_profile_t *p; clib_error_t *r; @@ -3646,23 +3814,24 @@ ikev2_set_profile_ts (vlib_main_t * vm, u8 * name, u8 protocol_id, return r; } + if (ip_addr_version (&start_addr) != ip_addr_version (&end_addr)) + return clib_error_return (0, "IP address version mismatch!"); + if (is_local) { - p->loc_ts.start_addr.as_u32 = start_addr.as_u32; - p->loc_ts.end_addr.as_u32 = end_addr.as_u32; + ikev2_set_ts_addrs (&p->loc_ts, &start_addr, &end_addr); p->loc_ts.start_port = start_port; p->loc_ts.end_port = end_port; p->loc_ts.protocol_id = protocol_id; - p->loc_ts.ts_type = 7; + ikev2_set_ts_type (&p->loc_ts, &start_addr); } else { - p->rem_ts.start_addr.as_u32 = start_addr.as_u32; - p->rem_ts.end_addr.as_u32 = end_addr.as_u32; + ikev2_set_ts_addrs (&p->rem_ts, &start_addr, &end_addr); p->rem_ts.start_port = start_port; p->rem_ts.end_port = end_port; p->rem_ts.protocol_id = protocol_id; - p->rem_ts.ts_type = 7; + ikev2_set_ts_type (&p->rem_ts, &start_addr); } return 0; @@ -3671,7 +3840,7 @@ ikev2_set_profile_ts (vlib_main_t * vm, u8 * name, u8 protocol_id, clib_error_t * ikev2_set_profile_responder (vlib_main_t * vm, u8 * name, - u32 sw_if_index, ip4_address_t ip4) + u32 sw_if_index, ip_address_t addr) { ikev2_profile_t *p; clib_error_t *r; @@ -3685,7 +3854,7 @@ ikev2_set_profile_responder (vlib_main_t * vm, u8 * name, } p->responder.sw_if_index = sw_if_index; - p->responder.ip4 = ip4; + ip_address_copy (&p->responder.addr, &addr); return 0; } @@ -3835,7 +4004,6 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) { ikev2_profile_t *p; clib_error_t *r; - ip4_main_t *im = &ip4_main; ikev2_main_t *km = &ikev2_main; p = ikev2_profile_index_by_name (name); @@ -3846,7 +4014,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) return r; } - if (p->responder.sw_if_index == ~0 || p->responder.ip4.data_u32 == 0) + if (p->responder.sw_if_index == ~0 + || ip_address_is_zero (&p->responder.addr)) { r = clib_error_return (0, "responder not set for profile %v", name); return r; @@ -3858,16 +4027,29 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) vlib_buffer_t *b0; ike_header_t *ike0; u32 bi0 = 0; - ip_lookup_main_t *lm = &im->lookup_main; - u32 if_add_index0; int len = sizeof (ike_header_t); + ip4_address_t *if_ip4; + ip6_address_t *if_ip6; + ip_address_t if_ip = IP_ADDRESS_V4_ALL_0S; - /* Get own iface IP */ - if_add_index0 = - lm->if_address_pool_index_by_sw_if_index[p->responder.sw_if_index]; - ip_interface_address_t *if_add = - pool_elt_at_index (lm->if_address_pool, if_add_index0); - ip4_address_t *if_ip = ip_interface_address_get_address (lm, if_add); + if (ip_addr_version (&p->responder.addr) == AF_IP4) + { + if_ip4 = ip4_interface_first_address (&ip4_main, + p->responder.sw_if_index, 0); + if (if_ip4) + { + ip_address_set (&if_ip, if_ip4, AF_IP4); + } + } + else + { + if_ip6 = ip6_interface_first_address (&ip6_main, + p->responder.sw_if_index); + if (if_ip6) + { + ip_address_set (&if_ip, if_ip6, AF_IP6); + } + } bi0 = ikev2_get_new_ike_header_buff (vm, &b0); if (!bi0) @@ -3920,8 +4102,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) u8 *nat_detection_sha1 = ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa.ispi), clib_host_to_net_u64 (sa.rspi), - if_ip->as_u32, - clib_host_to_net_u16 (IKEV2_PORT)); + &if_ip, clib_host_to_net_u16 (IKEV2_PORT)); ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP, nat_detection_sha1); @@ -3929,7 +4110,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) nat_detection_sha1 = ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa.ispi), clib_host_to_net_u64 (sa.rspi), - p->responder.ip4.as_u32, + &p->responder.addr, clib_host_to_net_u16 (sa.dst_port)); ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_DESTINATION_IP, @@ -3964,8 +4145,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) vec_add (sa.last_sa_init_req_packet_data, ike0, len); /* add data to the SA then add it to the pool */ - sa.iaddr.as_u32 = if_ip->as_u32; - sa.raddr.as_u32 = p->responder.ip4.as_u32; + ip_address_copy (&sa.iaddr, &if_ip); + ip_address_copy (&sa.raddr, &p->responder.addr); sa.i_id.type = p->loc_id.type; sa.i_id.data = vec_dup (p->loc_id.data); sa.r_id.type = p->rem_id.type; @@ -3985,12 +4166,13 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) clib_memcpy_fast (sa0, &sa, sizeof (*sa0)); hash_set (km->sa_by_ispi, sa0->ispi, sa0 - km->sais); - ikev2_send_ike (vm, if_ip, &p->responder.ip4, bi0, len, + ikev2_send_ike (vm, &if_ip, &p->responder.addr, bi0, len, IKEV2_PORT, sa.dst_port, sa.sw_if_index); - 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); + ikev2_elog_exchange ("ispi %lx rspi %lx IKEV2_EXCHANGE_SA_INIT sent to ", + clib_host_to_net_u64 (sa0->ispi), 0, + ip_addr_v4 (&p->responder.addr).as_u32, + ip_addr_version (&p->responder.addr) == AF_IP4); } return 0; @@ -4240,12 +4422,14 @@ ikev2_init (vlib_main_t * vm) km->sw_if_indices = hash_create (0, 0); km->udp_ports = hash_create (0, sizeof (uword)); - udp_register_dst_port (vm, IKEV2_PORT, ikev2_node.index, 1); - udp_register_dst_port (vm, IKEV2_PORT_NATT, ikev2_node.index, 1); + 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"); + vlib_punt_hdl_t punt_hdl = vlib_punt_client_register ("ikev2-ip4"); vlib_punt_register (punt_hdl, ipsec_punt_reason[IPSEC_PUNT_IP4_SPI_UDP_0], - "ikev2"); + "ikev2-ip4"); ikev2_cli_reference (); km->log_level = IKEV2_LOG_ERROR; @@ -4316,13 +4500,17 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa, ip46_address_t remote_ip; if (sa->is_initiator) { - ip46_address_set_ip4 (&local_ip, &sa->iaddr); - ip46_address_set_ip4 (&remote_ip, &sa->raddr); + local_ip = to_ip46 (ip_addr_version (&sa->iaddr), + ip_addr_bytes (&sa->iaddr)); + remote_ip = to_ip46 (ip_addr_version (&sa->raddr), + ip_addr_bytes (&sa->raddr)); } else { - ip46_address_set_ip4 (&local_ip, &sa->raddr); - ip46_address_set_ip4 (&remote_ip, &sa->iaddr); + local_ip = to_ip46 (ip_addr_version (&sa->raddr), + ip_addr_bytes (&sa->raddr)); + remote_ip = to_ip46 (ip_addr_version (&sa->iaddr), + ip_addr_bytes (&sa->iaddr)); } /* *INDENT-OFF* */ @@ -4460,7 +4648,7 @@ static void ikev2_send_informational_request (ikev2_sa_t * sa) { ikev2_main_t *km = &ikev2_main; - ip4_address_t *src, *dst; + ip_address_t *src, *dst; ike_header_t *ike0; vlib_buffer_t *b0; u32 bi0 = 0; diff --git a/src/plugins/ikev2/ikev2.h b/src/plugins/ikev2/ikev2.h index 36ac85a39c5..47c301f33a1 100644 --- a/src/plugins/ikev2/ikev2.h +++ b/src/plugins/ikev2/ikev2.h @@ -369,6 +369,12 @@ typedef enum #undef _ } ikev2_id_type_t; +typedef enum +{ + TS_IPV4_ADDR_RANGE = 7, + TS_IPV6_ADDR_RANGE = 8, +} ikev2_traffic_selector_type_t; + clib_error_t *ikev2_init (vlib_main_t * vm); clib_error_t *ikev2_set_local_key (vlib_main_t * vm, u8 * file); clib_error_t *ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add); @@ -379,11 +385,11 @@ clib_error_t *ikev2_set_profile_id (vlib_main_t * vm, u8 * name, u8 id_type, u8 * data, int is_local); clib_error_t *ikev2_set_profile_ts (vlib_main_t * vm, u8 * name, u8 protocol_id, u16 start_port, - u16 end_port, ip4_address_t start_addr, - ip4_address_t end_addr, int is_local); + u16 end_port, ip_address_t start_addr, + ip_address_t end_addr, int is_local); clib_error_t *ikev2_set_profile_responder (vlib_main_t * vm, u8 * name, u32 sw_if_index, - ip4_address_t ip4); + ip_address_t addr); clib_error_t *ikev2_set_profile_ike_transforms (vlib_main_t * vm, u8 * name, ikev2_transform_encr_type_t crypto_alg, diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c index c73505b2421..33ff0853832 100644 --- a/src/plugins/ikev2/ikev2_api.c +++ b/src/plugins/ikev2/ikev2_api.c @@ -98,8 +98,8 @@ cp_ts (vl_api_ikev2_ts_t * vl_api_ts, ikev2_ts_t * ts, u8 is_local) vl_api_ts->protocol_id = ts->protocol_id; vl_api_ts->start_port = ts->start_port; vl_api_ts->end_port = ts->end_port; - ip4_address_encode (&ts->start_addr, vl_api_ts->start_addr); - ip4_address_encode (&ts->end_addr, vl_api_ts->end_addr); + ip_address_encode2 (&ts->start_addr, &vl_api_ts->start_addr); + ip_address_encode2 (&ts->end_addr, &vl_api_ts->end_addr); } static void @@ -116,7 +116,7 @@ cp_responder (vl_api_ikev2_responder_t * vl_api_responder, ikev2_responder_t * responder) { vl_api_responder->sw_if_index = responder->sw_if_index; - ip4_address_encode (&responder->ip4, vl_api_responder->ip4); + ip_address_encode2 (&responder->addr, &vl_api_responder->addr); } void @@ -208,8 +208,8 @@ send_sa (ikev2_sa_t * sa, vl_api_ikev2_sa_dump_t * mp, u32 api_sa_index) vl_api_ikev2_keys_t* k = &rsa->keys; rsa->profile_index = rsa->profile_index; rsa->sa_index = api_sa_index; - ip4_address_encode (&sa->iaddr, rsa->iaddr); - ip4_address_encode (&sa->raddr, rsa->raddr); + 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); @@ -593,9 +593,9 @@ vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp) vlib_main_t *vm = vlib_get_main (); clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); - ip4_address_t start_addr, end_addr; - ip4_address_decode (mp->ts.start_addr, &start_addr); - ip4_address_decode (mp->ts.end_addr, &end_addr); + ip_address_t start_addr, end_addr; + ip_address_decode2 (&mp->ts.start_addr, &start_addr); + ip_address_decode2 (&mp->ts.end_addr, &end_addr); error = ikev2_set_profile_ts (vm, tmp, mp->ts.protocol_id, clib_net_to_host_u16 (mp->ts.start_port), @@ -642,11 +642,11 @@ vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp) clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); - ip4_address_t ip4; - ip4_address_decode (mp->responder.ip4, &ip4); + ip_address_t ip; + ip_address_decode2 (&mp->responder.addr, &ip); u32 sw_if_index = clib_net_to_host_u32 (mp->responder.sw_if_index); - error = ikev2_set_profile_responder (vm, tmp, sw_if_index, ip4); + error = ikev2_set_profile_responder (vm, tmp, sw_if_index, ip); vec_free (tmp); if (error) rv = VNET_API_ERROR_UNSPECIFIED; diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c index 727e3473627..c948578eb23 100644 --- a/src/plugins/ikev2/ikev2_cli.c +++ b/src/plugins/ikev2/ikev2_cli.c @@ -55,8 +55,8 @@ format_ikev2_traffic_selector (u8 * s, va_list * va) s = format (s, "%u type %u protocol_id %u addr " "%U - %U port %u - %u\n", index, ts->ts_type, ts->protocol_id, - format_ip4_address, &ts->start_addr, - format_ip4_address, &ts->end_addr, + format_ip_address, &ts->start_addr, + format_ip_address, &ts->end_addr, clib_net_to_host_u16 (ts->start_port), clib_net_to_host_u16 (ts->end_port)); return s; @@ -127,8 +127,8 @@ format_ikev2_sa (u8 * s, va_list * va) u32 indent = 1; s = format (s, "iip %U ispi %lx rip %U rspi %lx", - format_ip4_address, &sa->iaddr, sa->ispi, - format_ip4_address, &sa->raddr, sa->rspi); + format_ip_address, &sa->iaddr, sa->ispi, + format_ip_address, &sa->raddr, sa->rspi); if (!details) return s; @@ -279,11 +279,9 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, u8 *data = 0; u32 tmp1, tmp2, tmp3; u64 tmp4, tmp5; - ip4_address_t ip4; - ip4_address_t end_addr; + ip_address_t ip, end_addr; u32 responder_sw_if_index = (u32) ~ 0; u32 tun_sw_if_index = (u32) ~ 0; - ip4_address_t responder_ip4; ikev2_transform_encr_type_t crypto_alg; ikev2_transform_integ_type_t integ_alg; ikev2_transform_dh_type_t dh_type; @@ -333,10 +331,10 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "set %U id local %U %U", unformat_ikev2_token, &name, unformat_ikev2_id_type, &id_type, - unformat_ip4_address, &ip4)) + unformat_ip_address, &ip)) { - data = vec_new (u8, 4); - clib_memcpy (data, ip4.as_u8, 4); + data = vec_new (u8, ip_address_size (&ip)); + clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip)); r = ikev2_set_profile_id (vm, name, (u8) id_type, data, /*local */ 1); goto done; @@ -361,10 +359,10 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "set %U id remote %U %U", unformat_ikev2_token, &name, unformat_ikev2_id_type, &id_type, - unformat_ip4_address, &ip4)) + unformat_ip_address, &ip)) { - data = vec_new (u8, 4); - clib_memcpy (data, ip4.as_u8, 4); + data = vec_new (u8, ip_address_size (&ip)); + clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip)); r = ikev2_set_profile_id (vm, name, (u8) id_type, data, /*remote */ 0); goto done; @@ -389,36 +387,32 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "set %U traffic-selector local " "ip-range %U - %U port-range %u - %u protocol %u", unformat_ikev2_token, &name, - unformat_ip4_address, &ip4, - unformat_ip4_address, &end_addr, - &tmp1, &tmp2, &tmp3)) + unformat_ip_address, &ip, + unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3)) { r = ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2, - ip4, end_addr, /*local */ 1); + ip, end_addr, /*local */ 1); goto done; } else if (unformat (line_input, "set %U traffic-selector remote " "ip-range %U - %U port-range %u - %u protocol %u", unformat_ikev2_token, &name, - unformat_ip4_address, &ip4, - unformat_ip4_address, &end_addr, - &tmp1, &tmp2, &tmp3)) + unformat_ip_address, &ip, + unformat_ip_address, &end_addr, &tmp1, &tmp2, &tmp3)) { r = ikev2_set_profile_ts (vm, name, (u8) tmp3, (u16) tmp1, (u16) tmp2, - ip4, end_addr, /*remote */ 0); + ip, end_addr, /*remote */ 0); goto done; } else if (unformat (line_input, "set %U responder %U %U", unformat_ikev2_token, &name, unformat_vnet_sw_interface, vnm, - &responder_sw_if_index, unformat_ip4_address, - &responder_ip4)) + &responder_sw_if_index, unformat_ip_address, &ip)) { r = - ikev2_set_profile_responder (vm, name, responder_sw_if_index, - responder_ip4); + ikev2_set_profile_responder (vm, name, responder_sw_if_index, ip); goto done; } else if (unformat (line_input, "set %U tunnel %U", @@ -565,7 +559,7 @@ show_ikev2_profile_command_fn (vlib_main_t * vm, if (p->loc_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR) vlib_cli_output(vm, " local id-type %U data %U", format_ikev2_id_type, p->loc_id.type, - format_ip4_address, p->loc_id.data); + format_ip_address, p->loc_id.data); else if (p->loc_id.type == IKEV2_ID_TYPE_ID_KEY_ID) vlib_cli_output(vm, " local id-type %U data 0x%U", format_ikev2_id_type, p->loc_id.type, @@ -581,7 +575,7 @@ show_ikev2_profile_command_fn (vlib_main_t * vm, if (p->rem_id.type == IKEV2_ID_TYPE_ID_IPV4_ADDR) vlib_cli_output(vm, " remote id-type %U data %U", format_ikev2_id_type, p->rem_id.type, - format_ip4_address, p->rem_id.data); + format_ip_address, p->rem_id.data); else if (p->rem_id.type == IKEV2_ID_TYPE_ID_KEY_ID) vlib_cli_output(vm, " remote id-type %U data 0x%U", format_ikev2_id_type, p->rem_id.type, @@ -592,19 +586,19 @@ show_ikev2_profile_command_fn (vlib_main_t * vm, format_ikev2_id_type, p->rem_id.type, p->rem_id.data); } - if (p->loc_ts.end_addr.as_u32) + if (!ip_address_is_zero (&p->loc_ts.start_addr)) vlib_cli_output(vm, " local traffic-selector addr %U - %U port %u - %u" " protocol %u", - format_ip4_address, &p->loc_ts.start_addr, - format_ip4_address, &p->loc_ts.end_addr, + format_ip_address, &p->loc_ts.start_addr, + format_ip_address, &p->loc_ts.end_addr, p->loc_ts.start_port, p->loc_ts.end_port, p->loc_ts.protocol_id); - if (p->rem_ts.end_addr.as_u32) + if (!ip_address_is_zero (&p->rem_ts.start_addr)) vlib_cli_output(vm, " remote traffic-selector addr %U - %U port %u - %u" " protocol %u", - format_ip4_address, &p->rem_ts.start_addr, - format_ip4_address, &p->rem_ts.end_addr, + format_ip_address, &p->rem_ts.start_addr, + format_ip_address, &p->rem_ts.end_addr, p->rem_ts.start_port, p->rem_ts.end_port, p->rem_ts.protocol_id); if (~0 != p->tun_itf) @@ -613,7 +607,7 @@ show_ikev2_profile_command_fn (vlib_main_t * vm, if (~0 != p->responder.sw_if_index) vlib_cli_output(vm, " responder %U %U", format_vnet_sw_if_index_name, vnet_get_main(), p->responder.sw_if_index, - format_ip4_address, &p->responder.ip4); + format_ip_address, &p->responder.addr); if (p->udp_encap) vlib_cli_output(vm, " udp-encap"); diff --git a/src/plugins/ikev2/ikev2_payload.c b/src/plugins/ikev2/ikev2_payload.c index b7d7098605c..c03054aa9cd 100644 --- a/src/plugins/ikev2/ikev2_payload.c +++ b/src/plugins/ikev2/ikev2_payload.c @@ -37,14 +37,23 @@ typedef CLIB_PACKED (struct { /* *INDENT-ON* */ /* *INDENT-OFF* */ +typedef CLIB_PACKED (struct { + ip4_address_t start_addr; + ip4_address_t end_addr; +}) ikev2_ip4_addr_pair_t; + +typedef CLIB_PACKED (struct { + ip6_address_t start_addr; + ip6_address_t end_addr; +}) ikev2_ip6_addr_pair_t; + typedef CLIB_PACKED (struct { u8 ts_type; u8 protocol_id; u16 selector_len; u16 start_port; u16 end_port; - ip4_address_t start_addr; - ip4_address_t end_addr; + u8 addr_pair[0]; }) ikev2_ts_payload_entry_t; /* *INDENT-OFF* */ @@ -286,12 +295,46 @@ ikev2_payload_add_auth (ikev2_payload_chain_t * c, ikev2_auth_t * auth) ikev2_payload_add_data (c, auth->data); } +static void +ikev2_payload_add_ts_entry (u8 ** data, ikev2_ts_t * ts) +{ + u8 * tmp; + ikev2_ts_payload_entry_t *entry; + int len = sizeof (*entry); + + if (ts->ts_type == TS_IPV4_ADDR_RANGE) + len += sizeof (ikev2_ip4_addr_pair_t); + else + len += sizeof (ikev2_ip6_addr_pair_t); + + vec_add2 (data[0], tmp, len); + entry = (ikev2_ts_payload_entry_t *) tmp; + entry->ts_type = ts->ts_type; + entry->protocol_id = ts->protocol_id; + entry->selector_len = clib_host_to_net_u16 (len); + entry->start_port = clib_host_to_net_u16 (ts->start_port); + entry->end_port = clib_host_to_net_u16 (ts->end_port); + + if (ts->ts_type == TS_IPV4_ADDR_RANGE) + { + ikev2_ip4_addr_pair_t *pair = (ikev2_ip4_addr_pair_t*) entry->addr_pair; + ip_address_copy_addr (&pair->start_addr, &ts->start_addr); + ip_address_copy_addr (&pair->end_addr, &ts->end_addr); + } + else + { + ikev2_ip6_addr_pair_t *pair = (ikev2_ip6_addr_pair_t*) entry->addr_pair; + ip_address_copy_addr (&pair->start_addr, &ts->start_addr); + ip_address_copy_addr (&pair->end_addr, &ts->end_addr); + } +} + void ikev2_payload_add_ts (ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type) { ike_ts_payload_header_t *tsh; ikev2_ts_t *ts2; - u8 *data = 0, *tmp; + u8 *data = 0; tsh = (ike_ts_payload_header_t *) ikev2_payload_add_hdr (c, type, @@ -300,17 +343,9 @@ ikev2_payload_add_ts (ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type) vec_foreach (ts2, ts) { - ASSERT (ts2->ts_type == 7); /*TS_IPV4_ADDR_RANGE */ - ikev2_ts_payload_entry_t *entry; - vec_add2 (data, tmp, sizeof (*entry)); - entry = (ikev2_ts_payload_entry_t *) tmp; - entry->ts_type = ts2->ts_type; - entry->protocol_id = ts2->protocol_id; - entry->selector_len = clib_host_to_net_u16 (16); - entry->start_port = clib_host_to_net_u16 (ts2->start_port); - entry->end_port = clib_host_to_net_u16 (ts2->end_port); - entry->start_addr.as_u32 = ts2->start_addr.as_u32; - entry->end_addr.as_u32 = ts2->end_addr.as_u32; + ASSERT (ts2->ts_type == TS_IPV4_ADDR_RANGE || + ts2->ts_type == TS_IPV6_ADDR_RANGE); + ikev2_payload_add_ts_entry (&data, ts2); } ikev2_payload_add_data (c, data); @@ -413,31 +448,56 @@ ikev2_parse_ts_payload (ike_payload_header_t * ikep, u32 rlen) { ike_ts_payload_header_t *tsp = (ike_ts_payload_header_t *) ikep; ikev2_ts_t *r = 0, *ts; - u8 i; + ikev2_ip4_addr_pair_t *pair4; + ikev2_ip6_addr_pair_t *pair6; + int p = 0, n_left; + ikev2_ts_payload_entry_t *pe; if (sizeof (*tsp) > rlen) return 0; - if (sizeof (*tsp) + tsp->num_ts * sizeof (ikev2_ts_payload_entry_t) > rlen) - return 0; + rlen -= sizeof (*tsp); + n_left = tsp->num_ts; - for (i = 0; i < tsp->num_ts; i++) + while (n_left && p + sizeof (*pe) < rlen) { - if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */ + pe = (ikev2_ts_payload_entry_t *) (((u8 *)tsp->ts) + p); + p += sizeof (*pe); + + if (pe->ts_type != TS_IPV4_ADDR_RANGE && + pe->ts_type != TS_IPV6_ADDR_RANGE) { ikev2_elog_uint (IKEV2_LOG_ERROR, - "unsupported TS type received (%u)", tsp->ts[i].ts_type); - continue; + "unsupported TS type received (%u)", pe->ts_type); + return 0; } vec_add2 (r, ts, 1); - ts->ts_type = tsp->ts[i].ts_type; - ts->protocol_id = tsp->ts[i].protocol_id; - ts->start_port = tsp->ts[i].start_port; - ts->end_port = tsp->ts[i].end_port; - ts->start_addr.as_u32 = tsp->ts[i].start_addr.as_u32; - ts->end_addr.as_u32 = tsp->ts[i].end_addr.as_u32; + ts->ts_type = pe->ts_type; + ts->protocol_id = pe->protocol_id; + ts->start_port = pe->start_port; + ts->end_port = pe->end_port; + + if (pe->ts_type == TS_IPV4_ADDR_RANGE) + { + pair4 = (ikev2_ip4_addr_pair_t*) pe->addr_pair; + ip_address_set (&ts->start_addr, &pair4->start_addr, AF_IP4); + ip_address_set (&ts->end_addr, &pair4->end_addr, AF_IP4); + p += sizeof (*pair4); + } + else + { + pair6 = (ikev2_ip6_addr_pair_t*) pe->addr_pair; + ip_address_set (&ts->start_addr, &pair6->start_addr, AF_IP6); + ip_address_set (&ts->end_addr, &pair6->end_addr, AF_IP6); + p += sizeof (*pair6); + } + n_left--; } + + if (n_left) + return 0; + return r; } diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h index f6f9989e4b2..68a546a0f48 100644 --- a/src/plugins/ikev2/ikev2_priv.h +++ b/src/plugins/ikev2/ikev2_priv.h @@ -81,7 +81,7 @@ do { \ } \ } while (0) \ -#define ikev2_elog_exchange(_format, _ispi, _rspi, _addr) \ +#define ikev2_elog_exchange_internal(_format, _ispi, _rspi, _addr) \ do { \ ikev2_main_t *km = &ikev2_main; \ if (PREDICT_FALSE (km->log_level >= IKEV2_LOG_DEBUG)) \ @@ -110,6 +110,17 @@ do { \ } \ } while (0) \ +#define IKE_ELOG_IP4_FMT "%d.%d.%d.%d" +#define IKE_ELOG_IP6_FMT "[v6]:%x%x:%x%x" + +#define ikev2_elog_exchange(_fmt, _ispi, _rspi, _addr, _v4) \ +do { \ + if (_v4) \ + ikev2_elog_exchange_internal (_fmt IKE_ELOG_IP4_FMT, _ispi, _rspi, _addr);\ + else \ + ikev2_elog_exchange_internal (_fmt IKE_ELOG_IP6_FMT, _ispi, _rspi, _addr);\ +} while (0) + #define ikev2_elog_uint(_level, _format, _val) \ do { \ ikev2_main_t *km = &ikev2_main; \ @@ -156,31 +167,6 @@ do { \ } \ } while (0) -#define ikev2_elog_peers(_level, _format, _ip1, _ip2) \ -do { \ - ikev2_main_t *km = &ikev2_main; \ - if (PREDICT_FALSE (km->log_level >= _level)) \ - { \ - ELOG_TYPE_DECLARE (e) = \ - { \ - .format = "ikev2: " _format, \ - .format_args = "i1i1i1i1i1i1i1i1", \ - }; \ - CLIB_PACKED(struct { \ - u8 i11; u8 i12; u8 i13; u8 i14; \ - u8 i21; u8 i22; u8 i23; u8 i24; }) *ed; \ - ed = ELOG_DATA (&vlib_global_main.elog_main, e); \ - ed->i14 = (_ip1) >> 24; \ - ed->i13 = (_ip1) >> 16; \ - ed->i12 = (_ip1) >> 8; \ - ed->i11 = (_ip1); \ - ed->i24 = (_ip2) >> 24; \ - ed->i23 = (_ip2) >> 16; \ - ed->i22 = (_ip2) >> 8; \ - ed->i21 = (_ip2); \ - } \ -} while (0) - #define ikev2_elog_error(_msg) \ _ikev2_elog(IKEV2_LOG_ERROR, "[error] " _msg) #define ikev2_elog_warning(_msg) \ @@ -258,19 +244,19 @@ typedef struct typedef struct { - u8 ts_type; + ikev2_traffic_selector_type_t ts_type; u8 protocol_id; u16 selector_len; u16 start_port; u16 end_port; - ip4_address_t start_addr; - ip4_address_t end_addr; + ip_address_t start_addr; + ip_address_t end_addr; } ikev2_ts_t; typedef struct { u32 sw_if_index; - ip4_address_t ip4; + ip_address_t addr; } ikev2_responder_t; typedef struct @@ -368,8 +354,8 @@ typedef struct ikev2_state_t state; u8 unsupported_cp; u8 initial_contact; - ip4_address_t iaddr; - ip4_address_t raddr; + ip_address_t iaddr; + ip_address_t raddr; u64 ispi; u64 rspi; u8 *i_nonce; diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c index 222f01ad123..81a222c0971 100644 --- a/src/plugins/ikev2/ikev2_test.c +++ b/src/plugins/ikev2/ikev2_test.c @@ -135,7 +135,7 @@ MACRO_FORMAT (auth_method) s = format (s, " %s", id->data); break; case IKEV2_ID_TYPE_ID_IPV4_ADDR: - s = format (s, " %U", format_ip4_address, id->data); + s = format (s, " %U", format_ip_address, id->data); break; case IKEV2_ID_TYPE_ID_KEY_ID: s = format (s, " 0x%U", format_hex_bytes, id->data, id->data_len); @@ -225,7 +225,6 @@ static void vl_api_ikev2_profile_details_t_handler { vat_main_t *vam = ikev2_test_main.vat_main; vl_api_ikev2_profile_t *p = &mp->profile; - ip4_address_t start_addr, end_addr; fformat (vam->ofp, "profile %s\n", p->name); @@ -256,21 +255,17 @@ static void vl_api_ikev2_profile_details_t_handler format_ikev2_id_type_and_data, &p->rem_id); } - ip4_address_decode (p->loc_ts.start_addr, &start_addr); - ip4_address_decode (p->loc_ts.end_addr, &end_addr); fformat (vam->ofp, " local traffic-selector addr %U - %U port %u - %u" " protocol %u\n", - format_ip4_address, &start_addr, - format_ip4_address, &end_addr, + format_ip_address, &p->loc_ts.start_addr, + format_ip_address, &p->loc_ts.end_addr, clib_net_to_host_u16 (p->loc_ts.start_port), clib_net_to_host_u16 (p->loc_ts.end_port), p->loc_ts.protocol_id); - ip4_address_decode (p->rem_ts.start_addr, &start_addr); - ip4_address_decode (p->rem_ts.end_addr, &end_addr); fformat (vam->ofp, " remote traffic-selector addr %U - %U port %u - %u" " protocol %u\n", - format_ip4_address, &start_addr, - format_ip4_address, &end_addr, + format_ip_address, &p->rem_ts.start_addr, + format_ip_address, &p->rem_ts.end_addr, clib_net_to_host_u16 (p->rem_ts.start_port), clib_net_to_host_u16 (p->rem_ts.end_port), p->rem_ts.protocol_id); u32 tun_itf = clib_net_to_host_u32 (p->tun_itf); @@ -280,7 +275,7 @@ static void vl_api_ikev2_profile_details_t_handler u32 sw_if_index = clib_net_to_host_u32 (p->responder.sw_if_index); if (~0 != sw_if_index) fformat (vam->ofp, " responder idx %d %U\n", - sw_if_index, format_ip4_address, &p->responder.ip4); + sw_if_index, format_ip_address, &p->responder.addr); if (p->udp_encap) fformat (vam->ofp, " udp-encap\n"); @@ -348,18 +343,18 @@ vl_api_ikev2_sa_details_t_handler (vl_api_ikev2_sa_details_t * mp) { vat_main_t *vam = ikev2_test_main.vat_main; vl_api_ikev2_sa_t *sa = &mp->sa; - ip4_address_t iaddr; - ip4_address_t raddr; + ip_address_t iaddr; + ip_address_t raddr; vl_api_ikev2_keys_t *k = &sa->keys; vl_api_ikev2_sa_t_endian (sa); - ip4_address_decode (sa->iaddr, &iaddr); - ip4_address_decode (sa->raddr, &raddr); + 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, " iip %U ispi %lx rip %U rspi %lx\n", format_ip4_address, - &iaddr, sa->ispi, format_ip4_address, &raddr, sa->rspi); + 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); @@ -526,18 +521,17 @@ static void { vat_main_t *vam = ikev2_test_main.vat_main; vl_api_ikev2_ts_t *ts = &mp->ts; - ip4_address_t start_addr; - ip4_address_t end_addr; + ip_address_t start_addr, end_addr; vl_api_ikev2_ts_t_endian (ts); - ip4_address_decode (ts->start_addr, &start_addr); - ip4_address_decode (ts->end_addr, &end_addr); + ip_address_decode2 (&ts->start_addr, &start_addr); + ip_address_decode2 (&ts->end_addr, &end_addr); fformat (vam->ofp, " %s protocol_id %u addr " "%U - %U port %u - %u\n", ts->is_local, ts->protocol_id, - format_ip4_address, &start_addr, - format_ip4_address, &end_addr, ts->start_port, ts->end_port); + format_ip_address, &start_addr, + format_ip_address, &end_addr, ts->start_port, ts->end_port); vam->result_ready = 1; } @@ -797,7 +791,7 @@ api_ikev2_profile_set_id (vat_main_t * vam) u8 *data = 0; u8 is_local = 0; u32 id_type = 0; - ip4_address_t ip4; + ip_address_t ip; int ret; const char *valid_chars = "a-zA-Z0-9_"; @@ -808,10 +802,10 @@ api_ikev2_profile_set_id (vat_main_t * vam) vec_add1 (name, 0); else if (unformat (i, "id_type %U", unformat_ikev2_id_type, &id_type)) ; - else if (unformat (i, "id_data %U", unformat_ip4_address, &ip4)) + else if (unformat (i, "id_data %U", unformat_ip_address, &ip)) { - data = vec_new (u8, 4); - clib_memcpy (data, ip4.as_u8, 4); + data = vec_new (u8, ip_address_size (&ip)); + clib_memcpy (data, ip_addr_bytes (&ip), ip_address_size (&ip)); } else if (unformat (i, "id_data 0x%U", unformat_hex_string, &data)) ; @@ -875,14 +869,12 @@ api_ikev2_profile_set_ts (vat_main_t * vam) u8 *name = 0; u8 is_local = 0; u32 proto = 0, start_port = 0, end_port = (u32) ~ 0; - ip4_address_t start_addr, end_addr; + ip_address_t start_addr, end_addr; + u8 start_addr_set = 0, end_addr_set = 0; const char *valid_chars = "a-zA-Z0-9_"; int ret; - start_addr.as_u32 = 0; - end_addr.as_u32 = (u32) ~ 0; - while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) { if (unformat (i, "name %U", unformat_token, valid_chars, &name)) @@ -894,10 +886,10 @@ api_ikev2_profile_set_ts (vat_main_t * vam) else if (unformat (i, "end_port %d", &end_port)) ; else - if (unformat (i, "start_addr %U", unformat_ip4_address, &start_addr)) - ; - else if (unformat (i, "end_addr %U", unformat_ip4_address, &end_addr)) - ; + if (unformat (i, "start_addr %U", unformat_ip_address, &start_addr)) + start_addr_set = 1; + else if (unformat (i, "end_addr %U", unformat_ip_address, &end_addr)) + end_addr_set = 1; else if (unformat (i, "local")) is_local = 1; else if (unformat (i, "remote")) @@ -909,6 +901,12 @@ api_ikev2_profile_set_ts (vat_main_t * vam) } } + if (!start_addr_set || !end_addr_set) + { + errmsg ("missing start or end address"); + return -99; + } + if (!vec_len (name)) { errmsg ("profile name must be specified"); @@ -927,8 +925,8 @@ api_ikev2_profile_set_ts (vat_main_t * vam) mp->ts.protocol_id = (u8) proto; mp->ts.start_port = clib_host_to_net_u16 ((u16) start_port); mp->ts.end_port = clib_host_to_net_u16 ((u16) end_port); - ip4_address_encode (&start_addr, mp->ts.start_addr); - ip4_address_encode (&end_addr, mp->ts.end_addr); + ip_address_encode2 (&start_addr, &mp->ts.start_addr); + ip_address_encode2 (&end_addr, &mp->ts.end_addr); clib_memcpy (mp->name, name, vec_len (name)); vec_free (name); @@ -1035,7 +1033,7 @@ api_ikev2_set_responder (vat_main_t * vam) int ret; u8 *name = 0; u32 sw_if_index = ~0; - ip4_address_t address; + ip_address_t address; const char *valid_chars = "a-zA-Z0-9_"; @@ -1043,7 +1041,7 @@ api_ikev2_set_responder (vat_main_t * vam) { if (unformat (i, "%U interface %d address %U", unformat_token, valid_chars, - &name, &sw_if_index, unformat_ip4_address, &address)) + &name, &sw_if_index, unformat_ip_address, &address)) vec_add1 (name, 0); else { @@ -1070,7 +1068,7 @@ api_ikev2_set_responder (vat_main_t * vam) vec_free (name); mp->responder.sw_if_index = clib_host_to_net_u32 (sw_if_index); - ip4_address_encode (&address, mp->responder.ip4); + ip_address_encode2 (&address, &mp->responder.addr); S (mp); W (ret); diff --git a/src/plugins/ikev2/ikev2_types.api b/src/plugins/ikev2/ikev2_types.api index 58297c05e9c..0f998b196c2 100644 --- a/src/plugins/ikev2/ikev2_types.api +++ b/src/plugins/ikev2/ikev2_types.api @@ -34,8 +34,8 @@ typedef ikev2_ts u8 protocol_id; u16 start_port; u16 end_port; - vl_api_ip4_address_t start_addr; - vl_api_ip4_address_t end_addr; + vl_api_address_t start_addr; + vl_api_address_t end_addr; }; typedef ikev2_auth @@ -49,7 +49,7 @@ typedef ikev2_auth typedef ikev2_responder { vl_api_interface_index_t sw_if_index; - vl_api_ip4_address_t ip4; + vl_api_address_t addr; }; typedef ikev2_ike_transforms @@ -134,8 +134,8 @@ typedef ikev2_sa u64 ispi; u64 rspi; - vl_api_ip4_address_t iaddr; - vl_api_ip4_address_t raddr; + vl_api_address_t iaddr; + vl_api_address_t raddr; vl_api_ikev2_keys_t keys; diff --git a/src/plugins/ikev2/test/test_ikev2.py b/src/plugins/ikev2/test/test_ikev2.py index 0bdc417fb2d..a47c59f578f 100644 --- a/src/plugins/ikev2/test/test_ikev2.py +++ b/src/plugins/ikev2/test/test_ikev2.py @@ -9,15 +9,20 @@ from cryptography.hazmat.primitives.ciphers import ( algorithms, modes, ) -from ipaddress import IPv4Address +from ipaddress import IPv4Address, IPv6Address, ip_address from scapy.layers.ipsec import ESP from scapy.layers.inet import IP, UDP, Ether +from scapy.layers.inet6 import IPv6 from scapy.packet import raw, Raw from scapy.utils import long_converter from framework import VppTestCase, VppTestRunner from vpp_ikev2 import Profile, IDType, AuthMethod from vpp_papi import VppEnum +try: + text_type = unicode +except NameError: + text_type = str KEY_PAD = b"Key Pad for IKEv2" SALT_SIZE = 4 @@ -156,9 +161,9 @@ class IKEv2ChildSA(object): class IKEv2SA(object): - def __init__(self, test, is_initiator=True, spi=b'\x04' * 8, - i_id=None, r_id=None, id_type='fqdn', nonce=None, - auth_data=None, local_ts=None, remote_ts=None, + def __init__(self, test, is_initiator=True, i_id=None, r_id=None, + spi=b'\x01\x02\x03\x04\x05\x06\x07\x08', id_type='fqdn', + nonce=None, auth_data=None, local_ts=None, remote_ts=None, auth_method='shared-key', priv_key=None, natt=False): self.natt = natt if natt: @@ -182,12 +187,12 @@ class IKEv2SA(object): self.id_type = id_type self.auth_method = auth_method if self.is_initiator: - self.rspi = None + self.rspi = 8 * b'\x00' self.ispi = spi self.i_nonce = nonce else: self.rspi = spi - self.ispi = None + self.ispi = 8 * b'\x00' self.r_nonce = None self.child_sas = [IKEv2ChildSA(local_ts, remote_ts)] @@ -416,18 +421,25 @@ class IKEv2SA(object): ct = ep.load[:-integ_trunc] return self.decrypt(ct) - def generate_ts(self): + def build_ts_addr(self, ts, version): + return {'starting_address_v' + version: ts['start_addr'], + 'ending_address_v' + version: ts['end_addr']} + + def generate_ts(self, is_ip4): c = self.child_sas[0] - ts1 = ikev2.IPv4TrafficSelector( - IP_protocol_ID=0, - start_port=0, - end_port=0xffff, - starting_address_v4=c.local_ts['start_addr'], - ending_address_v4=c.local_ts['end_addr']) - ts2 = ikev2.IPv4TrafficSelector( - IP_protocol_ID=0, - starting_address_v4=c.remote_ts['start_addr'], - ending_address_v4=c.remote_ts['end_addr']) + ts_data = {'IP_protocol_ID': 0, + 'start_port': 0, + 'end_port': 0xffff} + if is_ip4: + ts_data.update(self.build_ts_addr(c.local_ts, '4')) + ts1 = ikev2.IPv4TrafficSelector(**ts_data) + ts_data.update(self.build_ts_addr(c.remote_ts, '4')) + ts2 = ikev2.IPv4TrafficSelector(**ts_data) + else: + ts_data.update(self.build_ts_addr(c.local_ts, '6')) + ts1 = ikev2.IPv6TrafficSelector(**ts_data) + ts_data.update(self.build_ts_addr(c.remote_ts, '6')) + ts2 = ikev2.IPv6TrafficSelector(**ts_data) return ([ts1], [ts2]) def set_ike_props(self, crypto, crypto_key_len, integ, prf, dh): @@ -474,7 +486,7 @@ class IKEv2SA(object): return self.crypto_attr(self.esp_crypto_key_len) def compute_nat_sha1(self, ip, port): - data = self.ispi + b'\x00' * 8 + ip + (port).to_bytes(2, 'big') + data = self.ispi + self.rspi + ip + (port).to_bytes(2, 'big') digest = hashes.Hash(hashes.SHA1(), backend=default_backend()) digest.update(data) return digest.finalize() @@ -493,6 +505,8 @@ class TemplateResponder(VppTestCase): i.admin_up() i.config_ip4() i.resolve_arp() + i.config_ip6() + i.resolve_ndp() @classmethod def tearDownClass(cls): @@ -504,6 +518,8 @@ class TemplateResponder(VppTestCase): self.p.add_vpp_config() self.assertIsNotNone(self.p.query_vpp_config()) self.sa.generate_dh_data() + self.vapi.cli('ikev2 set logging level 4') + self.vapi.cli('event-lo clear') def tearDown(self): super(TemplateResponder, self).tearDown() @@ -528,16 +544,25 @@ class TemplateResponder(VppTestCase): ike_msg = self.encrypt_ike_msg(header, del_sa, 'Delete') packet = self.create_packet(self.pg0, ike_msg, self.sa.sport, self.sa.dport, - self.sa.natt) + self.sa.natt, self.ip6) self.pg0.add_stream(packet) self.pg0.enable_capture() self.pg_start() capture = self.pg0.get_capture(1) self.verify_del_sa(capture[0]) - def create_packet(self, src_if, msg, sport=500, dport=500, natt=False): + def create_packet(self, src_if, msg, sport=500, dport=500, natt=False, + use_ip6=False): + if use_ip6: + src_ip = src_if.remote_ip6 + dst_ip = src_if.local_ip6 + ip_layer = IPv6 + else: + src_ip = src_if.remote_ip4 + dst_ip = src_if.local_ip4 + ip_layer = IP res = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=src_if.remote_ip4, dst=src_if.local_ip4) / + ip_layer(src=src_ip, dst=dst_ip) / UDP(sport=sport, dport=dport)) if natt: # insert non ESP marker @@ -575,16 +600,24 @@ class TemplateResponder(VppTestCase): load=self.sa.i_nonce)) if behind_nat: - src_nat = self.sa.compute_nat_sha1(b'\x0a\x0a\x0a\x01', - self.sa.sport) - nat_detection = ikev2.IKEv2_payload_Notify( - type='NAT_DETECTION_SOURCE_IP', - load=src_nat) - self.sa.init_req_packet = self.sa.init_req_packet / nat_detection + src_address = b'\x0a\x0a\x0a\x01' + else: + src_address = bytes(self.pg0.local_ip4, 'ascii') + + src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport) + dst_nat = self.sa.compute_nat_sha1(bytes(self.pg0.remote_ip4, 'ascii'), + self.sa.sport) + nat_src_detection = ikev2.IKEv2_payload_Notify( + type='NAT_DETECTION_SOURCE_IP', load=src_nat) + nat_dst_detection = ikev2.IKEv2_payload_Notify( + type='NAT_DETECTION_DESTINATION_IP', load=dst_nat) + self.sa.init_req_packet = (self.sa.init_req_packet / + nat_src_detection / + nat_dst_detection) ike_msg = self.create_packet(self.pg0, self.sa.init_req_packet, self.sa.sport, self.sa.dport, - self.sa.natt) + self.sa.natt, self.ip6) self.pg0.add_stream(ike_msg) self.pg0.enable_capture() self.pg_start() @@ -642,7 +675,7 @@ class TemplateResponder(VppTestCase): props = (ikev2.IKEv2_payload_Proposal(proposal=1, proto='ESP', SPIsize=4, SPI=os.urandom(4), trans_nb=4, trans=trans)) - tsi, tsr = self.sa.generate_ts() + tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4) plain = (ikev2.IKEv2_payload_IDi(next_payload='IDr', IDtype=self.sa.id_type, load=self.sa.i_id) / ikev2.IKEv2_payload_IDr(next_payload='AUTH', @@ -666,7 +699,7 @@ class TemplateResponder(VppTestCase): ike_msg = self.encrypt_ike_msg(header, plain, 'IDi') packet = self.create_packet(self.pg0, ike_msg, self.sa.sport, - self.sa.dport, self.sa.natt) + self.sa.dport, self.sa.natt, self.ip6) self.pg0.add_stream(packet) self.pg0.enable_capture() self.pg_start() @@ -681,6 +714,8 @@ class TemplateResponder(VppTestCase): # ipsec register for port 4500 esp = packet[ESP] ih = self.verify_and_remove_non_esp_marker(esp) + + self.assertEqual(ih.version, 0x20) return ih def verify_sa_init(self, packet): @@ -776,10 +811,14 @@ class TemplateResponder(VppTestCase): r = self.vapi.ikev2_sa_dump() self.assertEqual(len(r), 1) sa = r[0].sa - self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, 'little')) + self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, 'big')) self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, 'big')) - self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4)) - self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4)) + if self.ip6: + self.assertEqual(sa.iaddr, IPv6Address(self.pg0.remote_ip6)) + self.assertEqual(sa.raddr, IPv6Address(self.pg0.local_ip6)) + else: + self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4)) + self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4)) self.verify_keymat(sa.keys, self.sa, 'sk_d') self.verify_keymat(sa.keys, self.sa, 'sk_ai') self.verify_keymat(sa.keys, self.sa, 'sk_ar') @@ -806,7 +845,7 @@ class TemplateResponder(VppTestCase): self.verify_keymat(csa.keys, c, 'sk_ei') self.verify_keymat(csa.keys, c, 'sk_er') - tsi, tsr = self.sa.generate_ts() + tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4) tsi = tsi[0] tsr = tsr[0] r = self.vapi.ikev2_traffic_selector_dump( @@ -838,10 +877,17 @@ class TemplateResponder(VppTestCase): self.assertTrue(api_ts.is_local) else: self.assertFalse(api_ts.is_local) - self.assertEqual(api_ts.start_addr, - IPv4Address(ts.starting_address_v4)) - self.assertEqual(api_ts.end_addr, - IPv4Address(ts.ending_address_v4)) + + if self.p.ts_is_ip4: + self.assertEqual(api_ts.start_addr, + IPv4Address(ts.starting_address_v4)) + self.assertEqual(api_ts.end_addr, + IPv4Address(ts.ending_address_v4)) + else: + self.assertEqual(api_ts.start_addr, + IPv6Address(ts.starting_address_v6)) + self.assertEqual(api_ts.end_addr, + IPv6Address(ts.ending_address_v6)) self.assertEqual(api_ts.start_port, ts.start_port) self.assertEqual(api_ts.end_port, ts.end_port) self.assertEqual(api_ts.protocol_id, ts.IP_protocol_ID) @@ -872,6 +918,7 @@ class Ikev2Params(object): is_natt = 'natt' in params and params['natt'] or False self.p = Profile(self, 'pr1') + self.ip6 = False if 'ip6' not in params else params['ip6'] if 'auth' in params and params['auth'] == 'rsa-sig': auth_method = 'rsa-sig' @@ -897,8 +944,12 @@ class Ikev2Params(object): self.p.add_local_id(id_type='fqdn', data=b'vpp.home') self.p.add_remote_id(id_type='fqdn', data=b'roadwarrior.example.com') - self.p.add_local_ts(start_addr='10.10.10.0', end_addr='10.10.10.255') - self.p.add_remote_ts(start_addr='10.0.0.0', end_addr='10.0.0.255') + loc_ts = {'start_addr': '10.10.10.0', 'end_addr': '10.10.10.255'} if\ + 'loc_ts' not in params else params['loc_ts'] + rem_ts = {'start_addr': '10.0.0.0', 'end_addr': '10.0.0.255'} if\ + 'rem_ts' not in params else params['rem_ts'] + self.p.add_local_ts(**loc_ts) + self.p.add_remote_ts(**rem_ts) self.sa = IKEv2SA(self, i_id=self.p.remote_id['data'], r_id=self.p.local_id['data'], @@ -964,14 +1015,14 @@ class TestApi(VppTestCase): def test_profile_api(self): """ test profile dump API """ - loc_ts = { + loc_ts4 = { 'proto': 8, 'start_port': 1, 'end_port': 19, 'start_addr': '3.3.3.2', 'end_addr': '3.3.3.3', } - rem_ts = { + rem_ts4 = { 'proto': 9, 'start_port': 10, 'end_port': 119, @@ -979,14 +1030,29 @@ class TestApi(VppTestCase): 'end_addr': '2.3.4.6', } + loc_ts6 = { + 'proto': 8, + 'start_port': 1, + 'end_port': 19, + 'start_addr': 'ab::1', + 'end_addr': 'ab::4', + } + rem_ts6 = { + 'proto': 9, + 'start_port': 10, + 'end_port': 119, + 'start_addr': 'cd::12', + 'end_addr': 'cd::13', + } + conf = { 'p1': { 'name': 'p1', 'loc_id': ('fqdn', b'vpp.home'), 'rem_id': ('fqdn', b'roadwarrior.example.com'), - 'loc_ts': loc_ts, - 'rem_ts': rem_ts, - 'responder': {'sw_if_index': 0, 'ip4': '5.6.7.8'}, + 'loc_ts': loc_ts4, + 'rem_ts': rem_ts4, + 'responder': {'sw_if_index': 0, 'addr': '5.6.7.8'}, 'ike_ts': { 'crypto_alg': 20, 'crypto_key_size': 32, @@ -1008,10 +1074,10 @@ class TestApi(VppTestCase): 'p2': { 'name': 'p2', 'loc_id': ('ip4-addr', b'192.168.2.1'), - 'rem_id': ('ip4-addr', b'192.168.2.2'), - 'loc_ts': loc_ts, - 'rem_ts': rem_ts, - 'responder': {'sw_if_index': 4, 'ip4': '5.6.7.99'}, + 'rem_id': ('ip6-addr', b'abcd::1'), + 'loc_ts': loc_ts6, + 'rem_ts': rem_ts6, + 'responder': {'sw_if_index': 4, 'addr': 'def::10'}, 'ike_ts': { 'crypto_alg': 12, 'crypto_key_size': 16, @@ -1042,12 +1108,14 @@ class TestApi(VppTestCase): self.assertEqual(api_ts.protocol_id, cfg_ts['proto']) self.assertEqual(api_ts.start_port, cfg_ts['start_port']) self.assertEqual(api_ts.end_port, cfg_ts['end_port']) - self.assertEqual(api_ts.start_addr, IPv4Address(cfg_ts['start_addr'])) - self.assertEqual(api_ts.end_addr, IPv4Address(cfg_ts['end_addr'])) + self.assertEqual(api_ts.start_addr, + ip_address(text_type(cfg_ts['start_addr']))) + self.assertEqual(api_ts.end_addr, + ip_address(text_type(cfg_ts['end_addr']))) def verify_responder(self, api_r, cfg_r): self.assertEqual(api_r.sw_if_index, cfg_r['sw_if_index']) - self.assertEqual(api_r.ip4, IPv4Address(cfg_r['ip4'])) + self.assertEqual(api_r.addr, ip_address(cfg_r['addr'])) def verify_transforms(self, api_ts, cfg_ts): self.assertEqual(api_ts.crypto_alg, cfg_ts['crypto_alg']) @@ -1150,9 +1218,15 @@ class Test_IKE_AES_GCM_16_256(TemplateResponder, Ikev2Params): """ def config_tc(self): self.config_params({ + 'ip6': True, + 'natt': True, 'ike-crypto': ('AES-GCM-16ICV', 32), 'ike-integ': 'NULL', - 'ike-dh': '2048MODPgr'}) + 'ike-dh': '2048MODPgr', + 'loc_ts': {'start_addr': 'ab:cd::0', + 'end_addr': 'ab:cd::10'}, + 'rem_ts': {'start_addr': '11::0', + 'end_addr': '11::100'}}) class TestMalformedMessages(TemplateResponder, Ikev2Params): @@ -1164,8 +1238,8 @@ class TestMalformedMessages(TemplateResponder, Ikev2Params): def config_tc(self): self.config_params() - def assert_counter(self, count, name): - node_name = '/err/ikev2/' + name + def assert_counter(self, count, name, version='ip4'): + node_name = '/err/ikev2-%s/' % version + name self.assertEqual(count, self.statistics.get_err_counter(node_name)) def create_ike_init_msg(self, length=None, payload=None): diff --git a/src/plugins/ikev2/test/vpp_ikev2.py b/src/plugins/ikev2/test/vpp_ikev2.py index b3339d0ea86..6ae30201450 100644 --- a/src/plugins/ikev2/test/vpp_ikev2.py +++ b/src/plugins/ikev2/test/vpp_ikev2.py @@ -1,3 +1,4 @@ +from ipaddress import IPv4Address, AddressValueError from vpp_object import VppObject from vpp_papi import VppEnum @@ -12,7 +13,8 @@ class AuthMethod: class IDType: v = {'ip4-addr': 1, - 'fqdn': 2} + 'fqdn': 2, + 'ip6-addr': 5} @staticmethod def value(key): return IDType.v[key] @@ -52,7 +54,8 @@ class Profile(VppObject): 'is_local': False} def add_local_ts(self, start_addr, end_addr, start_port=0, end_port=0xffff, - proto=0): + proto=0, is_ip4=True): + self.ts_is_ip4 = is_ip4 self.local_ts = {'is_local': True, 'protocol_id': proto, 'start_port': start_port, @@ -62,6 +65,12 @@ class Profile(VppObject): def add_remote_ts(self, start_addr, end_addr, start_port=0, end_port=0xffff, proto=0): + try: + IPv4Address(start_addr) + is_ip4 = True + except AddressValueError: + is_ip4 = False + self.ts_is_ip4 = is_ip4 self.remote_ts = {'is_local': False, 'protocol_id': proto, 'start_port': start_port, -- 2.16.6