ikev2: support responder hostname 25/31525/2
authorFilip Tehlar <ftehlar@cisco.com>
Mon, 22 Feb 2021 16:15:51 +0000 (16:15 +0000)
committerDamjan Marion <dmarion@me.com>
Mon, 15 Mar 2021 17:38:05 +0000 (17:38 +0000)
Type: feature
Ticket: VPP-1901

Change-Id: I1ad222b54363fd35679d0132d458345a9a18362c
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
src/plugins/dns/dns.c
src/plugins/dns/dns.h
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_priv.h
src/plugins/ikev2/ikev2_test.c
src/plugins/ikev2/test/test_ikev2.py
src/plugins/ikev2/test/vpp_ikev2.py

index b4830e4..f3ce4fc 100644 (file)
@@ -1159,9 +1159,8 @@ found_last_request:
 }
 
 int
-vnet_dns_response_to_reply (u8 * response,
-                           vl_api_dns_resolve_name_reply_t * rmp,
-                           u32 * min_ttlp)
+vnet_dns_response_to_reply (u8 *response, dns_resolve_name_t *rn,
+                           u32 *min_ttlp)
 {
   dns_header_t *h;
   dns_query_t *qp;
@@ -1172,7 +1171,7 @@ vnet_dns_response_to_reply (u8 * response,
   u16 flags;
   u16 rcode;
   u32 ttl;
-  int pointer_chase;
+  int pointer_chase, addr_set = 0;
 
   h = (dns_header_t *) response;
   flags = clib_net_to_host_u16 (h->flags);
@@ -1269,32 +1268,32 @@ vnet_dns_response_to_reply (u8 * response,
        {
        case DNS_TYPE_A:
          /* Collect an ip4 address. Do not pass go. Do not collect $200 */
-         memcpy (rmp->ip4_address, rr->rdata, sizeof (ip4_address_t));
-         rmp->ip4_set = 1;
+         ip_address_set (&rn->address, rr->rdata, AF_IP4);
          ttl = clib_net_to_host_u32 (rr->ttl);
+         addr_set += 1;
          if (min_ttlp && *min_ttlp > ttl)
            *min_ttlp = ttl;
          break;
        case DNS_TYPE_AAAA:
          /* Collect an ip6 address. Do not pass go. Do not collect $200 */
-         memcpy (rmp->ip6_address, rr->rdata, sizeof (ip6_address_t));
+         ip_address_set (&rn->address, rr->rdata, AF_IP6);
          ttl = clib_net_to_host_u32 (rr->ttl);
          if (min_ttlp && *min_ttlp > ttl)
            *min_ttlp = ttl;
-         rmp->ip6_set = 1;
+         addr_set += 1;
          break;
 
        default:
          break;
        }
       /* Might as well stop ASAP */
-      if (rmp->ip4_set && rmp->ip6_set)
+      if (addr_set > 1)
        break;
       pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
       curpos = pos;
     }
 
-  if ((rmp->ip4_set + rmp->ip6_set) == 0)
+  if (addr_set == 0)
     return VNET_API_ERROR_NAME_SERVER_NO_ADDRESSES;
   return 0;
 }
@@ -1435,15 +1434,35 @@ vnet_dns_response_to_name (u8 * response,
   return 0;
 }
 
+__clib_export int
+dns_resolve_name (u8 *name, dns_cache_entry_t **ep, dns_pending_request_t *t0,
+                 dns_resolve_name_t *rn)
+{
+  dns_main_t *dm = &dns_main;
+  vlib_main_t *vm = vlib_get_main ();
+
+  int rv = vnet_dns_resolve_name (vm, dm, name, t0, ep);
+
+  /* Error, e.g. not enabled? Tell the user */
+  if (rv < 0)
+    return rv;
+
+  /* Resolution pending? Don't reply... */
+  if (ep[0] == 0)
+    return 0;
+
+  return vnet_dns_response_to_reply (ep[0]->dns_response, rn, 0 /* ttl-ptr */);
+}
+
 static void
 vl_api_dns_resolve_name_t_handler (vl_api_dns_resolve_name_t * mp)
 {
-  vlib_main_t *vm = vlib_get_main ();
   dns_main_t *dm = &dns_main;
   vl_api_dns_resolve_name_reply_t *rmp;
-  dns_cache_entry_t *ep;
+  dns_cache_entry_t *ep = 0;
   dns_pending_request_t _t0, *t0 = &_t0;
   int rv;
+  dns_resolve_name_t rn;
 
   /* Sanitize the name slightly */
   mp->name[ARRAY_LEN (mp->name) - 1] = 0;
@@ -1452,7 +1471,7 @@ vl_api_dns_resolve_name_t_handler (vl_api_dns_resolve_name_t * mp)
   t0->client_index = mp->client_index;
   t0->client_context = mp->context;
 
-  rv = vnet_dns_resolve_name (vm, dm, mp->name, t0, &ep);
+  rv = dns_resolve_name (mp->name, &ep, t0, &rn);
 
   /* Error, e.g. not enabled? Tell the user */
   if (rv < 0)
@@ -1466,11 +1485,13 @@ vl_api_dns_resolve_name_t_handler (vl_api_dns_resolve_name_t * mp)
     return;
 
   /* *INDENT-OFF* */
-  REPLY_MACRO2(VL_API_DNS_RESOLVE_NAME_REPLY,
-  ({
-    rv = vnet_dns_response_to_reply (ep->dns_response, rmp, 0 /* ttl-ptr */);
-    rmp->retval = clib_host_to_net_u32 (rv);
-  }));
+  REPLY_MACRO2 (VL_API_DNS_RESOLVE_NAME_REPLY, ({
+                 ip_address_copy_addr (rmp->ip4_address, &rn.address);
+                 if (ip_addr_version (&rn.address) == AF_IP4)
+                   rmp->ip4_set = 1;
+                 else
+                   rmp->ip6_set = 1;
+               }));
   /* *INDENT-ON* */
 }
 
@@ -2568,6 +2589,7 @@ static clib_error_t *
 test_dns_fmt_command_fn (vlib_main_t * vm,
                         unformat_input_t * input, vlib_cli_command_t * cmd)
 {
+  dns_resolve_name_t _rn, *rn = &_rn;
   u8 *dns_reply_data = 0;
   int verbose = 0;
   int rv;
@@ -2593,7 +2615,7 @@ test_dns_fmt_command_fn (vlib_main_t * vm,
 
   clib_memset (rmp, 0, sizeof (*rmp));
 
-  rv = vnet_dns_response_to_reply (dns_reply_data, rmp, 0 /* ttl-ptr */ );
+  rv = vnet_dns_response_to_reply (dns_reply_data, rn, 0 /* ttl-ptr */);
 
   switch (rv)
     {
@@ -2606,12 +2628,7 @@ test_dns_fmt_command_fn (vlib_main_t * vm,
       break;
 
     case 0:
-      if (rmp->ip4_set)
-       vlib_cli_output (vm, "ip4 address: %U", format_ip4_address,
-                        (ip4_address_t *) rmp->ip4_address);
-      if (rmp->ip6_set)
-       vlib_cli_output (vm, "ip6 address: %U", format_ip6_address,
-                        (ip6_address_t *) rmp->ip6_address);
+      vlib_cli_output (vm, "ip address: %U", format_ip_address, &rn->address);
       break;
     }
 
@@ -2746,7 +2763,8 @@ vnet_send_dns4_reply (vlib_main_t * vm, dns_main_t * dm,
   u32 *to_next;
   u8 *dns_response;
   u8 *reply;
-  vl_api_dns_resolve_name_reply_t _rnr, *rnr = &_rnr;
+  /* vl_api_dns_resolve_name_reply_t _rnr, *rnr = &_rnr; */
+  dns_resolve_name_t _rn, *rn = &_rn;
   vl_api_dns_resolve_ip_reply_t _rir, *rir = &_rir;
   u32 ttl = 64, tmp;
   u32 qp_offset;
@@ -2761,13 +2779,13 @@ vnet_send_dns4_reply (vlib_main_t * vm, dns_main_t * dm,
   if (pr->request_type == DNS_PEER_PENDING_NAME_TO_IP)
     {
       /* Quick and dirty way to dig up the A-record address. $$ FIXME */
-      clib_memset (rnr, 0, sizeof (*rnr));
-      if (vnet_dns_response_to_reply (ep->dns_response, rnr, &ttl))
+      clib_memset (rn, 0, sizeof (*rn));
+      if (vnet_dns_response_to_reply (ep->dns_response, rn, &ttl))
        {
          /* clib_warning ("response_to_reply failed..."); */
          is_fail = 1;
        }
-      if (rnr->ip4_set == 0)
+      else if (ip_addr_version (&rn->address) != AF_IP4)
        {
          /* clib_warning ("No A-record..."); */
          is_fail = 1;
@@ -2927,7 +2945,7 @@ found_src_address:
          rr->class = clib_host_to_net_u16 (1 /* internet */ );
          rr->ttl = clib_host_to_net_u32 (ttl);
          rr->rdlength = clib_host_to_net_u16 (sizeof (ip4_address_t));
-         clib_memcpy (rr->rdata, rnr->ip4_address, sizeof (ip4_address_t));
+         ip_address_copy_addr (rr->rdata, &rn->address);
        }
       else
        {
index e6ca440..74b0778 100644 (file)
@@ -39,6 +39,11 @@ typedef struct
   u8 *name;
 } dns_pending_request_t;
 
+typedef struct
+{
+  ip_address_t address;
+} dns_resolve_name_t;
+
 typedef enum
 {
   DNS_API_PENDING_NAME_TO_IP = 1,
@@ -223,6 +228,9 @@ dns_cache_unlock (dns_main_t * dm)
     }
 }
 
+extern int dns_resolve_name (u8 *name, dns_cache_entry_t **ep,
+                            dns_pending_request_t *t0,
+                            dns_resolve_name_t *rn);
 #endif /* included_dns_h */
 
 /*
index 32e1a91..ff9ed72 100644 (file)
@@ -331,6 +331,17 @@ autoreply define ikev2_set_responder
   option status="in_progress";
 };
 
+autoreply define ikev2_set_responder_hostname
+{
+  u32 client_index;
+  u32 context;
+
+  string name[64];
+  string hostname[64];
+  vl_api_interface_index_t sw_if_index;
+  option status="in_progress";
+};
+
 /** \brief IKEv2: Set IKEv2 IKE transforms in SA_INIT proposal (RFC 7296)
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
index aeed73e..fa65376 100644 (file)
@@ -26,6 +26,7 @@
 #include <vnet/ipip/ipip.h>
 #include <plugins/ikev2/ikev2.h>
 #include <plugins/ikev2/ikev2_priv.h>
+#include <plugins/dns/dns.h>
 #include <openssl/sha.h>
 #include <vnet/ipsec/ipsec_punt.h>
 #include <plugins/ikev2/ikev2.api_enum.h>
@@ -3856,6 +3857,12 @@ ikev2_cleanup_profile_sessions (ikev2_main_t * km, ikev2_profile_t * p)
   vec_free (del_sai);
 }
 
+static void
+ikev2_profile_responder_free (ikev2_responder_t *r)
+{
+  vec_free (r->hostname);
+}
+
 static void
 ikev2_profile_free (ikev2_profile_t * p)
 {
@@ -3865,6 +3872,8 @@ ikev2_profile_free (ikev2_profile_t * p)
   if (p->auth.key)
     EVP_PKEY_free (p->auth.key);
 
+  ikev2_profile_responder_free (&p->responder);
+
   vec_free (p->loc_id.data);
   vec_free (p->rem_id.data);
 }
@@ -4042,6 +4051,27 @@ ikev2_set_profile_ts (vlib_main_t * vm, u8 * name, u8 protocol_id,
   return 0;
 }
 
+clib_error_t *
+ikev2_set_profile_responder_hostname (vlib_main_t *vm, u8 *name, u8 *hostname,
+                                     u32 sw_if_index)
+{
+  ikev2_profile_t *p;
+  clib_error_t *r;
+
+  p = ikev2_profile_index_by_name (name);
+
+  if (!p)
+    {
+      r = clib_error_return (0, "unknown profile %v", name);
+      return r;
+    }
+
+  p->responder.is_resolved = 0;
+  p->responder.sw_if_index = sw_if_index;
+  p->responder.hostname = vec_dup (hostname);
+
+  return 0;
+}
 
 clib_error_t *
 ikev2_set_profile_responder (vlib_main_t * vm, u8 * name,
@@ -4058,6 +4088,7 @@ ikev2_set_profile_responder (vlib_main_t * vm, u8 * name,
       return r;
     }
 
+  p->responder.is_resolved = 1;
   p->responder.sw_if_index = sw_if_index;
   ip_address_copy (&p->responder.addr, &addr);
 
@@ -4226,6 +4257,31 @@ ikev2_get_if_address (u32 sw_if_index, ip_address_family_t af,
   return 0;
 }
 
+static clib_error_t *
+ikev2_resolve_responder_hostname (vlib_main_t *vm, ikev2_responder_t *r)
+{
+  ikev2_main_t *km = &ikev2_main;
+  dns_cache_entry_t *ep = 0;
+  dns_pending_request_t _t0, *t0 = &_t0;
+  dns_resolve_name_t _rn, *rn = &_rn;
+  int rv;
+
+  if (!km->dns_resolve_name)
+    return clib_error_return (0, "cannot load symbols from dns plugin");
+
+  t0->request_type = DNS_API_PENDING_NAME_TO_IP;
+  rv = km->dns_resolve_name (r->hostname, &ep, t0, rn);
+  if (rv < 0)
+    return clib_error_return (0, "dns lookup failure");
+
+  if (ep == 0)
+    return 0;
+
+  ip_address_copy (&r->addr, &rn->address);
+  r->is_resolved = 1;
+  return 0;
+}
+
 clib_error_t *
 ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
 {
@@ -4236,7 +4292,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
   ike_header_t *ike0;
   u32 bi0 = 0;
   int len = sizeof (ike_header_t), valid_ip = 0;
-  ip_address_t if_ip = ip_address_initializer;
+  ip_address_t src_if_ip = ip_address_initializer;
 
   p = ikev2_profile_index_by_name (name);
 
@@ -4246,15 +4302,26 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
       return r;
     }
 
-  if (p->responder.sw_if_index == ~0
-      || ip_address_is_zero (&p->responder.addr))
+  if (p->responder.sw_if_index == ~0 ||
+      (ip_address_is_zero (&p->responder.addr) &&
+       vec_len (p->responder.hostname) == 0))
     {
       r = clib_error_return (0, "responder not set for profile %v", name);
       return r;
     }
 
-  if (ikev2_get_if_address (p->responder.sw_if_index,
-                           ip_addr_version (&p->responder.addr), &if_ip))
+  if (!p->responder.is_resolved)
+    {
+      /* try to resolve using dns plugin
+       * success does not mean we have resolved the name */
+      r = ikev2_resolve_responder_hostname (vm, &p->responder);
+      if (r)
+       return r;
+    }
+
+  if (p->responder.is_resolved &&
+      ikev2_get_if_address (p->responder.sw_if_index,
+                           ip_addr_version (&p->responder.addr), &src_if_ip))
     {
       valid_ip = 1;
     }
@@ -4308,10 +4375,9 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
              sizeof (sa.childs[0].i_proposals[0].spi));
 
   /* Add NAT detection notification messages (mandatory) */
-  u8 *nat_detection_sha1 =
-    ikev2_compute_nat_sha1 (clib_host_to_net_u64 (sa.ispi),
-                           clib_host_to_net_u64 (sa.rspi),
-                           &if_ip, clib_host_to_net_u16 (IKEV2_PORT));
+  u8 *nat_detection_sha1 = ikev2_compute_nat_sha1 (
+    clib_host_to_net_u64 (sa.ispi), clib_host_to_net_u64 (sa.rspi), &src_if_ip,
+    clib_host_to_net_u16 (IKEV2_PORT));
 
   ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP,
                            nat_detection_sha1);
@@ -4365,7 +4431,7 @@ 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 */
-  ip_address_copy (&sa.iaddr, &if_ip);
+  ip_address_copy (&sa.iaddr, &src_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);
@@ -4388,8 +4454,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
 
   if (valid_ip)
     {
-      ikev2_send_ike (vm, &if_ip, &p->responder.addr, bi0, len,
-                     IKEV2_PORT, sa.dst_port, sa.sw_if_index);
+      ikev2_send_ike (vm, &src_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 ",
@@ -4397,14 +4463,6 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
         ip_addr_v4 (&p->responder.addr).as_u32,
         ip_addr_version (&p->responder.addr) == AF_IP4);
     }
-  else
-    {
-      r =
-       clib_error_return (0, "interface  %U does not have any IP address!",
-                          format_vnet_sw_if_index_name, vnet_get_main (),
-                          p->responder.sw_if_index);
-      return r;
-    }
 
   return 0;
 }
@@ -4732,15 +4790,19 @@ ikev2_init (vlib_main_t * vm)
                      "ikev2-ip4-natt");
   ikev2_cli_reference ();
 
+  km->dns_resolve_name =
+    vlib_get_plugin_symbol ("dns_plugin.so", "dns_resolve_name");
+  if (!km->dns_resolve_name)
+    ikev2_log_error ("cannot load symbols from dns plugin");
+
   km->log_level = IKEV2_LOG_ERROR;
   km->log_class = vlib_log_register_class ("ikev2", 0);
   return 0;
 }
 
 /* *INDENT-OFF* */
-VLIB_INIT_FUNCTION (ikev2_init) =
-{
-  .runs_after = VLIB_INITS("ipsec_init", "ipsec_punt_init"),
+VLIB_INIT_FUNCTION (ikev2_init) = {
+  .runs_after = VLIB_INITS ("ipsec_init", "ipsec_punt_init", "dns_init"),
 };
 /* *INDENT-ON* */
 
@@ -4928,15 +4990,44 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
 }
 
 static void
-ikev2_process_pending_sa_init_one (ikev2_main_t * km, ikev2_sa_t * sa)
+ikev2_process_pending_sa_init_one (vlib_main_t *vm, ikev2_main_t *km,
+                                  ikev2_sa_t *sa)
 {
   ikev2_profile_t *p;
   u32 bi0;
   u8 *nat_sha, *np;
+  p = pool_elt_at_index (km->profiles, sa->profile_index);
+
+  if (!p->responder.is_resolved)
+    {
+      clib_error_t *r = ikev2_resolve_responder_hostname (vm, &p->responder);
+      if (r)
+       {
+         clib_error_free (r);
+         return;
+       }
+
+      if (!p->responder.is_resolved)
+       return;
+
+      ip_address_copy (&sa->raddr, &p->responder.addr);
+
+      /* update nat detection destination hash */
+      np = ikev2_find_ike_notify_payload (
+       (ike_header_t *) sa->last_sa_init_req_packet_data,
+       IKEV2_NOTIFY_MSG_NAT_DETECTION_DESTINATION_IP);
+      if (np)
+       {
+         nat_sha = ikev2_compute_nat_sha1 (
+           clib_host_to_net_u64 (sa->ispi), clib_host_to_net_u64 (sa->rspi),
+           &sa->raddr, clib_host_to_net_u16 (sa->dst_port));
+         clib_memcpy_fast (np, nat_sha, vec_len (nat_sha));
+         vec_free (nat_sha);
+       }
+    }
 
   if (ip_address_is_zero (&sa->iaddr))
     {
-      p = pool_elt_at_index (km->profiles, sa->profile_index);
       if (!ikev2_get_if_address (p->responder.sw_if_index,
                                 ip_addr_version (&p->responder.addr),
                                 &sa->iaddr))
@@ -4973,7 +5064,7 @@ ikev2_process_pending_sa_init_one (ikev2_main_t * km, ikev2_sa_t * sa)
 }
 
 static void
-ikev2_process_pending_sa_init (ikev2_main_t * km)
+ikev2_process_pending_sa_init (vlib_main_t *vm, ikev2_main_t *km)
 {
   u32 sai;
   u64 ispi;
@@ -4986,7 +5077,7 @@ ikev2_process_pending_sa_init (ikev2_main_t * km)
     if (sa->init_response_received)
       continue;
 
-    ikev2_process_pending_sa_init_one (km, sa);
+    ikev2_process_pending_sa_init_one (vm, km, sa);
   }));
   /* *INDENT-ON* */
 }
@@ -5153,7 +5244,7 @@ ikev2_mngr_process_fn (vlib_main_t * vm, vlib_node_runtime_t * rt,
        }
       /* *INDENT-ON* */
 
-      ikev2_process_pending_sa_init (km);
+      ikev2_process_pending_sa_init (vm, km);
     }
   return 0;
 }
index 893d954..308ffe5 100644 (file)
@@ -395,6 +395,9 @@ clib_error_t *ikev2_set_profile_ts (vlib_main_t * vm, u8 * name,
 clib_error_t *ikev2_set_profile_responder (vlib_main_t * vm, u8 * name,
                                           u32 sw_if_index,
                                           ip_address_t addr);
+clib_error_t *ikev2_set_profile_responder_hostname (vlib_main_t *vm, u8 *name,
+                                                   u8 *hostname,
+                                                   u32 sw_if_index);
 clib_error_t *ikev2_set_profile_ike_transforms (vlib_main_t * vm, u8 * name,
                                                ikev2_transform_encr_type_t
                                                crypto_alg,
index 9dab692..d104e54 100644 (file)
@@ -685,6 +685,38 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
   REPLY_MACRO (VL_API_IKEV2_SET_LOCAL_KEY_REPLY);
 }
 
+static void
+vl_api_ikev2_set_responder_hostname_t_handler (
+  vl_api_ikev2_set_responder_hostname_t *mp)
+{
+  vl_api_ikev2_set_responder_hostname_reply_t *rmp;
+  int rv = 0;
+
+#if WITH_LIBSSL > 0
+  vlib_main_t *vm = vlib_get_main ();
+  clib_error_t *error;
+
+  u8 *tmp = format (0, "%s", mp->name);
+  u8 *hn = format (0, "%s", mp->hostname);
+  u32 sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
+
+  error = ikev2_set_profile_responder_hostname (vm, tmp, hn, sw_if_index);
+  vec_free (tmp);
+  vec_free (hn);
+
+  if (error)
+    {
+      ikev2_log_error ("%U", format_clib_error, error);
+      clib_error_free (error);
+      rv = VNET_API_ERROR_UNSPECIFIED;
+    }
+#else
+  rv = VNET_API_ERROR_UNIMPLEMENTED;
+#endif
+
+  REPLY_MACRO (VL_API_IKEV2_SET_RESPONDER_HOSTNAME_REPLY);
+}
+
 static void
 vl_api_ikev2_set_responder_t_handler (vl_api_ikev2_set_responder_t * mp)
 {
index 7778166..3523ce0 100644 (file)
@@ -444,6 +444,15 @@ ikev2_profile_add_del_command_fn (vlib_main_t * vm,
            ikev2_set_profile_responder (vm, name, responder_sw_if_index, ip);
          goto done;
        }
+      else if (unformat (line_input, "set %U responder %U %v",
+                        unformat_ikev2_token, &name,
+                        unformat_vnet_sw_interface, vnm,
+                        &responder_sw_if_index, &data))
+       {
+         r = ikev2_set_profile_responder_hostname (vm, name, data,
+                                                   responder_sw_if_index);
+         goto done;
+       }
       else if (unformat (line_input, "set %U tunnel %U",
                         unformat_ikev2_token, &name,
                         unformat_vnet_sw_interface, vnm, &tun_sw_if_index))
@@ -615,9 +624,10 @@ show_ikev2_profile_command_fn (vlib_main_t * vm,
       vlib_cli_output(vm, "  protected tunnel %U",
                       format_vnet_sw_if_index_name, vnet_get_main(), p->tun_itf);
     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_ip_address, &p->responder.addr);
+      vlib_cli_output (vm, "  responder %U %U %v",
+                      format_vnet_sw_if_index_name, vnet_get_main (),
+                      p->responder.sw_if_index, format_ip_address,
+                      &p->responder.addr, p->responder.hostname);
     if (p->udp_encap)
       vlib_cli_output(vm, "  udp-encap");
 
index ea630b8..4c56b98 100644 (file)
@@ -257,6 +257,8 @@ typedef struct
 {
   u32 sw_if_index;
   ip_address_t addr;
+  u8 *hostname;
+  u8 is_resolved;
 } ikev2_responder_t;
 
 typedef struct
@@ -526,6 +528,9 @@ typedef struct
 
   /* dead peer detection */
   u8 dpd_disabled;
+
+  /* pointer to name resolver function in dns plugin */
+  int (*dns_resolve_name) ();
 } ikev2_main_t;
 
 extern ikev2_main_t ikev2_main;
index 98b3fa0..b63778e 100644 (file)
@@ -1060,6 +1060,53 @@ api_ikev2_set_tunnel_interface (vat_main_t * vam)
   return (0);
 }
 
+static int
+api_ikev2_set_responder_hostname (vat_main_t *vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_ikev2_set_responder_hostname_t *mp;
+  int ret;
+  u8 *name = 0, *hn = 0;
+
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "%U hostname %v", unformat_token, valid_chars, &name,
+                   &hn))
+       {
+         vec_add1 (name, 0);
+         vec_add1 (hn, 0);
+       }
+      else
+       {
+         errmsg ("parse error '%U'", format_unformat_error, i);
+         return -99;
+       }
+    }
+
+  if (!vec_len (name))
+    {
+      errmsg ("profile name must be specified");
+      return -99;
+    }
+
+  if (vec_len (name) > 64)
+    {
+      errmsg ("profile name too long");
+      return -99;
+    }
+
+  M (IKEV2_SET_RESPONDER_HOSTNAME, mp);
+
+  clib_memcpy (mp->name, name, vec_len (name));
+  clib_memcpy (mp->hostname, hn, vec_len (hn));
+  vec_free (name);
+  vec_free (hn);
+
+  S (mp);
+  W (ret);
+  return ret;
+}
+
 static int
 api_ikev2_set_responder (vat_main_t * vam)
 {
index dea9a6a..558e8a0 100644 (file)
@@ -1422,6 +1422,20 @@ class Ikev2Params(object):
         if udp_encap:
             self.p.set_udp_encap(True)
 
+        if 'responder_hostname' in params:
+            hn = params['responder_hostname']
+            self.p.add_responder_hostname(hn)
+
+            # configure static dns record
+            self.vapi.dns_name_server_add_del(
+                is_ip6=0, is_add=1,
+                server_address=IPv4Address(u'8.8.8.8').packed)
+            self.vapi.dns_enable_disable(enable=1)
+
+            cmd = "dns cache add {} {}".format(hn['hostname'],
+                                               self.pg0.remote_ip4)
+            self.vapi.cli(cmd)
+
         self.sa = IKEv2SA(self, i_id=idi['data'], r_id=idr['data'],
                           is_initiator=is_init,
                           id_type=self.p.local_id['id_type'],
@@ -1683,8 +1697,6 @@ class TestInitiatorPsk(TemplateInitiator, Ikev2Params):
         self.config_params({
             'is_initiator': False,  # seen from test case perspective
                                     # thus vpp is initiator
-            'responder': {'sw_if_index': self.pg0.sw_if_index,
-                           'addr': self.pg0.remote_ip4},
             'ike-crypto': ('AES-GCM-16ICV', 32),
             'ike-integ': 'NULL',
             'ike-dh': '3072MODPgr',
@@ -1697,7 +1709,9 @@ class TestInitiatorPsk(TemplateInitiator, Ikev2Params):
                 'crypto_alg': 12,  # "aes-cbc"
                 'crypto_key_size': 256,
                 # "hmac-sha2-256-128"
-                'integ_alg': 12}})
+                'integ_alg': 12},
+            'responder_hostname': {'hostname': 'vpp.responder.org',
+                                   'sw_if_index': self.pg0.sw_if_index}})
 
 
 @tag_fixme_vpp_workers
index dd1c3fc..de20812 100644 (file)
@@ -82,6 +82,9 @@ class Profile(VppObject):
                           'start_addr': start_addr,
                           'end_addr': end_addr}
 
+    def add_responder_hostname(self, hn):
+        self.responder_hostname = hn
+
     def add_responder(self, responder):
         self.responder = responder
 
@@ -138,6 +141,11 @@ class Profile(VppObject):
             self.vapi.ikev2_set_responder(name=self.profile_name,
                                           responder=self.responder)
 
+        if hasattr(self, 'responder_hostname'):
+            print(self.responder_hostname)
+            self.vapi.ikev2_set_responder_hostname(name=self.profile_name,
+                                                   **self.responder_hostname)
+
         if hasattr(self, 'ike_transforms'):
             self.vapi.ikev2_set_ike_transforms(name=self.profile_name,
                                                tr=self.ike_transforms)