Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dns/client: add async getaddrinfo usage #470

Merged
merged 4 commits into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
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
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;
}