Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 126 additions & 8 deletions subsys/net/lib/shell/dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static void dns_result_cb(enum dns_resolve_status status,
break;
}

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

K_MSGQ_DEFINE(dns_infoq, sizeof(struct dns_addrinfo), 3, 1);

static void dns_service_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
int r;
const struct shell *sh = user_data;

if (status == DNS_EAI_CANCELED) {
PR_WARNING("dns: Timeout while resolving service.\n");
return;
}

if ((status == DNS_EAI_INPROGRESS) && (info != NULL)) {
/*
* Only queue results that can be further processed.
*/
r = k_msgq_put(&dns_infoq, info, K_NO_WAIT);
if (r < 0) {
PR_WARNING("dns: k_msgq_put error %d", r);
}
}
}

static const char *printable_iface(const char *iface_name,
const char *found,
const char *not_found)
Expand Down Expand Up @@ -237,7 +262,7 @@ static int cmd_net_dns_query(const struct shell *sh, size_t argc, char *argv[])
{

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

ret = dns_resolve_name(ctx, host, qtype, NULL, dns_result_cb,
(void *)sh, DNS_TIMEOUT);
(void *)sh, DNS_QUERY_TIMEOUT);
if (ret < 0) {
PR_WARNING("Cannot resolve '%s' (%d)\n", host, ret);
} else {
Expand Down Expand Up @@ -378,9 +403,11 @@ static int cmd_net_dns_list(const struct shell *sh, size_t argc, char *argv[])
static int cmd_net_dns_service(const struct shell *sh, size_t argc, char *argv[])
{
#if defined(CONFIG_DNS_RESOLVER)
#define DNS_TIMEOUT (MSEC_PER_SEC * 2) /* ms */
#define DNS_SERVICE_TIMEOUT (MSEC_PER_SEC * 4) /* ms */
struct dns_resolve_context *ctx;
char *cp;
char *service;
uint16_t port;
uint16_t dns_id;
int ret, arg = 1;

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

/* remove any lingering info data */
k_msgq_purge(&dns_infoq);

ctx = dns_resolve_get_default();
if (ctx == NULL) {
PR_WARNING("No default DNS context found.\n");
return -ENOEXEC;
}

ret = dns_resolve_service(ctx, service, &dns_id, dns_result_cb,
(void *)sh, DNS_TIMEOUT);
ret = dns_resolve_service(ctx, service, &dns_id, dns_service_cb,
(void *)sh, DNS_SERVICE_TIMEOUT);
if (ret < 0) {
PR_WARNING("Cannot resolve '%s' (%d)\n", service, ret);
} else {
PR("Query for '%s' sent.\n", service);
return ret;
}

PR("Resolve for '%s' service sent.\n", service);
port = 0;
for (;;) {
struct dns_addrinfo info;
enum dns_query_type qtype;
char query[DNS_MAX_NAME_SIZE + 1];
union {
char in4[INET_ADDRSTRLEN];
char in6[INET6_ADDRSTRLEN];
} str;

ret = k_msgq_get(&dns_infoq, &info, K_MSEC(DNS_SERVICE_TIMEOUT));
if (ret < 0) {
/* just assume a timeout so no more data to process */
break;
}

switch (info.ai_family) {
case AF_INET:
cp = net_addr_ntop(AF_INET,
&net_sin(&info.ai_addr)->sin_addr,
str.in4, sizeof(str.in4));
PR("AF_INET %s:%u\n", cp ? cp : "<invalid>", port);
break;

case AF_INET6:
cp = net_addr_ntop(AF_INET6,
&net_sin6(&info.ai_addr)->sin6_addr,
str.in6, sizeof(str.in6));
PR("AF_INET6 [%s]:%u\n", cp ? cp : "<invalid>", port);
break;

case AF_LOCAL:
PR("AF_LOCAL %.*s\n",
(int)info.ai_addrlen, info.ai_canonname);

snprintf(query, sizeof(query), "%.*s",
info.ai_addrlen, info.ai_canonname);

qtype = DNS_QUERY_TYPE_SRV;
ret = dns_resolve_name(ctx, query, qtype,
&dns_id,
dns_service_cb, (void *)sh,
DNS_SERVICE_TIMEOUT);
if (ret < 0) {
return ret;
}
break;

case AF_UNSPEC:
if (info.ai_extension == DNS_RESOLVE_SRV) {
PR("SRV %d %d %d %.*s\n",
info.ai_srv.priority,
info.ai_srv.weight,
info.ai_srv.port,
(int)info.ai_srv.targetlen,
info.ai_srv.target);

port = info.ai_srv.port;

snprintf(query, sizeof(query), "%.*s",
info.ai_srv.targetlen,
info.ai_srv.target);

/*
* Sending a query for both AAAA and A records
* should be ok, but the resolver doesn't
* gracefully handle the query for different
* types.
*/
qtype = DNS_QUERY_TYPE_AAAA;
ret = dns_resolve_name(ctx, query, qtype,
&dns_id,
dns_service_cb,
(void *)sh,
DNS_SERVICE_TIMEOUT);
if (ret < 0) {
return ret;
}
break;
}

__fallthrough;
default:
PR_WARNING("dns: unhandled info %u on msgq\n", info.ai_family);
break;
}
}
#else
PR_INFO("DNS resolver not supported. Set CONFIG_DNS_RESOLVER to "
Expand Down