samples: net: dns: Add mDNS client support to DNS resolver sample
The DNS resolver example enables mDNS client support and then queries zephyr.local hostname. The net-tools project has example avahi-daemon script that will response these .local queries and can be used in testing. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
1865b91f97
commit
af63ae28ec
3 changed files with 181 additions and 86 deletions
|
@ -13,6 +13,10 @@ If a CNAME is received, the DNS resolver will create another DNS query.
|
|||
The number of additional queries is controlled by the
|
||||
DNS_RESOLVER_ADDITIONAL_QUERIES Kconfig variable.
|
||||
|
||||
The multicast DNS (mDNS) client resolver support can be enabled by setting
|
||||
CONFIG_MDNS_RESOLVER Kconfig variable.
|
||||
See https://tools.ietf.org/html/rfc6762 for more details about mDNS.
|
||||
|
||||
For more information about DNS configuration variables, see:
|
||||
:file:`subsys/net/lib/dns/Kconfig`. The DNS resolver API can be found at
|
||||
:file:`include/net/dns_resolve.h`. The sample code can be found at:
|
||||
|
@ -34,28 +38,6 @@ Requirements
|
|||
dnsmasq -v
|
||||
Dnsmasq version 2.76 Copyright (c) 2000-2016 Simon Kelley
|
||||
|
||||
|
||||
|
||||
Wiring
|
||||
******
|
||||
|
||||
The ENC28J60 module is an Ethernet device with SPI interface.
|
||||
The following pins must be connected from the ENC28J60 device to the
|
||||
Arduino 101 board:
|
||||
|
||||
=========== ===================================
|
||||
Arduino 101 ENC28J60 (pin numbers on the board)
|
||||
=========== ===================================
|
||||
D13 SCK (1)
|
||||
D12 SO (3)
|
||||
D11 SI (2)
|
||||
D10 CS (7)
|
||||
D04 INT (5)
|
||||
3.3V VCC (10)
|
||||
GDN GND (9)
|
||||
=========== ===================================
|
||||
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
|
@ -90,9 +72,7 @@ Open a terminal window and type:
|
|||
.. code-block:: console
|
||||
|
||||
$ cd net-tools
|
||||
$ ./dnsmasq.sh
|
||||
|
||||
('su' or 'sudo' may be required.)
|
||||
$ sudo ./dnsmasq.sh
|
||||
|
||||
The default project configurations settings for this sample uses the public
|
||||
Google DNS servers. In order to use the local dnsmasq server, please edit
|
||||
|
@ -122,9 +102,15 @@ Open a terminal window and type:
|
|||
|
||||
$ killall -s KILL dnsmasq
|
||||
|
||||
|
||||
Try to launch the dnsmasq application again.
|
||||
|
||||
For testing mDNS, use Avahi script in net-tools project:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ cd net-tools
|
||||
$ ./avahi-daemon.sh
|
||||
|
||||
QEMU x86
|
||||
========
|
||||
|
||||
|
@ -186,3 +172,19 @@ Open a terminal window and type:
|
|||
Use 'dmesg' to find the right USB device.
|
||||
|
||||
Once the binary is loaded into the Arduino 101 board, press the RESET button.
|
||||
|
||||
The ENC28J60 module is an Ethernet device with SPI interface.
|
||||
The following pins must be connected from the ENC28J60 device to the
|
||||
Arduino 101 board:
|
||||
|
||||
=========== ===================================
|
||||
Arduino 101 ENC28J60 (pin numbers on the board)
|
||||
=========== ===================================
|
||||
D13 SCK (1)
|
||||
D12 SO (3)
|
||||
D11 SI (2)
|
||||
D10 CS (7)
|
||||
D04 INT (5)
|
||||
3.3V VCC (10)
|
||||
GDN GND (9)
|
||||
=========== ===================================
|
||||
|
|
|
@ -3,19 +3,19 @@ CONFIG_NET_UDP=y
|
|||
CONFIG_RANDOM_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_NET_PKT_RX_COUNT=4
|
||||
CONFIG_NET_PKT_TX_COUNT=4
|
||||
CONFIG_NET_BUF_RX_COUNT=14
|
||||
CONFIG_NET_BUF_TX_COUNT=14
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=10
|
||||
CONFIG_NET_BUF_TX_COUNT=10
|
||||
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
|
||||
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG=y
|
||||
CONFIG_SYS_LOG_NET_LEVEL=4
|
||||
CONFIG_SYS_LOG_NET_LEVEL=2
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
#CONFIG_NET_DEBUG_NET_PKT=y
|
||||
CONFIG_NET_DEBUG_NET_PKT=y
|
||||
CONFIG_NET_DEBUG_DNS_RESOLVE=y
|
||||
#CONFIG_NET_DEBUG_CONTEXT=y
|
||||
#CONFIG_NET_DEBUG_CORE=y
|
||||
|
@ -24,27 +24,35 @@ CONFIG_NET_DEBUG_DNS_RESOLVE=y
|
|||
#CONFIG_NET_DEBUG_IPV6=y
|
||||
#CONFIG_NET_DEBUG_UDP=y
|
||||
#CONFIG_NET_DEBUG_DHCPV4=y
|
||||
#CONFIG_SLIP_DEBUG=y
|
||||
#CONFIG_NET_DEBUG_L2_ETHERNET=y
|
||||
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
|
||||
# Enable the DNS resolver
|
||||
CONFIG_DNS_RESOLVER=y
|
||||
# Enable additional buffers
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=5
|
||||
# Enable additional queries
|
||||
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
|
||||
# Enable mDNS support
|
||||
CONFIG_MDNS_RESOLVER=y
|
||||
|
||||
CONFIG_DNS_RESOLVER_MAX_SERVERS=2
|
||||
CONFIG_DNS_SERVER_IP_ADDRESSES=y
|
||||
CONFIG_DNS_NUM_CONCUR_QUERIES=2
|
||||
CONFIG_DNS_NUM_CONCUR_QUERIES=5
|
||||
|
||||
# Use local dnsmasq server for testing
|
||||
CONFIG_DNS_SERVER1="[2001:db8::2]:15353"
|
||||
CONFIG_DNS_SERVER2="192.0.2.2:15353"
|
||||
|
||||
# Google DNS IPv4 and IPv6 servers
|
||||
CONFIG_DNS_SERVER1="8.8.8.8"
|
||||
CONFIG_DNS_SERVER2="2001:4860:4860::8888"
|
||||
#CONFIG_DNS_SERVER1="8.8.8.8"
|
||||
#CONFIG_DNS_SERVER2="2001:4860:4860::8888"
|
||||
|
||||
CONFIG_NET_DHCPV4=y
|
||||
# Router is needed when resolving using external DNS servers
|
||||
CONFIG_NET_APP_NEED_IPV6_ROUTER=n
|
||||
|
||||
CONFIG_NET_MGMT=y
|
||||
CONFIG_NET_MGMT_EVENT=y
|
||||
|
@ -52,7 +60,11 @@ CONFIG_NET_MGMT_EVENT=y
|
|||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_APP_SETTINGS=y
|
||||
CONFIG_NET_APP_NEED_IPV6=y
|
||||
CONFIG_NET_APP_NEED_IPV4=y
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
|
||||
|
||||
CONFIG_MAIN_STACK_SIZE=1504
|
||||
|
|
|
@ -20,7 +20,18 @@
|
|||
#include <net/net_mgmt.h>
|
||||
#include <net/dns_resolve.h>
|
||||
|
||||
#define DNS_TIMEOUT 2000 /* ms */
|
||||
#if defined(CONFIG_MDNS_RESOLVER)
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct k_delayed_work mdns_ipv4_timer;
|
||||
static void do_mdns_ipv4_lookup(struct k_work *work);
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct k_delayed_work mdns_ipv6_timer;
|
||||
static void do_mdns_ipv6_lookup(struct k_work *work);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DNS_TIMEOUT K_SECONDS(2)
|
||||
|
||||
void dns_result_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
|
@ -54,6 +65,64 @@ void dns_result_cb(enum dns_resolve_status status,
|
|||
return;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
hr_family = "IPv4";
|
||||
addr = &net_sin(&info->ai_addr)->sin_addr;
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV4)
|
||||
k_delayed_work_init(&mdns_ipv4_timer, do_mdns_ipv4_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv4_timer, 0);
|
||||
#endif
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
hr_family = "IPv6";
|
||||
addr = &net_sin6(&info->ai_addr)->sin6_addr;
|
||||
|
||||
#if defined(CONFIG_MDNS_RESOLVER) && defined(CONFIG_NET_IPV6)
|
||||
k_delayed_work_init(&mdns_ipv6_timer, do_mdns_ipv6_lookup);
|
||||
k_delayed_work_submit(&mdns_ipv6_timer, 0);
|
||||
#endif
|
||||
} else {
|
||||
NET_ERR("Invalid IP address family %d", info->ai_family);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_INFO("%s %s address: %s", user_data ? (char *)user_data : "<null>", hr_family,
|
||||
net_addr_ntop(info->ai_family, addr,
|
||||
hr_addr, sizeof(hr_addr)));
|
||||
}
|
||||
|
||||
void mdns_result_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
char hr_addr[NET_IPV6_ADDR_LEN];
|
||||
char *hr_family;
|
||||
void *addr;
|
||||
|
||||
switch (status) {
|
||||
case DNS_EAI_CANCELED:
|
||||
NET_INFO("DNS query was canceled");
|
||||
return;
|
||||
case DNS_EAI_FAIL:
|
||||
NET_INFO("DNS resolve failed");
|
||||
return;
|
||||
case DNS_EAI_NODATA:
|
||||
NET_INFO("Cannot resolve address");
|
||||
return;
|
||||
case DNS_EAI_ALLDONE:
|
||||
NET_INFO("DNS resolving finished");
|
||||
return;
|
||||
case DNS_EAI_INPROGRESS:
|
||||
break;
|
||||
default:
|
||||
NET_INFO("DNS resolving error (%d)", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
hr_family = "IPv4";
|
||||
addr = &net_sin(&info->ai_addr)->sin_addr;
|
||||
|
@ -65,7 +134,7 @@ void dns_result_cb(enum dns_resolve_status status,
|
|||
return;
|
||||
}
|
||||
|
||||
NET_INFO("%s address: %s", hr_family,
|
||||
NET_INFO("%s %s address: %s", user_data ? (char *)user_data : "<null>", hr_family,
|
||||
net_addr_ntop(info->ai_family, addr,
|
||||
hr_addr, sizeof(hr_addr)));
|
||||
}
|
||||
|
@ -76,14 +145,15 @@ static struct k_delayed_work ipv4_timer;
|
|||
|
||||
static void do_ipv4_lookup(struct k_work *work)
|
||||
{
|
||||
static const char *query = "www.zephyrproject.org";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv4 address (%d)", ret);
|
||||
|
@ -147,6 +217,32 @@ static void setup_dhcpv4(struct net_if *iface)
|
|||
#define setup_dhcpv4(...)
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) || defined(CONFIG_NET_DHCPV4)
|
||||
#if defined(CONFIG_MDNS_RESOLVER)
|
||||
static void do_mdns_ipv4_lookup(struct k_work *work)
|
||||
{
|
||||
static const char *query = "zephyr.local";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
NET_DBG("Doing mDNS IPv4 query");
|
||||
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
mdns_result_cb,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve mDNS IPv4 address (%d)", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("mDNS id %u", dns_id);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_DHCPV4)
|
||||
|
||||
#if !defined(CONFIG_NET_APP_MY_IPV4_ADDR)
|
||||
|
@ -155,6 +251,7 @@ static void setup_dhcpv4(struct net_if *iface)
|
|||
|
||||
static void setup_ipv4(struct net_if *iface)
|
||||
{
|
||||
static const char *query = "www.zephyrproject.org";
|
||||
char hr_addr[NET_IPV4_ADDR_LEN];
|
||||
struct in_addr addr;
|
||||
u16_t dns_id;
|
||||
|
@ -170,11 +267,11 @@ static void setup_ipv4(struct net_if *iface)
|
|||
NET_INFO("IPv4 address: %s",
|
||||
net_addr_ntop(AF_INET, &addr, hr_addr, NET_IPV4_ADDR_LEN));
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_A,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv4 address (%d)", ret);
|
||||
|
@ -194,19 +291,17 @@ static void setup_ipv4(struct net_if *iface)
|
|||
#error "You need to define an IPv6 address!"
|
||||
#endif
|
||||
|
||||
static struct net_mgmt_event_callback mgmt6_cb;
|
||||
static struct k_delayed_work ipv6_timer;
|
||||
|
||||
static void do_ipv6_lookup(struct k_work *work)
|
||||
static void do_ipv6_lookup(void)
|
||||
{
|
||||
static const char *query = "www.zephyrproject.org";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
ret = dns_get_addr_info("www.zephyrproject.org",
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
&dns_id,
|
||||
dns_result_cb,
|
||||
NULL,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve IPv6 address (%d)", ret);
|
||||
|
@ -216,48 +311,34 @@ static void do_ipv6_lookup(struct k_work *work)
|
|||
NET_DBG("DNS id %u", dns_id);
|
||||
}
|
||||
|
||||
/* DNS query will most probably fail if we do not have a default
|
||||
* router configured because typically the DNS server is outside of local
|
||||
* network. So wait for that before continuing.
|
||||
*/
|
||||
static void ipv6_router_add_handler(struct net_mgmt_event_callback *cb,
|
||||
u32_t mgmt_event,
|
||||
struct net_if *iface)
|
||||
{
|
||||
if (mgmt_event != NET_EVENT_IPV6_ROUTER_ADD) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We cannot run DNS lookup directly from this thread as the
|
||||
* management event thread stack is very small by default.
|
||||
* So run it from work queue instead.
|
||||
*/
|
||||
k_delayed_work_init(&ipv6_timer, do_ipv6_lookup);
|
||||
k_delayed_work_submit(&ipv6_timer, 0);
|
||||
}
|
||||
|
||||
static void setup_ipv6(struct net_if *iface)
|
||||
{
|
||||
char hr_addr[NET_IPV6_ADDR_LEN];
|
||||
struct in6_addr addr;
|
||||
do_ipv6_lookup();
|
||||
}
|
||||
|
||||
if (net_addr_pton(AF_INET6, CONFIG_NET_APP_MY_IPV6_ADDR, &addr)) {
|
||||
NET_ERR("Invalid address: %s", CONFIG_NET_APP_MY_IPV6_ADDR);
|
||||
#if defined(CONFIG_MDNS_RESOLVER)
|
||||
static void do_mdns_ipv6_lookup(struct k_work *work)
|
||||
{
|
||||
static const char *query = "zephyr.local";
|
||||
u16_t dns_id;
|
||||
int ret;
|
||||
|
||||
NET_DBG("Doing mDNS IPv6 query");
|
||||
|
||||
ret = dns_get_addr_info(query,
|
||||
DNS_QUERY_TYPE_AAAA,
|
||||
&dns_id,
|
||||
mdns_result_cb,
|
||||
(void *)query,
|
||||
DNS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve mDNS IPv6 address (%d)", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
net_mgmt_init_event_callback(&mgmt6_cb, ipv6_router_add_handler,
|
||||
NET_EVENT_IPV6_ROUTER_ADD);
|
||||
net_mgmt_add_event_callback(&mgmt6_cb);
|
||||
|
||||
net_if_ipv6_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
|
||||
|
||||
NET_INFO("IPv6 address: %s",
|
||||
net_addr_ntop(AF_INET6, &addr, hr_addr, NET_IPV6_ADDR_LEN));
|
||||
|
||||
NET_INFO("Waiting for IPv6 default router notification "
|
||||
"before issuing DNS query");
|
||||
NET_DBG("mDNS id %u", dns_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define setup_ipv6(...)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue