1 /*
2  * PgBouncer - Lightweight connection pooler for PostgreSQL.
3  *
4  * Copyright (c) 2007-2010  Marko Kreen, Skype Technologies OÜ
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include "bouncer.h"
20 
21 #include <usual/netdb.h>
22 
23 #if !defined(USE_EVDNS) && !defined(USE_UDNS) && !defined(USE_CARES)
24 #define USE_GETADDRINFO_A
25 #endif
26 
27 #ifdef USE_EVDNS
28 #include <event2/dns.h>
29 #define addrinfo evutil_addrinfo
30 #define freeaddrinfo evutil_freeaddrinfo
31 #endif /* USE_EVDNS */
32 
33 #ifdef USE_CARES
34 #include <ares.h>
35 #include <ares_dns.h>
36 #ifndef WIN32
37 #include <arpa/nameser.h>
38 #else
39 #include <nameser.h>
40 #endif
41 #define ZONE_RECHECK 1
42 #else
43 /* only c-ares requires this */
44 #define impl_per_loop(ctx)
45 #endif
46 
47 #ifdef USE_UDNS
48 #include <udns.h>
49 #define ZONE_RECHECK 1
50 #endif
51 
52 #ifndef ZONE_RECHECK
53 #define ZONE_RECHECK 0
54 /* no implementation, also avoid 'unused' warning */
55 #define impl_query_soa_serial(ctx, name) do { if (0) got_zone_serial(ctx, NULL); } while (0)
56 #define cf_dns_zone_check_period (0)
57 #endif
58 
59 /*
60  * There can be several client request (tokens)
61  * attached to single actual request.
62  */
63 struct DNSToken {
64 	struct List node;
65 	adns_callback_f cb_func;
66 	void *cb_arg;
67 };
68 
69 /*
70  * Cached DNS query (hostname).
71  */
72 struct DNSRequest {
73 	struct AANode node;	/* DNSContext->req_tree */
74 	struct List znode;	/* DNSZone->host_list */
75 
76 	struct DNSContext *ctx;
77 	struct DNSZone *zone;
78 
79 	struct List ucb_list;	/* DNSToken->node */
80 
81 	char *name;
82 	int namelen;
83 
84 	bool done;
85 
86 	struct addrinfo *result;
87 	struct addrinfo *current;
88 	struct addrinfo *oldres;
89 
90 	usec_t res_ttl;
91 };
92 
93 /* zone name serial */
94 struct DNSZone {
95 	struct List lnode;		/* DNSContext->zone_list */
96 	struct AANode tnode;		/* DNSContext->zone_tree */
97 
98 	struct StatList host_list;	/* DNSRequest->znode */
99 
100 	char *zonename;
101 	uint32_t serial;
102 };
103 
104 /*
105  * Top struct for DNS data.
106  */
107 struct DNSContext {
108 	struct AATree req_tree;
109 	void *edns;
110 
111 	struct AATree zone_tree;	/* DNSZone->tnode */
112 	struct List zone_list;		/* DNSZone->lnode */
113 
114 	struct DNSZone *cur_zone;
115 	struct event ev_zone_timer;
116 	int zone_state;
117 
118 	int active;	/* number of in-flight queries */
119 };
120 
121 static void deliver_info(struct DNSRequest *req);
122 static void got_result_gai(int result, struct addrinfo *res, void *arg);
123 
124 static void zone_register(struct DNSContext *ctx, struct DNSRequest *req);
125 static void zone_init(struct DNSContext *ctx);
126 static void zone_free(struct DNSContext *ctx);
127 
128 static void got_zone_serial(struct DNSContext *ctx, uint32_t *serial);
129 
130 /*
131  * Custom addrinfo generation
132  */
133 
134 #if defined(USE_UDNS) || defined(USE_CARES)
135 
mk_addrinfo(const void * adr,int af)136 static struct addrinfo *mk_addrinfo(const void *adr, int af)
137 {
138 	struct addrinfo *ai;
139 
140 	ai = calloc(1, sizeof(*ai));
141 	if (!ai)
142 		return NULL;
143 
144 	if (af == AF_INET) {
145 		struct sockaddr_in *sa4;
146 		sa4 = calloc(1, sizeof(*sa4));
147 		if (!sa4)
148 			goto failed;
149 		memcpy(&sa4->sin_addr, adr, 4);
150 		sa4->sin_family = af;
151 		ai->ai_addr = (struct sockaddr *)sa4;
152 		ai->ai_addrlen = sizeof(*sa4);
153 	} else if (af == AF_INET6) {
154 		struct sockaddr_in6 *sa6;
155 		sa6 = calloc(1, sizeof(*sa6));
156 		if (!sa6)
157 			goto failed;
158 		memcpy(&sa6->sin6_addr, adr, sizeof(sa6->sin6_addr));
159 		sa6->sin6_family = af;
160 		ai->ai_addr = (struct sockaddr *)sa6;
161 		ai->ai_addrlen = sizeof(*sa6);
162 	}
163 	ai->ai_protocol = IPPROTO_TCP;
164 	ai->ai_socktype = SOCK_STREAM;
165 	ai->ai_family = af;
166 	return ai;
167 failed:
168 	free(ai);
169 	return NULL;
170 }
171 
172 #define freeaddrinfo(x) local_freeaddrinfo(x)
173 
freeaddrinfo(struct addrinfo * ai)174 static void freeaddrinfo(struct addrinfo *ai)
175 {
176 	struct addrinfo *cur;
177 	while (ai) {
178 		cur = ai;
179 		ai = ai->ai_next;
180 		free(cur->ai_addr);
181 		free(cur);
182 	}
183 }
184 
185 #if defined(USE_UDNS)
186 
convert_ipv4_result(const struct in_addr * adrs,int count)187 static inline struct addrinfo *convert_ipv4_result(const struct in_addr *adrs, int count)
188 {
189 	struct addrinfo *ai, *first = NULL, *last = NULL;
190 	int i;
191 
192 	for (i = 0; i < count; i++) {
193 		ai = mk_addrinfo(&adrs[i], AF_INET);
194 		if (!ai)
195 			goto failed;
196 
197 		if (!first)
198 			first = ai;
199 		else
200 			last->ai_next = ai;
201 		last = ai;
202 	}
203 	return first;
204 failed:
205 	freeaddrinfo(first);
206 	return NULL;
207 }
208 
209 #endif /* USE_UDNS */
210 
211 #ifdef USE_CARES
212 
convert_hostent(const struct hostent * h)213 static inline struct addrinfo *convert_hostent(const struct hostent *h)
214 {
215 	struct addrinfo *ai, *first = NULL, *last = NULL;
216 	int i;
217 
218 	for (i = 0; h->h_addr_list[i]; i++) {
219 		ai = mk_addrinfo(h->h_addr_list[i], h->h_addrtype);
220 		if (!ai)
221 			goto failed;
222 
223 		if (!first)
224 			first = ai;
225 		else
226 			last->ai_next = ai;
227 		last = ai;
228 	}
229 	return first;
230 failed:
231 	freeaddrinfo(first);
232 	return NULL;
233 }
234 
235 #endif /* USE_CARES */
236 
237 #endif /* custom addrinfo */
238 
239 
240 /*
241  * ADNS with glibc's getaddrinfo_a()
242  */
243 
244 #ifdef USE_GETADDRINFO_A
245 
adns_get_backend(void)246 const char *adns_get_backend(void)
247 {
248 #ifdef HAVE_GETADDRINFO_A
249 	return "libc"
250 #ifdef __GLIBC__
251 	"-" STR(__GLIBC__) "." STR(__GLIBC_MINOR__);
252 #endif
253 	;
254 #else
255 	return "compat";
256 #endif
257 }
258 
259 struct GaiRequest {
260 	struct List node;
261 	struct DNSRequest *req;
262 	struct gaicb gairq;
263 };
264 
265 struct GaiContext {
266 	struct DNSContext *ctx;
267 	struct List gairq_list;
268 	struct event ev;
269 	struct sigevent sev;
270 };
271 
dns_signal(int f,short ev,void * arg)272 static void dns_signal(int f, short ev, void *arg)
273 {
274 	struct GaiContext *gctx = arg;
275 	struct List *el, *tmp;
276 	struct GaiRequest *rq;
277 	int e;
278 	list_for_each_safe(el, &gctx->gairq_list, tmp) {
279 		rq = container_of(el, struct GaiRequest, node);
280 		e = gai_error(&rq->gairq);
281 		if (e == EAI_INPROGRESS)
282 			continue;
283 
284 		/* got one */
285 		list_del(&rq->node);
286 		got_result_gai(e, rq->gairq.ar_result, rq->req);
287 		free(rq);
288 	}
289 }
290 
impl_init(struct DNSContext * ctx)291 static bool impl_init(struct DNSContext *ctx)
292 {
293 	struct GaiContext *gctx;
294 
295 	if (cf_resolv_conf && cf_resolv_conf[0]) {
296 		log_error("resolv_conf setting is not supported by libc adns");
297 		return false;
298 	}
299 
300 	gctx = calloc(1, sizeof(*gctx));
301 	if (!gctx)
302 		return false;
303 	list_init(&gctx->gairq_list);
304 	gctx->ctx = ctx;
305 
306 	gctx->sev.sigev_notify = SIGEV_SIGNAL;
307 	gctx->sev.sigev_signo = SIGALRM;
308 
309 	evsignal_assign(&gctx->ev, pgb_event_base, SIGALRM, dns_signal, gctx);
310 	if (evsignal_add(&gctx->ev, NULL) < 0) {
311 		free(gctx);
312 		return false;
313 	}
314 	ctx->edns = gctx;
315 	return true;
316 }
317 
impl_launch_query(struct DNSRequest * req)318 static void impl_launch_query(struct DNSRequest *req)
319 {
320 	static const struct addrinfo hints = { .ai_socktype = SOCK_STREAM };
321 
322 	struct GaiContext *gctx = req->ctx->edns;
323 	struct GaiRequest *grq;
324 	int res;
325 	struct gaicb *cb;
326 
327 	grq = calloc(1, sizeof(*grq));
328 	if (!grq)
329 		goto failed2;
330 
331 	list_init(&grq->node);
332 	grq->req = req;
333 	grq->gairq.ar_name = req->name;
334 	grq->gairq.ar_request = &hints;
335 	list_append(&gctx->gairq_list, &grq->node);
336 
337 	cb = &grq->gairq;
338 	res = getaddrinfo_a(GAI_NOWAIT, &cb, 1, &gctx->sev);
339 	if (res != 0)
340 		goto failed;
341 	return;
342 
343 failed:
344 	if (res == EAI_SYSTEM) {
345 		log_warning("dns: getaddrinfo_a(%s)=%d, errno=%d (%s)",
346 			    req->name, res, errno, strerror(errno));
347 	} else {
348 		log_warning("dns: getaddrinfo_a(%s)=%d", req->name, res);
349 	}
350 	list_del(&grq->node);
351 	free(grq);
352 failed2:
353 	req->done = true;
354 	deliver_info(req);
355 }
356 
impl_release(struct DNSContext * ctx)357 static void impl_release(struct DNSContext *ctx)
358 {
359 	struct GaiContext *gctx = ctx->edns;
360 	if (gctx) {
361 		evsignal_del(&gctx->ev);
362 		free(gctx);
363 		ctx->edns = NULL;
364 	}
365 }
366 
367 #endif /* USE_GETADDRINFO_A */
368 
369 
370 /*
371  * ADNS with libevent2 <event2/dns.h>
372  */
373 
374 #ifdef USE_EVDNS
375 
adns_get_backend(void)376 const char *adns_get_backend(void)
377 {
378 	return "evdns2";
379 }
380 
381 /*
382  * Confusingly, this is not the same as evdns_err_to_string().
383  */
_evdns_base_resolv_conf_parse_err_to_string(int err)384 static const char *_evdns_base_resolv_conf_parse_err_to_string(int err)
385 {
386 	switch (err) {
387 	case 0: return "no error";
388 	case 1: return "failed to open file";
389 	case 2: return "failed to stat file";
390 	case 3: return "file too large";
391 	case 4: return "out of memory";
392 	case 5: return "short read from file";
393 	case 6: return "no nameservers listed in the file";
394 	default: return "[Unknown error code]";
395 	}
396 }
397 
impl_init(struct DNSContext * ctx)398 static bool impl_init(struct DNSContext *ctx)
399 {
400 	if (cf_resolv_conf && cf_resolv_conf[0]) {
401 		int err;
402 
403 		ctx->edns = evdns_base_new(pgb_event_base, 0);
404 		if (!ctx->edns) {
405 			log_error("evdns_base_new failed");
406 			return false;
407 		}
408 		err = evdns_base_resolv_conf_parse(ctx->edns, DNS_OPTIONS_ALL,
409 						   cf_resolv_conf);
410 		if (err) {
411 			log_error("evdns parsing of \"%s\" failed: %s",
412 				  cf_resolv_conf,
413 				  _evdns_base_resolv_conf_parse_err_to_string(err));
414 			return false;
415 		}
416 	} else {
417 		ctx->edns = evdns_base_new(pgb_event_base, 1);
418 		if (!ctx->edns) {
419 			log_error("evdns_base_new failed");
420 			return false;
421 		}
422 	}
423 	return true;
424 }
425 
impl_launch_query(struct DNSRequest * req)426 static void impl_launch_query(struct DNSRequest *req)
427 {
428 	static const struct addrinfo hints = { .ai_socktype = SOCK_STREAM };
429 
430 	struct evdns_getaddrinfo_request *gai_req;
431 	struct evdns_base *dns = req->ctx->edns;
432 
433 	gai_req = evdns_getaddrinfo(dns, req->name, NULL, &hints, got_result_gai, req);
434 	log_noise("dns: evdns_getaddrinfo(%s)=%p", req->name, gai_req);
435 }
436 
impl_release(struct DNSContext * ctx)437 static void impl_release(struct DNSContext *ctx)
438 {
439 	struct evdns_base *dns = ctx->edns;
440 	evdns_base_free(dns, 0);
441 }
442 
443 #endif /* USE_EVDNS */
444 
445 
446 /*
447  * ADNS with <udns.h>
448  */
449 
450 #ifdef USE_UDNS
451 
452 struct UdnsMeta {
453 	struct dns_ctx *ctx;
454 	struct event ev_io;
455 	struct event ev_timer;
456 	bool timer_active;
457 };
458 
adns_get_backend(void)459 const char *adns_get_backend(void)
460 {
461 	return "udns " UDNS_VERSION;
462 }
463 
udns_timer_setter(struct dns_ctx * uctx,int timeout,void * arg)464 static void udns_timer_setter(struct dns_ctx *uctx, int timeout, void *arg)
465 {
466 	struct DNSContext *ctx = arg;
467 	struct UdnsMeta *udns = ctx->edns;
468 
469 	log_noise("udns_timer_setter: ctx=%p timeout=%d", uctx, timeout);
470 
471 	if (udns->timer_active) {
472 		event_del(&udns->ev_timer);
473 		udns->timer_active = false;
474 	}
475 
476 	if (uctx && timeout >= 0) {
477 		struct timeval tv = { .tv_sec = timeout, .tv_usec = 0 };
478 		evtimer_add(&udns->ev_timer, &tv);
479 		udns->timer_active = true;
480 	}
481 }
482 
udns_timer_cb(int d,short fl,void * arg)483 static void udns_timer_cb(int d, short fl, void *arg)
484 {
485 	struct DNSContext *ctx = arg;
486 	struct UdnsMeta *udns = ctx->edns;
487 	time_t now = get_cached_time() / USEC;
488 
489 	log_noise("udns_timer_cb");
490 
491 	dns_timeouts(udns->ctx, 10, now);
492 }
493 
udns_io_cb(int fd,short fl,void * arg)494 static void udns_io_cb(int fd, short fl, void *arg)
495 {
496 	struct DNSContext *ctx = arg;
497 	struct UdnsMeta *udns = ctx->edns;
498 	time_t now = get_cached_time() / USEC;
499 
500 	log_noise("udns_io_cb");
501 
502 	dns_ioevent(udns->ctx, now);
503 }
504 
udns_result_a4(struct dns_ctx * ctx,struct dns_rr_a4 * a4,void * data)505 static void udns_result_a4(struct dns_ctx *ctx, struct dns_rr_a4 *a4, void *data)
506 {
507 	struct DNSRequest *req = data;
508 	struct addrinfo *res = NULL;
509 	int err;
510 
511 	err = dns_status(ctx);
512 	if (err < 0) {
513 		log_warning("udns_result_a4: %s: query failed [%d]", req->name, err);
514 	} else if (a4) {
515 		log_noise("udns_result_a4: %s: %d ips", req->name, a4->dnsa4_nrr);
516 		res = convert_ipv4_result(a4->dnsa4_addr, a4->dnsa4_nrr);
517 		free(a4);
518 	} else {
519 		log_warning("udns_result_a4: %s: missing result", req->name);
520 	}
521 	got_result_gai(0, res, req);
522 }
523 
impl_launch_query(struct DNSRequest * req)524 static void impl_launch_query(struct DNSRequest *req)
525 {
526 	struct UdnsMeta *udns = req->ctx->edns;
527 	struct dns_query *q;
528 	int flags = 0;
529 
530 	q = dns_submit_a4(udns->ctx, req->name, flags, udns_result_a4, req);
531 	if (q) {
532 		log_noise("dns: udns_launch_query(%s)=%p", req->name, q);
533 	} else {
534 		log_warning("dns: udns_launch_query(%s)=NULL", req->name);
535 	}
536 }
537 
impl_init(struct DNSContext * ctx)538 static bool impl_init(struct DNSContext *ctx)
539 {
540 	int fd;
541 	struct dns_ctx *dctx;
542 	struct UdnsMeta *udns;
543 	int err;
544 
545 	if (cf_resolv_conf && cf_resolv_conf[0]) {
546 		log_error("resolv_conf setting is not supported by udns");
547 		return false;
548 	}
549 
550 	dns_init(NULL, 0);
551 
552 	dctx = dns_new(NULL);
553 	if (!dctx)
554 		return false;
555 
556 	udns = calloc(1, sizeof(*udns));
557 	if (!udns)
558 		return false;
559 	ctx->edns = udns;
560 	udns->ctx = dctx;
561 
562 	/* i/o callback setup */
563 	fd = dns_open(dctx);
564 	if (fd <= 0) {
565 		log_error("dns_open failed: fd=%d", fd);
566 		return false;
567 	}
568 	event_assign(&udns->ev_io, pgb_event_base, fd, EV_READ | EV_PERSIST, udns_io_cb, ctx);
569 	err = event_add(&udns->ev_io, NULL);
570 	if (err < 0)
571 		log_warning("impl_init: event_add failed: %s", strerror(errno));
572 
573 	/* timer setup */
574 	evtimer_assign(&udns->ev_timer, pgb_event_base, udns_timer_cb, ctx);
575 	dns_set_tmcbck(udns->ctx, udns_timer_setter, ctx);
576 
577 	return true;
578 }
579 
impl_release(struct DNSContext * ctx)580 static void impl_release(struct DNSContext *ctx)
581 {
582 	struct UdnsMeta *udns = ctx->edns;
583 
584 	event_del(&udns->ev_io);
585 	dns_free(udns->ctx);
586 	if (udns->timer_active) {
587 		event_del(&udns->ev_timer);
588 		udns->timer_active = false;
589 	}
590 }
591 
592 /*
593  * generic SOA query for UDNS
594  */
595 
596 struct SOA {
597 	dns_rr_common(dnssoa);
598 
599 	char *dnssoa_nsname;
600 	char *dnssoa_hostmaster;
601 	uint32_t dnssoa_serial;
602 	uint32_t dnssoa_refresh;
603 	uint32_t dnssoa_retry;
604 	uint32_t dnssoa_expire;
605 	uint32_t dnssoa_minttl;
606 };
607 
608 typedef void query_soa_fn(struct dns_ctx *ctx, struct SOA *result, void *data);
609 
parse_soa(dnscc_t * qdn,dnscc_t * pkt,dnscc_t * cur,dnscc_t * end,void ** result)610 static int parse_soa(dnscc_t *qdn, dnscc_t *pkt, dnscc_t *cur, dnscc_t *end, void **result)
611 {
612 	struct SOA *soa = NULL;
613 	int res, len;
614 	struct dns_parse p;
615 	struct dns_rr rr;
616 	dnsc_t buf[DNS_MAXDN];
617 	char *s;
618 
619 	/* calc size */
620 	len = 0;
621 	dns_initparse(&p, qdn, pkt, cur, end);
622 	while ((res = dns_nextrr(&p, &rr)) > 0) {
623 		cur = rr.dnsrr_dptr;
624 
625 		res = dns_getdn(pkt, &cur, end, buf, sizeof(buf));
626 		if (res <= 0)
627 			goto failed;
628 		len += dns_dntop_size(buf);
629 
630 		res = dns_getdn(pkt, &cur, end, buf, sizeof(buf));
631 		if (res <= 0)
632 			goto failed;
633 		len += dns_dntop_size(buf);
634 
635 		if (cur + 5*4 != rr.dnsrr_dend)
636 			goto failed;
637 	}
638 	if (res < 0 || p.dnsp_nrr != 1)
639 		goto failed;
640 	len += dns_stdrr_size(&p);
641 
642 	/* allocate */
643 	soa = malloc(sizeof(*soa) + len);
644 	if (!soa)
645 		return DNS_E_NOMEM;
646 
647 	/* fill with data */
648 	soa->dnssoa_nrr = 1;
649 	dns_rewind(&p, qdn);
650 	dns_nextrr(&p, &rr);
651 	s = (char *)(soa + 1);
652 	cur = rr.dnsrr_dptr;
653 
654 	soa->dnssoa_nsname = s;
655 	dns_getdn(pkt, &cur, end, buf, sizeof(buf));
656 	s += dns_dntop(buf, s, DNS_MAXNAME);
657 
658 	soa->dnssoa_hostmaster = s;
659 	dns_getdn(pkt, &cur, end, buf, sizeof(buf));
660 	s += dns_dntop(buf, s, DNS_MAXNAME);
661 
662 	soa->dnssoa_serial = dns_get32(cur + 0*4);
663 	soa->dnssoa_refresh = dns_get32(cur + 1*4);
664 	soa->dnssoa_retry = dns_get32(cur + 2*4);
665 	soa->dnssoa_expire = dns_get32(cur + 3*4);
666 	soa->dnssoa_minttl = dns_get32(cur + 4*4);
667 
668 	dns_stdrr_finish((struct dns_rr_null *)soa, s, &p);
669 
670 	*result = soa;
671 	return 0;
672 failed:
673 	free(soa);
674 	return DNS_E_PROTOCOL;
675 }
676 
677 static struct dns_query *
submit_soa(struct dns_ctx * ctx,const char * name,int flags,query_soa_fn * cb,void * data)678 submit_soa(struct dns_ctx *ctx, const char *name, int flags, query_soa_fn *cb, void *data)
679 {
680 	  return dns_submit_p(ctx, name, DNS_C_IN, DNS_T_SOA, flags,
681 			      parse_soa, (dns_query_fn *)cb, data);
682 }
683 
684 /*
685  * actual "get serial" part
686  */
687 
udns_result_soa(struct dns_ctx * uctx,struct SOA * soa,void * data)688 static void udns_result_soa(struct dns_ctx *uctx, struct SOA *soa, void *data)
689 {
690 	struct DNSContext *ctx = data;
691 
692 	if (!soa) {
693 		log_noise("SOA query failed");
694 		got_zone_serial(ctx, NULL);
695 		return;
696 	}
697 
698 	log_noise("SOA1: cname=%s qname=%s ttl=%u nrr=%u",
699 		  soa->dnssoa_cname, soa->dnssoa_qname,
700 		  soa->dnssoa_ttl, soa->dnssoa_nrr);
701 	log_noise("SOA2: nsname=%s hostmaster=%s serial=%u refresh=%u retry=%u expire=%u minttl=%u",
702 		  soa->dnssoa_nsname, soa->dnssoa_hostmaster, soa->dnssoa_serial, soa->dnssoa_refresh,
703 		  soa->dnssoa_retry, soa->dnssoa_expire, soa->dnssoa_minttl);
704 
705 	got_zone_serial(ctx, &soa->dnssoa_serial);
706 
707 	free(soa);
708 }
709 
impl_query_soa_serial(struct DNSContext * ctx,const char * zonename)710 static int impl_query_soa_serial(struct DNSContext *ctx, const char *zonename)
711 {
712 	struct UdnsMeta *udns = ctx->edns;
713 	struct dns_query *q;
714 	int flags = 0;
715 
716 	log_debug("udns: impl_query_soa_serial: name=%s", zonename);
717 	q = submit_soa(udns->ctx, zonename, flags, udns_result_soa, ctx);
718 	if (!q) {
719 		log_error("impl_query_soa_serial failed: %s", zonename);
720 	}
721 	return 0;
722 }
723 
724 #endif /* USE_UDNS */
725 
726 
727 /*
728  * ADNS with <ares.h>
729  */
730 
731 #ifdef USE_CARES
732 
733 #define MAX_CARES_FDS 16
734 
735 struct XaresFD {
736 	struct event ev;		/* fd event state is persistent */
737 	struct XaresMeta *meta;		/* pointer to parent context */
738 	ares_socket_t sock;		/* socket value */
739 	short wait;			/* EV_READ / EV_WRITE */
740 	bool in_use;			/* is this slot assigned */
741 };
742 
743 struct XaresMeta {
744 	/* c-ares descriptor */
745 	ares_channel chan;
746 
747 	/* how many elements in fds array are in use */
748 	int max_fds;
749 
750 	/* static array for fds */
751 	struct XaresFD fds[MAX_CARES_FDS];
752 
753 	/* timer event is one-shot */
754 	struct event ev_timer;
755 
756 	/* is timer activated? */
757 	bool timer_active;
758 
759 	/* If dns events happened during event loop,
760 	   timer may need recalibration. */
761 	bool got_events;
762 
763 };
764 
adns_get_backend(void)765 const char *adns_get_backend(void)
766 {
767 	return "c-ares " ARES_VERSION_STR;
768 }
769 
770 
771 /* called by libevent on timer timeout */
xares_timer_cb(evutil_socket_t sock,short flags,void * arg)772 static void xares_timer_cb(evutil_socket_t sock, short flags, void *arg)
773 {
774 	struct DNSContext *ctx = arg;
775 	struct XaresMeta *meta = ctx->edns;
776 
777 	ares_process_fd(meta->chan, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
778 
779 	meta->timer_active = false;
780 	meta->got_events = true;
781 }
782 
783 /* called by libevent on fd event */
xares_fd_cb(evutil_socket_t sock,short flags,void * arg)784 static void xares_fd_cb(evutil_socket_t sock, short flags, void *arg)
785 {
786 	struct XaresFD *xfd = arg;
787 	struct XaresMeta *meta = xfd->meta;
788 	ares_socket_t r, w;
789 
790 	r = (flags & EV_READ) ? xfd->sock : ARES_SOCKET_BAD;
791 	w = (flags & EV_WRITE) ? xfd->sock : ARES_SOCKET_BAD;
792 	ares_process_fd(meta->chan, r, w);
793 
794 	meta->got_events = true;
795 }
796 
797 /* called by c-ares on new socket creation */
xares_new_socket_cb(ares_socket_t sock,int sock_type,void * arg)798 static int xares_new_socket_cb(ares_socket_t sock, int sock_type, void *arg)
799 {
800 	struct DNSContext *ctx = arg;
801 	struct XaresMeta *meta = ctx->edns;
802 	struct XaresFD *xfd;
803 	int pos;
804 
805 	/* find free slot in array */
806 	for (pos = 0; pos < meta->max_fds; pos++) {
807 		if (!meta->fds[pos].in_use)
808 			break;
809 	}
810 	if (pos >= MAX_CARES_FDS) {
811 		log_warning("c-ares fd overflow");
812 		return ARES_ENOMEM;
813 	}
814 	if (pos == meta->max_fds)
815 		meta->max_fds++;
816 
817 	/* fill it */
818 	xfd = &meta->fds[pos];
819 	xfd->meta = meta;
820 	xfd->sock = sock;
821 	xfd->wait = 0;
822 	xfd->in_use = true;
823 	return ARES_SUCCESS;
824 }
825 
826 /* called by c-ares on socket state change (r=w=0 means socket close) */
xares_state_cb(void * arg,ares_socket_t sock,int r,int w)827 static void xares_state_cb(void *arg, ares_socket_t sock, int r, int w)
828 {
829 	struct DNSContext *ctx = arg;
830 	struct XaresMeta *meta = ctx->edns;
831 	struct XaresFD *xfd;
832 	int pos;
833 	short new_wait = 0;
834 
835 	if (r)
836 		new_wait |= EV_READ;
837 	if (w)
838 		new_wait |= EV_WRITE;
839 
840 	/* find socket */
841 	for (pos = 0; pos < meta->max_fds; pos++) {
842 		xfd = &meta->fds[pos];
843 		if (!xfd->in_use)
844 			continue;
845 
846 		if (xfd->sock != sock)
847 			continue;
848 
849 		/* no change? */
850 		if (xfd->wait == new_wait)
851 			return;
852 
853 		goto re_set;
854 	}
855 
856 	log_warning("adns: c-ares state change for unknown fd: %u", (unsigned)sock);
857 	return;
858 
859 re_set:
860 	if (xfd->wait)
861 		event_del(&xfd->ev);
862 	xfd->wait = new_wait;
863 	if (new_wait) {
864 		event_assign(&xfd->ev, pgb_event_base, sock, new_wait | EV_PERSIST, xares_fd_cb, xfd);
865 		if (event_add(&xfd->ev, NULL) < 0)
866 			log_warning("adns: event_add failed: %s", strerror(errno));
867 	} else {
868 		xfd->in_use = false;
869 	}
870 	return;
871 }
872 
873 /* called by c-ares on dns reply */
xares_host_cb(void * arg,int status,int timeouts,struct hostent * h)874 static void xares_host_cb(void *arg, int status, int timeouts, struct hostent *h)
875 {
876 	struct DNSRequest *req = arg;
877 	struct addrinfo *res = NULL;
878 
879 	log_noise("dns: xares_host_cb(%s)=%s", req->name, ares_strerror(status));
880 	if (status == ARES_SUCCESS) {
881 		res = convert_hostent(h);
882 		got_result_gai(0, res, req);
883 	} else {
884 		log_debug("DNS lookup failed: %s - %s", req->name, ares_strerror(status));
885 		got_result_gai(0, res, req);
886 	}
887 }
888 
889 /* send hostname query */
impl_launch_query(struct DNSRequest * req)890 static void impl_launch_query(struct DNSRequest *req)
891 {
892 	struct XaresMeta *meta = req->ctx->edns;
893 	int af;
894 
895 /*
896  * c-ares <= 1.10 cannot resolve CNAME with AF_UNSPEC.
897  *
898  * Force IPv4 there.
899  *
900  * Fixed in "host_callback: Fall back to AF_INET on searching with AF_UNSPEC" (c1fe47f)
901  * in c-ares repo.
902  */
903 #if ARES_VERSION <= 0x10A00
904 #warning c-ares <=1.10 has buggy IPv6 support; this PgBouncer build will use IPv4 only.
905 	af = AF_INET;
906 #else
907 	af = AF_UNSPEC;
908 #endif
909 	log_noise("dns: ares_gethostbyname(%s)", req->name);
910 	ares_gethostbyname(meta->chan, req->name, af, xares_host_cb, req);
911 
912 	meta->got_events = true;
913 }
914 
915 /* re-set timer if any dns event happened */
impl_per_loop(struct DNSContext * ctx)916 static void impl_per_loop(struct DNSContext *ctx)
917 {
918 	struct timeval tv, *tvp;
919 	struct XaresMeta *meta = ctx->edns;
920 
921 	if (!meta->got_events)
922 		return;
923 
924 	if (meta->timer_active) {
925 		event_del(&meta->ev_timer);
926 		meta->timer_active = false;
927 	}
928 
929 	tvp = ares_timeout(meta->chan, NULL, &tv);
930 	if (tvp != NULL) {
931 		if (event_add(&meta->ev_timer, tvp) < 0)
932 			log_warning("impl_per_loop: event_add failed: %s", strerror(errno));
933 		meta->timer_active = true;
934 	}
935 
936 	meta->got_events = false;
937 }
938 
939 /* c-ares setup */
impl_init(struct DNSContext * ctx)940 static bool impl_init(struct DNSContext *ctx)
941 {
942 	struct XaresMeta *meta;
943 	int err;
944 	int mask;
945 	struct ares_options opts;
946 
947 	err = ares_library_init(ARES_LIB_INIT_ALL);
948 	if (err) {
949 		log_error("ares_library_init: %s", ares_strerror(err));
950 		return false;
951 	}
952 
953 	meta = calloc(1, sizeof(*meta));
954 	if (!meta)
955 		return false;
956 
957 	memset(&opts, 0, sizeof(opts));
958 	opts.sock_state_cb = xares_state_cb;
959 	opts.sock_state_cb_data = ctx;
960 	mask = ARES_OPT_SOCK_STATE_CB;
961 	if (cf_resolv_conf && cf_resolv_conf[0]) {
962 #ifdef ARES_OPT_RESOLVCONF
963 		opts.resolvconf_path = strdup(cf_resolv_conf);
964 		if (!opts.resolvconf_path) {
965 			free(meta);
966 			return false;
967 		}
968 		mask |= ARES_OPT_RESOLVCONF;
969 #else
970 		log_error("resolv_conf setting is not supported by this version of c-ares");
971 		free(meta);
972 		return false;
973 #endif
974 	}
975 
976 	err = ares_init_options(&meta->chan, &opts, mask);
977 	if (err) {
978 		free(meta);
979 		log_error("ares_library_init: %s", ares_strerror(err));
980 		return false;
981 	}
982 
983 	ares_set_socket_callback(meta->chan, xares_new_socket_cb, ctx);
984 
985 	evtimer_assign(&meta->ev_timer, pgb_event_base, xares_timer_cb, ctx);
986 
987 	ctx->edns = meta;
988 	return true;
989 }
990 
991 /* c-ares shutdown */
impl_release(struct DNSContext * ctx)992 static void impl_release(struct DNSContext *ctx)
993 {
994 	struct XaresMeta *meta = ctx->edns;
995 
996 	ares_destroy(meta->chan);
997 	ares_library_cleanup();
998 
999 	if (meta->timer_active)
1000 		event_del(&meta->ev_timer);
1001 
1002 	free(meta);
1003 	ctx->edns = NULL;
1004 }
1005 
1006 /*
1007  * query SOA with c-ares
1008  */
1009 
1010 #ifndef HAVE_ARES_PARSE_SOA_REPLY
1011 
1012 #define ares_soa_reply		xares_soa_reply
1013 #define ares_parse_soa_reply	xares_parse_soa_reply
1014 
1015 struct ares_soa_reply {
1016 	char *nsname;
1017 	char *hostmaster;
1018 	uint32_t serial;
1019 	uint32_t refresh;
1020 	uint32_t retry;
1021 	uint32_t expire;
1022 	uint32_t minttl;
1023 };
1024 
xares_free_soa(struct ares_soa_reply * soa)1025 static void xares_free_soa(struct ares_soa_reply *soa)
1026 {
1027 	if (soa) {
1028 		if (soa->nsname)
1029 			free(soa->nsname);
1030 		if (soa->hostmaster)
1031 			free(soa->hostmaster);
1032 		free(soa);
1033 	}
1034 }
1035 
1036 /*
1037  * Full SOA reply packet structure (rfc1035)
1038  *
1039  * 1) header
1040  *   id:16, flags:16, qdcount:16, ancount:16, nscount:16, arcount:16
1041  *
1042  * 2) query (qdcount)
1043  *   qname:name, qtype:16, qclass:16
1044  *
1045  * 3) answer (ancount)
1046  *   name:name, type:16, class:16, ttl:32, rdlength:16
1047  *
1048  * 3.1) soa rdata
1049  *   nsname:name, hostmaster:name,
1050  *   serial:32, refresh:32, retry:32, expire:32, minimum:32
1051  *
1052  * 4) authority (nscount) - ignored
1053  *
1054  * 5) additional (arcount) - ignored
1055  */
ares_parse_soa_reply(const unsigned char * abuf,int alen,struct ares_soa_reply ** soa_p)1056 static int ares_parse_soa_reply(const unsigned char *abuf, int alen, struct ares_soa_reply **soa_p)
1057 {
1058 	const unsigned char *aptr;
1059 	long len;
1060 	char *qname = NULL, *rr_name = NULL;
1061 	struct ares_soa_reply *soa = NULL;
1062 	int qdcount, ancount;
1063 	int status;
1064 
1065 	if (alen < NS_HFIXEDSZ)
1066 		return ARES_EBADRESP;
1067 
1068 	/* parse message header */
1069 	qdcount = DNS_HEADER_QDCOUNT(abuf);
1070 	ancount = DNS_HEADER_ANCOUNT(abuf);
1071 	if (qdcount != 1 || ancount != 1)
1072 		return ARES_EBADRESP;
1073 	aptr = abuf + NS_HFIXEDSZ;
1074 
1075 	/* allocate result struct */
1076 	soa = calloc(1, sizeof(*soa));
1077 	if (!soa)
1078 		return ARES_ENOMEM;
1079 
1080 	/* parse query */
1081 	status = ares_expand_name(aptr, abuf, alen, &qname, &len);
1082 	if (status != ARES_SUCCESS)
1083 		goto failed_stat;
1084 	aptr += len;
1085 
1086 	/* skip qtype & qclass */
1087 	if (aptr + NS_QFIXEDSZ > abuf + alen)
1088 		goto failed;
1089 	aptr += NS_QFIXEDSZ;
1090 
1091 	/* parse RR header */
1092 	status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
1093 	if (status != ARES_SUCCESS)
1094 		goto failed_stat;
1095 	aptr += len;
1096 
1097 	/* skip rr_type, rr_class, rr_ttl, rr_rdlen */
1098 	if (aptr + NS_RRFIXEDSZ > abuf + alen)
1099 		goto failed;
1100 	aptr += NS_RRFIXEDSZ;
1101 
1102 	/* nsname */
1103 	status = ares_expand_name(aptr, abuf, alen, &soa->nsname, &len);
1104 	if (status != ARES_SUCCESS)
1105 		goto failed_stat;
1106 	aptr += len;
1107 
1108 	/* hostmaster */
1109 	status = ares_expand_name(aptr, abuf, alen, &soa->hostmaster, &len);
1110 	if (status != ARES_SUCCESS)
1111 		goto failed_stat;
1112 	aptr += len;
1113 
1114 	/* integer fields */
1115 	if (aptr + 5*4 > abuf + alen)
1116 		goto failed;
1117 	soa->serial = DNS__32BIT(aptr + 0*4);
1118 	soa->refresh = DNS__32BIT(aptr + 1*4);
1119 	soa->retry = DNS__32BIT(aptr + 2*4);
1120 	soa->expire = DNS__32BIT(aptr + 3*4);
1121 	soa->minttl = DNS__32BIT(aptr + 4*4);
1122 
1123 	log_noise("ares SOA result: qname=%s rr_name=%s serial=%u", qname, rr_name, soa->serial);
1124 
1125 	free(qname);
1126 	free(rr_name);
1127 
1128 	*soa_p = soa;
1129 
1130 	return ARES_SUCCESS;
1131 
1132 failed:
1133 	status = ARES_EBADRESP;
1134 
1135 failed_stat:
1136 	xares_free_soa(soa);
1137 	if (qname)
1138 		free(qname);
1139 	if (rr_name)
1140 		free(rr_name);
1141 	return (status == ARES_EBADNAME) ? ARES_EBADRESP : status;
1142 }
1143 
1144 #else /* HAVE_ARES_PARSE_SOA_REPLY */
1145 
xares_free_soa(struct ares_soa_reply * soa)1146 static void xares_free_soa(struct ares_soa_reply *soa)
1147 {
1148 	ares_free_data(soa);
1149 }
1150 
1151 #endif /* HAVE_ARES_PARSE_SOA_REPLY */
1152 
1153 
1154 /* called by c-ares on SOA reply */
xares_soa_cb(void * arg,int status,int timeouts,unsigned char * abuf,int alen)1155 static void xares_soa_cb(void *arg, int status, int timeouts,
1156 			 unsigned char *abuf, int alen)
1157 {
1158 	struct DNSContext *ctx = arg;
1159 	struct XaresMeta *meta = ctx->edns;
1160 	struct ares_soa_reply *soa = NULL;
1161 
1162 	meta->got_events = true;
1163 
1164 	log_noise("ares SOA result: %s", ares_strerror(status));
1165 	if (status != ARES_SUCCESS) {
1166 		got_zone_serial(ctx, NULL);
1167 		return;
1168 	}
1169 
1170 	status = ares_parse_soa_reply(abuf, alen, &soa);
1171 	if (status == ARES_SUCCESS) {
1172 		got_zone_serial(ctx, &soa->serial);
1173 	} else {
1174 		log_warning("ares_parse_soa: %s", ares_strerror(status));
1175 		got_zone_serial(ctx, NULL);
1176 	}
1177 
1178 	xares_free_soa(soa);
1179 }
1180 
1181 /* send SOA query */
impl_query_soa_serial(struct DNSContext * ctx,const char * zonename)1182 static int impl_query_soa_serial(struct DNSContext *ctx, const char *zonename)
1183 {
1184 	struct XaresMeta *meta = ctx->edns;
1185 
1186 	log_debug("dns: ares query SOA(%s)", zonename);
1187 	ares_search(meta->chan, zonename, ns_c_in, ns_t_soa,
1188 		    xares_soa_cb, ctx);
1189 
1190 	meta->got_events = true;
1191 	return 0;
1192 }
1193 
1194 #endif /* USE_CARES */
1195 
1196 
1197 /*
1198  * Generic framework
1199  */
1200 
deliver_info(struct DNSRequest * req)1201 static void deliver_info(struct DNSRequest *req)
1202 {
1203 	struct DNSContext *ctx = req->ctx;
1204 	struct DNSToken *ucb;
1205 	struct List *el;
1206 	const struct addrinfo *ai = req->current;
1207 	char sabuf[128];
1208 
1209 	ctx->active--;
1210 
1211 loop:
1212 	/* get next req */
1213 	el = list_pop(&req->ucb_list);
1214 	if (!el)
1215 		return;
1216 	ucb = container_of(el, struct DNSToken, node);
1217 
1218 	/* launch callback */
1219 	log_noise("dns: deliver_info(%s) addr=%s", req->name,
1220 		  ai ? sa2str(ai->ai_addr, sabuf, sizeof(sabuf)) : "NULL");
1221 	ucb->cb_func(ucb->cb_arg,
1222 		     ai ? ai->ai_addr : NULL,
1223 		     ai ? ai->ai_addrlen : 0);
1224 	free(ucb);
1225 
1226 	/* scroll req list */
1227 	if (ai) {
1228 		req->current = ai->ai_next;
1229 		if (!req->current)
1230 			req->current = req->result;
1231 	}
1232 
1233 	goto loop;
1234 }
1235 
req_cmp(uintptr_t arg,struct AANode * node)1236 static int req_cmp(uintptr_t arg, struct AANode *node)
1237 {
1238 	const char *s1 = (char *)arg;
1239 	struct DNSRequest *req = container_of(node, struct DNSRequest, node);
1240 	return strcmp(s1, req->name);
1241 }
1242 
req_reset(struct DNSRequest * req)1243 static void req_reset(struct DNSRequest *req)
1244 {
1245 	req->done = false;
1246 	if (req->result) {
1247 		if (req->oldres)
1248 			freeaddrinfo(req->oldres);
1249 		req->oldres = req->result;
1250 	}
1251 	req->result = req->current = NULL;
1252 }
1253 
req_free(struct AANode * node,void * arg)1254 static void req_free(struct AANode *node, void *arg)
1255 {
1256 	struct DNSToken *ucb;
1257 	struct DNSRequest *req;
1258 	struct List *el;
1259 	req = container_of(node, struct DNSRequest, node);
1260 	while ((el = list_pop(&req->ucb_list)) != NULL) {
1261 		ucb = container_of(el, struct DNSToken, node);
1262 		free(ucb);
1263 	}
1264 	req_reset(req);
1265 	if (req->oldres) {
1266 		freeaddrinfo(req->oldres);
1267 		req->oldres = NULL;
1268 	}
1269 	if (req->zone)
1270 		statlist_remove(&req->zone->host_list, &req->znode);
1271 	free(req->name);
1272 	free(req);
1273 }
1274 
adns_create_context(void)1275 struct DNSContext *adns_create_context(void)
1276 {
1277 	struct DNSContext *ctx;
1278 
1279 	log_debug("adns_create_context: %s", adns_get_backend());
1280 
1281 	ctx = calloc(1, sizeof(*ctx));
1282 	if (!ctx)
1283 		return NULL;
1284 
1285 	aatree_init(&ctx->req_tree, req_cmp, req_free);
1286 	zone_init(ctx);
1287 
1288 	if (!impl_init(ctx)) {
1289 		adns_free_context(ctx);
1290 		return NULL;
1291 	}
1292 	return ctx;
1293 }
1294 
adns_free_context(struct DNSContext * ctx)1295 void adns_free_context(struct DNSContext *ctx)
1296 {
1297 	if (ctx) {
1298 		impl_release(ctx);
1299 		aatree_destroy(&ctx->req_tree);
1300 		zone_free(ctx);
1301 		free(ctx);
1302 	}
1303 }
1304 
adns_resolve(struct DNSContext * ctx,const char * name,adns_callback_f cb_func,void * cb_arg)1305 struct DNSToken *adns_resolve(struct DNSContext *ctx, const char *name, adns_callback_f cb_func, void *cb_arg)
1306 {
1307 	int namelen = strlen(name);
1308 	struct DNSRequest *req;
1309 	struct DNSToken *ucb;
1310 	struct AANode *node;
1311 
1312 	/* setup actual lookup */
1313 	node = aatree_search(&ctx->req_tree, (uintptr_t)name);
1314 	if (node) {
1315 		req = container_of(node, struct DNSRequest, node);
1316 	} else {
1317 		log_noise("dns: new req: %s", name);
1318 		req = calloc(1, sizeof(*req));
1319 		if (!req)
1320 			goto nomem;
1321 		req->name = strdup(name);
1322 		if (!req->name) {
1323 			free(req);
1324 			goto nomem;
1325 		}
1326 		req->ctx = ctx;
1327 		req->namelen = namelen;
1328 		list_init(&req->ucb_list);
1329 		list_init(&req->znode);
1330 		aatree_insert(&ctx->req_tree, (uintptr_t)req->name, &req->node);
1331 
1332 		zone_register(ctx, req);
1333 
1334 		ctx->active++;
1335 		impl_launch_query(req);
1336 	}
1337 
1338 	/* remember user callback */
1339 	ucb = calloc(1, sizeof(*ucb));
1340 	if (!ucb)
1341 		goto nomem;
1342 	list_init(&ucb->node);
1343 	ucb->cb_func = cb_func;
1344 	ucb->cb_arg = cb_arg;
1345 	list_append(&req->ucb_list, &ucb->node);
1346 
1347 	/* if already have final result, report it */
1348 	if (req->done) {
1349 		if (req->res_ttl < get_cached_time()) {
1350 			log_noise("dns: ttl over: %s", req->name);
1351 			req_reset(req);
1352 			ctx->active++;
1353 			impl_launch_query(req);
1354 		} else {
1355 			deliver_info(req);
1356 		}
1357 	}
1358 	/* if ->done, then we have already reported */
1359 	return req->done ? NULL : ucb;
1360 nomem:
1361 	log_warning("dns(%s): req failed, no mem", name);
1362 	cb_func(cb_arg, NULL, 0);
1363 	return NULL;
1364 }
1365 
cmp_addrinfo(const struct addrinfo * a1,const struct addrinfo * a2)1366 static int cmp_addrinfo(const struct addrinfo *a1, const struct addrinfo *a2)
1367 {
1368     if (a1->ai_family != a2->ai_family)
1369 		return a1->ai_family - a2->ai_family;
1370     if (a1->ai_addrlen != a2->ai_addrlen)
1371 		return a1->ai_addrlen - a2->ai_addrlen;
1372 
1373     return memcmp(a1->ai_addr, a2->ai_addr, a1->ai_addrlen);
1374 }
1375 
1376 /* check if new dns reply is missing some IP compared to old one */
check_req_result_changes(struct DNSRequest * req)1377 static void check_req_result_changes(struct DNSRequest *req)
1378 {
1379 	struct addrinfo *ai, *aj;
1380 
1381 	for (ai = req->oldres; ai; ai = ai->ai_next) {
1382 		bool found = false;
1383 		for (aj = req->result; aj; aj = aj->ai_next) {
1384 			if (cmp_addrinfo(ai, aj) == 0) {
1385 				found = true;
1386 				break;
1387 			}
1388 		}
1389 
1390 		/* missing IP (possible DNS failover) make connections to it dirty */
1391 		if (!found)
1392 			tag_host_addr_dirty(req->name, ai->ai_addr);
1393 	}
1394 }
1395 
1396 /* struct addrinfo -> deliver_info() */
got_result_gai(int result,struct addrinfo * res,void * arg)1397 static void got_result_gai(int result, struct addrinfo *res, void *arg)
1398 {
1399 	struct DNSRequest *req = arg;
1400 
1401 	req_reset(req);
1402 
1403 	if (result == 0 && res) {
1404 		req->result = res;
1405 		req->current = res;
1406 
1407 		if (req->oldres)
1408 			check_req_result_changes(req);
1409 
1410 		/* show all results */
1411 		if (cf_verbose > 1) {
1412 			const struct addrinfo *ai = res;
1413 			int n = 0;
1414 			char buf[128];
1415 			while (ai) {
1416 				log_noise("DNS: %s[%d] = %s [%s]", req->name, n++,
1417 					  sa2str(ai->ai_addr, buf, sizeof(buf)),
1418 					  ai->ai_socktype == SOCK_STREAM ? "STREAM" : "OTHER");
1419 				ai = ai->ai_next;
1420 			}
1421 		}
1422 		req->res_ttl = get_cached_time() + cf_dns_max_ttl;
1423 	} else {
1424 		/* lookup failed */
1425 		log_warning("DNS lookup failed: %s: result=%d", req->name, result);
1426 		req->res_ttl = get_cached_time() + cf_dns_nxdomain_ttl;
1427 	}
1428 
1429 	req->done = true;
1430 
1431 	deliver_info(req);
1432 }
1433 
adns_cancel(struct DNSContext * ctx,struct DNSToken * tk)1434 void adns_cancel(struct DNSContext *ctx, struct DNSToken *tk)
1435 {
1436 	list_del(&tk->node);
1437 	memset(tk, 0, sizeof(*tk));
1438 	free(tk);
1439 }
1440 
adns_info(struct DNSContext * ctx,int * names,int * zones,int * queries,int * pending)1441 void adns_info(struct DNSContext *ctx, int *names, int *zones, int *queries, int *pending)
1442 {
1443 	*names = ctx->req_tree.count;
1444 	*zones = ctx->zone_tree.count;
1445 	*queries = ctx->active;
1446 	*pending = 0;
1447 }
1448 
1449 /*
1450  * zone code
1451  */
1452 
zone_item_free(struct AANode * n,void * arg)1453 static void zone_item_free(struct AANode *n, void *arg)
1454 {
1455 	struct DNSZone *z = container_of(n, struct DNSZone, tnode);
1456 
1457 	list_del(&z->lnode);
1458 	free(z->zonename);
1459 	free(z);
1460 }
1461 
zone_item_cmp(uintptr_t val1,struct AANode * n2)1462 static int zone_item_cmp(uintptr_t val1, struct AANode *n2)
1463 {
1464 	const char *name1 = (const char *)val1;
1465 	struct DNSZone *z2 = container_of(n2, struct DNSZone, tnode);
1466 	return strcasecmp(name1, z2->zonename);
1467 }
1468 
zone_init(struct DNSContext * ctx)1469 static void zone_init(struct DNSContext *ctx)
1470 {
1471 	aatree_init(&ctx->zone_tree, zone_item_cmp, zone_item_free);
1472 	list_init(&ctx->zone_list);
1473 }
1474 
zone_free(struct DNSContext * ctx)1475 static void zone_free(struct DNSContext *ctx)
1476 {
1477 	aatree_destroy(&ctx->zone_tree);
1478 }
1479 
zone_register(struct DNSContext * ctx,struct DNSRequest * req)1480 static void zone_register(struct DNSContext *ctx, struct DNSRequest *req)
1481 {
1482 	struct DNSZone *z;
1483 	struct AANode *n;
1484 	const char *name;
1485 
1486 	log_debug("zone_register(%s)", req->name);
1487 
1488 	name = strchr(req->name, '.');
1489 	if (!name || name[1] == 0)
1490 		return;
1491 	name++;
1492 	log_debug("zone_register(%s): name=%s", req->name, name);
1493 
1494 	n = aatree_search(&ctx->zone_tree, (uintptr_t)name);
1495 	if (n) {
1496 		/* already exists */
1497 		z = container_of(n, struct DNSZone, tnode);
1498 		req->zone = z;
1499 		statlist_append(&z->host_list, &req->znode);
1500 		return;
1501 	}
1502 
1503 	/* create struct */
1504 	z = calloc(1, sizeof(*z));
1505 	if (!z)
1506 		return;
1507 	z->zonename = strdup(name);
1508 	if (!z->zonename) {
1509 		free(z);
1510 		return;
1511 	}
1512 	statlist_init(&z->host_list, "host_list");
1513 	list_init(&z->lnode);
1514 
1515 	/* link */
1516 	aatree_insert(&ctx->zone_tree, (uintptr_t)z->zonename, &z->tnode);
1517 	list_append(&ctx->zone_list, &z->lnode);
1518 	statlist_append(&z->host_list, &req->znode);
1519 	req->zone = z;
1520 }
1521 
zone_timer(evutil_socket_t fd,short flg,void * arg)1522 static void zone_timer(evutil_socket_t fd, short flg, void *arg)
1523 {
1524 	struct DNSContext *ctx = arg;
1525 	struct List *el;
1526 	struct DNSZone *z;
1527 
1528 	if (list_empty(&ctx->zone_list)) {
1529 		ctx->zone_state = 0;
1530 		return;
1531 	}
1532 
1533 	el = list_first(&ctx->zone_list);
1534 	z = container_of(el, struct DNSZone, lnode);
1535 	ctx->zone_state = 1;
1536 	ctx->cur_zone = z;
1537 	ctx->active++;
1538 	impl_query_soa_serial(ctx, z->zonename);
1539 }
1540 
launch_zone_timer(struct DNSContext * ctx)1541 static void launch_zone_timer(struct DNSContext *ctx)
1542 {
1543 	struct timeval tv;
1544 
1545 	tv.tv_sec = cf_dns_zone_check_period / USEC;
1546 	tv.tv_usec = cf_dns_zone_check_period % USEC;
1547 
1548 	evtimer_assign(&ctx->ev_zone_timer, pgb_event_base, zone_timer, ctx);
1549 	safe_evtimer_add(&ctx->ev_zone_timer, &tv);
1550 
1551 	ctx->zone_state = 2;
1552 }
1553 
adns_zone_cache_maint(struct DNSContext * ctx)1554 void adns_zone_cache_maint(struct DNSContext *ctx)
1555 {
1556 	if (!cf_dns_zone_check_period) {
1557 		if (ctx->zone_state == 2) {
1558 			event_del(&ctx->ev_zone_timer);
1559 			ctx->zone_state = 0;
1560 		}
1561 		ctx->cur_zone = NULL;
1562 		return;
1563 	} else if (ctx->zone_state == 0) {
1564 		if (list_empty(&ctx->zone_list))
1565 			return;
1566 		launch_zone_timer(ctx);
1567 	}
1568 }
1569 
zone_requeue(struct DNSContext * ctx,struct DNSZone * z)1570 static void zone_requeue(struct DNSContext *ctx, struct DNSZone *z)
1571 {
1572 	struct List *el;
1573 	struct DNSRequest *req;
1574 	statlist_for_each(el, &z->host_list) {
1575 		req = container_of(el, struct DNSRequest, znode);
1576 		if (!req->done)
1577 			continue;
1578 		req->res_ttl = 0;
1579 		ctx->active++;
1580 		impl_launch_query(req);
1581 	}
1582 }
1583 
got_zone_serial(struct DNSContext * ctx,uint32_t * serial)1584 static void got_zone_serial(struct DNSContext *ctx, uint32_t *serial)
1585 {
1586 	struct DNSZone *z = ctx->cur_zone;
1587 	struct List *el;
1588 
1589 	ctx->active--;
1590 
1591 	if (!ctx->zone_state || !z)
1592 		return;
1593 
1594 	if (serial) {
1595 		/* wraparound compare */
1596 		int32_t s1 = z->serial;
1597 		int32_t s2 = *serial;
1598 		int32_t ds = s2 - s1;
1599 		if (ds > 0) {
1600 			log_info("zone '%s' serial changed: old=%u new=%u",
1601 				 z->zonename, z->serial, *serial);
1602 			z->serial = *serial;
1603 			zone_requeue(ctx, z);
1604 		} else {
1605 			log_debug("zone '%s' unchanged: serial=%u", z->zonename, *serial);
1606 		}
1607 	} else {
1608 		log_debug("failure to get zone '%s' serial", z->zonename);
1609 	}
1610 
1611 	el = z->lnode.next;
1612 	if (el != &ctx->zone_list) {
1613 		z = container_of(el, struct DNSZone, lnode);
1614 		ctx->cur_zone = z;
1615 
1616 		ctx->active++;
1617 		impl_query_soa_serial(ctx, z->zonename);
1618 	} else {
1619 		launch_zone_timer(ctx);
1620 	}
1621 }
1622 
1623 /*
1624  * Cache walkers
1625  */
1626 
1627 struct WalkInfo {
1628 	adns_walk_name_f name_cb;
1629 	adns_walk_zone_f zone_cb;
1630 	void *arg;
1631 };
1632 
walk_name(struct AANode * n,void * arg)1633 static void walk_name(struct AANode *n, void *arg)
1634 {
1635 	struct WalkInfo *w = arg;
1636 	struct DNSRequest *req = container_of(n, struct DNSRequest, node);
1637 
1638 	w->name_cb(w->arg, req->name, req->result, req->res_ttl);
1639 }
1640 
walk_zone(struct AANode * n,void * arg)1641 static void walk_zone(struct AANode *n, void *arg)
1642 {
1643 	struct WalkInfo *w = arg;
1644 	struct DNSZone *z = container_of(n, struct DNSZone, tnode);
1645 
1646 	w->zone_cb(w->arg, z->zonename, z->serial, statlist_count(&z->host_list));
1647 }
1648 
adns_walk_names(struct DNSContext * ctx,adns_walk_name_f cb,void * arg)1649 void adns_walk_names(struct DNSContext *ctx, adns_walk_name_f cb, void *arg)
1650 {
1651 	struct WalkInfo w;
1652 	w.name_cb = cb;
1653 	w.arg = arg;
1654 	aatree_walk(&ctx->req_tree, AA_WALK_IN_ORDER, walk_name, &w);
1655 }
1656 
adns_walk_zones(struct DNSContext * ctx,adns_walk_zone_f cb,void * arg)1657 void adns_walk_zones(struct DNSContext *ctx, adns_walk_zone_f cb, void *arg)
1658 {
1659 	struct WalkInfo w;
1660 	w.zone_cb = cb;
1661 	w.arg = arg;
1662 	aatree_walk(&ctx->zone_tree, AA_WALK_IN_ORDER, walk_zone, &w);
1663 }
1664 
adns_per_loop(struct DNSContext * ctx)1665 void adns_per_loop(struct DNSContext *ctx)
1666 {
1667 	impl_per_loop(ctx);
1668 }
1669