VPP-1027: DNS name resolver
This patch is a plausible first-cut, suitable for initial testing by
vcl (host stack client library).
Main features;
- recursive name resolution
- multiple ip4/ip6 name servers
- cache size limit enforcement
- currently limited to 65K
- ttl / aging
- static mapping support
- show / clear / debug CLI commands
Binary APIs provided for the following:
- add/delete name servers
- enable/disable the name cache
- resolve a name
To Do list:
- Respond to ip4/ip6 client DNS requests (vs. binary API requests)
- Perf / scale tuning
- map pending transaction ids to pool indices, so the cache
can (greatly) exceed 65K entries
- Security improvements
- Use unpredictable dns transaction IDs, related to previous item
- Make sure that response-packet src ip addresses match the server
- Add binary APIs
- deliver raw response data to clients
- control recursive name resolution
- Documentation
Change-Id: I48c373d5c05d7108ccd814d4055caf8c75ca10b7
Signed-off-by: Dave Barach <dave@barachs.net>
This commit is contained in:
committed by
Florin Coras
parent
7e550693df
commit
6545716c07
+172
-5
@@ -2179,6 +2179,39 @@ static void vl_api_memfd_segment_create_reply_t_handler_json
|
||||
clib_warning ("no");
|
||||
}
|
||||
|
||||
static void vl_api_dns_resolve_name_reply_t_handler
|
||||
(vl_api_dns_resolve_name_reply_t * mp)
|
||||
{
|
||||
vat_main_t *vam = &vat_main;
|
||||
i32 retval = ntohl (mp->retval);
|
||||
if (vam->async_mode)
|
||||
{
|
||||
vam->async_errors += (retval < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vam->retval = retval;
|
||||
vam->result_ready = 1;
|
||||
|
||||
if (retval == 0)
|
||||
{
|
||||
if (mp->ip4_set)
|
||||
clib_warning ("ip4 address %U", format_ip4_address,
|
||||
(ip4_address_t *) mp->ip4_address);
|
||||
if (mp->ip6_set)
|
||||
clib_warning ("ip6 address %U", format_ip6_address,
|
||||
(ip6_address_t *) mp->ip6_address);
|
||||
}
|
||||
else
|
||||
clib_warning ("retval %d", retval);
|
||||
}
|
||||
}
|
||||
|
||||
static void vl_api_dns_resolve_name_reply_t_handler_json
|
||||
(vl_api_dns_resolve_name_reply_t * mp)
|
||||
{
|
||||
clib_warning ("no");
|
||||
}
|
||||
|
||||
static void vl_api_ip_address_details_t_handler
|
||||
(vl_api_ip_address_details_t * mp)
|
||||
@@ -5066,8 +5099,8 @@ _(want_stats_reply) \
|
||||
_(cop_interface_enable_disable_reply) \
|
||||
_(cop_whitelist_enable_disable_reply) \
|
||||
_(sw_interface_clear_stats_reply) \
|
||||
_(ioam_enable_reply) \
|
||||
_(ioam_disable_reply) \
|
||||
_(ioam_enable_reply) \
|
||||
_(ioam_disable_reply) \
|
||||
_(one_add_del_locator_reply) \
|
||||
_(one_add_del_local_eid_reply) \
|
||||
_(one_add_del_remote_mapping_reply) \
|
||||
@@ -5117,7 +5150,9 @@ _(p2p_ethernet_del_reply) \
|
||||
_(lldp_config_reply) \
|
||||
_(sw_interface_set_lldp_reply) \
|
||||
_(tcp_configure_src_addresses_reply) \
|
||||
_(app_namespace_add_del_reply)
|
||||
_(app_namespace_add_del_reply) \
|
||||
_(dns_enable_disable_reply) \
|
||||
_(dns_name_server_add_del_reply)
|
||||
|
||||
#define _(n) \
|
||||
static void vl_api_##n##_t_handler \
|
||||
@@ -5422,7 +5457,10 @@ _(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply) \
|
||||
_(LLDP_CONFIG_REPLY, lldp_config_reply) \
|
||||
_(SW_INTERFACE_SET_LLDP_REPLY, sw_interface_set_lldp_reply) \
|
||||
_(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \
|
||||
_(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply)
|
||||
_(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply) \
|
||||
_(DNS_ENABLE_DISABLE_REPLY, dns_enable_disable_reply) \
|
||||
_(DNS_NAME_SERVER_ADD_DEL_REPLY, dns_name_server_add_del_reply) \
|
||||
_(DNS_RESOLVE_NAME_REPLY, dns_resolve_name_reply)
|
||||
|
||||
#define foreach_standalone_reply_msg \
|
||||
_(SW_INTERFACE_EVENT, sw_interface_event) \
|
||||
@@ -5432,7 +5470,7 @@ _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
|
||||
_(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
|
||||
_(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \
|
||||
_(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) \
|
||||
_(MEMFD_SEGMENT_CREATE_REPLY, memfd_segment_create_reply)
|
||||
_(MEMFD_SEGMENT_CREATE_REPLY, memfd_segment_create_reply) \
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -20830,6 +20868,132 @@ api_memfd_segment_create (vat_main_t * vam)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
api_dns_enable_disable (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *line_input = vam->input;
|
||||
vl_api_dns_enable_disable_t *mp;
|
||||
u8 enable_disable = 1;
|
||||
int ret;
|
||||
|
||||
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (line_input, "disable"))
|
||||
enable_disable = 0;
|
||||
if (unformat (line_input, "enable"))
|
||||
enable_disable = 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (DNS_ENABLE_DISABLE, mp);
|
||||
mp->enable = enable_disable;
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
/* Wait for the reply */
|
||||
W (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
api_dns_resolve_name (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *line_input = vam->input;
|
||||
vl_api_dns_resolve_name_t *mp;
|
||||
u8 *name = 0;
|
||||
int ret;
|
||||
|
||||
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (line_input, "%s", &name))
|
||||
;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (vec_len (name) > 127)
|
||||
{
|
||||
errmsg ("name too long");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (DNS_RESOLVE_NAME, mp);
|
||||
memcpy (mp->name, name, vec_len (name));
|
||||
vec_free (name);
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
/* Wait for the reply */
|
||||
W (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
api_dns_name_server_add_del (vat_main_t * vam)
|
||||
{
|
||||
unformat_input_t *i = vam->input;
|
||||
vl_api_dns_name_server_add_del_t *mp;
|
||||
u8 is_add = 1;
|
||||
ip6_address_t ip6_server;
|
||||
ip4_address_t ip4_server;
|
||||
int ip6_set = 0;
|
||||
int ip4_set = 0;
|
||||
int ret = 0;
|
||||
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "%U", unformat_ip6_address, &ip6_server))
|
||||
ip6_set = 1;
|
||||
else if (unformat (i, "%U", unformat_ip4_address, &ip4_server))
|
||||
ip4_set = 1;
|
||||
else if (unformat (i, "del"))
|
||||
is_add = 0;
|
||||
else
|
||||
{
|
||||
clib_warning ("parse error '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
if (ip4_set && ip6_set)
|
||||
{
|
||||
errmsg ("Only one server address allowed per message");
|
||||
return -99;
|
||||
}
|
||||
if ((ip4_set + ip6_set) == 0)
|
||||
{
|
||||
errmsg ("Server address required");
|
||||
return -99;
|
||||
}
|
||||
|
||||
/* Construct the API message */
|
||||
M (DNS_NAME_SERVER_ADD_DEL, mp);
|
||||
|
||||
if (ip6_set)
|
||||
{
|
||||
memcpy (mp->server_address, &ip6_server, sizeof (ip6_address_t));
|
||||
mp->is_ip6 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (mp->server_address, &ip4_server, sizeof (ip4_address_t));
|
||||
mp->is_ip6 = 0;
|
||||
}
|
||||
|
||||
mp->is_add = is_add;
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
|
||||
/* Wait for a reply, return good/bad news */
|
||||
W (ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
q_or_quit (vat_main_t * vam)
|
||||
{
|
||||
@@ -21621,6 +21785,9 @@ _(sw_interface_set_lldp, "<intfc> | sw_if_index <nn> [port-desc <description>]\n
|
||||
_(tcp_configure_src_addresses, "<ip4|6>first-<ip4|6>last [vrf <id>]") \
|
||||
_(memfd_segment_create,"size <nnn>") \
|
||||
_(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
|
||||
_(dns_enable_disable, "[enable][disable]") \
|
||||
_(dns_name_server_add_del, "<ip-address> [del]") \
|
||||
_(dns_resolve_name, "<hostname>")
|
||||
|
||||
/* List of command functions, CLI names map directly to functions */
|
||||
#define foreach_cli_function \
|
||||
|
||||
@@ -665,7 +665,22 @@ vl_msg_api_config (vl_msg_api_msg_config_t * c)
|
||||
{
|
||||
api_main_t *am = &api_main;
|
||||
|
||||
ASSERT (c->id > 0);
|
||||
/*
|
||||
* This happens during the java core tests if the message
|
||||
* dictionary is missing newly added xxx_reply_t messages.
|
||||
* Should never happen, but since I shot myself in the foot once
|
||||
* this way, I thought I'd make it easy to debug if I ever do
|
||||
* it again... (;-)...
|
||||
*/
|
||||
if (c->id == 0)
|
||||
{
|
||||
if (c->name)
|
||||
clib_warning ("Trying to register %s with a NULL msg id!", c->name);
|
||||
else
|
||||
clib_warning ("Trying to register a NULL msg with a NULL msg id!");
|
||||
clib_warning ("Did you forget to call setup_message_id_table?");
|
||||
return;
|
||||
}
|
||||
|
||||
#define _(a) vec_validate (am->a, c->id);
|
||||
foreach_msg_api_vector;
|
||||
|
||||
+16
@@ -812,6 +812,22 @@ nobase_include_HEADERS += \
|
||||
|
||||
API_FILES += vnet/span/span.api
|
||||
|
||||
########################################
|
||||
# DNS proxy, API
|
||||
########################################
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/dns/dns.c \
|
||||
vnet/dns/dns.h \
|
||||
vnet/dns/dns_packet.h \
|
||||
vnet/dns/reply_node.c \
|
||||
vnet/dns/resolver_process.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/dns/dns.api.h \
|
||||
vnet/dns/dns.h
|
||||
|
||||
API_FILES += vnet/dns/dns.api
|
||||
|
||||
########################################
|
||||
# Packet generator
|
||||
########################################
|
||||
|
||||
@@ -122,6 +122,14 @@ _(APP_WRONG_NS_SECRET, -129, "Wrong app namespace secret") \
|
||||
_(APP_CONNECT_SCOPE, -130, "Connect scope") \
|
||||
_(APP_ALREADY_ATTACHED, -131, "App already attached") \
|
||||
_(SESSION_REDIRECT, -132, "Redirect failed") \
|
||||
_(ILLEGAL_NAME, -133, "Illegal name") \
|
||||
_(NO_NAME_SERVERS, -134, "No name servers configured") \
|
||||
_(NAME_SERVER_NOT_FOUND, -135, "Name server not found") \
|
||||
_(NAME_RESOLUTION_NOT_ENABLED, -136, "Name resolution not enabled") \
|
||||
_(NAME_SERVER_FORMAT_ERROR, -137, "Server format error (bug!)") \
|
||||
_(NAME_SERVER_NO_SUCH_NAME, -138, "No such name") \
|
||||
_(NAME_SERVER_NO_ADDRESSES, -139, "No addresses available") \
|
||||
_(NAME_SERVER_NEXT_SERVER, -140, "Retry with new server")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
vl_api_version 1.0.0
|
||||
|
||||
/** \brief enable/disable name resolution
|
||||
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_enable - 1 = enable, 0 = disable
|
||||
*/
|
||||
autoreply define dns_enable_disable {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 enable;
|
||||
};
|
||||
|
||||
/** \brief add or delete an upstream name server
|
||||
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_ip6 - an ip6 name server
|
||||
@param is_add - add = 1, delete = 0
|
||||
@param server_address - server ip address
|
||||
*/
|
||||
autoreply define dns_name_server_add_del {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_ip6;
|
||||
u8 is_add;
|
||||
u8 server_address[16];
|
||||
};
|
||||
|
||||
/** \brief DNS name resolution request
|
||||
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param name - the name to resolve
|
||||
*/
|
||||
define dns_resolve_name {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 name[128];
|
||||
};
|
||||
|
||||
define dns_resolve_name_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u8 ip4_set;
|
||||
u8 ip6_set;
|
||||
u8 ip4_address[4];
|
||||
u8 ip6_address[16];
|
||||
};
|
||||
|
||||
+2114
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef included_dns_h
|
||||
#define included_dns_h
|
||||
|
||||
#include <vppinfra/time.h>
|
||||
#include <vppinfra/cache.h>
|
||||
#include <vppinfra/error.h>
|
||||
|
||||
#include <vppinfra/hash.h>
|
||||
#include <vnet/dns/dns_packet.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** flags */
|
||||
volatile u8 flags;
|
||||
|
||||
/** The name in "normal human being" notation, e.g. www.foobar.com */
|
||||
u8 *name;
|
||||
|
||||
/** Expiration time */
|
||||
f64 expiration_time;
|
||||
|
||||
/** Cached dns request, for sending retries */
|
||||
u8 *dns_request;
|
||||
|
||||
/** Retry parameters */
|
||||
int retry_count;
|
||||
int server_rotor;
|
||||
int server_af;
|
||||
f64 retry_timer;
|
||||
|
||||
/** Cached dns response */
|
||||
u8 *dns_response;
|
||||
|
||||
/** Clients awaiting responses */
|
||||
u32 *api_clients_to_notify;
|
||||
u32 *api_client_contexts;
|
||||
ip4_address_t *ip4_peers_to_notify;
|
||||
ip6_address_t *ip6_peers_to_notify;
|
||||
} dns_cache_entry_t;
|
||||
|
||||
#define DNS_CACHE_ENTRY_FLAG_VALID (1<<0) /**< we have Actual Data */
|
||||
#define DNS_CACHE_ENTRY_FLAG_STATIC (1<<1) /**< static entry */
|
||||
|
||||
#define DNS_RETRIES_PER_SERVER 3
|
||||
|
||||
#define DNS_RESOLVER_EVENT_RESOLVED 1
|
||||
#define DNS_RESOLVER_EVENT_PENDING 2
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/** Pool of cache entries */
|
||||
dns_cache_entry_t *entries;
|
||||
|
||||
/** Pool indices of unresolved entries */
|
||||
u32 *unresolved_entries;
|
||||
|
||||
/** Find cached record by name */
|
||||
uword *cache_entry_by_name;
|
||||
uword *cache_lock;
|
||||
|
||||
/** enable / disable flag */
|
||||
int is_enabled;
|
||||
|
||||
/** upstream name servers, e.g. 8.8.8.8 */
|
||||
ip4_address_t *ip4_name_servers;
|
||||
ip6_address_t *ip6_name_servers;
|
||||
|
||||
/** config parameters */
|
||||
u32 name_cache_size;
|
||||
u32 max_ttl_in_seconds;
|
||||
u32 random_seed;
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t *vlib_main;
|
||||
vnet_main_t *vnet_main;
|
||||
} dns_main_t;
|
||||
|
||||
extern dns_main_t dns_main;
|
||||
|
||||
extern vlib_node_registration_t dns46_reply_node;
|
||||
extern vlib_node_registration_t dns_resolver_node;
|
||||
|
||||
#define foreach_dns46_reply_error \
|
||||
_(PROCESSED, "DNS reply pkts processed") \
|
||||
_(NO_ELT, "No DNS pool element") \
|
||||
_(FORMAT_ERROR, "DNS format errors") \
|
||||
_(TEST_DROP, "DNS reply pkt dropped for test purposes")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(sym,str) DNS46_REPLY_ERROR_##sym,
|
||||
foreach_dns46_reply_error
|
||||
#undef _
|
||||
DNS46_REPLY_N_ERROR,
|
||||
} dns46_reply_error_t;
|
||||
|
||||
void vnet_send_dns_request (dns_main_t * dm, dns_cache_entry_t * ep);
|
||||
int vnet_dns_cname_indirection_nolock (dns_main_t * dm,
|
||||
dns_cache_entry_t * ep, u8 * reply);
|
||||
int vnet_dns_delete_entry_by_index_nolock (dns_main_t * dm, u32 index);
|
||||
|
||||
format_function_t format_dns_reply;
|
||||
|
||||
static inline void
|
||||
dns_cache_lock (dns_main_t * dm)
|
||||
{
|
||||
if (dm->cache_lock)
|
||||
{
|
||||
while (__sync_lock_test_and_set (dm->cache_lock, 1))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
dns_cache_unlock (dns_main_t * dm)
|
||||
{
|
||||
if (dm->cache_lock)
|
||||
{
|
||||
CLIB_MEMORY_BARRIER ();
|
||||
*dm->cache_lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* included_dns_h */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef included_dns_packet_h
|
||||
#define included_dns_packet_h
|
||||
|
||||
/**
|
||||
* DNS packet header format
|
||||
*/
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
typedef CLIB_PACKED (struct {
|
||||
u16 id; /**< transaction ID */
|
||||
u16 flags; /**< flags */
|
||||
u16 qdcount; /**< number of questions */
|
||||
u16 anscount; /**< number of answers */
|
||||
u16 nscount; /**< number of name servers */
|
||||
u16 arcount; /**< number of additional records */
|
||||
}) dns_header_t;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define DNS_RCODE_MASK (0xf)
|
||||
#define DNS_RCODE_NO_ERROR 0
|
||||
#define DNS_RCODE_FORMAT_ERROR 1
|
||||
#define DNS_RCODE_SERVER_FAILURE 2
|
||||
#define DNS_RCODE_NAME_ERROR 3
|
||||
#define DNS_RCODE_NOT_IMPLEMENTED 4
|
||||
#define DNS_RCODE_REFUSED 5
|
||||
|
||||
#define DNS_RA (1<<7) /**< recursion available */
|
||||
#define DNS_RD (1<<8) /**< recursion desired */
|
||||
#define DNS_TC (1<<9) /**< truncation */
|
||||
#define DNS_AA (1<<10) /**< authoritative answer */
|
||||
#define DNS_OPCODE_MASK (0xf<<11) /**< opcode mask */
|
||||
#define DNS_OPCODE_QUERY (0<<11) /**< standard query */
|
||||
#define DNS_OPCODE_IQUERY (1<<11) /**< inverse query (deprecated) */
|
||||
#define DNS_OPCODE_STATUS (2<<11) /**< server status */
|
||||
#define DNS_QR (1<<15) /**< query=0, response=1 */
|
||||
|
||||
|
||||
/*
|
||||
* Note: in DNS-land, www.foobar.com is encoded as three "labels,"
|
||||
* each of which amount to a 1 octet length followed by up to 63
|
||||
* octets of name. Don't forget to add a "null root label" after the last
|
||||
* real one, or the poor slob trying to parse the name will have
|
||||
* no chance whatsoever.
|
||||
*
|
||||
* All RRs have the same top level format shown below:
|
||||
*
|
||||
* 1 1 1 1 1 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | |
|
||||
* / /
|
||||
* / NAME /
|
||||
* | |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | TYPE |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | CLASS |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | TTL |
|
||||
* | |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | RDLENGTH |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
|
||||
* / RDATA /
|
||||
* / /
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
*
|
||||
*
|
||||
* DNS "questions" have the following format:
|
||||
*
|
||||
* 1 1 1 1 1 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | |
|
||||
* / QNAME /
|
||||
* / /
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | QTYPE |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
* | QCLASS |
|
||||
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
*/
|
||||
|
||||
/**
|
||||
* DNS "question" fixed header.
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
typedef CLIB_PACKED (struct {
|
||||
u16 type; /**< record type requested */
|
||||
u16 class; /**< class, 1 = internet */
|
||||
}) dns_query_t;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* DNS RR fixed header.
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
typedef CLIB_PACKED (struct {
|
||||
u16 type; /**< record type */
|
||||
u16 class; /**< class, 1 = internet */
|
||||
u32 ttl; /**< time to live, in seconds */
|
||||
u16 rdlength;
|
||||
/**< length of r */
|
||||
u8 rdata[0];
|
||||
}) dns_rr_t;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* There are quite a number of DNS record types
|
||||
* Feel free to add as needed
|
||||
*/
|
||||
#define foreach_dns_type \
|
||||
_(A, 1) /**< ip4 host address */ \
|
||||
_(AAAA, 28) /**< ip6 host address */ \
|
||||
_(ALL, 255) /**< all available data */ \
|
||||
_(TEXT, 16) /**< a text string */ \
|
||||
_(NAMESERVER, 2) /**< a nameserver */ \
|
||||
_(CNAME, 5) /**< a CNAME (alias) */ \
|
||||
_(MAIL_EXCHANGE, 15) /**< a mail exchange */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define _(name,value) DNS_TYPE_##name = value,
|
||||
foreach_dns_type
|
||||
#undef _
|
||||
} dns_type_t;
|
||||
|
||||
#define DNS_CLASS_IN 1 /**< The Internet */
|
||||
|
||||
|
||||
#endif /* included_dns_packet_h */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vnet/dns/dns.h>
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
|
||||
vlib_node_registration_t dns46_reply_node;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 pool_index;
|
||||
u32 disposition;
|
||||
} dns46_reply_trace_t;
|
||||
|
||||
/* packet trace format function */
|
||||
static u8 *
|
||||
format_dns46_reply_trace (u8 * s, va_list * args)
|
||||
{
|
||||
CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
|
||||
CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
|
||||
dns46_reply_trace_t *t = va_arg (*args, dns46_reply_trace_t *);
|
||||
|
||||
s = format (s, "DNS46_REPLY: pool index %d, disposition %d",
|
||||
t->pool_index, t->disposition);
|
||||
return s;
|
||||
}
|
||||
|
||||
vlib_node_registration_t dns46_reply_node;
|
||||
|
||||
static char *dns46_reply_error_strings[] = {
|
||||
#define _(sym,string) string,
|
||||
foreach_dns46_reply_error
|
||||
#undef _
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DNS46_REPLY_NEXT_DROP,
|
||||
DNS46_REPLY_N_NEXT,
|
||||
} dns46_reply_next_t;
|
||||
|
||||
static uword
|
||||
dns46_reply_node_fn (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
u32 n_left_from, *from, *to_next;
|
||||
dns46_reply_next_t next_index;
|
||||
|
||||
from = vlib_frame_vector_args (frame);
|
||||
n_left_from = frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
u32 n_left_to_next;
|
||||
|
||||
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
|
||||
|
||||
#if 0
|
||||
while (n_left_from >= 4 && n_left_to_next >= 2)
|
||||
{
|
||||
u32 next0 = DNS46_REPLY_NEXT_INTERFACE_OUTPUT;
|
||||
u32 next1 = DNS46_REPLY_NEXT_INTERFACE_OUTPUT;
|
||||
u32 sw_if_index0, sw_if_index1;
|
||||
u8 tmp0[6], tmp1[6];
|
||||
ethernet_header_t *en0, *en1;
|
||||
u32 bi0, bi1;
|
||||
vlib_buffer_t *b0, *b1;
|
||||
|
||||
/* Prefetch next iteration. */
|
||||
{
|
||||
vlib_buffer_t *p2, *p3;
|
||||
|
||||
p2 = vlib_get_buffer (vm, from[2]);
|
||||
p3 = vlib_get_buffer (vm, from[3]);
|
||||
|
||||
vlib_prefetch_buffer_header (p2, LOAD);
|
||||
vlib_prefetch_buffer_header (p3, LOAD);
|
||||
|
||||
CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
|
||||
CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
|
||||
}
|
||||
|
||||
/* speculatively enqueue b0 and b1 to the current next frame */
|
||||
to_next[0] = bi0 = from[0];
|
||||
to_next[1] = bi1 = from[1];
|
||||
from += 2;
|
||||
to_next += 2;
|
||||
n_left_from -= 2;
|
||||
n_left_to_next -= 2;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
b1 = vlib_get_buffer (vm, bi1);
|
||||
|
||||
/* $$$$$ End of processing 2 x packets $$$$$ */
|
||||
|
||||
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
|
||||
{
|
||||
if (b0->flags & VLIB_BUFFER_IS_TRACED)
|
||||
{
|
||||
dns46_reply_trace_t *t =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*t));
|
||||
t->sw_if_index = sw_if_index0;
|
||||
t->next_index = next0;
|
||||
}
|
||||
if (b1->flags & VLIB_BUFFER_IS_TRACED)
|
||||
{
|
||||
dns46_reply_trace_t *t =
|
||||
vlib_add_trace (vm, node, b1, sizeof (*t));
|
||||
t->sw_if_index = sw_if_index1;
|
||||
t->next_index = next1;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify speculative enqueues, maybe switch current next frame */
|
||||
vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, bi1, next0, next1);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
u32 bi0;
|
||||
vlib_buffer_t *b0;
|
||||
u32 next0 = DNS46_REPLY_NEXT_DROP;
|
||||
dns_header_t *d0;
|
||||
u32 pool_index0;
|
||||
u32 error0;
|
||||
u8 *resp0 = 0;
|
||||
|
||||
/* speculatively enqueue b0 to the current next frame */
|
||||
bi0 = from[0];
|
||||
to_next[0] = bi0;
|
||||
from += 1;
|
||||
to_next += 1;
|
||||
n_left_from -= 1;
|
||||
|
||||
n_left_to_next -= 1;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
d0 = vlib_buffer_get_current (b0);
|
||||
|
||||
pool_index0 = clib_host_to_net_u16 (d0->id);
|
||||
|
||||
/* Save the reply */
|
||||
vec_validate (resp0, vlib_buffer_length_in_chain (vm, b0) - 1);
|
||||
clib_memcpy (resp0, d0, vlib_buffer_length_in_chain (vm, b0));
|
||||
|
||||
/*
|
||||
* Deal with everything in process ctx on the main thread
|
||||
*/
|
||||
vlib_process_signal_event_mt (vm, dns_resolver_node.index,
|
||||
DNS_RESOLVER_EVENT_RESOLVED,
|
||||
(uword) resp0);
|
||||
error0 = DNS46_REPLY_ERROR_PROCESSED;
|
||||
|
||||
b0->error = node->errors[error0];
|
||||
|
||||
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
|
||||
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
|
||||
{
|
||||
dns46_reply_trace_t *t =
|
||||
vlib_add_trace (vm, node, b0, sizeof (*t));
|
||||
t->disposition = error0;
|
||||
t->pool_index = pool_index0;
|
||||
}
|
||||
|
||||
/* verify speculative enqueue, maybe switch current next frame */
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
|
||||
to_next, n_left_to_next,
|
||||
bi0, next0);
|
||||
}
|
||||
|
||||
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
|
||||
}
|
||||
|
||||
return frame->n_vectors;
|
||||
}
|
||||
|
||||
VLIB_REGISTER_NODE (dns46_reply_node) =
|
||||
{
|
||||
.function = dns46_reply_node_fn,.name = "dns46_reply",.vector_size =
|
||||
sizeof (u32),.format_trace = format_dns46_reply_trace,.type =
|
||||
VLIB_NODE_TYPE_INTERNAL,.n_errors =
|
||||
ARRAY_LEN (dns46_reply_error_strings),.error_strings =
|
||||
dns46_reply_error_strings,.n_next_nodes = DNS46_REPLY_N_NEXT,
|
||||
/* edit / add dispositions here */
|
||||
.next_nodes =
|
||||
{
|
||||
[DNS46_REPLY_NEXT_DROP] = "error-drop",}
|
||||
,};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Cisco and/or its affiliates.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vnet/dns/dns.h>
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
|
||||
#include <vnet/vnet_msg_enum.h>
|
||||
|
||||
#define vl_typedefs /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_typedefs
|
||||
|
||||
#define vl_endianfun /* define message structures */
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
#include <vnet/vnet_all_api_h.h>
|
||||
#undef vl_printfun
|
||||
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
vlib_node_registration_t dns_resolver_node;
|
||||
|
||||
extern int
|
||||
vnet_dns_response_to_reply (u8 * response,
|
||||
vl_api_dns_resolve_name_reply_t * rmp,
|
||||
u32 * min_ttlp);
|
||||
|
||||
static void
|
||||
resolve_event (dns_main_t * dm, f64 now, u8 * reply)
|
||||
{
|
||||
vlib_main_t *vm = dm->vlib_main;
|
||||
dns_header_t *d;
|
||||
u32 pool_index;
|
||||
dns_cache_entry_t *ep;
|
||||
u32 min_ttl;
|
||||
u16 flags;
|
||||
u16 rcode;
|
||||
int i;
|
||||
int rv = 0;
|
||||
|
||||
d = (dns_header_t *) reply;
|
||||
flags = clib_net_to_host_u16 (d->flags);
|
||||
rcode = flags & DNS_RCODE_MASK;
|
||||
|
||||
/* $$$ u16 limits cache to 65K entries, fix later multiple dst ports */
|
||||
pool_index = clib_net_to_host_u16 (d->id);
|
||||
dns_cache_lock (dm);
|
||||
|
||||
if (pool_is_free_index (dm->entries, pool_index))
|
||||
{
|
||||
vec_free (reply);
|
||||
vlib_node_increment_counter (vm, dns46_reply_node.index,
|
||||
DNS46_REPLY_ERROR_NO_ELT, 1);
|
||||
dns_cache_unlock (dm);
|
||||
return;
|
||||
}
|
||||
|
||||
ep = pool_elt_at_index (dm->entries, pool_index);
|
||||
|
||||
if (ep->dns_response)
|
||||
vec_free (ep->dns_response);
|
||||
|
||||
/* Handle [sic] recursion AKA CNAME indirection */
|
||||
if (vnet_dns_cname_indirection_nolock (dm, ep, reply))
|
||||
{
|
||||
dns_cache_unlock (dm);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the response */
|
||||
ep->dns_response = reply;
|
||||
/* Pick some sensible default. */
|
||||
ep->expiration_time = now + 600.0;
|
||||
if (vec_len (ep->dns_response))
|
||||
ep->flags |= DNS_CACHE_ENTRY_FLAG_VALID;
|
||||
|
||||
/* Most likely, send 1 message */
|
||||
for (i = 0; i < vec_len (ep->api_clients_to_notify); i++)
|
||||
{
|
||||
vl_api_registration_t *regp;
|
||||
vl_api_dns_resolve_name_reply_t *rmp;
|
||||
|
||||
regp = vl_api_client_index_to_registration
|
||||
(ep->api_clients_to_notify[i]);
|
||||
|
||||
if (regp == 0)
|
||||
continue;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp) + vec_len (ep->dns_response));
|
||||
rmp->_vl_msg_id = clib_host_to_net_u16 (VL_API_DNS_RESOLVE_NAME_REPLY);
|
||||
rmp->context = ep->api_client_contexts[i];
|
||||
min_ttl = ~0;
|
||||
rv = vnet_dns_response_to_reply (ep->dns_response, rmp, &min_ttl);
|
||||
if (min_ttl != ~0)
|
||||
ep->expiration_time = now + min_ttl;
|
||||
rmp->retval = clib_host_to_net_u32 (rv);
|
||||
vl_msg_api_send (regp, (u8 *) rmp);
|
||||
}
|
||||
vec_free (ep->api_clients_to_notify);
|
||||
vec_free (ep->api_client_contexts);
|
||||
|
||||
/* $$$ Add ip4/ip6 reply code */
|
||||
|
||||
for (i = 0; i < vec_len (dm->unresolved_entries); i++)
|
||||
{
|
||||
if (dm->unresolved_entries[i] == pool_index)
|
||||
{
|
||||
vec_delete (dm->unresolved_entries, 1, i);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
clib_warning ("pool index %d AWOL from unresolved vector", pool_index);
|
||||
|
||||
found:
|
||||
/* Deal with bogus names, server issues, etc. */
|
||||
switch (rcode)
|
||||
{
|
||||
default:
|
||||
case DNS_RCODE_NO_ERROR:
|
||||
break;
|
||||
|
||||
case DNS_RCODE_SERVER_FAILURE:
|
||||
case DNS_RCODE_NOT_IMPLEMENTED:
|
||||
case DNS_RCODE_REFUSED:
|
||||
if (ep->server_af == 0)
|
||||
clib_warning ("name server %U backfire",
|
||||
format_ip4_address,
|
||||
dm->ip4_name_servers + ep->server_rotor);
|
||||
else
|
||||
clib_warning ("name server %U backfire",
|
||||
format_ip6_address,
|
||||
dm->ip6_name_servers + ep->server_rotor);
|
||||
/* FALLTHROUGH */
|
||||
case DNS_RCODE_NAME_ERROR:
|
||||
case DNS_RCODE_FORMAT_ERROR:
|
||||
/* remove trash from the cache... */
|
||||
vnet_dns_delete_entry_by_index_nolock (dm, ep - dm->entries);
|
||||
break;
|
||||
}
|
||||
|
||||
dns_cache_unlock (dm);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
retry_scan (dns_main_t * dm, f64 now)
|
||||
{
|
||||
int i;
|
||||
dns_cache_entry_t *ep;
|
||||
|
||||
for (i = 0; i < vec_len (dm->unresolved_entries); i++)
|
||||
{
|
||||
dns_cache_lock (dm);
|
||||
ep = pool_elt_at_index (dm->entries, dm->unresolved_entries[i]);
|
||||
|
||||
ASSERT ((ep->flags & DNS_CACHE_ENTRY_FLAG_VALID) == 0);
|
||||
|
||||
vnet_send_dns_request (dm, ep);
|
||||
dns_cache_unlock (dm);
|
||||
}
|
||||
}
|
||||
|
||||
static uword
|
||||
dns_resolver_process (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * rt, vlib_frame_t * f)
|
||||
{
|
||||
dns_main_t *dm = &dns_main;
|
||||
f64 now;
|
||||
f64 timeout = 1000.0;
|
||||
uword *event_data = 0;
|
||||
uword event_type;
|
||||
int i;
|
||||
|
||||
while (1)
|
||||
{
|
||||
vlib_process_wait_for_event_or_clock (vm, timeout);
|
||||
|
||||
now = vlib_time_now (vm);
|
||||
|
||||
event_type = vlib_process_get_events (vm, (uword **) & event_data);
|
||||
|
||||
switch (event_type)
|
||||
{
|
||||
/* Send one of these when a resolution is pending */
|
||||
case DNS_RESOLVER_EVENT_PENDING:
|
||||
timeout = 2.0;
|
||||
break;
|
||||
|
||||
case DNS_RESOLVER_EVENT_RESOLVED:
|
||||
for (i = 0; i < vec_len (event_data); i++)
|
||||
resolve_event (dm, now, (u8 *) event_data[i]);
|
||||
break;
|
||||
|
||||
case ~0: /* timeout */
|
||||
retry_scan (dm, now);
|
||||
break;
|
||||
}
|
||||
vec_reset_length (event_data);
|
||||
|
||||
/* No work? Back to slow timeout mode... */
|
||||
if (vec_len (dm->unresolved_entries) == 0)
|
||||
timeout = 1000.0;
|
||||
}
|
||||
return 0; /* or not */
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_REGISTER_NODE (dns_resolver_node) =
|
||||
{
|
||||
.function = dns_resolver_process,
|
||||
.type = VLIB_NODE_TYPE_PROCESS,
|
||||
.name = "dns-resolver-process",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
||||
@@ -137,6 +137,9 @@ do { \
|
||||
if ((error = vlib_call_init_function (vm, flow_classify_init)))
|
||||
return error;
|
||||
|
||||
if ((error = vlib_call_init_function (vm, dns_init)))
|
||||
return error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -78,6 +78,7 @@ typedef enum
|
||||
} udp_error_t;
|
||||
|
||||
#define foreach_udp4_dst_port \
|
||||
_ (53, dns) \
|
||||
_ (67, dhcp_to_server) \
|
||||
_ (68, dhcp_to_client) \
|
||||
_ (500, ikev2) \
|
||||
@@ -91,10 +92,12 @@ _ (4789, vxlan) \
|
||||
_ (4789, vxlan6) \
|
||||
_ (4790, VXLAN_GPE) \
|
||||
_ (6633, vpath_3) \
|
||||
_ (6081, geneve)
|
||||
_ (6081, geneve) \
|
||||
_ (53053, dns_reply)
|
||||
|
||||
|
||||
#define foreach_udp6_dst_port \
|
||||
_ (53, dns6) \
|
||||
_ (547, dhcpv6_to_server) \
|
||||
_ (546, dhcpv6_to_client) \
|
||||
_ (2152, GTPU6) \
|
||||
@@ -104,7 +107,8 @@ _ (4341, lisp_gpe6) \
|
||||
_ (4342, lisp_cp6) \
|
||||
_ (4790, VXLAN6_GPE) \
|
||||
_ (6633, vpath6_3) \
|
||||
_ (6081, geneve6)
|
||||
_ (6081, geneve6) \
|
||||
_ (53053, dns_reply6)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <vnet/policer/policer.api.h>
|
||||
#include <vnet/ethernet/p2p_ethernet.api.h>
|
||||
#include <vnet/tcp/tcp.api.h>
|
||||
#include <vnet/dns/dns.api.h>
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
||||
@@ -3127,6 +3127,16 @@ static void *vl_api_lldp_config_t_print
|
||||
s = format (s, "system_name %s ", mp->system_name);
|
||||
s = format (s, "tx_hold %d ", ntohl (mp->tx_hold));
|
||||
s = format (s, "tx_interval %d ", ntohl (mp->tx_interval));
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void *vl_api_dns_enable_disable_t_print
|
||||
(vl_api_dns_enable_disable_t * mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: dns_enable_disable ");
|
||||
s = format (s, "%s ", mp->enable ? "enable" : "disable");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
@@ -3160,6 +3170,35 @@ static void *vl_api_sw_interface_set_lldp_t_print
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void *vl_api_dns_name_server_add_del_t_print
|
||||
(vl_api_dns_name_server_add_del_t * mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: dns_name_server_add_del ");
|
||||
if (mp->is_ip6)
|
||||
s = format (s, "%U ", format_ip6_address,
|
||||
(ip6_address_t *) mp->server_address);
|
||||
else
|
||||
s = format (s, "%U ", format_ip4_address,
|
||||
(ip4_address_t *) mp->server_address);
|
||||
|
||||
if (mp->is_add == 0)
|
||||
s = format (s, "del ");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void *vl_api_dns_resolve_name_t_print
|
||||
(vl_api_dns_resolve_name_t * mp, void *handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: dns_resolve_name ");
|
||||
s = format (s, "%s ", mp->name);
|
||||
FINISH;
|
||||
}
|
||||
|
||||
#define foreach_custom_print_no_arg_function \
|
||||
_(lisp_eid_table_vni_dump) \
|
||||
_(lisp_map_resolver_dump) \
|
||||
@@ -3352,7 +3391,10 @@ _(P2P_ETHERNET_DEL, p2p_ethernet_del) \
|
||||
_(TCP_CONFIGURE_SRC_ADDRESSES, tcp_configure_src_addresses) \
|
||||
_(APP_NAMESPACE_ADD_DEL, app_namespace_add_del) \
|
||||
_(LLDP_CONFIG, lldp_config) \
|
||||
_(SW_INTERFACE_SET_LLDP, sw_interface_set_lldp)
|
||||
_(SW_INTERFACE_SET_LLDP, sw_interface_set_lldp) \
|
||||
_(DNS_ENABLE_DISABLE, dns_enable_disable) \
|
||||
_(DNS_NAME_SERVER_ADD_DEL, dns_name_server_add_del) \
|
||||
_(DNS_RESOLVE_NAME, dns_resolve_name)
|
||||
void
|
||||
vl_msg_api_custom_dump_configure (api_main_t * am)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user