1 /* udns_resolver.c
2    resolver stuff (main module)
3 
4    Copyright (C) 2005  Michael Tokarev <mjt@corpit.ru>
5    This file is part of UDNS library, an async DNS stub resolver.
6 
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11 
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16 
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library, in file named COPYING.LGPL; if not,
19    write to the Free Software Foundation, Inc., 59 Temple Place,
20    Suite 330, Boston, MA  02111-1307  USA
21 
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27 #if defined(_WINDOWS) || defined(WINDOWS)
28 # include <winsock2.h>          /* includes <windows.h> */
29 # include <ws2tcpip.h>          /* needed for struct in6_addr */
30 #else
31 # include <sys/types.h>
32 # include <sys/socket.h>
33 # include <netinet/in.h>
34 # include <unistd.h>
35 # include <fcntl.h>
36 # include <sys/time.h>
37 # ifdef HAVE_POLL
38 #  include <sys/poll.h>
39 # else
40 #  ifdef HAVE_SYS_SELECT_H
41 #   include <sys/select.h>
42 #  endif
43 # endif
44 # ifdef HAVE_TIMES
45 #  include <sys/times.h>
46 # endif
47 # define closesocket(sock) close(sock)
48 #endif	/* !WINDOWS */
49 
50 #include <stdlib.h>
51 #include <string.h>
52 #include <time.h>
53 #include <errno.h>
54 #include <assert.h>
55 #include <stddef.h>
56 #include "udns.h"
57 
58 #ifndef EAFNOSUPPORT
59 # define EAFNOSUPPORT EINVAL
60 #endif
61 #ifndef MSG_DONTWAIT
62 # define MSG_DONTWAIT 0
63 #endif
64 
65 struct dns_qlist {
66   struct dns_query *head, *tail;
67 };
68 
69 struct dns_query {
70   struct dns_query *dnsq_next;          /* double-linked list */
71   struct dns_query *dnsq_prev;
72   unsigned dnsq_origdnl0;		/* original query DN len w/o last 0 */
73   unsigned dnsq_flags;			/* control flags for this query */
74   unsigned dnsq_servi;			/* index of next server to try */
75   unsigned dnsq_servwait;		/* bitmask: servers left to wait */
76   unsigned dnsq_servskip;		/* bitmask: servers to skip */
77   unsigned dnsq_servnEDNS0;		/* bitmask: servers refusing EDNS0 */
78   unsigned dnsq_try;			/* number of tries made so far */
79   dnscc_t *dnsq_nxtsrch;		/* next search pointer @dnsc_srchbuf */
80   time_t dnsq_deadline;			/* when current try will expire */
81   dns_parse_fn *dnsq_parse;		/* parse: raw => application */
82   dns_query_fn *dnsq_cbck;		/* the callback to call when done */
83   void *dnsq_cbdata;			/* user data for the callback */
84 #ifndef NDEBUG
85   struct dns_ctx *dnsq_ctx;		/* the resolver context */
86 #endif
87   /* char fields at the end to avoid padding */
88   dnsc_t dnsq_id[2];			/* query ID */
89   dnsc_t dnsq_typcls[4];		/* requested RR type+class */
90   dnsc_t dnsq_dn[DNS_MAXDN+DNS_DNPAD];	/* the query DN +alignment */
91 };
92 
93 /* working with dns_query lists */
94 
qlist_init(struct dns_qlist * list)95 static __inline void qlist_init(struct dns_qlist *list) {
96   list->head = list->tail = NULL;
97 }
98 
qlist_remove(struct dns_qlist * list,struct dns_query * q)99 static __inline void qlist_remove(struct dns_qlist *list, struct dns_query *q) {
100    if (q->dnsq_prev) q->dnsq_prev->dnsq_next = q->dnsq_next;
101    else list->head = q->dnsq_next;
102    if (q->dnsq_next) q->dnsq_next->dnsq_prev = q->dnsq_prev;
103    else list->tail = q->dnsq_prev;
104 }
105 
106 static __inline void
qlist_add_head(struct dns_qlist * list,struct dns_query * q)107 qlist_add_head(struct dns_qlist *list, struct dns_query *q) {
108   q->dnsq_next = list->head;
109   if (list->head) list->head->dnsq_prev = q;
110   else list->tail = q;
111   list->head = q;
112   q->dnsq_prev = NULL;
113 }
114 
115 static __inline void
qlist_insert_after(struct dns_qlist * list,struct dns_query * q,struct dns_query * prev)116 qlist_insert_after(struct dns_qlist *list,
117                    struct dns_query *q, struct dns_query *prev) {
118   if ((q->dnsq_prev = prev) != NULL) {
119     if ((q->dnsq_next = prev->dnsq_next) != NULL)
120       q->dnsq_next->dnsq_prev = q;
121     else
122       list->tail = q;
123     prev->dnsq_next = q;
124   }
125   else
126     qlist_add_head(list, q);
127 }
128 
129 union sockaddr_ns {
130   struct sockaddr sa;
131   struct sockaddr_in sin;
132 #ifdef HAVE_IPv6
133   struct sockaddr_in6 sin6;
134 #endif
135 };
136 
137 #define sin_eq(a,b) \
138 	((a).sin_port == (b).sin_port && \
139 	 (a).sin_addr.s_addr == (b).sin_addr.s_addr)
140 #define sin6_eq(a,b) \
141 	((a).sin6_port == (b).sin6_port && \
142 	 memcmp(&(a).sin6_addr, &(b).sin6_addr, sizeof(struct in6_addr)) == 0)
143 
144 struct dns_ctx {		/* resolver context */
145   /* settings */
146   unsigned dnsc_flags;			/* various flags */
147   unsigned dnsc_timeout;		/* timeout (base value) for queries */
148   unsigned dnsc_ntries;			/* number of retries */
149   unsigned dnsc_ndots;			/* ndots to assume absolute name */
150   unsigned dnsc_port;			/* default port (DNS_PORT) */
151   unsigned dnsc_udpbuf;			/* size of UDP buffer */
152   /* array of nameserver addresses */
153   union sockaddr_ns dnsc_serv[DNS_MAXSERV];
154   unsigned dnsc_nserv;			/* number of nameservers */
155   unsigned dnsc_salen;			/* length of socket addresses */
156   dnsc_t dnsc_srchbuf[1024];		/* buffer for searchlist */
157   dnsc_t *dnsc_srchend;			/* current end of srchbuf */
158 
159   dns_utm_fn *dnsc_utmfn;		/* register/cancel timer events */
160   void *dnsc_utmctx;			/* user timer context for utmfn() */
161   time_t dnsc_utmexp;			/* when user timer expires */
162 
163   dns_dbgfn *dnsc_udbgfn;		/* debugging function */
164 
165   /* dynamic data */
166   struct udns_jranctx dnsc_jran;	/* random number generator state */
167   unsigned dnsc_nextid;			/* next queue ID to use if !0 */
168   int dnsc_udpsock;			/* UDP socket */
169   struct dns_qlist dnsc_qactive;	/* active list sorted by deadline */
170   int dnsc_nactive;			/* number entries in dnsc_qactive */
171   dnsc_t *dnsc_pbuf;			/* packet buffer (udpbuf size) */
172   int dnsc_qstatus;			/* last query status value */
173 };
174 
175 static const struct {
176   const char *name;
177   enum dns_opt opt;
178   unsigned offset;
179   unsigned min, max;
180 } dns_opts[] = {
181 #define opt(name,opt,field,min,max) \
182 	{name,opt,offsetof(struct dns_ctx,field),min,max}
183   opt("retrans", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300),
184   opt("timeout", DNS_OPT_TIMEOUT, dnsc_timeout, 1,300),
185   opt("retry",    DNS_OPT_NTRIES, dnsc_ntries, 1,50),
186   opt("attempts", DNS_OPT_NTRIES, dnsc_ntries, 1,50),
187   opt("ndots", DNS_OPT_NDOTS, dnsc_ndots, 0,1000),
188   opt("port", DNS_OPT_PORT, dnsc_port, 1,0xffff),
189   opt("udpbuf", DNS_OPT_UDPSIZE, dnsc_udpbuf, DNS_MAXPACKET,65536),
190 #undef opt
191 };
192 #define dns_ctxopt(ctx,idx) (*((unsigned*)(((char*)ctx)+dns_opts[idx].offset)))
193 
194 #define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n')
195 
196 struct dns_ctx dns_defctx;
197 
198 #define SETCTX(ctx) if (!ctx) ctx = &dns_defctx
199 #define SETCTXINITED(ctx) SETCTX(ctx); assert(CTXINITED(ctx))
200 #define CTXINITED(ctx) (ctx->dnsc_flags & DNS_INITED)
201 #define SETCTXFRESH(ctx) SETCTXINITED(ctx); assert(!CTXOPEN(ctx))
202 #define SETCTXINACTIVE(ctx) \
203 		SETCTXINITED(ctx); assert(!ctx->dnsc_nactive)
204 #define SETCTXOPEN(ctx) SETCTXINITED(ctx); assert(CTXOPEN(ctx))
205 #define CTXOPEN(ctx) (ctx->dnsc_udpsock >= 0)
206 
207 #if defined(NDEBUG) || !defined(DEBUG)
208 #define dns_assert_ctx(ctx)
209 #else
dns_assert_ctx(const struct dns_ctx * ctx)210 static void dns_assert_ctx(const struct dns_ctx *ctx) {
211   int nactive = 0;
212   const struct dns_query *q;
213   for(q = ctx->dnsc_qactive.head; q; q = q->dnsq_next) {
214     assert(q->dnsq_ctx == ctx);
215     assert(q == (q->dnsq_next ?
216                  q->dnsq_next->dnsq_prev : ctx->dnsc_qactive.tail));
217     assert(q == (q->dnsq_prev ?
218                  q->dnsq_prev->dnsq_next : ctx->dnsc_qactive.head));
219     ++nactive;
220   }
221   assert(nactive == ctx->dnsc_nactive);
222 }
223 #endif
224 
225 enum {
226   DNS_INTERNAL		= 0xffff, /* internal flags mask */
227   DNS_INITED		= 0x0001, /* the context is initialized */
228   DNS_ASIS_DONE		= 0x0002, /* search: skip the last as-is query */
229   DNS_SEEN_NODATA	= 0x0004, /* search: NODATA has been received */
230 };
231 
dns_add_serv(struct dns_ctx * ctx,const char * serv)232 int dns_add_serv(struct dns_ctx *ctx, const char *serv) {
233   union sockaddr_ns *sns;
234   SETCTXFRESH(ctx);
235   if (!serv)
236     return (ctx->dnsc_nserv = 0);
237   if (ctx->dnsc_nserv >= DNS_MAXSERV)
238     return errno = ENFILE, -1;
239   sns = &ctx->dnsc_serv[ctx->dnsc_nserv];
240   memset(sns, 0, sizeof(*sns));
241   if (dns_pton(AF_INET, serv, &sns->sin.sin_addr) > 0) {
242     sns->sin.sin_family = AF_INET;
243     return ++ctx->dnsc_nserv;
244   }
245 #ifdef HAVE_IPv6
246   if (dns_pton(AF_INET6, serv, &sns->sin6.sin6_addr) > 0) {
247     sns->sin6.sin6_family = AF_INET6;
248     return ++ctx->dnsc_nserv;
249   }
250 #endif
251   errno = EINVAL;
252   return -1;
253 }
254 
dns_add_serv_s(struct dns_ctx * ctx,const struct sockaddr * sa)255 int dns_add_serv_s(struct dns_ctx *ctx, const struct sockaddr *sa) {
256   SETCTXFRESH(ctx);
257   if (!sa)
258     return (ctx->dnsc_nserv = 0);
259   if (ctx->dnsc_nserv >= DNS_MAXSERV)
260     return errno = ENFILE, -1;
261 #ifdef HAVE_IPv6
262   else if (sa->sa_family == AF_INET6)
263     ctx->dnsc_serv[ctx->dnsc_nserv].sin6 = *(struct sockaddr_in6*)sa;
264 #endif
265   else if (sa->sa_family == AF_INET)
266     ctx->dnsc_serv[ctx->dnsc_nserv].sin = *(struct sockaddr_in*)sa;
267   else
268     return errno = EAFNOSUPPORT, -1;
269   return ++ctx->dnsc_nserv;
270 }
271 
dns_set_opts(struct dns_ctx * ctx,const char * opts)272 int dns_set_opts(struct dns_ctx *ctx, const char *opts) {
273   unsigned i, v;
274   int err = 0;
275   SETCTXINACTIVE(ctx);
276   for(;;) {
277     while(ISSPACE(*opts)) ++opts;
278     if (!*opts) break;
279     for(i = 0; ; ++i) {
280       if (i >= sizeof(dns_opts)/sizeof(dns_opts[0])) { ++err; break; }
281       v = strlen(dns_opts[i].name);
282       if (strncmp(dns_opts[i].name, opts, v) != 0 ||
283           (opts[v] != ':' && opts[v] != '='))
284         continue;
285       opts += v + 1;
286       v = 0;
287       if (*opts < '0' || *opts > '9') { ++err; break; }
288       do v = v * 10 + (*opts++ - '0');
289       while (*opts >= '0' && *opts <= '9');
290       if (v < dns_opts[i].min) v = dns_opts[i].min;
291       if (v > dns_opts[i].max) v = dns_opts[i].max;
292       dns_ctxopt(ctx, i) = v;
293       break;
294     }
295     while(*opts && !ISSPACE(*opts)) ++opts;
296   }
297   return err;
298 }
299 
dns_set_opt(struct dns_ctx * ctx,enum dns_opt opt,int val)300 int dns_set_opt(struct dns_ctx *ctx, enum dns_opt opt, int val) {
301   int prev;
302   unsigned i;
303   SETCTXINACTIVE(ctx);
304   for(i = 0; i < sizeof(dns_opts)/sizeof(dns_opts[0]); ++i) {
305     if (dns_opts[i].opt != opt) continue;
306     prev = dns_ctxopt(ctx, i);
307     if (val >= 0) {
308       unsigned v = val;
309       if (v < dns_opts[i].min || v > dns_opts[i].max) {
310         errno = EINVAL;
311         return -1;
312       }
313       dns_ctxopt(ctx, i) = v;
314     }
315     return prev;
316   }
317   if (opt == DNS_OPT_FLAGS) {
318     prev = ctx->dnsc_flags & ~DNS_INTERNAL;
319     if (val >= 0)
320       ctx->dnsc_flags =
321         (ctx->dnsc_flags & DNS_INTERNAL) | (val & ~DNS_INTERNAL);
322     return prev;
323   }
324   errno = ENOSYS;
325   return -1;
326 }
327 
dns_add_srch(struct dns_ctx * ctx,const char * srch)328 int dns_add_srch(struct dns_ctx *ctx, const char *srch) {
329   int dnl;
330   SETCTXINACTIVE(ctx);
331   if (!srch) {
332     memset(ctx->dnsc_srchbuf, 0, sizeof(ctx->dnsc_srchbuf));
333     ctx->dnsc_srchend = ctx->dnsc_srchbuf;
334     return 0;
335   }
336   dnl =
337     sizeof(ctx->dnsc_srchbuf) - (ctx->dnsc_srchend - ctx->dnsc_srchbuf) - 1;
338   dnl = dns_sptodn(srch, ctx->dnsc_srchend, dnl);
339   if (dnl > 0)
340     ctx->dnsc_srchend += dnl;
341   ctx->dnsc_srchend[0] = '\0';	/* we ensure the list is always ends at . */
342   if (dnl > 0)
343     return 0;
344   errno = EINVAL;
345   return -1;
346 }
347 
dns_drop_utm(struct dns_ctx * ctx)348 static void dns_drop_utm(struct dns_ctx *ctx) {
349   if (ctx->dnsc_utmfn)
350     ctx->dnsc_utmfn(NULL, -1, ctx->dnsc_utmctx);
351   ctx->dnsc_utmctx = NULL;
352   ctx->dnsc_utmexp = -1;
353 }
354 
355 static void
_dns_request_utm(struct dns_ctx * ctx,time_t now)356 _dns_request_utm(struct dns_ctx *ctx, time_t now) {
357   struct dns_query *q;
358   time_t deadline;
359   int timeout;
360   q = ctx->dnsc_qactive.head;
361   if (!q)
362     deadline = -1, timeout = -1;
363   else if (!now || q->dnsq_deadline <= now)
364     deadline = 0, timeout = 0;
365   else
366     deadline = q->dnsq_deadline, timeout = (int)(deadline - now);
367   if (ctx->dnsc_utmexp == deadline)
368     return;
369   ctx->dnsc_utmfn(ctx, timeout, ctx->dnsc_utmctx);
370   ctx->dnsc_utmexp = deadline;
371 }
372 
373 static __inline void
dns_request_utm(struct dns_ctx * ctx,time_t now)374 dns_request_utm(struct dns_ctx *ctx, time_t now) {
375   if (ctx->dnsc_utmfn)
376     _dns_request_utm(ctx, now);
377 }
378 
dns_set_dbgfn(struct dns_ctx * ctx,dns_dbgfn * dbgfn)379 void dns_set_dbgfn(struct dns_ctx *ctx, dns_dbgfn *dbgfn) {
380   SETCTXINITED(ctx);
381   ctx->dnsc_udbgfn = dbgfn;
382 }
383 
384 void
dns_set_tmcbck(struct dns_ctx * ctx,dns_utm_fn * fn,void * data)385 dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data) {
386   SETCTXINITED(ctx);
387   dns_drop_utm(ctx);
388   ctx->dnsc_utmfn = fn;
389   ctx->dnsc_utmctx = data;
390   if (CTXOPEN(ctx))
391     dns_request_utm(ctx, 0);
392 }
393 
dns_nonrandom_32(void)394 static unsigned dns_nonrandom_32(void) {
395 #if defined(_WINDOWS) || defined(WINDOWS)
396   FILETIME ft;
397   GetSystemTimeAsFileTime(&ft);
398   return ft.dwLowDateTime;
399 #else
400   struct timeval tv;
401   gettimeofday(&tv, NULL);
402   return tv.tv_usec;
403 #endif
404 }
405 
406 /* This is historic deprecated API */
407 UDNS_API unsigned dns_random16(void);
dns_random16(void)408 unsigned dns_random16(void) {
409   unsigned x = dns_nonrandom_32();
410   return (x ^ (x >> 16)) & 0xffff;
411 }
412 
dns_init_rng(struct dns_ctx * ctx)413 static void dns_init_rng(struct dns_ctx *ctx) {
414   udns_jraninit(&ctx->dnsc_jran, dns_nonrandom_32());
415   ctx->dnsc_nextid = 0;
416 }
417 
dns_close(struct dns_ctx * ctx)418 void dns_close(struct dns_ctx *ctx) {
419   struct dns_query *q, *p;
420   SETCTX(ctx);
421   if (CTXINITED(ctx)) {
422     if (ctx->dnsc_udpsock >= 0)
423       closesocket(ctx->dnsc_udpsock);
424     ctx->dnsc_udpsock = -1;
425     if (ctx->dnsc_pbuf)
426       free(ctx->dnsc_pbuf);
427     ctx->dnsc_pbuf = NULL;
428     q = ctx->dnsc_qactive.head;
429     while((p = q) != NULL) {
430       q = q->dnsq_next;
431       free(p);
432     }
433     qlist_init(&ctx->dnsc_qactive);
434     ctx->dnsc_nactive = 0;
435     dns_drop_utm(ctx);
436   }
437 }
438 
dns_reset(struct dns_ctx * ctx)439 void dns_reset(struct dns_ctx *ctx) {
440   SETCTX(ctx);
441   dns_close(ctx);
442   memset(ctx, 0, sizeof(*ctx));
443   ctx->dnsc_timeout = 4;
444   ctx->dnsc_ntries = 3;
445   ctx->dnsc_ndots = 1;
446   ctx->dnsc_udpbuf = DNS_EDNS0PACKET;
447   ctx->dnsc_port = DNS_PORT;
448   ctx->dnsc_udpsock = -1;
449   ctx->dnsc_srchend = ctx->dnsc_srchbuf;
450   qlist_init(&ctx->dnsc_qactive);
451   dns_init_rng(ctx);
452   ctx->dnsc_flags = DNS_INITED;
453 }
454 
dns_new(const struct dns_ctx * copy)455 struct dns_ctx *dns_new(const struct dns_ctx *copy) {
456   struct dns_ctx *ctx;
457   SETCTXINITED(copy);
458   dns_assert_ctx(copy);
459   ctx = malloc(sizeof(*ctx));
460   if (!ctx)
461     return NULL;
462   *ctx = *copy;
463   ctx->dnsc_udpsock = -1;
464   qlist_init(&ctx->dnsc_qactive);
465   ctx->dnsc_nactive = 0;
466   ctx->dnsc_pbuf = NULL;
467   ctx->dnsc_qstatus = 0;
468   ctx->dnsc_srchend = ctx->dnsc_srchbuf +
469     (copy->dnsc_srchend - copy->dnsc_srchbuf);
470   ctx->dnsc_utmfn = NULL;
471   ctx->dnsc_utmctx = NULL;
472   dns_init_rng(ctx);
473   return ctx;
474 }
475 
dns_free(struct dns_ctx * ctx)476 void dns_free(struct dns_ctx *ctx) {
477   assert(ctx != NULL && ctx != &dns_defctx);
478   dns_reset(ctx);
479   free(ctx);
480 }
481 
dns_open(struct dns_ctx * ctx)482 int dns_open(struct dns_ctx *ctx) {
483   int sock;
484   unsigned i;
485   int port;
486   union sockaddr_ns *sns;
487 #ifdef HAVE_IPv6
488   unsigned have_inet6 = 0;
489 #endif
490 
491   SETCTXINITED(ctx);
492   assert(!CTXOPEN(ctx));
493 
494   port = htons((unsigned short)ctx->dnsc_port);
495   /* ensure we have at least one server */
496   if (!ctx->dnsc_nserv) {
497     sns = ctx->dnsc_serv;
498     sns->sin.sin_family = AF_INET;
499     sns->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
500     ctx->dnsc_nserv = 1;
501   }
502 
503   for (i = 0; i < ctx->dnsc_nserv; ++i) {
504     sns = &ctx->dnsc_serv[i];
505     /* set port for each sockaddr */
506 #ifdef HAVE_IPv6
507     if (sns->sa.sa_family == AF_INET6) {
508       if (!sns->sin6.sin6_port) sns->sin6.sin6_port = (unsigned short)port;
509       ++have_inet6;
510     }
511     else
512 #endif
513     {
514       assert(sns->sa.sa_family == AF_INET);
515       if (!sns->sin.sin_port) sns->sin.sin_port = (unsigned short)port;
516     }
517   }
518 
519 #ifdef HAVE_IPv6
520   if (have_inet6 && have_inet6 < ctx->dnsc_nserv) {
521     /* convert all IPv4 addresses to IPv6 V4MAPPED */
522     struct sockaddr_in6 sin6;
523     memset(&sin6, 0, sizeof(sin6));
524     sin6.sin6_family = AF_INET6;
525     /* V4MAPPED: ::ffff:1.2.3.4 */
526     sin6.sin6_addr.s6_addr[10] = 0xff;
527     sin6.sin6_addr.s6_addr[11] = 0xff;
528     for(i = 0; i < ctx->dnsc_nserv; ++i) {
529       sns = &ctx->dnsc_serv[i];
530       if (sns->sa.sa_family == AF_INET) {
531         sin6.sin6_port = sns->sin.sin_port;
532         memcpy(sin6.sin6_addr.s6_addr + 4*3, &sns->sin.sin_addr, 4);
533         sns->sin6 = sin6;
534       }
535     }
536   }
537 
538   ctx->dnsc_salen = have_inet6 ?
539     sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
540 
541   if (have_inet6)
542     sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
543   else
544     sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
545 #else /* !HAVE_IPv6 */
546   sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
547   ctx->dnsc_salen = sizeof(struct sockaddr_in);
548 #endif /* HAVE_IPv6 */
549 
550   if (sock < 0) {
551     ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
552     return -1;
553   }
554 #if defined(_WINDOWS) || defined(WINDOWS)
555   { unsigned long on = 1;
556     if (ioctlsocket(sock, FIONBIO, &on) == SOCKET_ERROR) {
557       closesocket(sock);
558       ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
559       return -1;
560     }
561   }
562 #else	/* !WINDOWS */
563   if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) < 0 ||
564       fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
565     closesocket(sock);
566     ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
567     return -1;
568   }
569 #endif	/* WINDOWS */
570   /* allocate the packet buffer */
571   if ((ctx->dnsc_pbuf = malloc(ctx->dnsc_udpbuf)) == NULL) {
572     closesocket(sock);
573     ctx->dnsc_qstatus = DNS_E_NOMEM;
574     errno = ENOMEM;
575     return -1;
576   }
577 
578   ctx->dnsc_udpsock = sock;
579   dns_request_utm(ctx, 0);
580   return sock;
581 }
582 
dns_sock(const struct dns_ctx * ctx)583 int dns_sock(const struct dns_ctx *ctx) {
584   SETCTXINITED(ctx);
585   return ctx->dnsc_udpsock;
586 }
587 
dns_active(const struct dns_ctx * ctx)588 int dns_active(const struct dns_ctx *ctx) {
589   SETCTXINITED(ctx);
590   dns_assert_ctx(ctx);
591   return ctx->dnsc_nactive;
592 }
593 
dns_status(const struct dns_ctx * ctx)594 int dns_status(const struct dns_ctx *ctx) {
595   SETCTX(ctx);
596   return ctx->dnsc_qstatus;
597 }
dns_setstatus(struct dns_ctx * ctx,int status)598 void dns_setstatus(struct dns_ctx *ctx, int status) {
599   SETCTX(ctx);
600   ctx->dnsc_qstatus = status;
601 }
602 
603 /* End the query: disconnect it from the active list, free it,
604  * and return the result to the caller.
605  */
606 static void
dns_end_query(struct dns_ctx * ctx,struct dns_query * q,int status,void * result)607 dns_end_query(struct dns_ctx *ctx, struct dns_query *q,
608               int status, void *result) {
609   dns_query_fn *cbck = q->dnsq_cbck;
610   void *cbdata = q->dnsq_cbdata;
611   ctx->dnsc_qstatus = status;
612   assert((status < 0 && result == 0) || (status >= 0 && result != 0));
613   assert(cbck != 0);	/*XXX callback may be NULL */
614   assert(ctx->dnsc_nactive > 0);
615   --ctx->dnsc_nactive;
616   qlist_remove(&ctx->dnsc_qactive, q);
617   /* force the query to be unconnected */
618   /*memset(q, 0, sizeof(*q));*/
619 #ifndef NDEBUG
620   q->dnsq_ctx = NULL;
621 #endif
622   free(q);
623   cbck(ctx, result, cbdata);
624 }
625 
626 #define DNS_DBG(ctx, code, sa, slen, pkt, plen) \
627   do { \
628     if (ctx->dnsc_udbgfn) \
629       ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, 0, 0); \
630   } while(0)
631 #define DNS_DBGQ(ctx, q, code, sa, slen, pkt, plen) \
632   do { \
633     if (ctx->dnsc_udbgfn) \
634       ctx->dnsc_udbgfn(code, (sa), slen, pkt, plen, q, q->dnsq_cbdata); \
635   } while(0)
636 
dns_newid(struct dns_ctx * ctx,struct dns_query * q)637 static void dns_newid(struct dns_ctx *ctx, struct dns_query *q) {
638   /* this is how we choose an identifier for a new query (qID).
639    * For now, it's just sequential number, incremented for every query, and
640    * thus obviously trivial to guess.
641    * There are two choices:
642    *  a) use sequential numbers.  It is plain insecure. In DNS, there are two
643    *   places where random numbers are (or can) be used to increase security:
644    *   random qID and random source port number.  Without this randomness
645    *   (udns uses fixed port for all queries), or when the randomness is weak,
646    *   it's trivial to spoof query replies.  With randomness however, it
647    *   becomes a bit more difficult task.  Too bad we only have 16 bits for
648    *   our security, as qID is only two bytes.  It isn't a security per se,
649    *   to rely on those 16 bits - an attacker can just flood us with fake
650    *   replies with all possible qIDs (only 65536 of them), and in this case,
651    *   even if we'll use true random qIDs, we'll be in trouble (not protected
652    *   against spoofing).  Yes, this is only possible on a high-speed network
653    *   (probably on the LAN only, since usually a border router for a LAN
654    *   protects internal machines from packets with spoofed local addresses
655    *   from outside, and usually a nameserver resides on LAN), but it's
656    *   still very well possible to send us fake replies.
657    *   In other words: there's nothing a DNS (stub) resolver can do against
658    *   spoofing attacks, unless DNSSEC is in use, which helps here alot.
659    *   Too bad that DNSSEC isn't widespread, so relying on it isn't an
660    *   option in almost all cases...
661    *  b) use random qID, based on some random-number generation mechanism.
662    *   This way, we increase our protection a bit (see above - it's very weak
663    *   still), but we also increase risk of qID reuse and matching late replies
664    *   that comes to queries we've sent before against new queries.  There are
665    *   some more corner cases around that, as well - for example, normally,
666    *   udns tries to find the query for a given reply by qID, *and* by
667    *   verifying that the query DN and other parameters are also the same
668    *   (so if the new query is against another domain name, old reply will
669    *   be ignored automatically).  But certain types of replies which we now
670    *   handle - for example, FORMERR reply from servers which refuses to
671    *   process EDNS0-enabled packets - comes without all the query parameters
672    *   but the qID - so we're forced to use qID only when determining which
673    *   query the given reply corresponds to.  This makes us even more
674    *   vulnerable to spoofing attacks, because an attacker don't even need to
675    *   know which queries we perform to spoof the replies - he only needs to
676    *   flood us with fake FORMERR "replies".
677    *
678    * That all to say: using sequential (or any other trivially guessable)
679    * numbers for qIDs is insecure, but the whole thing is inherently insecure
680    * as well, and this "extra weakness" that comes from weak qID choosing
681    * algorithm adds almost nothing to the underlying problem.
682    *
683    * It CAN NOT be made secure.  Period.  That's it.
684    * Unless we choose to implement DNSSEC, which is a whole different story.
685    * Forcing TCP mode makes it better, but who uses TCP for DNS anyway?
686    * (and it's hardly possible because of huge impact on the recursive
687    * nameservers).
688    *
689    * Note that ALL stub resolvers (again, unless they implement and enforce
690    * DNSSEC) suffers from this same problem.
691    *
692    * Here, I use a pseudo-random number generator for qIDs, instead of a
693    * simpler sequential IDs.  This is _not_ more secure than sequential
694    * ID, but some found random IDs more enjoyeable for some reason.  So
695    * here it goes.
696    */
697 
698   /* Use random number and check if it's unique.
699    * If it's not, try again up to 5 times.
700    */
701   unsigned loop;
702   dnsc_t c0, c1;
703   for(loop = 0; loop < 5; ++loop) {
704     const struct dns_query *c;
705     if (!ctx->dnsc_nextid)
706       ctx->dnsc_nextid = udns_jranval(&ctx->dnsc_jran);
707     c0 = ctx->dnsc_nextid & 0xff;
708     c1 = (ctx->dnsc_nextid >> 8) & 0xff;
709     ctx->dnsc_nextid >>= 16;
710     for(c = ctx->dnsc_qactive.head; c; c = c->dnsq_next)
711       if (c->dnsq_id[0] == c0 && c->dnsq_id[1] == c1)
712         break; /* found such entry, try again */
713     if (!c)
714       break;
715   }
716   q->dnsq_id[0] = c0; q->dnsq_id[1] = c1;
717 
718   /* reset all parameters relevant for previous query lifetime */
719   q->dnsq_try = 0;
720   q->dnsq_servi = 0;
721   /*XXX probably should keep dnsq_servnEDNS0 bits?
722    * See also comments in dns_ioevent() about FORMERR case */
723   q->dnsq_servwait = q->dnsq_servskip = q->dnsq_servnEDNS0 = 0;
724 }
725 
726 /* Find next search suffix and fills in q->dnsq_dn.
727  * Return 0 if no more to try. */
dns_next_srch(struct dns_ctx * ctx,struct dns_query * q)728 static int dns_next_srch(struct dns_ctx *ctx, struct dns_query *q) {
729   unsigned dnl;
730 
731   for(;;) {
732     if (q->dnsq_nxtsrch > ctx->dnsc_srchend)
733       return 0;
734     dnl = dns_dnlen(q->dnsq_nxtsrch);
735     if (dnl + q->dnsq_origdnl0 <= DNS_MAXDN &&
736         (*q->dnsq_nxtsrch || !(q->dnsq_flags & DNS_ASIS_DONE)))
737       break;
738     q->dnsq_nxtsrch += dnl;
739   }
740   memcpy(q->dnsq_dn + q->dnsq_origdnl0, q->dnsq_nxtsrch, dnl);
741   if (!*q->dnsq_nxtsrch)
742     q->dnsq_flags |= DNS_ASIS_DONE;
743   q->dnsq_nxtsrch += dnl;
744   dns_newid(ctx, q); /* new ID for new qDN */
745   return 1;
746 }
747 
748 /* find the server to try for current iteration.
749  * Note that current dnsq_servi may point to a server we should skip --
750  * in that case advance to the next server.
751  * Return true if found, false if all tried.
752  */
dns_find_serv(const struct dns_ctx * ctx,struct dns_query * q)753 static int dns_find_serv(const struct dns_ctx *ctx, struct dns_query *q) {
754   while(q->dnsq_servi < ctx->dnsc_nserv) {
755     if (!(q->dnsq_servskip & (1 << q->dnsq_servi)))
756       return 1;
757     ++q->dnsq_servi;
758   }
759   return 0;
760 }
761 
762 /* format and send the query to a given server.
763  * In case of network problem (sendto() fails), return -1,
764  * else return 0.
765  */
766 static int
dns_send_this(struct dns_ctx * ctx,struct dns_query * q,unsigned servi,time_t now)767 dns_send_this(struct dns_ctx *ctx, struct dns_query *q,
768               unsigned servi, time_t now) {
769   unsigned qlen;
770   unsigned tries;
771 
772   { /* format the query buffer */
773     dnsc_t *p = ctx->dnsc_pbuf;
774     memset(p, 0, DNS_HSIZE);
775     if (!(q->dnsq_flags & DNS_NORD)) p[DNS_H_F1] |= DNS_HF1_RD;
776     if (q->dnsq_flags & DNS_AAONLY) p[DNS_H_F1] |= DNS_HF1_AA;
777     if (q->dnsq_flags & DNS_SET_CD) p[DNS_H_F2] |= DNS_HF2_CD;
778     p[DNS_H_QDCNT2] = 1;
779     memcpy(p + DNS_H_QID, q->dnsq_id, 2);
780     p = dns_payload(p);
781     /* copy query dn */
782     p += dns_dntodn(q->dnsq_dn, p, DNS_MAXDN);
783     /* query type and class */
784     memcpy(p, q->dnsq_typcls, 4); p += 4;
785     /* add EDNS0 record. DO flag requires it */
786     if (q->dnsq_flags & DNS_SET_DO ||
787         (ctx->dnsc_udpbuf > DNS_MAXPACKET &&
788          !(q->dnsq_servnEDNS0 & (1 << servi)))) {
789       *p++ = 0;			/* empty (root) DN */
790       p = dns_put16(p, DNS_T_OPT);
791       p = dns_put16(p, ctx->dnsc_udpbuf);
792       /* EDNS0 RCODE & VERSION; rest of the TTL field; RDLEN */
793       memset(p, 0, 2+2+2);
794       if (q->dnsq_flags & DNS_SET_DO) p[2] |= DNS_EF1_DO;
795       p += 2+2+2;
796       ctx->dnsc_pbuf[DNS_H_ARCNT2] = 1;
797     }
798     qlen = p - ctx->dnsc_pbuf;
799     assert(qlen <= ctx->dnsc_udpbuf);
800   }
801 
802   /* send the query */
803   tries = 10;
804   while (sendto(ctx->dnsc_udpsock, (void*)ctx->dnsc_pbuf, qlen, 0,
805                 &ctx->dnsc_serv[servi].sa, ctx->dnsc_salen) < 0) {
806     /*XXX just ignore the sendto() error for now and try again.
807      * In the future, it may be possible to retrieve the error code
808      * and find which operation/query failed.
809      *XXX try the next server too? (if ENETUNREACH is returned immediately)
810      */
811     if (--tries) continue;
812     /* if we can't send the query, fail it. */
813     dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0);
814     return -1;
815   }
816   DNS_DBGQ(ctx, q, 1,
817            &ctx->dnsc_serv[servi].sa, sizeof(union sockaddr_ns),
818            ctx->dnsc_pbuf, qlen);
819   q->dnsq_servwait |= 1 << servi;	/* expect reply from this ns */
820 
821   q->dnsq_deadline = now +
822     (dns_find_serv(ctx, q) ? 1 : ctx->dnsc_timeout << q->dnsq_try);
823 
824   /* move the query to the proper place, according to the new deadline */
825   qlist_remove(&ctx->dnsc_qactive, q);
826   { /* insert from the tail */
827     struct dns_query *p;
828     for(p = ctx->dnsc_qactive.tail; p; p = p->dnsq_prev)
829       if (p->dnsq_deadline <= q->dnsq_deadline)
830 	break;
831     qlist_insert_after(&ctx->dnsc_qactive, q, p);
832   }
833 
834   return 0;
835 }
836 
837 /* send the query out using next available server
838  * and add it to the active list, or, if no servers available,
839  * end it.
840  */
841 static void
dns_send(struct dns_ctx * ctx,struct dns_query * q,time_t now)842 dns_send(struct dns_ctx *ctx, struct dns_query *q, time_t now) {
843 
844   /* if we can't send the query, return TEMPFAIL even when searching:
845    * we can't be sure whenever the name we tried to search exists or not,
846    * so don't continue searching, or we may find the wrong name. */
847 
848   if (!dns_find_serv(ctx, q)) {
849     /* no more servers in this iteration.  Try the next cycle */
850     q->dnsq_servi = 0;	/* reset */
851     q->dnsq_try++;	/* next try */
852     if (q->dnsq_try >= ctx->dnsc_ntries ||
853         !dns_find_serv(ctx, q)) {
854       /* no more servers and tries, fail the query */
855       /* return TEMPFAIL even when searching: no more tries for this
856        * searchlist, and no single definitive reply (handled in dns_ioevent()
857        * in NOERROR or NXDOMAIN cases) => all nameservers failed to process
858        * current search list element, so we don't know whenever the name exists.
859        */
860       dns_end_query(ctx, q, DNS_E_TEMPFAIL, 0);
861       return;
862     }
863   }
864 
865   dns_send_this(ctx, q, q->dnsq_servi++, now);
866 }
867 
dns_dummy_cb(struct dns_ctx * ctx,void * result,void * data)868 static void dns_dummy_cb(struct dns_ctx *ctx, void *result, void *data) {
869   if (result) free(result);
870   data = ctx = 0;	/* used */
871 }
872 
873 /* The (only, main, real) query submission routine.
874  * Allocate new query structure, initialize it, check validity of
875  * parameters, and add it to the head of the active list, without
876  * trying to send it (to be picked up on next event).
877  * Error return (without calling the callback routine) -
878  *  no memory or wrong parameters.
879  *XXX The `no memory' case probably should go to the callback anyway...
880  */
881 struct dns_query *
dns_submit_dn(struct dns_ctx * ctx,dnscc_t * dn,int qcls,int qtyp,int flags,dns_parse_fn * parse,dns_query_fn * cbck,void * data)882 dns_submit_dn(struct dns_ctx *ctx,
883               dnscc_t *dn, int qcls, int qtyp, int flags,
884               dns_parse_fn *parse, dns_query_fn *cbck, void *data) {
885   struct dns_query *q;
886   SETCTXOPEN(ctx);
887   dns_assert_ctx(ctx);
888 
889   q = calloc(sizeof(*q), 1);
890   if (!q) {
891     ctx->dnsc_qstatus = DNS_E_NOMEM;
892     return NULL;
893   }
894 
895 #ifndef NDEBUG
896   q->dnsq_ctx = ctx;
897 #endif
898   q->dnsq_parse = parse;
899   q->dnsq_cbck = cbck ? cbck : dns_dummy_cb;
900   q->dnsq_cbdata = data;
901 
902   q->dnsq_origdnl0 = dns_dntodn(dn, q->dnsq_dn, sizeof(q->dnsq_dn));
903   assert(q->dnsq_origdnl0 > 0);
904   --q->dnsq_origdnl0;		/* w/o the trailing 0 */
905   dns_put16(q->dnsq_typcls+0, qtyp);
906   dns_put16(q->dnsq_typcls+2, qcls);
907   q->dnsq_flags = (flags | ctx->dnsc_flags) & ~DNS_INTERNAL;
908 
909   if (flags & DNS_NOSRCH ||
910       dns_dnlabels(q->dnsq_dn) > ctx->dnsc_ndots) {
911     q->dnsq_nxtsrch = flags & DNS_NOSRCH ?
912       ctx->dnsc_srchend /* end of the search list if no search requested */ :
913       ctx->dnsc_srchbuf /* beginning of the list, but try as-is first */;
914     q->dnsq_flags |= DNS_ASIS_DONE;
915     dns_newid(ctx, q);
916   }
917   else {
918     q->dnsq_nxtsrch = ctx->dnsc_srchbuf;
919     dns_next_srch(ctx, q);
920   }
921 
922   /* q->dnsq_deadline is set to 0 (calloc above): the new query is
923    * "already expired" when first inserted into queue, so it's safe
924    * to insert it into the head of the list.  Next call to dns_timeouts()
925    * will actually send it.
926    */
927   qlist_add_head(&ctx->dnsc_qactive, q);
928   ++ctx->dnsc_nactive;
929   dns_request_utm(ctx, 0);
930 
931   return q;
932 }
933 
934 struct dns_query *
dns_submit_p(struct dns_ctx * ctx,const char * name,int qcls,int qtyp,int flags,dns_parse_fn * parse,dns_query_fn * cbck,void * data)935 dns_submit_p(struct dns_ctx *ctx,
936              const char *name, int qcls, int qtyp, int flags,
937              dns_parse_fn *parse, dns_query_fn *cbck, void *data) {
938   int isabs;
939   SETCTXOPEN(ctx);
940   if (dns_ptodn(name, 0, ctx->dnsc_pbuf, DNS_MAXDN, &isabs) <= 0) {
941     ctx->dnsc_qstatus = DNS_E_BADQUERY;
942     return NULL;
943   }
944   if (isabs)
945     flags |= DNS_NOSRCH;
946   return
947     dns_submit_dn(ctx, ctx->dnsc_pbuf, qcls, qtyp, flags, parse, cbck, data);
948 }
949 
950 /* process readable fd condition.
951  * To be usable in edge-triggered environment, the routine
952  * should consume all input so it should loop over.
953  * Note it isn't really necessary to loop here, because
954  * an application may perform the loop just fine by it's own,
955  * but in this case we should return some sensitive result,
956  * to indicate when to stop calling and error conditions.
957  * Note also we may encounter all sorts of recvfrom()
958  * errors which aren't fatal, and at the same time we may
959  * loop forever if an error IS fatal.
960  */
dns_ioevent(struct dns_ctx * ctx,time_t now)961 void dns_ioevent(struct dns_ctx *ctx, time_t now) {
962   int r;
963   unsigned servi;
964   struct dns_query *q;
965   dnsc_t *pbuf;
966   dnscc_t *pend, *pcur;
967   void *result;
968   union sockaddr_ns sns;
969   socklen_t slen;
970 
971   SETCTX(ctx);
972   if (!CTXOPEN(ctx))
973     return;
974   dns_assert_ctx(ctx);
975   pbuf = ctx->dnsc_pbuf;
976 
977   if (!now) now = time(NULL);
978 
979 again: /* receive the reply */
980 
981   slen = sizeof(sns);
982   r = recvfrom(ctx->dnsc_udpsock, (void*)pbuf, ctx->dnsc_udpbuf,
983                MSG_DONTWAIT, &sns.sa, &slen);
984   if (r < 0) {
985     /*XXX just ignore recvfrom() errors for now.
986      * in the future it may be possible to determine which
987      * query failed and requeue it.
988      * Note there may be various error conditions, triggered
989      * by both local problems and remote problems.  It isn't
990      * quite trivial to determine whenever an error is local
991      * or remote.  On local errors, we should stop, while
992      * remote errors should be ignored (for now anyway).
993      */
994 #if defined(_WINDOWS) || defined(WINDOWS)
995     if (WSAGetLastError() == WSAEWOULDBLOCK)
996 #else
997     if (errno == EAGAIN)
998 #endif
999     {
1000       dns_request_utm(ctx, now);
1001       return;
1002     }
1003     goto again;
1004   }
1005 
1006   pend = pbuf + r;
1007   pcur = dns_payload(pbuf);
1008 
1009   /* check reply header */
1010   if (pcur > pend || dns_numqd(pbuf) > 1 || dns_opcode(pbuf) != 0) {
1011     DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r);
1012     goto again;
1013   }
1014 
1015   /* find the matching query, by qID */
1016   for (q = ctx->dnsc_qactive.head; ; q = q->dnsq_next) {
1017     if (!q) {
1018       /* no more requests: old reply? */
1019       DNS_DBG(ctx, -5/*no matching query*/, &sns.sa, slen, pbuf, r);
1020       goto again;
1021     }
1022     if (pbuf[DNS_H_QID1] == q->dnsq_id[0] &&
1023         pbuf[DNS_H_QID2] == q->dnsq_id[1])
1024       break;
1025   }
1026 
1027   /* if we have numqd, compare with our query qDN */
1028   if (dns_numqd(pbuf)) {
1029     /* decode the qDN */
1030     dnsc_t dn[DNS_MAXDN];
1031     if (dns_getdn(pbuf, &pcur, pend, dn, sizeof(dn)) < 0 ||
1032         pcur + 4 > pend) {
1033       DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r);
1034       goto again;
1035     }
1036     if (!dns_dnequal(dn, q->dnsq_dn) ||
1037         memcmp(pcur, q->dnsq_typcls, 4) != 0) {
1038       /* not this query */
1039       DNS_DBG(ctx, -5/*no matching query*/, &sns.sa, slen, pbuf, r);
1040       goto again;
1041     }
1042     /* here, query match, and pcur points past qDN in query section in pbuf */
1043   }
1044   /* if no numqd, we only allow FORMERR rcode */
1045   else if (dns_rcode(pbuf) != DNS_R_FORMERR) {
1046     /* treat it as bad reply if !FORMERR */
1047     DNS_DBG(ctx, -1/*bad reply*/, &sns.sa, slen, pbuf, r);
1048     goto again;
1049   }
1050   else {
1051     /* else it's FORMERR, handled below */
1052   }
1053 
1054   /* find server */
1055 #ifdef HAVE_IPv6
1056   if (sns.sa.sa_family == AF_INET6 && slen >= sizeof(sns.sin6)) {
1057     for(servi = 0; servi < ctx->dnsc_nserv; ++servi)
1058       if (sin6_eq(ctx->dnsc_serv[servi].sin6, sns.sin6))
1059         break;
1060   }
1061   else
1062 #endif
1063   if (sns.sa.sa_family == AF_INET && slen >= sizeof(sns.sin)) {
1064     for(servi = 0; servi < ctx->dnsc_nserv; ++servi)
1065       if (sin_eq(ctx->dnsc_serv[servi].sin, sns.sin))
1066         break;
1067   }
1068   else
1069     servi = ctx->dnsc_nserv;
1070 
1071   /* check if we expect reply from this server.
1072    * Note we can receive reply from first try if we're already at next */
1073   if (!(q->dnsq_servwait & (1 << servi))) { /* if ever asked this NS */
1074     DNS_DBG(ctx, -2/*wrong server*/, &sns.sa, slen, pbuf, r);
1075     goto again;
1076   }
1077 
1078   /* we got (some) reply for our query */
1079 
1080   DNS_DBGQ(ctx, q, 0, &sns.sa, slen, pbuf, r);
1081   q->dnsq_servwait &= ~(1 << servi);	/* don't expect reply from this serv */
1082 
1083   /* process the RCODE */
1084   switch(dns_rcode(pbuf)) {
1085 
1086   case DNS_R_NOERROR:
1087     if (dns_tc(pbuf)) {
1088       /* possible truncation.  We can't deal with it. */
1089       /*XXX for now, treat TC bit the same as SERVFAIL.
1090        * It is possible to:
1091        *  a) try to decode the reply - may be ANSWER section is ok;
1092        *  b) check if server understands EDNS0, and if it is, and
1093        *   answer still don't fit, end query.
1094        */
1095       break;
1096     }
1097     if (!dns_numan(pbuf)) {	/* no data of requested type */
1098       if (dns_next_srch(ctx, q)) {
1099         /* if we're searching, try next searchlist element,
1100          * but remember NODATA reply. */
1101         q->dnsq_flags |= DNS_SEEN_NODATA;
1102         dns_send(ctx, q, now);
1103       }
1104       else
1105         /* else - nothing to search any more - finish the query.
1106          * It will be NODATA since we've seen a NODATA reply. */
1107         dns_end_query(ctx, q, DNS_E_NODATA, 0);
1108     }
1109     /* we've got a positive reply here */
1110     else if (q->dnsq_parse) {
1111       /* if we have parsing routine, call it and return whatever it returned */
1112       /* don't try to re-search if NODATA here.  For example,
1113        * if we asked for A but only received CNAME.  Unless we'll
1114        * someday do recursive queries.  And that's problematic too, since
1115        * we may be dealing with specific AA-only nameservers for a given
1116        * domain, but CNAME points elsewhere...
1117        */
1118       r = q->dnsq_parse(q->dnsq_dn, pbuf, pcur, pend, &result);
1119       dns_end_query(ctx, q, r, r < 0 ? NULL : result);
1120     }
1121     /* else just malloc+copy the raw DNS reply */
1122     else if ((result = malloc(r)) == NULL)
1123       dns_end_query(ctx, q, DNS_E_NOMEM, NULL);
1124     else {
1125       memcpy(result, pbuf, r);
1126       dns_end_query(ctx, q, r, result);
1127     }
1128     goto again;
1129 
1130   case DNS_R_NXDOMAIN:	/* Non-existing domain. */
1131     if (dns_next_srch(ctx, q))
1132       /* more search entries exists, try them. */
1133       dns_send(ctx, q, now);
1134     else
1135       /* nothing to search anymore. End the query, returning either NODATA
1136        * if we've seen it before, or NXDOMAIN if not. */
1137       dns_end_query(ctx, q,
1138            q->dnsq_flags & DNS_SEEN_NODATA ? DNS_E_NODATA : DNS_E_NXDOMAIN, 0);
1139     goto again;
1140 
1141   case DNS_R_FORMERR:
1142   case DNS_R_NOTIMPL:
1143     /* for FORMERR and NOTIMPL rcodes, if we tried EDNS0-enabled query,
1144      * try w/o EDNS0. */
1145     if (ctx->dnsc_udpbuf > DNS_MAXPACKET &&
1146         !(q->dnsq_servnEDNS0 & (1 << servi))) {
1147       /* we always trying EDNS0 first if enabled, and retry a given query
1148        * if not available. Maybe it's better to remember inavailability of
1149        * EDNS0 in ctx as a per-NS flag, and never try again for this NS.
1150        * For long-running applications.. maybe they will change the nameserver
1151        * while we're running? :)  Also, since FORMERR is the only rcode we
1152        * allow to be header-only, and in this case the only check we do to
1153        * find a query it belongs to is qID (not qDN+qCLS+qTYP), it's much
1154        * easier to spoof and to force us to perform non-EDNS0 queries only...
1155        */
1156       q->dnsq_servnEDNS0 |= 1 << servi;
1157       dns_send_this(ctx, q, servi, now);
1158       goto again;
1159     }
1160     /* else we handle it the same as SERVFAIL etc */
1161 
1162   case DNS_R_SERVFAIL:
1163   case DNS_R_REFUSED:
1164     /* for these rcodes, advance this request
1165      * to the next server and reschedule */
1166   default: /* unknown rcode? hmmm... */
1167     break;
1168   }
1169 
1170   /* here, we received unexpected reply */
1171   q->dnsq_servskip |= (1 << servi);	/* don't retry this server */
1172 
1173   /* we don't expect replies from this server anymore.
1174    * But there may be other servers.  Some may be still processing our
1175    * query, and some may be left to try.
1176    * We just ignore this reply and wait a bit more if some NSes haven't
1177    * replied yet (dnsq_servwait != 0), and let the situation to be handled
1178    * on next event processing.  Timeout for this query is set correctly,
1179    * if not taking into account the one-second difference - we can try
1180    * next server in the same iteration sooner.
1181    */
1182 
1183   /* try next server */
1184   if (!q->dnsq_servwait) {
1185     /* next retry: maybe some other servers will reply next time.
1186      * dns_send() will end the query for us if no more servers to try.
1187      * Note we can't continue with the next searchlist element here:
1188      * we don't know if the current qdn exists or not, there's no definitive
1189      * answer yet (which is seen in cases above).
1190      *XXX standard resolver also tries as-is query in case all nameservers
1191      * failed to process our query and if not tried before.  We don't do it.
1192      */
1193     dns_send(ctx, q, now);
1194   }
1195   else {
1196     /* else don't do anything - not all servers replied yet */
1197   }
1198   goto again;
1199 
1200 }
1201 
1202 /* handle all timeouts */
dns_timeouts(struct dns_ctx * ctx,int maxwait,time_t now)1203 int dns_timeouts(struct dns_ctx *ctx, int maxwait, time_t now) {
1204   /* this is a hot routine */
1205   struct dns_query *q;
1206 
1207   SETCTX(ctx);
1208   dns_assert_ctx(ctx);
1209 
1210   /* Pick up first entry from query list.
1211    * If its deadline has passed, (re)send it
1212    * (dns_send() will move it next in the list).
1213    * If not, this is the query which determines the closest deadline.
1214    */
1215 
1216   q = ctx->dnsc_qactive.head;
1217   if (!q)
1218     return maxwait;
1219   if (!now)
1220     now = time(NULL);
1221   do {
1222     if (q->dnsq_deadline > now) { /* first non-expired query */
1223       int w = (int)(q->dnsq_deadline - now);
1224       if (maxwait < 0 || maxwait > w)
1225         maxwait = w;
1226       break;
1227     }
1228     else {
1229       /* process expired deadline */
1230       dns_send(ctx, q, now);
1231     }
1232   } while((q = ctx->dnsc_qactive.head) != NULL);
1233 
1234   dns_request_utm(ctx, now); /* update timer with new deadline */
1235   return maxwait;
1236 }
1237 
1238 struct dns_resolve_data {
1239   int   dnsrd_done;
1240   void *dnsrd_result;
1241 };
1242 
dns_resolve_cb(struct dns_ctx * ctx,void * result,void * data)1243 static void dns_resolve_cb(struct dns_ctx *ctx, void *result, void *data) {
1244   struct dns_resolve_data *d = data;
1245   d->dnsrd_result = result;
1246   d->dnsrd_done = 1;
1247   ctx = ctx;
1248 }
1249 
dns_resolve(struct dns_ctx * ctx,struct dns_query * q)1250 void *dns_resolve(struct dns_ctx *ctx, struct dns_query *q) {
1251   time_t now;
1252   struct dns_resolve_data d;
1253   int n;
1254   SETCTXOPEN(ctx);
1255 
1256   if (!q)
1257     return NULL;
1258 
1259   assert(ctx == q->dnsq_ctx);
1260   dns_assert_ctx(ctx);
1261   /* do not allow re-resolving syncronous queries */
1262   assert(q->dnsq_cbck != dns_resolve_cb && "can't resolve syncronous query");
1263   if (q->dnsq_cbck == dns_resolve_cb) {
1264     ctx->dnsc_qstatus = DNS_E_BADQUERY;
1265     return NULL;
1266   }
1267   q->dnsq_cbck = dns_resolve_cb;
1268   q->dnsq_cbdata = &d;
1269   d.dnsrd_done = 0;
1270 
1271   now = time(NULL);
1272   while(!d.dnsrd_done && (n = dns_timeouts(ctx, -1, now)) >= 0) {
1273 #ifdef HAVE_POLL
1274     struct pollfd pfd;
1275     pfd.fd = ctx->dnsc_udpsock;
1276     pfd.events = POLLIN;
1277     n = poll(&pfd, 1, n * 1000);
1278 #else
1279     fd_set rfd;
1280     struct timeval tv;
1281     FD_ZERO(&rfd);
1282     FD_SET(ctx->dnsc_udpsock, &rfd);
1283     tv.tv_sec = n; tv.tv_usec = 0;
1284     n = select(ctx->dnsc_udpsock + 1, &rfd, NULL, NULL, &tv);
1285 #endif
1286     now = time(NULL);
1287     if (n > 0)
1288       dns_ioevent(ctx, now);
1289   }
1290 
1291   return d.dnsrd_result;
1292 }
1293 
dns_resolve_dn(struct dns_ctx * ctx,dnscc_t * dn,int qcls,int qtyp,int flags,dns_parse_fn * parse)1294 void *dns_resolve_dn(struct dns_ctx *ctx,
1295                      dnscc_t *dn, int qcls, int qtyp, int flags,
1296                      dns_parse_fn *parse) {
1297   return
1298     dns_resolve(ctx,
1299       dns_submit_dn(ctx, dn, qcls, qtyp, flags, parse, NULL, NULL));
1300 }
1301 
dns_resolve_p(struct dns_ctx * ctx,const char * name,int qcls,int qtyp,int flags,dns_parse_fn * parse)1302 void *dns_resolve_p(struct dns_ctx *ctx,
1303                     const char *name, int qcls, int qtyp, int flags,
1304                     dns_parse_fn *parse) {
1305   return
1306     dns_resolve(ctx,
1307       dns_submit_p(ctx, name, qcls, qtyp, flags, parse, NULL, NULL));
1308 }
1309 
dns_cancel(struct dns_ctx * ctx,struct dns_query * q)1310 int dns_cancel(struct dns_ctx *ctx, struct dns_query *q) {
1311   SETCTX(ctx);
1312   dns_assert_ctx(ctx);
1313   assert(q->dnsq_ctx == ctx);
1314   /* do not allow cancelling syncronous queries */
1315   assert(q->dnsq_cbck != dns_resolve_cb && "can't cancel syncronous query");
1316   if (q->dnsq_cbck == dns_resolve_cb)
1317     return (ctx->dnsc_qstatus = DNS_E_BADQUERY);
1318   qlist_remove(&ctx->dnsc_qactive, q);
1319   --ctx->dnsc_nactive;
1320   dns_request_utm(ctx, 0);
1321   return 0;
1322 }
1323 
1324