net: shell: Add DNS query support

Add "net dns <hostname> [A | AAAA]" command support that can be
used to query IPv4 or IPv6 address for a given host name.

Change-Id: I86b2258efa994a67163f9b3b340f44d65767f11b
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-03-21 11:03:57 +02:00
commit aa11cef227

View file

@ -15,6 +15,7 @@
#include <shell/shell.h>
#include <net/net_if.h>
#include <net/dns_resolve.h>
#include <misc/printk.h>
#include "route.h"
@ -568,6 +569,198 @@ static int shell_cmd_conn(int argc, char *argv[])
return 0;
}
#if defined(CONFIG_DNS_RESOLVER)
static void dns_result_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
bool *first = user_data;
if (status == DNS_EAI_CANCELED) {
printk("\nTimeout while resolving name.\n");
*first = false;
return;
}
if (status == DNS_EAI_INPROGRESS && info) {
char addr[NET_IPV6_ADDR_LEN];
if (*first) {
printk("\n");
*first = false;
}
if (info->ai_family == AF_INET) {
net_addr_ntop(AF_INET,
&net_sin(&info->ai_addr)->sin_addr,
addr, NET_IPV4_ADDR_LEN);
} else if (info->ai_family == AF_INET6) {
net_addr_ntop(AF_INET6,
&net_sin6(&info->ai_addr)->sin6_addr,
addr, NET_IPV6_ADDR_LEN);
} else {
strncpy(addr, "Invalid protocol family",
sizeof(addr));
}
printk("\t%s\n", addr);
return;
}
if (status == DNS_EAI_ALLDONE) {
printk("All results received\n");
*first = false;
return;
}
if (status == DNS_EAI_FAIL) {
printk("No such name found.\n");
*first = false;
return;
}
printk("Unhandled status %d received\n", status);
}
static void print_dns_info(struct dns_resolve_context *ctx)
{
int i;
printk("DNS servers:\n");
for (i = 0; i < CONFIG_DNS_RESOLVER_MAX_SERVERS; i++) {
if (ctx->servers[i].dns_server.family == AF_INET) {
printk("\t%s:%u\n",
net_sprint_ipv4_addr(
&net_sin(&ctx->servers[i].dns_server)->
sin_addr),
ntohs(net_sin(&ctx->servers[i].
dns_server)->sin_port));
} else if (ctx->servers[i].dns_server.family == AF_INET6) {
printk("\t[%s]:%u\n",
net_sprint_ipv6_addr(
&net_sin6(&ctx->servers[i].dns_server)->
sin6_addr),
ntohs(net_sin6(&ctx->servers[i].
dns_server)->sin6_port));
}
}
printk("Pending queries:\n");
for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
int32_t remaining;
if (!ctx->queries[i].cb) {
continue;
}
remaining =
k_delayed_work_remaining_get(&ctx->queries[i].timer);
if (ctx->queries[i].query_type == DNS_QUERY_TYPE_A) {
printk("\tIPv4[%u]: %s remaining %d\n",
ctx->queries[i].id,
ctx->queries[i].query,
remaining);
} else if (ctx->queries[i].query_type == DNS_QUERY_TYPE_AAAA) {
printk("\tIPv6[%u]: %s remaining %d\n",
ctx->queries[i].id,
ctx->queries[i].query,
remaining);
}
}
}
#endif
static int shell_cmd_dns(int argc, char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
#define DNS_TIMEOUT 2000 /* ms */
struct dns_resolve_context *ctx;
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
char *host, *type = NULL;
bool first = true;
int arg = 1;
int ret, i;
if (strcmp(argv[0], "dns")) {
arg++;
}
if (!argv[arg]) {
/* DNS status */
ctx = dns_resolve_get_default();
if (!ctx) {
printk("No default DNS context found.\n");
return 0;
}
print_dns_info(ctx);
return 0;
}
if (strcmp(argv[arg], "cancel") == 0) {
ctx = dns_resolve_get_default();
if (!ctx) {
printk("No default DNS context found.\n");
return 0;
}
for (ret = 0, i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) {
if (!ctx->queries[i].cb) {
continue;
}
if (!dns_resolve_cancel(ctx, ctx->queries[i].id)) {
ret++;
}
}
if (ret) {
printk("Cancelled %d pending requests.\n", ret);
} else {
printk("No pending DNS requests.\n");
}
return 0;
}
host = argv[arg++];
if (argv[arg]) {
type = argv[arg];
}
if (type) {
if (strcmp(type, "A") == 0) {
qtype = DNS_QUERY_TYPE_A;
printk("IPv4 address type\n");
} else if (strcmp(type, "AAAA") == 0) {
qtype = DNS_QUERY_TYPE_AAAA;
printk("IPv6 address type\n");
} else {
printk("Unknown query type, specify either "
"A or AAAA\n");
return 0;
}
}
ret = dns_get_addr_info(host, qtype, NULL, dns_result_cb, &first,
DNS_TIMEOUT);
if (ret < 0) {
printk("Cannot resolve '%s' (%d)\n", host, ret);
} else {
printk("Query for '%s' sent.\n", host);
}
#else
printk("DNS resolver not supported.\n");
#endif
return 0;
}
static int shell_cmd_iface(int argc, char *argv[])
{
ARG_UNUSED(argc);
@ -1323,6 +1516,10 @@ static int shell_cmd_help(int argc, char *argv[])
/* Keep the commands in alphabetical order */
printk("net allocs\n\tPrint network buffer allocations\n");
printk("net conn\n\tPrint information about network connections\n");
printk("net dns\n\tShow how DNS is configured\n");
printk("net dns cancel\n\tCancel all pending requests\n");
printk("net dns <hostname> [A or AAAA]\n\tQuery IPv4 address (default)"
" or IPv6 address for a host name\n");
printk("net iface\n\tPrint information about network interfaces\n");
printk("net mem\n\tPrint network buffer information\n");
printk("net nbr\n\tPrint neighbor information\n");
@ -1341,6 +1538,7 @@ static struct shell_cmd net_commands[] = {
/* Keep the commands in alphabetical order */
{ "allocs", shell_cmd_allocs, NULL },
{ "conn", shell_cmd_conn, NULL },
{ "dns", shell_cmd_dns, NULL },
{ "help", shell_cmd_help, NULL },
{ "iface", shell_cmd_iface, NULL },
{ "mem", shell_cmd_mem, NULL },