Skip to content
Permalink
Browse files

Fix 669 - use thread-safe res_n* functions over res_* functions. Fixes

…#174. Fixes #668.

Found by: fhorst
Patch by: michaelortmann
Fixes: #174, #669

Eggdrop is based on mtr, so this fix is based on newer code from mtr: https://github.com/traviscross/mtr/blob/f456d04e389e254ddf683a2d0e85c49cc1c3402d/dns.c
Fix memleak in coredns.c dorequest()
  • Loading branch information...
michaelortmann authored and vanosg committed Jun 25, 2019
1 parent b288a36 commit 35912bea960d0710008a299b646b6b712bfbb7b1
Showing with 46 additions and 41 deletions.
  1. +0 −5 aclocal.m4
  2. +30 −20 src/mod/dns.mod/coredns.c
  3. +16 −16 src/mod/dns.mod/dns.c
@@ -752,11 +752,6 @@ AC_DEFUN([EGG_CHECK_OS],
FreeBSD|OpenBSD|NetBSD)
SHLIB_CC="$CC -fPIC"
SHLIB_LD="$CC -shared"
case "$egg_cv_var_system_type" in
*NetBSD)
AC_DEFINE(NETBSD_HACKS, 1, [Define if running under NetBSD.])
;;
esac
;;
DragonFly)
SHLIB_CC="$CC -fPIC"
@@ -204,6 +204,18 @@ static char sendstring[1024 + 1];

static const char nullstring[] = "";

#ifdef res_ninit
#define MY_RES_INIT() res_ninit(&myres);
#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \
res_nmkquery(&myres, a, b, c, d, e, f, g, h, i)
struct __res_state myres;
#else
#define MY_RES_INIT() res_init();
#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \
res_mkquery(a, b, c, d, e, f, g, h, i)
#define myres _res
#endif


/*
* Miscellaneous helper functions
@@ -724,16 +736,17 @@ static void dorequest(char *s, int type, uint16_t id)
* CPUs.
*/
buf = nmalloc(MAX_PACKETSIZE + 1);
r = res_mkquery(QUERY, s, C_IN, type, NULL, 0, NULL, buf, MAX_PACKETSIZE);
r = RES_MKQUERY(QUERY, s, C_IN, type, NULL, 0, NULL, buf, MAX_PACKETSIZE);
if (r == -1) {
nfree(buf);
ddebug0(RES_ERR "Query too large.");
return;
}
hp = (packetheader *) buf;
hp->id = id; /* htons() deliberately left out (redundant) */
for (i = 0; i < _res.nscount; i++)
for (i = 0; i < myres.nscount; i++)
(void) sendto(resfd, buf, r, 0,
(struct sockaddr *) &_res.nsaddr_list[i],
(struct sockaddr *) &myres.nsaddr_list[i],
sizeof(struct sockaddr));
nfree(buf);
}
@@ -1092,17 +1105,17 @@ static void dns_ack(void)
}
/* Check to see if this server is actually one we sent to */
if (from.sin_addr.s_addr == localhost) {
for (i = 0; i < _res.nscount; i++)
for (i = 0; i < myres.nscount; i++)
/* 0.0.0.0 replies as 127.0.0.1 */
if ((_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) ||
(!_res.nsaddr_list[i].sin_addr.s_addr))
if ((myres.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr) ||
(!myres.nsaddr_list[i].sin_addr.s_addr))
break;
} else {
for (i = 0; i < _res.nscount; i++)
if (_res.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
for (i = 0; i < myres.nscount; i++)
if (myres.nsaddr_list[i].sin_addr.s_addr == from.sin_addr.s_addr)
break;
}
if (i == _res.nscount)
if (i == myres.nscount)
ddebug1(RES_ERR "Received reply from unknown source: %s",
iptostr((struct sockaddr *) &from));
else
@@ -1273,17 +1286,14 @@ static int init_dns_core(void)
int i;

/* Initialise the resolv library. */
res_init();
#ifdef NETBSD_HACKS
puts("netbsd found. if eggdrop crashes with\n"
" _res is not supported for multi-threaded programs.\n"
" [1] Abort trap (core dumped) ./eggdrop -nt\n"
"dns.mod must be disabled by commenting out in eggdrop.conf\n"
" #loadmodule dns");
#endif
_res.options |= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
for (i = 0; i < _res.nscount; i++)
_res.nsaddr_list[i].sin_family = AF_INET;
MY_RES_INIT();
if (!myres.nscount) {
putlog(LOG_MISC, "*", "No nameservers defined.");
return 0;
}
myres.options |= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
for (i = 0; i < myres.nscount; i++)
myres.nsaddr_list[i].sin_family = AF_INET;

if (!init_dns_network())
return 0;
@@ -148,9 +148,9 @@ static char *dns_change(ClientData cdata, Tcl_Interp *irp,
Tcl_DString ds;

Tcl_DStringInit(&ds);
for (i = 0; i < _res.nscount; i++) {
for (i = 0; i < myres.nscount; i++) {
egg_snprintf(buf, sizeof buf, "%s:%d", iptostr((struct sockaddr *)
&_res.nsaddr_list[i]), ntohs(_res.nsaddr_list[i].sin_port));
&myres.nsaddr_list[i]), ntohs(myres.nsaddr_list[i].sin_port));
Tcl_DStringAppendElement(&ds, buf);
}
slist = Tcl_DStringValue(&ds);
@@ -162,7 +162,7 @@ static char *dns_change(ClientData cdata, Tcl_Interp *irp,
if (code == TCL_ERROR)
return "variable must be a list";
/* reinitialize the list */
_res.nscount = 0;
myres.nscount = 0;
for (i = 0; i < lc; i++) {
if ((p = strchr(list[i], ':'))) {
*p++ = 0;
@@ -171,10 +171,10 @@ static char *dns_change(ClientData cdata, Tcl_Interp *irp,
} else
port = NAMESERVER_PORT; /* port 53 */
/* Ignore invalid addresses */
if (egg_inet_aton(list[i], &_res.nsaddr_list[_res.nscount].sin_addr)) {
_res.nsaddr_list[_res.nscount].sin_port = htons(port);
_res.nsaddr_list[_res.nscount].sin_family = AF_INET;
_res.nscount++;
if (egg_inet_aton(list[i], &myres.nsaddr_list[myres.nscount].sin_addr)) {
myres.nsaddr_list[myres.nscount].sin_port = htons(port);
myres.nsaddr_list[myres.nscount].sin_family = AF_INET;
myres.nscount++;
}
}
Tcl_Free((char *) list);
@@ -225,10 +225,10 @@ static int dns_report(int idx, int details)

dprintf(idx, " Async DNS resolver is active.\n");
dprintf(idx, " DNS server list:");
for (i = 0; i < _res.nscount; i++)
dprintf(idx, " %s:%d", iptostr((struct sockaddr *) &_res.nsaddr_list[i]),
ntohs(_res.nsaddr_list[i].sin_port));
if (!_res.nscount)
for (i = 0; i < myres.nscount; i++)
dprintf(idx, " %s:%d", iptostr((struct sockaddr *) &myres.nsaddr_list[i]),
ntohs(myres.nsaddr_list[i].sin_port));
if (!myres.nscount)
dprintf(idx, " NO DNS SERVERS FOUND!\n");
dprintf(idx, "\n");
dprintf(idx, " Using %d byte%s of memory\n", size,
@@ -240,10 +240,10 @@ static int dns_report(int idx, int details)
static int dns_check_servercount(void)
{
static int oldcount = -1;
if (oldcount != _res.nscount && !_res.nscount) {
if (oldcount != myres.nscount && !myres.nscount) {
putlog(LOG_MISC, "*", "WARNING: No nameservers found. Please set the dns-servers config variable.");
}
oldcount = _res.nscount;
oldcount = myres.nscount;
return 0;
}

@@ -307,9 +307,9 @@ char *dns_start(Function *global_funcs)
dcc[idx].sock = resfd;
dcc[idx].timeval = now;
strcpy(dcc[idx].nick, "(dns)");
memcpy(&dcc[idx].sockname.addr.sa, &_res.nsaddr_list[0],
sizeof(_res.nsaddr_list[0]));
dcc[idx].sockname.addrlen = sizeof(_res.nsaddr_list[0]);
memcpy(&dcc[idx].sockname.addr.sa, &myres.nsaddr_list[0],
sizeof(myres.nsaddr_list[0]));
dcc[idx].sockname.addrlen = sizeof(myres.nsaddr_list[0]);

Tcl_TraceVar(interp, "dns-servers",
TCL_TRACE_READS | TCL_TRACE_WRITES | TCL_TRACE_UNSETS,

0 comments on commit 35912be

Please sign in to comment.
You can’t perform that action at this time.