Skip to content

Commit

Permalink
dns/client: add async getaddrinfo (#470)
Browse files Browse the repository at this point in the history
  • Loading branch information
sreimers authored Aug 14, 2022
1 parent 18fb840 commit 6729125
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/re_dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ struct dnsc_conf {
uint32_t conn_timeout; /* in [ms] */
uint32_t idle_timeout; /* in [ms] */
uint32_t cache_ttl_max; /* in [s] 0 for disabled */
bool getaddrinfo; /* use getaddrinfo (by default disabled) */
};

int dnsc_alloc(struct dnsc **dcpp, const struct dnsc_conf *conf,
Expand All @@ -220,6 +221,7 @@ int dnsc_notify(struct dns_query **qp, struct dnsc *dnsc, const char *name,
dns_query_h *qh, void *arg);
void dnsc_cache_flush(struct dnsc *dnsc);
void dnsc_cache_max(struct dnsc *dnsc, uint32_t max);
void dnsc_getaddrinfo(struct dnsc *dnsc, bool active);


/* DNS System functions */
Expand Down
137 changes: 137 additions & 0 deletions src/dns/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
* Copyright (C) 2010 Creytiv.com
* Copyright (C) 2022 Sebastian Reimers
*/
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1

#ifndef WIN32
#include <netdb.h>
#endif

#include <string.h>
#include <re_types.h>
#include <re_fmt.h>
Expand All @@ -17,6 +24,8 @@
#include <re_tcp.h>
#include <re_sys.h>
#include <re_dns.h>
#include <re_net.h>
#include <re_main.h>


#define DEBUG_MODULE "dnsc"
Expand All @@ -33,6 +42,7 @@ enum {
SRVC_MAX = 32,
RR_MAX = 32,
CACHE_TTL_MAX = 1800,
GETADDRINFO_TTL = 60
};


Expand Down Expand Up @@ -103,6 +113,7 @@ static const struct dnsc_conf default_conf = {
CONN_TIMEOUT,
IDLE_TIMEOUT,
CACHE_TTL_MAX,
false
};


Expand Down Expand Up @@ -765,6 +776,108 @@ static bool query_cache_handler(struct dns_query *q)
}


static int async_getaddrinfo(void *arg)
{
struct dns_query *q = arg;
int err;
struct addrinfo *res0 = NULL;
struct addrinfo *res;
struct addrinfo hints;
struct sa sa;

memset(&hints, 0, sizeof(hints));

if (q->type == DNS_TYPE_A)
hints.ai_family = AF_INET;
if (q->type == DNS_TYPE_AAAA)
hints.ai_family = AF_INET6;
hints.ai_flags = AI_ADDRCONFIG;

err = getaddrinfo(q->name, NULL, &hints, &res0);
if (err)
return EADDRNOTAVAIL;

for (res = res0; res; res = res->ai_next) {
struct dnsrr *rr = dns_rr_alloc();
if (!rr) {
err = ENOMEM;
goto out;
}

str_dup(&rr->name, q->name);

rr->dnsclass = DNS_CLASS_IN;
rr->ttl = GETADDRINFO_TTL;

err = sa_set_sa(&sa, res->ai_addr);
if (err) {
mem_deref(rr);
continue;
}

if (sa_af(&sa) == AF_INET) {
rr->type = DNS_TYPE_A;
rr->rdlen = 4;
rr->rdata.a.addr = sa_in(&sa);
}

if (sa_af(&sa) == AF_INET6) {
rr->type = DNS_TYPE_AAAA;
rr->rdlen = 16;
sa_in6(&sa, rr->rdata.aaaa.addr);
}

list_append(&q->rrlv[0], &rr->le_priv, rr);
}

out:
if (err)
list_flush(&q->rrlv[0]);

freeaddrinfo(res0);

return err;
}


static void getaddrinfo_h(int err, void *arg)
{
struct dns_query *q = arg;
bool cache = q->dnsc->conf.cache_ttl_max > 0;

DEBUG_INFO("--- ANSWER SECTION (getaddrinfo) id: %d ---\n", q->id);

if (!err) {
DEBUG_INFO("%H %s\n", dns_rr_print,
list_ledata(list_head(&q->rrlv[0])),
cache ? "(caching)" : "");
}

query_handler(q, err, &q->rrlv[0], &q->rrlv[1], &q->rrlv[2]);

if (err || !cache) {
mem_deref(q);
return;
}

hash_append(q->dnsc->ht_query_cache, hash_joaat_str_ci(q->name),
&q->le, q);
tmr_start(&q->tmr_ttl, GETADDRINFO_TTL * 1000, ttl_timeout_handler, q);
}


static int query_getaddrinfo(struct dns_query *q)
{
int err;

err = re_thread_async(async_getaddrinfo, getaddrinfo_h, q);
if (err)
DEBUG_WARNING("re_thread_async: %m\n", err);

return err;
}


static int query(struct dns_query **qp, struct dnsc *dnsc, uint8_t opcode,
const char *name, uint16_t type, uint16_t dnsclass,
const struct dnsrr *ans_rr, int proto,
Expand Down Expand Up @@ -826,6 +939,15 @@ static int query(struct dns_query **qp, struct dnsc *dnsc, uint8_t opcode,
if (query_cache_handler(q))
goto out;

if (dnsc->conf.getaddrinfo &&
(q->type == DNS_TYPE_A || q->type == DNS_TYPE_AAAA)) {
err = query_getaddrinfo(q);
if (err)
goto error;

goto out;
}

if (proto == IPPROTO_TCP)
q->mb.pos += 2;

Expand Down Expand Up @@ -1150,3 +1272,18 @@ void dnsc_cache_max(struct dnsc *dnsc, uint32_t max)
if (!max)
dnsc_cache_flush(dnsc);
}


/**
* Enable/Disable getaddrinfo usage
*
* @param dnsc DNS Client
* @param max true for enabled, otherwise disabled (default)
*/
void dnsc_getaddrinfo(struct dnsc *dnsc, bool active)
{
if (!dnsc)
return;

dnsc->conf.getaddrinfo = active;
}

0 comments on commit 6729125

Please sign in to comment.