Skip to content

Commit 7158f33

Browse files
ckhardinjhedberg
authored andcommitted
net: dns: extend the service resolver command line for ptr, srv, addr
The address resoution from RFC6763 is generally a PTR, SRV, TXT, and an A or AAAA. Records, so this change is mainly to start drawing a clear functional change between the DNS query shell and the DNS service shell that should be more of a "avahi-browse" or "dns-sd" functional style. So, this is not a very robust implementation since it is a chain of queries when the goal should be to get additional records from the message itself but those changes can be added iteratively. Basic point of this change is to show the procedure for the "browse" - PTR service resolution - SRV query from the result of the PTR - AAAA (or A) from the result of the SRV TXT records are ignored for now but should be added into this as additional record support is extended. Signed-off-by: Charles Hardin <ckhardin@gmail.com>
1 parent 6f41b3e commit 7158f33

File tree

1 file changed

+126
-8
lines changed
  • subsys/net/lib/shell

1 file changed

+126
-8
lines changed

subsys/net/lib/shell/dns.c

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static void dns_result_cb(enum dns_resolve_status status,
7070
break;
7171
}
7272

73-
/* fallthru */
73+
__fallthrough;
7474
default:
7575
strncpy(str, "Invalid proto family", MAX_STR_LEN + 1);
7676
break;
@@ -95,6 +95,31 @@ static void dns_result_cb(enum dns_resolve_status status,
9595
PR_WARNING("dns: Unhandled status %d received (errno %d)\n", status, errno);
9696
}
9797

98+
K_MSGQ_DEFINE(dns_infoq, sizeof(struct dns_addrinfo), 3, 1);
99+
100+
static void dns_service_cb(enum dns_resolve_status status,
101+
struct dns_addrinfo *info,
102+
void *user_data)
103+
{
104+
int r;
105+
const struct shell *sh = user_data;
106+
107+
if (status == DNS_EAI_CANCELED) {
108+
PR_WARNING("dns: Timeout while resolving service.\n");
109+
return;
110+
}
111+
112+
if ((status == DNS_EAI_INPROGRESS) && (info != NULL)) {
113+
/*
114+
* Only queue results that can be further processed.
115+
*/
116+
r = k_msgq_put(&dns_infoq, info, K_NO_WAIT);
117+
if (r < 0) {
118+
PR_WARNING("dns: k_msgq_put error %d", r);
119+
}
120+
}
121+
}
122+
98123
static const char *printable_iface(const char *iface_name,
99124
const char *found,
100125
const char *not_found)
@@ -237,7 +262,7 @@ static int cmd_net_dns_query(const struct shell *sh, size_t argc, char *argv[])
237262
{
238263

239264
#if defined(CONFIG_DNS_RESOLVER)
240-
#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
265+
#define DNS_QUERY_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
241266
struct dns_resolve_context *ctx;
242267
enum dns_query_type qtype = DNS_QUERY_TYPE_A;
243268
char *host, *type = NULL;
@@ -286,7 +311,7 @@ static int cmd_net_dns_query(const struct shell *sh, size_t argc, char *argv[])
286311
}
287312

288313
ret = dns_resolve_name(ctx, host, qtype, NULL, dns_result_cb,
289-
(void *)sh, DNS_TIMEOUT);
314+
(void *)sh, DNS_QUERY_TIMEOUT);
290315
if (ret < 0) {
291316
PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret);
292317
} else {
@@ -378,9 +403,11 @@ static int cmd_net_dns_list(const struct shell *sh, size_t argc, char *argv[])
378403
static int cmd_net_dns_service(const struct shell *sh, size_t argc, char *argv[])
379404
{
380405
#if defined(CONFIG_DNS_RESOLVER)
381-
#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
406+
#define DNS_SERVICE_TIMEOUT (MSEC_PER_SEC * 4) /* ms */
382407
struct dns_resolve_context *ctx;
408+
char *cp;
383409
char *service;
410+
uint16_t port;
384411
uint16_t dns_id;
385412
int ret, arg = 1;
386413

@@ -390,18 +417,109 @@ static int cmd_net_dns_service(const struct shell *sh, size_t argc, char *argv[]
390417
return -ENOEXEC;
391418
}
392419

420+
/* remove any lingering info data */
421+
k_msgq_purge(&dns_infoq);
422+
393423
ctx = dns_resolve_get_default();
394424
if (ctx == NULL) {
395425
PR_WARNING("No default DNS context found.\n");
396426
return -ENOEXEC;
397427
}
398428

399-
ret = dns_resolve_service(ctx, service, &dns_id, dns_result_cb,
400-
(void *)sh, DNS_TIMEOUT);
429+
ret = dns_resolve_service(ctx, service, &dns_id, dns_service_cb,
430+
(void *)sh, DNS_SERVICE_TIMEOUT);
401431
if (ret < 0) {
402432
PR_WARNING("Cannot resolve '%s' (%d)\n", service, ret);
403-
} else {
404-
PR("Query for '%s' sent.\n", service);
433+
return ret;
434+
}
435+
436+
PR("Resolve for '%s' service sent.\n", service);
437+
port = 0;
438+
for (;;) {
439+
struct dns_addrinfo info;
440+
enum dns_query_type qtype;
441+
char query[DNS_MAX_NAME_SIZE + 1];
442+
union {
443+
char in4[INET_ADDRSTRLEN];
444+
char in6[INET6_ADDRSTRLEN];
445+
} str;
446+
447+
ret = k_msgq_get(&dns_infoq, &info, K_MSEC(DNS_SERVICE_TIMEOUT));
448+
if (ret < 0) {
449+
/* just assume a timeout so no more data to process */
450+
break;
451+
}
452+
453+
switch (info.ai_family) {
454+
case AF_INET:
455+
cp = net_addr_ntop(AF_INET,
456+
&net_sin(&info.ai_addr)->sin_addr,
457+
str.in4, sizeof(str.in4));
458+
PR("AF_INET %s:%u\n", cp ? cp : "<invalid>", port);
459+
break;
460+
461+
case AF_INET6:
462+
cp = net_addr_ntop(AF_INET6,
463+
&net_sin6(&info.ai_addr)->sin6_addr,
464+
str.in6, sizeof(str.in6));
465+
PR("AF_INET6 [%s]:%u\n", cp ? cp : "<invalid>", port);
466+
break;
467+
468+
case AF_LOCAL:
469+
PR("AF_LOCAL %.*s\n",
470+
(int)info.ai_addrlen, info.ai_canonname);
471+
472+
snprintf(query, sizeof(query), "%.*s",
473+
info.ai_addrlen, info.ai_canonname);
474+
475+
qtype = DNS_QUERY_TYPE_SRV;
476+
ret = dns_resolve_name(ctx, query, qtype,
477+
&dns_id,
478+
dns_service_cb, (void *)sh,
479+
DNS_SERVICE_TIMEOUT);
480+
if (ret < 0) {
481+
return ret;
482+
}
483+
break;
484+
485+
case AF_UNSPEC:
486+
if (info.ai_extension == DNS_RESOLVE_SRV) {
487+
PR("SRV %d %d %d %.*s\n",
488+
info.ai_srv.priority,
489+
info.ai_srv.weight,
490+
info.ai_srv.port,
491+
(int)info.ai_srv.targetlen,
492+
info.ai_srv.target);
493+
494+
port = info.ai_srv.port;
495+
496+
snprintf(query, sizeof(query), "%.*s",
497+
info.ai_srv.targetlen,
498+
info.ai_srv.target);
499+
500+
/*
501+
* Sending a query for both AAAA and A records
502+
* should be ok, but the resolver doesn't
503+
* gracefully handle the query for different
504+
* types.
505+
*/
506+
qtype = DNS_QUERY_TYPE_AAAA;
507+
ret = dns_resolve_name(ctx, query, qtype,
508+
&dns_id,
509+
dns_service_cb,
510+
(void *)sh,
511+
DNS_SERVICE_TIMEOUT);
512+
if (ret < 0) {
513+
return ret;
514+
}
515+
break;
516+
}
517+
518+
__fallthrough;
519+
default:
520+
PR_WARNING("dns: unhandled info %u on msgq\n", info.ai_family);
521+
break;
522+
}
405523
}
406524
#else
407525
PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "

0 commit comments

Comments
 (0)