diff options
author | Dave Barach <dave@barachs.net> | 2019-08-21 19:23:00 -0400 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2019-08-22 15:05:49 +0000 |
commit | 34af0ccf5cf27d8a72119626d2d009222e4ff0a6 (patch) | |
tree | ab108d50c4b59de2122dd5f6cd8f06f3543a2b47 /src | |
parent | 2ca9a84bd00f2aee642d0147c1b99d4be5725a70 (diff) |
dns: make the dns name resolver a plugin
Type: refactor
Signed-off-by: Dave Barach <dave@barachs.net>
Change-Id: I823c2cd307a4613653a2d20f564dda062d4da31b
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/dns/CMakeLists.txt | 33 | ||||
-rw-r--r-- | src/plugins/dns/dns.api (renamed from src/vnet/dns/dns.api) | 11 | ||||
-rw-r--r-- | src/plugins/dns/dns.c (renamed from src/vnet/dns/dns.c) | 248 | ||||
-rw-r--r-- | src/plugins/dns/dns.h (renamed from src/vnet/dns/dns.h) | 7 | ||||
-rw-r--r-- | src/plugins/dns/dns_all_api_h.h | 19 | ||||
-rw-r--r-- | src/plugins/dns/dns_msg_enum.h | 31 | ||||
-rw-r--r-- | src/plugins/dns/dns_packet.h (renamed from src/vnet/dns/dns_packet.h) | 0 | ||||
-rw-r--r-- | src/plugins/dns/dns_test.c | 346 | ||||
-rw-r--r-- | src/plugins/dns/reply_node.c (renamed from src/vnet/dns/reply_node.c) | 2 | ||||
-rw-r--r-- | src/plugins/dns/request_node.c (renamed from src/vnet/dns/request_node.c) | 2 | ||||
-rw-r--r-- | src/plugins/dns/resolver_process.c (renamed from src/vnet/dns/resolver_process.c) | 21 | ||||
-rw-r--r-- | src/plugins/dns/test/test_dns.py | 110 | ||||
-rw-r--r-- | src/vat/api_format.c | 242 | ||||
-rw-r--r-- | src/vnet/CMakeLists.txt | 18 | ||||
-rw-r--r-- | src/vnet/vnet_all_api_h.h | 1 | ||||
-rw-r--r-- | src/vpp/api/custom_dump.c | 69 |
16 files changed, 767 insertions, 393 deletions
diff --git a/src/plugins/dns/CMakeLists.txt b/src/plugins/dns/CMakeLists.txt new file mode 100644 index 00000000000..5d1ac8628db --- /dev/null +++ b/src/plugins/dns/CMakeLists.txt @@ -0,0 +1,33 @@ + +# Copyright (c) <current-year> <your-organization> +# 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. + +add_vpp_plugin(dns + SOURCES + dns.c + dns.h + request_node.c + reply_node.c + resolver_process.c + + API_FILES + dns.api + + INSTALL_HEADERS + dns_all_api_h.h + dns_msg_enum.h + dns_packet.h + + API_TEST_SOURCES + dns_test.c +) diff --git a/src/vnet/dns/dns.api b/src/plugins/dns/dns.api index 4045b8111c4..a4faec6bbb5 100644 --- a/src/vnet/dns/dns.api +++ b/src/plugins/dns/dns.api @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + option version = "1.0.0"; /** \brief enable/disable name resolution @@ -21,7 +21,7 @@ option version = "1.0.0"; @param context - sender context, to match reply w/ request @param is_enable - 1 = enable, 0 = disable */ -autoreply define dns_enable_disable { +autoreply manual_print define dns_enable_disable { u32 client_index; u32 context; u8 enable; @@ -35,7 +35,7 @@ autoreply define dns_enable_disable { @param is_add - add = 1, delete = 0 @param server_address - server ip address */ -autoreply define dns_name_server_add_del { +autoreply manual_print define dns_name_server_add_del { u32 client_index; u32 context; u8 is_ip6; @@ -49,7 +49,7 @@ autoreply define dns_name_server_add_del { @param context - sender context, to match reply w/ request @param name - the name to resolve */ -define dns_resolve_name { +manual_print define dns_resolve_name { u32 client_index; u32 context; u8 name[256]; @@ -81,7 +81,7 @@ define dns_resolve_name_reply { @param is_ip6 - set if the reverse-DNS request is an ip6 address @param address - the address to map to a name */ -define dns_resolve_ip { +manual_print define dns_resolve_ip { u32 client_index; u32 context; u8 is_ip6; @@ -100,4 +100,3 @@ define dns_resolve_ip_reply { i32 retval; u8 name[256]; }; - diff --git a/src/vnet/dns/dns.c b/src/plugins/dns/dns.c index 304aa1868fe..6ae0ff18a68 100644 --- a/src/vnet/dns/dns.c +++ b/src/plugins/dns/dns.c @@ -13,32 +13,51 @@ * limitations under the License. */ -#include <vnet/dns/dns.h> - #include <vnet/vnet.h> -#include <vnet/fib/fib.h> -#include <vlibmemory/api.h> - #include <vnet/udp/udp.h> +#include <vnet/plugin/plugin.h> +#include <vnet/fib/fib_table.h> +#include <dns/dns.h> + +#include <vlibapi/api.h> +#include <vlibmemory/api.h> +#include <vpp/app/version.h> +#include <stdbool.h> -#include <vnet/vnet_msg_enum.h> +/* define message IDs */ +#include <dns/dns_msg_enum.h> -#define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> +/* define message structures */ +#define vl_typedefs +#include <dns/dns_all_api_h.h> #undef vl_typedefs -#define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> +/* define generated endian-swappers */ +#define vl_endianfun +#include <dns/dns_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> +#include <dns/dns_all_api_h.h> #undef vl_printfun +/* Get the API version number */ +#define vl_api_version(n,v) static u32 api_version=(v); +#include <dns/dns_all_api_h.h> +#undef vl_api_version + +#define REPLY_MSG_ID_BASE dm->msg_id_base #include <vlibapi/api_helper_macros.h> +/* Macro to finish up custom dump fns */ +#define FINISH \ + vec_add1 (s, 0); \ + vl_print (handle, (char *)s); \ + vec_free (s); \ + return handle; + dns_main_t dns_main; static int @@ -1559,44 +1578,25 @@ vl_api_dns_resolve_ip_t_handler (vl_api_dns_resolve_ip_t * mp) } #define vl_msg_name_crc_list -#include <vpp/api/vpe_all_api_h.h> +#include <dns/dns_all_api_h.h> #undef vl_msg_name_crc_list static void -setup_message_id_table (api_main_t * am) +setup_message_id_table (dns_main_t * dm) { -#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); +#define _(id,n,crc) \ + vl_msg_api_add_msg_name_crc (dm->api_main, #n "_" #crc, dm->msg_id_base + id); foreach_vl_msg_name_crc_dns; #undef _ } -#define foreach_dns_api_msg \ +#define foreach_dns_plugin_api_msg \ _(DNS_ENABLE_DISABLE, dns_enable_disable) \ _(DNS_NAME_SERVER_ADD_DEL, dns_name_server_add_del) \ _(DNS_RESOLVE_NAME, dns_resolve_name) \ _(DNS_RESOLVE_IP, dns_resolve_ip) static clib_error_t * -dns_api_hookup (vlib_main_t * vm) -{ -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_dns_api_msg; -#undef _ - - setup_message_id_table (&api_main); - return 0; -} - -VLIB_API_INIT_FUNCTION (dns_api_hookup); - - -static clib_error_t * dns_config_fn (vlib_main_t * vm, unformat_input_t * input) { dns_main_t *dm = &dns_main; @@ -1616,22 +1616,6 @@ dns_config_fn (vlib_main_t * vm, unformat_input_t * input) VLIB_CONFIG_FUNCTION (dns_config_fn, "dns"); -static clib_error_t * -dns_init (vlib_main_t * vm) -{ - dns_main_t *dm = &dns_main; - - dm->vlib_main = vm; - dm->vnet_main = vnet_get_main (); - dm->name_cache_size = 65535; - dm->max_ttl_in_seconds = 86400; - dm->random_seed = 0xDEADDABE; - - return 0; -} - -VLIB_INIT_FUNCTION (dns_init); - uword unformat_dns_reply (unformat_input_t * input, va_list * args) { @@ -2303,6 +2287,44 @@ VLIB_CLI_COMMAND (show_dns_cache_command) = /* *INDENT-ON* */ static clib_error_t * +show_dns_servers_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + dns_main_t *dm = &dns_main; + int i; + + if ((vec_len (dm->ip4_name_servers) + vec_len (dm->ip6_name_servers)) == 0) + return clib_error_return (0, "No name servers configured..."); + + if (vec_len (dm->ip4_name_servers)) + { + vlib_cli_output (vm, "ip4 name servers:"); + for (i = 0; i < vec_len (dm->ip4_name_servers); i++) + vlib_cli_output (vm, "%U", format_ip4_address, + dm->ip4_name_servers + i); + } + if (vec_len (dm->ip6_name_servers)) + { + vlib_cli_output (vm, "ip6 name servers:"); + for (i = 0; i < vec_len (dm->ip6_name_servers); i++) + vlib_cli_output (vm, "%U", format_ip6_address, + dm->ip4_name_servers + i); + } + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (show_dns_server_command) = +{ + .path = "show dns servers", + .short_help = "show dns servers", + .function = show_dns_servers_command_fn, +}; +/* *INDENT-ON* */ + + +static clib_error_t * dns_cache_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -3007,6 +3029,130 @@ found_src_address: } } +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; +} + +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; +} + +static void *vl_api_dns_resolve_ip_t_print + (vl_api_dns_resolve_ip_t * mp, void *handle) +{ + u8 *s; + + s = format (0, "SCRIPT: dns_resolve_ip "); + if (mp->is_ip6) + s = format (s, "%U ", format_ip6_address, mp->address); + else + s = format (s, "%U ", format_ip4_address, mp->address); + FINISH; +} + +static void +dns_custom_dump_configure (dns_main_t * dm) +{ +#define _(n,f) dm->api_main->msg_print_handlers \ + [VL_API_##n + dm->msg_id_base] \ + = (void *) vl_api_##f##_t_print; + foreach_dns_plugin_api_msg; +#undef _ +} + +/* Set up the API message handling tables */ +static clib_error_t * +dns_plugin_api_hookup (vlib_main_t * vm) +{ + dns_main_t *dmp = &dns_main; +#define _(N,n) \ + vl_msg_api_set_handlers((VL_API_##N + dmp->msg_id_base), \ + #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_dns_plugin_api_msg; +#undef _ + + return 0; +} + +static clib_error_t * +dns_init (vlib_main_t * vm) +{ + dns_main_t *dm = &dns_main; + u8 *name; + + dm->vlib_main = vm; + dm->vnet_main = vnet_get_main (); + dm->name_cache_size = 1000; + dm->max_ttl_in_seconds = 86400; + dm->random_seed = 0xDEADDABE; + dm->api_main = &api_main; + + name = format (0, "dns_%08x%c", api_version, 0); + + /* Ask for a correctly-sized block of API message decode slots */ + dm->msg_id_base = vl_msg_api_get_msg_ids + ((char *) name, VL_MSG_FIRST_AVAILABLE); + + (void) dns_plugin_api_hookup (vm); + + /* Add our API messages to the global name_crc hash table */ + setup_message_id_table (dm); + + dns_custom_dump_configure (dm); + + vec_free (name); + + return 0; +} + +VLIB_INIT_FUNCTION (dns_init); + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = +{ + .version = VPP_BUILD_VER, + .description = "Simple DNS name resolver", +}; +/* *INDENT-ON* */ + + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/dns/dns.h b/src/plugins/dns/dns.h index 6d0901020f9..0a3f7a935cb 100644 --- a/src/vnet/dns/dns.h +++ b/src/plugins/dns/dns.h @@ -21,9 +21,10 @@ #include <vppinfra/error.h> #include <vppinfra/hash.h> -#include <vnet/dns/dns_packet.h> +#include <dns/dns_packet.h> #include <vnet/ip/ip.h> #include <vppinfra/lock.h> +#include <vlibapi/api_common.h> typedef struct { @@ -117,9 +118,13 @@ typedef struct u32 max_ttl_in_seconds; u32 random_seed; + /** message-ID base */ + u16 msg_id_base; + /* convenience */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; + api_main_t *api_main; } dns_main_t; extern dns_main_t dns_main; diff --git a/src/plugins/dns/dns_all_api_h.h b/src/plugins/dns/dns_all_api_h.h new file mode 100644 index 00000000000..c226bcf18a4 --- /dev/null +++ b/src/plugins/dns/dns_all_api_h.h @@ -0,0 +1,19 @@ + +/* + * dns_all_api_h.h - skeleton vpp engine plug-in api #include file + * + * Copyright (c) <current-year> <your-organization> + * 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 the generated file, see BUILT_SOURCES in Makefile.am */ +#include <dns/dns.api.h> diff --git a/src/plugins/dns/dns_msg_enum.h b/src/plugins/dns/dns_msg_enum.h new file mode 100644 index 00000000000..bad374f7969 --- /dev/null +++ b/src/plugins/dns/dns_msg_enum.h @@ -0,0 +1,31 @@ + +/* + * dns_msg_enum.h - skeleton vpp engine plug-in message enumeration + * + * Copyright (c) <current-year> <your-organization> + * 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_msg_enum_h +#define included_dns_msg_enum_h + +#include <vppinfra/byte_order.h> + +#define vl_msg_id(n,h) n, +typedef enum { +#include <dns/dns_all_api_h.h> + /* We'll want to know how many messages IDs we need... */ + VL_MSG_FIRST_AVAILABLE, +} vl_msg_id_t; +#undef vl_msg_id + +#endif /* included_dns_msg_enum_h */ diff --git a/src/vnet/dns/dns_packet.h b/src/plugins/dns/dns_packet.h index da5ddfa64fe..da5ddfa64fe 100644 --- a/src/vnet/dns/dns_packet.h +++ b/src/plugins/dns/dns_packet.h diff --git a/src/plugins/dns/dns_test.c b/src/plugins/dns/dns_test.c new file mode 100644 index 00000000000..6b0b371dca1 --- /dev/null +++ b/src/plugins/dns/dns_test.c @@ -0,0 +1,346 @@ +/* + * dns.c - skeleton vpp-api-test plug-in + * + * Copyright (c) <current-year> <your-organization> + * 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 <vat/vat.h> +#include <vlibapi/api.h> +#include <vlibmemory/api.h> +#include <vppinfra/error.h> +#include <stdbool.h> +#include <vnet/ip/ip.h> + +uword unformat_sw_if_index (unformat_input_t * input, va_list * args); + +/* Declare message IDs */ +#include <dns/dns_msg_enum.h> + +/* define message structures */ +#define vl_typedefs +#include <dns/dns_all_api_h.h> +#undef vl_typedefs + +/* declare message handlers for each api */ + +#define vl_endianfun /* define message structures */ +#include <dns/dns_all_api_h.h> +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) +#define vl_printfun +#include <dns/dns_all_api_h.h> +#undef vl_printfun + +/* Get the API version number. */ +#define vl_api_version(n,v) static u32 api_version=(v); +#include <dns/dns_all_api_h.h> +#undef vl_api_version + +typedef struct +{ + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; +} dns_test_main_t; + +dns_test_main_t dns_test_main; + +#define __plugin_msg_base dns_test_main.msg_id_base +#include <vlibapi/vat_helper_macros.h> + +#define foreach_standard_reply_retval_handler \ +_(dns_enable_disable_reply) \ +_(dns_name_server_add_del_reply) + +#define _(n) \ + static void vl_api_##n##_t_handler \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = dns_test_main.vat_main; \ + i32 retval = (i32) clib_net_to_host_u32(mp->retval); \ + if (vam->async_mode) { \ + vam->async_errors += (retval < 0); \ + } else { \ + vam->retval = retval; \ + vam->result_ready = 1; \ + } \ + } +foreach_standard_reply_retval_handler; +#undef _ + +static void vl_api_dns_resolve_name_reply_t_handler + (vl_api_dns_resolve_name_reply_t * mp) +{ + vat_main_t *vam = dns_test_main.vat_main; + i32 retval = (i32) clib_net_to_host_u32 (mp->retval); + if (retval == 0) + { + if (mp->ip4_set) + clib_warning ("resolved: %U", format_ip4_address, mp->ip4_address); + if (mp->ip6_set) + clib_warning ("resolved: %U", format_ip6_address, mp->ip6_address); + } + if (vam->async_mode) + vam->async_errors += (retval < 0); + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_dns_resolve_ip_reply_t_handler + (vl_api_dns_resolve_ip_reply_t * mp) +{ + vat_main_t *vam = dns_test_main.vat_main; + i32 retval = (i32) clib_net_to_host_u32 (mp->retval); + if (retval == 0) + clib_warning ("resolved: %s", mp->name); + if (vam->async_mode) + vam->async_errors += (retval < 0); + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +/* + * Table of message reply handlers, must include boilerplate handlers + * we just generated + */ +#define foreach_vpe_api_reply_msg \ +_(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) \ +_(DNS_RESOLVE_IP_REPLY, dns_resolve_ip_reply) + +static int +api_dns_enable_disable (vat_main_t * vam) +{ + vl_api_dns_enable_disable_t *mp; + unformat_input_t *i = vam->input; + int enable = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "disable")) + enable = 0; + else if (unformat (i, "enable")) + enable = 1; + else + break; + } + + /* Construct the API message */ + M (DNS_ENABLE_DISABLE, mp); + mp->enable = enable; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +/* + * List of messages that the api test plugin sends, + * and that the data plane plugin processes + */ +#define foreach_vpe_api_msg \ +_(dns_enable_disable, "[enable][disable]") \ +_(dns_name_server_add_del, "<ip-address> [del]") \ +_(dns_resolve_name, "<hostname>") \ +_(dns_resolve_ip, "<ip4|ip6>") \ +_(dns_name_server_add_del, "<ip-address> [del]") \ +_(dns_resolve_name, "<hostname>") + +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_resolve_ip (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_dns_resolve_ip_t *mp; + int is_ip6 = -1; + ip4_address_t addr4; + ip6_address_t addr6; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_ip6_address, &addr6)) + is_ip6 = 1; + else if (unformat (line_input, "%U", unformat_ip4_address, &addr4)) + is_ip6 = 0; + else + break; + } + + if (is_ip6 == -1) + { + errmsg ("missing address"); + return -99; + } + + /* Construct the API message */ + M (DNS_RESOLVE_IP, mp); + mp->is_ip6 = is_ip6; + if (is_ip6) + memcpy (mp->address, &addr6, sizeof (addr6)); + else + memcpy (mp->address, &addr4, sizeof (addr4)); + + /* 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 void +dns_api_hookup (vat_main_t * vam) +{ + dns_test_main_t *dtmp = &dns_test_main; + /* Hook up handlers for replies from the data plane plug-in */ +#define _(N,n) \ + vl_msg_api_set_handlers((VL_API_##N + dtmp->msg_id_base), \ + #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_vpe_api_reply_msg; +#undef _ + + /* API messages we can send */ +#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); + foreach_vpe_api_msg; +#undef _ + + /* Help strings */ +#define _(n,h) hash_set_mem (vam->help_by_name, #n, h); + foreach_vpe_api_msg; +#undef _ +} + +VAT_PLUGIN_REGISTER (dns); + + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/dns/reply_node.c b/src/plugins/dns/reply_node.c index 77d54c84019..5d7e735e885 100644 --- a/src/vnet/dns/reply_node.c +++ b/src/plugins/dns/reply_node.c @@ -13,7 +13,7 @@ * limitations under the License. */ -#include <vnet/dns/dns.h> +#include <dns/dns.h> #include <vlib/vlib.h> #include <vnet/vnet.h> diff --git a/src/vnet/dns/request_node.c b/src/plugins/dns/request_node.c index f9ad7cc0ad8..d26e579cf47 100644 --- a/src/vnet/dns/request_node.c +++ b/src/plugins/dns/request_node.c @@ -13,7 +13,7 @@ * limitations under the License. */ -#include <vnet/dns/dns.h> +#include <dns/dns.h> #include <vlib/vlib.h> #include <vnet/vnet.h> diff --git a/src/vnet/dns/resolver_process.c b/src/plugins/dns/resolver_process.c index 4ed7c799ce2..802da53cec5 100644 --- a/src/vnet/dns/resolver_process.c +++ b/src/plugins/dns/resolver_process.c @@ -13,36 +13,37 @@ * limitations under the License. */ -#include <vnet/dns/dns.h> +#include <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 message IDs */ +#include <dns/dns_msg_enum.h> #define vl_typedefs /* define message structures */ -#include <vnet/vnet_all_api_h.h> +#include <dns/dns_all_api_h.h> #undef vl_typedefs #define vl_endianfun /* define message structures */ -#include <vnet/vnet_all_api_h.h> +#include <dns/dns_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> +#include <dns/dns_all_api_h.h> #undef vl_printfun #include <vlibapi/api_helper_macros.h> -extern int +int vnet_dns_response_to_reply (u8 * response, vl_api_dns_resolve_name_reply_t * rmp, u32 * min_ttlp); -extern int +int vnet_dns_response_to_name (u8 * response, vl_api_dns_resolve_ip_reply_t * rmp, u32 * min_ttlp); @@ -197,7 +198,8 @@ reply: rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = - clib_host_to_net_u16 (VL_API_DNS_RESOLVE_NAME_REPLY); + clib_host_to_net_u16 (VL_API_DNS_RESOLVE_NAME_REPLY + + dm->msg_id_base); rmp->context = pr->client_context; min_ttl = ~0; rv = vnet_dns_response_to_reply (ep->dns_response, rmp, &min_ttl); @@ -218,7 +220,8 @@ reply: rmp = vl_msg_api_alloc (sizeof (*rmp)); rmp->_vl_msg_id = - clib_host_to_net_u16 (VL_API_DNS_RESOLVE_IP_REPLY); + clib_host_to_net_u16 (VL_API_DNS_RESOLVE_IP_REPLY + + dm->msg_id_base); rmp->context = pr->client_context; min_ttl = ~0; rv = vnet_dns_response_to_name (ep->dns_response, rmp, &min_ttl); diff --git a/src/plugins/dns/test/test_dns.py b/src/plugins/dns/test/test_dns.py new file mode 100644 index 00000000000..307e73c983a --- /dev/null +++ b/src/plugins/dns/test/test_dns.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +import unittest + +from framework import VppTestCase, VppTestRunner +from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath +from vpp_ip import VppIpPrefix +from ipaddress import * + +import scapy.compat +from scapy.contrib.mpls import MPLS +from scapy.layers.inet import IP, UDP, TCP, ICMP, icmptypes, icmpcodes +from scapy.layers.l2 import Ether +from scapy.packet import Raw +from scapy.layers.dns import DNSRR, DNS, DNSQR + + +class TestDns(VppTestCase): + """ Dns Test Cases """ + + @classmethod + def setUpClass(cls): + super(TestDns, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestDns, cls).tearDownClass() + + def setUp(self): + super(TestDns, self).setUp() + + self.create_pg_interfaces(range(1)) + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + + def tearDown(self): + super(TestDns, self).tearDown() + + def create_stream(self, src_if): + """Create input packet stream for defined interface. + + :param VppInterface src_if: Interface to create packet stream for. + """ + good_request = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IP(src=src_if.remote_ip4) / + UDP(sport=1234, dport=53) / + DNS(rd=1, qd=DNSQR(qname="bozo.clown.org"))) + + bad_request = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / + IP(src=src_if.remote_ip4) / + UDP(sport=1234, dport=53) / + DNS(rd=1, qd=DNSQR(qname="no.clown.org"))) + pkts = [good_request, bad_request] + return pkts + + def verify_capture(self, dst_if, capture): + """Verify captured input packet stream for defined interface. + + :param VppInterface dst_if: Interface to verify captured packet stream + for. + :param list capture: Captured packet stream. + """ + self.logger.info("Verifying capture on interface %s" % dst_if.name) + for packet in capture: + dns = packet[DNS] + self.assertEqual(dns.an[0].rdata, '1.2.3.4') + + def test_dns_unittest(self): + """ DNS Name Resolver Basic Functional Test """ + + # Set up an upstream name resolver. We won't actually go there + self.vapi.dns_name_server_add_del( + is_ip6=0, is_add=1, server_address=IPv4Address(u'8.8.8.8').packed) + + # Enable name resolution + self.vapi.dns_enable_disable(enable=1) + + # Manually add a static dns cache entry + self.logger.info(self.vapi.cli("dns cache add bozo.clown.org 1.2.3.4")) + + # Test the binary API + rv = self.vapi.dns_resolve_name(name='bozo.clown.org') + self.assertEqual(rv.ip4_address, IPv4Address(u'1.2.3.4').packed) + + # Configure 127.0.0.1/8 on the pg interface + self.vapi.sw_interface_add_del_address( + sw_if_index=self.pg0.sw_if_index, + prefix=VppIpPrefix("127.0.0.1", 8).encode()) + + # Send a couple of DNS request packets, one for bozo.clown.org + # and one for no.clown.org which won't resolve + + pkts = self.create_stream(self.pg0) + self.pg0.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + + self.pg_start() + pkts = self.pg0.get_capture(1) + self.verify_capture(self.pg0, pkts) + + # Make sure that the cache contents are correct + str = self.vapi.cli("show dns cache verbose") + self.assertIn('1.2.3.4', str) + self.assertIn('[P] no.clown.org:', str) + +if __name__ == '__main__': + unittest.main(testRunner=VppTestRunner) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 7aa46f4015f..7efdadc103b 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -2565,70 +2565,6 @@ static void vl_api_create_vhost_user_if_reply_t_handler_json vam->result_ready = 1; } -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 ("not implemented"); -} - -static void vl_api_dns_resolve_ip_reply_t_handler - (vl_api_dns_resolve_ip_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) - { - clib_warning ("canonical name %s", mp->name); - } - else - clib_warning ("retval %d", retval); - } -} - -static void vl_api_dns_resolve_ip_reply_t_handler_json - (vl_api_dns_resolve_ip_reply_t * mp) -{ - clib_warning ("not implemented"); -} - - static void vl_api_ip_address_details_t_handler (vl_api_ip_address_details_t * mp) { @@ -5256,8 +5192,6 @@ _(p2p_ethernet_del_reply) \ _(lldp_config_reply) \ _(sw_interface_set_lldp_reply) \ _(tcp_configure_src_addresses_reply) \ -_(dns_enable_disable_reply) \ -_(dns_name_server_add_del_reply) \ _(session_rule_add_del_reply) \ _(ip_container_proxy_add_del_reply) \ _(output_acl_set_interface_reply) \ @@ -5574,10 +5508,6 @@ _(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) \ -_(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) \ -_(DNS_RESOLVE_IP_REPLY, dns_resolve_ip_reply) \ _(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \ _(SESSION_RULES_DETAILS, session_rules_details) \ _(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply) \ @@ -20954,172 +20884,6 @@ api_sock_init_shm (vat_main_t * vam) #endif } -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_resolve_ip (vat_main_t * vam) -{ - unformat_input_t *line_input = vam->input; - vl_api_dns_resolve_ip_t *mp; - int is_ip6 = -1; - ip4_address_t addr4; - ip6_address_t addr6; - int ret; - - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (line_input, "%U", unformat_ip6_address, &addr6)) - is_ip6 = 1; - else if (unformat (line_input, "%U", unformat_ip4_address, &addr4)) - is_ip6 = 0; - else - break; - } - - if (is_ip6 == -1) - { - errmsg ("missing address"); - return -99; - } - - /* Construct the API message */ - M (DNS_RESOLVE_IP, mp); - mp->is_ip6 = is_ip6; - if (is_ip6) - memcpy (mp->address, &addr6, sizeof (addr6)); - else - memcpy (mp->address, &addr4, sizeof (addr4)); - - /* 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 void vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp) { @@ -22384,12 +22148,6 @@ _(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>]") \ _(sock_init_shm, "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>") \ -_(dns_resolve_ip, "<ip4|ip6>") \ -_(dns_name_server_add_del, "<ip-address> [del]") \ -_(dns_resolve_name, "<hostname>") \ _(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> " \ "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>") \ _(session_rules_dump, "") \ diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 3ad53f988bf..2a783810fdd 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1031,24 +1031,6 @@ list(APPEND VNET_HEADERS list(APPEND VNET_API_FILES span/span.api) ############################################################################## -# DNS proxy, API -############################################################################## -list(APPEND VNET_SOURCES - dns/dns.c - dns/dns.h - dns/dns_packet.h - dns/reply_node.c - dns/request_node.c - dns/resolver_process.c -) - -list(APPEND VNET_HEADERS - dns/dns.h -) - -list(APPEND VNET_API_FILES dns/dns.api) - -############################################################################## # Packet generator ############################################################################## diff --git a/src/vnet/vnet_all_api_h.h b/src/vnet/vnet_all_api_h.h index dc0ab5fcf9b..ad6dd6a8d79 100644 --- a/src/vnet/vnet_all_api_h.h +++ b/src/vnet/vnet_all_api_h.h @@ -62,7 +62,6 @@ #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> #include <vnet/udp/udp.api.h> #include <vnet/bier/bier.api.h> #include <vnet/ip/punt.api.h> diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index c19acc37dcc..24c37a6872b 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -3638,29 +3638,6 @@ static void *vl_api_app_namespace_add_del_t_print FINISH; } -static void *vl_api_lldp_config_t_print - (vl_api_lldp_config_t * mp, void *handle) -{ - u8 *s; - - s = format (0, "SCRIPT: lldp_config "); - 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; -} - static void *vl_api_sw_interface_set_lldp_t_print (vl_api_sw_interface_set_lldp_t * mp, void *handle) { @@ -3690,45 +3667,15 @@ 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; -} - -static void *vl_api_dns_resolve_ip_t_print - (vl_api_dns_resolve_ip_t * mp, void *handle) +static void *vl_api_lldp_config_t_print + (vl_api_lldp_config_t * mp, void *handle) { u8 *s; - s = format (0, "SCRIPT: dns_resolve_ip "); - if (mp->is_ip6) - s = format (s, "%U ", format_ip6_address, mp->address); - else - s = format (s, "%U ", format_ip4_address, mp->address); + s = format (0, "SCRIPT: lldp_config "); + 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; } @@ -4006,10 +3953,6 @@ _(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) \ -_(DNS_ENABLE_DISABLE, dns_enable_disable) \ -_(DNS_NAME_SERVER_ADD_DEL, dns_name_server_add_del) \ -_(DNS_RESOLVE_NAME, dns_resolve_name) \ -_(DNS_RESOLVE_IP, dns_resolve_ip) \ _(SESSION_RULE_ADD_DEL, session_rule_add_del) \ _(OUTPUT_ACL_SET_INTERFACE, output_acl_set_interface) \ _(QOS_RECORD_ENABLE_DISABLE, qos_record_enable_disable) \ |