ikev2: support ipv6 traffic selectors & overlay 33/28733/11
authorFilip Tehlar <ftehlar@cisco.com>
Tue, 8 Sep 2020 06:08:05 +0000 (06:08 +0000)
committerBeno�t Ganne <bganne@cisco.com>
Mon, 5 Oct 2020 13:28:09 +0000 (13:28 +0000)
Ticket: VPP-1917
Type: feature

Change-Id: Ie9f22e7336aa7807b1967c48de9843df10fb575c
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/ikev2/ikev2.api
src/plugins/ikev2/ikev2.c
src/plugins/ikev2/ikev2.h
src/plugins/ikev2/ikev2_api.c
src/plugins/ikev2/ikev2_cli.c
src/plugins/ikev2/ikev2_payload.c
src/plugins/ikev2/ikev2_priv.h
src/plugins/ikev2/ikev2_test.c
src/plugins/ikev2/ikev2_types.api
src/plugins/ikev2/test/test_ikev2.py
src/plugins/ikev2/test/vpp_ikev2.py

index 1e1dbf9..a7aeff1 100644 (file)
@@ -264,7 +264,7 @@ autoreply define ikev2_profile_set_ts
 
   string name[64];
   vl_api_ikev2_ts_t ts;
-  option vat_help = "name <profile_name> protocol <proto> start_port <port> end_port <port> start_addr <ip4> end_addr <ip4> (local|remote)";
+  option vat_help = "name <profile_name> protocol <proto> start_port <port> end_port <port> start_addr <ip> end_addr <ip> (local|remote)";
   option status="in_progress";
 };
 
index bc37b7e..a266853 100644 (file)
@@ -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;
index 36ac85a..47c301f 100644 (file)
@@ -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,
index c73505b..33ff085 100644 (file)
@@ -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;
index 727e347..c948578 100644 (file)
@@ -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");
 
index b7d7098..c03054a 100644 (file)
@@ -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;
 }
 
index f6f9989..68a546a 100644 (file)
@@ -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;
index 222f01a..81a222c 100644 (file)
@@ -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);
index 58297c0..0f998b1 100644 (file)
@@ -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;
 
index 0bdc417..a47c59f 100644 (file)
@@ -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):
index b3339d0..6ae3020 100644 (file)
@@ -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,