aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2021-02-22 16:15:51 +0000
committerDamjan Marion <dmarion@me.com>2021-03-15 17:38:05 +0000
commitaf2cc6425e7615cb90359254ae8fd429e4fea198 (patch)
tree2968103d6c0ccbf1c55883d5d56e9a93720652e5
parent418abe2a259bc8c04c3b8839099204d56ae504ba (diff)
ikev2: support responder hostname
Type: feature Ticket: VPP-1901 Change-Id: I1ad222b54363fd35679d0132d458345a9a18362c Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
-rw-r--r--src/plugins/dns/dns.c78
-rw-r--r--src/plugins/dns/dns.h8
-rw-r--r--src/plugins/ikev2/ikev2.api11
-rw-r--r--src/plugins/ikev2/ikev2.c147
-rw-r--r--src/plugins/ikev2/ikev2.h3
-rw-r--r--src/plugins/ikev2/ikev2_api.c32
-rw-r--r--src/plugins/ikev2/ikev2_cli.c16
-rw-r--r--src/plugins/ikev2/ikev2_priv.h5
-rw-r--r--src/plugins/ikev2/ikev2_test.c47
-rw-r--r--src/plugins/ikev2/test/test_ikev2.py20
-rw-r--r--src/plugins/ikev2/test/vpp_ikev2.py8
11 files changed, 311 insertions, 64 deletions
diff --git a/src/plugins/dns/dns.c b/src/plugins/dns/dns.c
index b4830e422c7..f3ce4fc55c9 100644
--- a/src/plugins/dns/dns.c
+++ b/src/plugins/dns/dns.c
@@ -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
{
diff --git a/src/plugins/dns/dns.h b/src/plugins/dns/dns.h
index e6ca440b48a..74b0778353f 100644
--- a/src/plugins/dns/dns.h
+++ b/src/plugins/dns/dns.h
@@ -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 */
/*
diff --git a/src/plugins/ikev2/ikev2.api b/src/plugins/ikev2/ikev2.api
index 32e1a91d1e8..ff9ed72e888 100644
--- a/src/plugins/ikev2/ikev2.api
+++ b/src/plugins/ikev2/ikev2.api
@@ -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
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index aeed73ecdc3..fa653760b1d 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -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>
@@ -3857,6 +3858,12 @@ ikev2_cleanup_profile_sessions (ikev2_main_t * km, ikev2_profile_t * p)
}
static void
+ikev2_profile_responder_free (ikev2_responder_t *r)
+{
+ vec_free (r->hostname);
+}
+
+static void
ikev2_profile_free (ikev2_profile_t * p)
{
vec_free (p->name);
@@ -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;
}
diff --git a/src/plugins/ikev2/ikev2.h b/src/plugins/ikev2/ikev2.h
index 893d9544aa8..308ffe52ba4 100644
--- a/src/plugins/ikev2/ikev2.h
+++ b/src/plugins/ikev2/ikev2.h
@@ -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,
diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c
index 9dab6928fbc..d104e54579a 100644
--- a/src/plugins/ikev2/ikev2_api.c
+++ b/src/plugins/ikev2/ikev2_api.c
@@ -686,6 +686,38 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp)
}
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)
{
vl_api_ikev2_set_responder_reply_t *rmp;
diff --git a/src/plugins/ikev2/ikev2_cli.c b/src/plugins/ikev2/ikev2_cli.c
index 7778166254c..3523ce079b6 100644
--- a/src/plugins/ikev2/ikev2_cli.c
+++ b/src/plugins/ikev2/ikev2_cli.c
@@ -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");
diff --git a/src/plugins/ikev2/ikev2_priv.h b/src/plugins/ikev2/ikev2_priv.h
index ea630b86de4..4c56b980f1c 100644
--- a/src/plugins/ikev2/ikev2_priv.h
+++ b/src/plugins/ikev2/ikev2_priv.h
@@ -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;
diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c
index 98b3fa054ae..b63778ed103 100644
--- a/src/plugins/ikev2/ikev2_test.c
+++ b/src/plugins/ikev2/ikev2_test.c
@@ -1061,6 +1061,53 @@ api_ikev2_set_tunnel_interface (vat_main_t * vam)
}
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)
{
unformat_input_t *i = vam->input;
diff --git a/src/plugins/ikev2/test/test_ikev2.py b/src/plugins/ikev2/test/test_ikev2.py
index dea9a6a41c8..558e8a02f87 100644
--- a/src/plugins/ikev2/test/test_ikev2.py
+++ b/src/plugins/ikev2/test/test_ikev2.py
@@ -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
diff --git a/src/plugins/ikev2/test/vpp_ikev2.py b/src/plugins/ikev2/test/vpp_ikev2.py
index dd1c3fc986e..de2081268ee 100644
--- a/src/plugins/ikev2/test/vpp_ikev2.py
+++ b/src/plugins/ikev2/test/vpp_ikev2.py
@@ -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)