diff --git a/samples/net/dns_resolve/README.rst b/samples/net/dns_resolve/README.rst index fe0d1898d73..b16161ab6e2 100644 --- a/samples/net/dns_resolve/README.rst +++ b/samples/net/dns_resolve/README.rst @@ -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) +=========== =================================== diff --git a/samples/net/dns_resolve/prj.conf b/samples/net/dns_resolve/prj.conf index 340cf15e93d..83d325569c8 100644 --- a/samples/net/dns_resolve/prj.conf +++ b/samples/net/dns_resolve/prj.conf @@ -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 diff --git a/samples/net/dns_resolve/src/main.c b/samples/net/dns_resolve/src/main.c index 98c8197a7cd..a9e50bfdbce 100644 --- a/samples/net/dns_resolve/src/main.c +++ b/samples/net/dns_resolve/src/main.c @@ -20,7 +20,18 @@ #include #include -#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 : "", 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 : "", 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(...)