blob: 78ee62bcc8421361b1c928fc1ae6a02f371054b6 [file] [log] [blame]
Baptiste Assmann325137d2015-04-13 23:40:55 +02001/*
2 * Name server resolution
3 *
4 * Copyright 2014 Baptiste Assmann <bedis9@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19
20#include <sys/types.h>
21
22#include <common/time.h>
23#include <common/ticks.h>
24
Baptiste Assmannfa4a6632017-05-04 09:05:00 +020025#include <import/lru.h>
26#include <import/xxhash.h>
27
William Lallemand69e96442016-11-19 00:58:54 +010028#include <types/applet.h>
29#include <types/cli.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020030#include <types/global.h>
31#include <types/dns.h>
32#include <types/proto_udp.h>
William Lallemand69e96442016-11-19 00:58:54 +010033#include <types/stats.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020034
William Lallemand69e96442016-11-19 00:58:54 +010035#include <proto/channel.h>
36#include <proto/cli.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020037#include <proto/checks.h>
38#include <proto/dns.h>
39#include <proto/fd.h>
40#include <proto/log.h>
41#include <proto/server.h>
42#include <proto/task.h>
43#include <proto/proto_udp.h>
William Lallemand69e96442016-11-19 00:58:54 +010044#include <proto/stream_interface.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020045
46struct list dns_resolvers = LIST_HEAD_INIT(dns_resolvers);
47struct dns_resolution *resolution = NULL;
48
49static int64_t dns_query_id_seed; /* random seed */
50
Baptiste Assmannfa4a6632017-05-04 09:05:00 +020051static struct lru64_head *dns_lru_tree;
52static int dns_cache_size = 1024; /* arbitrary DNS cache size */
53
Baptiste Assmann325137d2015-04-13 23:40:55 +020054/* proto_udp callback functions for a DNS resolution */
55struct dgram_data_cb resolve_dgram_cb = {
56 .recv = dns_resolve_recv,
57 .send = dns_resolve_send,
58};
59
Baptiste Assmann201c07f2017-05-22 15:17:15 +020060/* local function prototypes */
61static int dns_run_resolution(struct dns_requester *requester);
62
Baptiste Assmann325137d2015-04-13 23:40:55 +020063#if DEBUG
64/*
65 * go through the resolutions associated to a resolvers section and print the ID and hostname in
66 * domain name format
67 * should be used for debug purpose only
68 */
69void dns_print_current_resolutions(struct dns_resolvers *resolvers)
70{
Baptiste Assmann201c07f2017-05-22 15:17:15 +020071 list_for_each_entry(resolution, &resolvers->resolution.curr, list) {
Baptiste Assmann325137d2015-04-13 23:40:55 +020072 printf(" resolution %d for %s\n", resolution->query_id, resolution->hostname_dn);
73 }
74}
75#endif
76
Baptiste Assmann201c07f2017-05-22 15:17:15 +020077void dump_dns_config()
78{
79 struct dns_resolvers *curr_resolvers = NULL;
80 struct dns_nameserver *curr_nameserver = NULL;
81 struct dns_resolution *curr_resolution = NULL;
82 struct dns_requester *curr_requester = NULL;
83
84 printf("===============\n");
85 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
86 printf("Resolvers: %s\n", curr_resolvers->id);
87
88 printf(" nameservers:\n");
89 list_for_each_entry(curr_nameserver, &curr_resolvers->nameserver_list, list) {
90 printf(" %s\n", curr_nameserver->id);
91 }
92
93/*
94 printf(" resolution.pool list:\n");
95 list_for_each_entry(curr_resolution, &curr_resolvers->resolution.pool, list) {
96 printf(" %p\n", curr_resolution);
97 }
98*/
99
100 printf(" resolution.wait list:\n");
101 list_for_each_entry(curr_resolution, &curr_resolvers->resolution.wait, list) {
102 printf(" %p %s\n", curr_resolution, curr_resolution->hostname_dn);
103 printf(" requester.wait list:\n");
104 list_for_each_entry(curr_requester, &curr_resolution->requester.wait, list) {
105 printf(" %p %s %d\n", curr_requester, objt_server(curr_requester->requester)->id, curr_requester->prefered_query_type);
106 }
107 printf(" requester.curr list:\n");
108 list_for_each_entry(curr_requester, &curr_resolution->requester.curr, list) {
109 printf(" %p %s %d\n", curr_requester, objt_server(curr_requester->requester)->id, curr_requester->prefered_query_type);
110 }
111 }
112 printf(" resolution.curr list:\n");
113 list_for_each_entry(curr_resolution, &curr_resolvers->resolution.curr, list) {
114 printf(" %p %s\n", curr_resolution, curr_resolution->hostname_dn);
115 printf(" requester.wait list:\n");
116 list_for_each_entry(curr_requester, &curr_resolution->requester.wait, list) {
117 printf(" %p %s %d\n", curr_requester, objt_server(curr_requester->requester)->id, curr_requester->prefered_query_type);
118 }
119 printf(" requester.curr list:\n");
120 list_for_each_entry(curr_requester, &curr_resolution->requester.curr, list) {
121 printf(" %p %s %d\n", curr_requester, objt_server(curr_requester->requester)->id, curr_requester->prefered_query_type);
122 }
123 }
124 }
125
126 printf("===============\n");
127}
128
129/*
130 * Initiates a new name resolution:
131 * - generates a query id
132 * - configure the resolution structure
133 * - startup the resolvers task if required
134 *
135 * returns:
136 * - 0 if everything started properly
137 * - -1 in case of error or if resolution already running
138 */
139int dns_trigger_resolution(struct dns_resolution *resolution)
140{
141 struct dns_requester *requester = NULL, *tmprequester;
142 struct dns_resolvers *resolvers = NULL;
143 int inter;
144
145 /* process the element of the wait queue */
146 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.wait, list) {
147 inter = 0;
148
149 switch (obj_type(requester->requester)) {
150 case OBJ_TYPE_SERVER:
151 inter = objt_server(requester->requester)->check.inter;
152 resolvers = objt_server(requester->requester)->resolvers;
153 break;
154 case OBJ_TYPE_NONE:
155 default:
156 return -1;
157 }
158
159 /* if data is fresh enough, let's use it */
160 if (!tick_is_expired(tick_add(resolution->last_resolution, inter), now_ms)) {
161 /* we only use cache if the response there is valid.
162 * If not valid, we run the resolution and move the requester to
163 * the run queue. */
164 if (resolution->status != RSLV_STATUS_VALID) {
165 LIST_DEL(&requester->list);
166 LIST_ADDQ(&resolution->requester.curr, &requester->list);
167 dns_run_resolution(requester);
168 continue;
169 }
170
171 requester->requester_cb(requester, NULL);
172 }
173 else {
174 LIST_DEL(&requester->list);
175 LIST_ADDQ(&resolution->requester.curr, &requester->list);
176 dns_run_resolution(requester);
177 }
178 }
179
180 if (resolvers)
181 dns_update_resolvers_timeout(resolvers);
182
183 return 0;
184}
185
Baptiste Assmann325137d2015-04-13 23:40:55 +0200186/*
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200187 * Prepare and send a DNS resolution.
188 *
189 * Return code:
190 * - 0 if no error occured
191 * - -1 in case of error
192 */
193static int
194dns_run_resolution(struct dns_requester *requester)
195{
196 struct dns_resolution *resolution;
197 struct dns_resolvers *resolvers;
198 int query_id, query_type, i;
199 struct proxy *proxy;
200
201 resolution = NULL;
202 resolvers = NULL;
203 proxy = NULL;
204 query_type = -1;
205 switch (obj_type(requester->requester)) {
206 case OBJ_TYPE_SERVER:
207 resolution = objt_server(requester->requester)->resolution;
208 resolvers = objt_server(requester->requester)->resolvers;
209 proxy = objt_server(requester->requester)->proxy;
210 query_type = requester->prefered_query_type;
211 break;
212 case OBJ_TYPE_NONE:
213 default:
214 return -1;
215 }
216
217 /*
218 * check if a resolution has already been started for this server
219 * return directly to avoid resolution pill up.
220 */
221 if (resolution->step != RSLV_STEP_NONE)
222 return 0;
223
224 /* generates a query id */
225 i = 0;
226 do {
227 query_id = dns_rnd16();
228 /* we do try only 100 times to find a free query id */
229 if (i++ > 100) {
230 chunk_printf(&trash, "could not generate a query id for %s, in resolvers %s",
231 resolution->hostname_dn, resolvers->id);
232
233 if (proxy)
234 send_log(proxy, LOG_NOTICE, "%s.\n", trash.str);
235 return -1;
236 }
237 } while (eb32_lookup(&resolvers->query_ids, query_id));
238
239 /* move the resolution into the run queue */
240 LIST_DEL(&resolution->list);
241 LIST_ADDQ(&resolvers->resolution.curr, &resolution->list);
242
243 /* now update resolution parameters */
244 resolution->query_id = query_id;
245 resolution->qid.key = query_id;
246 resolution->step = RSLV_STEP_RUNNING;
247 resolution->query_type = query_type;
248 resolution->try = resolvers->resolve_retries;
249 resolution->try_cname = 0;
250 resolution->nb_responses = 0;
251 eb32_insert(&resolvers->query_ids, &resolution->qid);
252
253 dns_send_query(resolution);
254 resolution->try -= 1;
255
256 /* update wakeup date if this resolution is the only one in the FIFO list */
257 if (dns_check_resolution_queue(resolvers) == 1) {
258 /* update task timeout */
259 dns_update_resolvers_timeout(resolvers);
260 task_queue(resolvers->t);
261 }
262
263 return 0;
264}
265
266/*
Baptiste Assmann325137d2015-04-13 23:40:55 +0200267 * check if there is more than 1 resolution in the resolver's resolution list
268 * return value:
269 * 0: empty list
270 * 1: exactly one entry in the list
271 * 2: more than one entry in the list
272 */
273int dns_check_resolution_queue(struct dns_resolvers *resolvers)
274{
275
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200276 if (LIST_ISEMPTY(&resolvers->resolution.curr))
Baptiste Assmann325137d2015-04-13 23:40:55 +0200277 return 0;
278
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200279 if ((resolvers->resolution.curr.n) && (resolvers->resolution.curr.n == resolvers->resolution.curr.p))
Baptiste Assmann325137d2015-04-13 23:40:55 +0200280 return 1;
281
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200282 if (! ((resolvers->resolution.curr.n == resolvers->resolution.curr.p)
283 && (&resolvers->resolution.curr != resolvers->resolution.curr.n)))
Baptiste Assmann325137d2015-04-13 23:40:55 +0200284 return 2;
285
286 return 0;
287}
288
289/*
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200290 * reset some resolution parameters to initial values and also delete the
291 * query ID from the resolver's tree.
Baptiste Assmann325137d2015-04-13 23:40:55 +0200292 */
293void dns_reset_resolution(struct dns_resolution *resolution)
294{
295 /* update resolution status */
296 resolution->step = RSLV_STEP_NONE;
297
298 resolution->try = 0;
299 resolution->try_cname = 0;
300 resolution->last_resolution = now_ms;
301 resolution->nb_responses = 0;
302
303 /* clean up query id */
304 eb32_delete(&resolution->qid);
305 resolution->query_id = 0;
306 resolution->qid.key = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200307}
308
309/*
310 * function called when a network IO is generated on a name server socket for an incoming packet
311 * It performs the following actions:
312 * - check if the packet requires processing (not outdated resolution)
313 * - ensure the DNS packet received is valid and call requester's callback
314 * - call requester's error callback if invalid response
Baptiste Assmann3cf7f982016-04-17 22:43:26 +0200315 * - check the dn_name in the packet against the one sent
Baptiste Assmann325137d2015-04-13 23:40:55 +0200316 */
317void dns_resolve_recv(struct dgram_conn *dgram)
318{
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200319 struct dns_nameserver *nameserver, *tmpnameserver;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200320 struct dns_resolvers *resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200321 struct dns_resolution *resolution = NULL;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200322 struct dns_query_item *query;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200323 unsigned char buf[DNS_MAX_UDP_MESSAGE + 1];
324 unsigned char *bufend;
William Lallemandcc9b94a2017-06-08 19:30:39 +0200325 int fd, buflen, dns_resp, need_resend = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200326 unsigned short query_id;
327 struct eb32_node *eb;
Baptiste Assmannfa4a6632017-05-04 09:05:00 +0200328 struct lru64 *lru = NULL;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200329 struct dns_requester *requester = NULL, *tmprequester = NULL;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200330
331 fd = dgram->t.sock.fd;
332
333 /* check if ready for reading */
334 if (!fd_recv_ready(fd))
335 return;
336
337 /* no need to go further if we can't retrieve the nameserver */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200338 if ((nameserver = dgram->owner) == NULL)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200339 return;
340
341 resolvers = nameserver->resolvers;
342
343 /* process all pending input messages */
344 while (1) {
345 /* read message received */
346 memset(buf, '\0', DNS_MAX_UDP_MESSAGE + 1);
347 if ((buflen = recv(fd, (char*)buf , DNS_MAX_UDP_MESSAGE, 0)) < 0) {
348 /* FIXME : for now we consider EAGAIN only */
349 fd_cant_recv(fd);
350 break;
351 }
352
353 /* message too big */
354 if (buflen > DNS_MAX_UDP_MESSAGE) {
355 nameserver->counters.too_big += 1;
356 continue;
357 }
358
359 /* initializing variables */
360 bufend = buf + buflen; /* pointer to mark the end of the buffer */
361
362 /* read the query id from the packet (16 bits) */
363 if (buf + 2 > bufend) {
364 nameserver->counters.invalid += 1;
365 continue;
366 }
367 query_id = dns_response_get_query_id(buf);
368
369 /* search the query_id in the pending resolution tree */
Baptiste Assmann01daef32015-09-02 22:05:24 +0200370 eb = eb32_lookup(&resolvers->query_ids, query_id);
371 if (eb == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +0200372 /* unknown query id means an outdated response and can be safely ignored */
373 nameserver->counters.outdated += 1;
374 continue;
375 }
376
377 /* known query id means a resolution in prgress */
378 resolution = eb32_entry(eb, struct dns_resolution, qid);
379
380 if (!resolution) {
381 nameserver->counters.outdated += 1;
382 continue;
383 }
384
385 /* number of responses received */
386 resolution->nb_responses += 1;
387
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200388 dns_resp = dns_validate_dns_response(buf, bufend, resolution);
Baptiste Assmann325137d2015-04-13 23:40:55 +0200389
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200390 switch (dns_resp) {
391 case DNS_RESP_VALID:
392 need_resend = 0;
393 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200394
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200395 case DNS_RESP_INVALID:
396 case DNS_RESP_QUERY_COUNT_ERROR:
397 case DNS_RESP_WRONG_NAME:
398 if (resolution->status != RSLV_STATUS_INVALID) {
399 resolution->status = RSLV_STATUS_INVALID;
400 resolution->last_status_change = now_ms;
401 }
402 nameserver->counters.invalid += 1;
403 need_resend = 0;
404 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200405
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200406 case DNS_RESP_ANCOUNT_ZERO:
407 if (resolution->status != RSLV_STATUS_OTHER) {
408 resolution->status = RSLV_STATUS_OTHER;
409 resolution->last_status_change = now_ms;
410 }
411 nameserver->counters.any_err += 1;
412 need_resend = 1;
413 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200414
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200415 case DNS_RESP_NX_DOMAIN:
416 if (resolution->status != RSLV_STATUS_NX) {
417 resolution->status = RSLV_STATUS_NX;
418 resolution->last_status_change = now_ms;
419 }
420 nameserver->counters.nx += 1;
421 need_resend = 0;
422 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200423
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200424 case DNS_RESP_REFUSED:
425 if (resolution->status != RSLV_STATUS_REFUSED) {
426 resolution->status = RSLV_STATUS_REFUSED;
427 resolution->last_status_change = now_ms;
428 }
429 nameserver->counters.refused += 1;
430 need_resend = 0;
431 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200432
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200433 case DNS_RESP_CNAME_ERROR:
434 if (resolution->status != RSLV_STATUS_OTHER) {
435 resolution->status = RSLV_STATUS_OTHER;
436 resolution->last_status_change = now_ms;
437 }
438 nameserver->counters.cname_error += 1;
439 need_resend = 1;
440 break;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200441
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200442 case DNS_RESP_TRUNCATED:
443 if (resolution->status != RSLV_STATUS_OTHER) {
444 resolution->status = RSLV_STATUS_OTHER;
445 resolution->last_status_change = now_ms;
446 }
447 nameserver->counters.truncated += 1;
448 need_resend = 1;
449 break;
Baptiste Assmann96972bc2015-09-09 00:46:58 +0200450
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200451 case DNS_RESP_NO_EXPECTED_RECORD:
452 if (resolution->status != RSLV_STATUS_OTHER) {
453 resolution->status = RSLV_STATUS_OTHER;
454 resolution->last_status_change = now_ms;
455 }
456 nameserver->counters.other += 1;
457 need_resend = 1;
458 break;
459
460 case DNS_RESP_ERROR:
461 case DNS_RESP_INTERNAL:
462 if (resolution->status != RSLV_STATUS_OTHER) {
463 resolution->status = RSLV_STATUS_OTHER;
464 resolution->last_status_change = now_ms;
465 }
466 nameserver->counters.other += 1;
467 need_resend = 1;
468 break;
469 }
470
471 /* some error codes trigger a re-send of the query, but switching the
472 * query type.
473 * This is the case for the following error codes:
474 * DNS_RESP_ANCOUNT_ZERO
475 * DNS_RESP_TRUNCATED
476 * DNS_RESP_ERROR
477 * DNS_RESP_INTERNAL
478 * DNS_RESP_NO_EXPECTED_RECORD
479 * DNS_RESP_CNAME_ERROR
480 */
481 if (need_resend) {
482 int family_prio;
483 int res_preferred_afinet, res_preferred_afinet6;
484
485 requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list);
486 switch (obj_type(requester->requester)) {
487 case OBJ_TYPE_SERVER:
488 family_prio = objt_server(requester->requester)->dns_opts.family_prio;
489 break;
490 case OBJ_TYPE_NONE:
491 default:
492 family_prio = AF_INET6;
493 }
494 res_preferred_afinet = family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
495 res_preferred_afinet6 = family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
496 if ((res_preferred_afinet || res_preferred_afinet6)
497 || (resolution->try > 0)) {
498 /* let's change the query type */
499 if (res_preferred_afinet6) {
500 /* fallback from AAAA to A */
501 resolution->query_type = DNS_RTYPE_A;
502 }
503 else if (res_preferred_afinet) {
504 /* fallback from A to AAAA */
505 resolution->query_type = DNS_RTYPE_AAAA;
506 }
507 else {
508 resolution->try -= 1;
509 if (family_prio == AF_INET) {
510 resolution->query_type = DNS_RTYPE_A;
511 } else {
512 resolution->query_type = DNS_RTYPE_AAAA;
513 }
514 }
515
516 dns_send_query(resolution);
517 /*
518 * move the resolution to the last element of the FIFO queue
519 * and update timeout wakeup based on the new first entry
520 */
521 if (dns_check_resolution_queue(resolvers) > 1) {
522 /* second resolution becomes first one */
523 LIST_DEL(&resolution->list);
524 /* ex first resolution goes to the end of the queue */
525 LIST_ADDQ(&resolvers->resolution.curr, &resolution->list);
526 }
527
528 dns_update_resolvers_timeout(resolvers);
529 goto next_packet;
530 }
531
532 /* if we're there, this means that we already ran out of chances to re-send
533 * the query */
534 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
535 requester->requester_error_cb(requester, dns_resp);
536 }
537 goto next_packet;
538 }
539
540 /* now processing those error codes only:
541 * DNS_RESP_NX_DOMAIN
542 * DNS_RESP_REFUSED
543 */
544 if (dns_resp != DNS_RESP_VALID) {
545 /* now parse list of requesters currently waiting for this resolution */
546 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
547 requester->requester_error_cb(requester, dns_resp);
548
549 /* we can move the requester the wait queue */
550 LIST_DEL(&requester->list);
551 LIST_ADDQ(&resolution->requester.wait, &requester->list);
552 }
553 goto next_packet;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200554 }
555
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200556 /* Now let's check the query's dname corresponds to the one we sent.
557 * We can check only the first query of the list. We send one query at a time
558 * so we get one query in the response */
Baptiste Assmann729c9012017-05-22 15:13:10 +0200559 query = LIST_NEXT(&resolution->response.query_list, struct dns_query_item *, list);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200560 if (query && memcmp(query->name, resolution->hostname_dn, resolution->hostname_dn_len) != 0) {
561 nameserver->counters.other += 1;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200562 /* now parse list of requesters currently waiting for this resolution */
563 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
564 requester->requester_error_cb(requester, DNS_RESP_WRONG_NAME);
565 /* we can move the requester the wait queue */
566 LIST_DEL(&requester->list);
567 LIST_ADDQ(&resolution->requester.wait, &requester->list);
568 }
569 goto next_packet;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200570 }
571
Baptiste Assmannfa4a6632017-05-04 09:05:00 +0200572 /* no errors, we can save the response in the cache */
573 if (dns_lru_tree) {
574 unsigned long long seed = 1;
575 struct chunk *buf = get_trash_chunk();
576 struct chunk *tmp = NULL;
577
578 chunk_reset(buf);
579 tmp = dns_cache_key(resolution->query_type, resolution->hostname_dn,
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200580 resolution->hostname_dn_len, buf);
Baptiste Assmannfa4a6632017-05-04 09:05:00 +0200581 if (!tmp) {
582 nameserver->counters.other += 1;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200583 /* now parse list of requesters currently waiting for this resolution */
584 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
585 requester->requester_error_cb(requester, DNS_RESP_ERROR);
586 /* we can move the requester the wait queue */
587 LIST_DEL(&requester->list);
588 LIST_ADDQ(&resolution->requester.wait, &requester->list);
589 }
590 goto next_packet;
Baptiste Assmannfa4a6632017-05-04 09:05:00 +0200591 }
592
593 lru = lru64_get(XXH64(buf->str, buf->len, seed),
594 dns_lru_tree, nameserver->resolvers, 1);
595
596 lru64_commit(lru, resolution, nameserver->resolvers, 1, NULL);
597 }
598
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200599 if (resolution->status != RSLV_STATUS_VALID) {
600 resolution->status = RSLV_STATUS_VALID;
601 resolution->last_status_change = now_ms;
602 }
603
Baptiste Assmann37bb3722015-08-07 10:18:32 +0200604 nameserver->counters.valid += 1;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200605 /* now parse list of requesters currently waiting for this resolution */
606 tmpnameserver = nameserver;
607 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
608 requester->requester_cb(requester, tmpnameserver);
609 /* we can move the requester the wait queue */
610 LIST_DEL(&requester->list);
611 LIST_ADDQ(&resolution->requester.wait, &requester->list);
612 /* first response is managed by the server, others are from the cache */
613 tmpnameserver = NULL;
614 }
615
616 next_packet:
617 /* resolution may be NULL when we receive an ICMP unreachable packet */
618 if (resolution && LIST_ISEMPTY(&resolution->requester.curr)) {
619 /* move the resolution into the wait queue */
620 LIST_DEL(&resolution->list);
621 LIST_ADDQ(&resolvers->resolution.wait, &resolution->list);
622 /* update last resolution date and time */
623 resolution->last_resolution = now_ms;
624 /* reset current status flag */
625 resolution->step = RSLV_STEP_NONE;
626 /* reset values */
627 dns_reset_resolution(resolution);
628 }
629
630 } // end of while "packets" loop
631
632 dns_update_resolvers_timeout(nameserver->resolvers);
Baptiste Assmann325137d2015-04-13 23:40:55 +0200633}
634
635/*
636 * function called when a resolvers network socket is ready to send data
637 * It performs the following actions:
638 */
639void dns_resolve_send(struct dgram_conn *dgram)
640{
641 int fd;
642 struct dns_nameserver *nameserver;
643 struct dns_resolvers *resolvers;
644 struct dns_resolution *resolution;
645
646 fd = dgram->t.sock.fd;
647
648 /* check if ready for sending */
649 if (!fd_send_ready(fd))
650 return;
651
652 /* we don't want/need to be waked up any more for sending */
653 fd_stop_send(fd);
654
655 /* no need to go further if we can't retrieve the nameserver */
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200656 if ((nameserver = dgram->owner) == NULL)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200657 return;
658
659 resolvers = nameserver->resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200660 resolution = LIST_NEXT(&resolvers->resolution.curr, struct dns_resolution *, list);
Baptiste Assmann325137d2015-04-13 23:40:55 +0200661
662 dns_send_query(resolution);
663 dns_update_resolvers_timeout(resolvers);
664}
665
666/*
667 * forge and send a DNS query to resolvers associated to a resolution
668 * It performs the following actions:
669 * returns:
670 * 0 in case of error or safe ignorance
671 * 1 if no error
672 */
673int dns_send_query(struct dns_resolution *resolution)
674{
Baptiste Assmann42746372017-05-03 12:12:02 +0200675 struct dns_resolvers *resolvers = NULL;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200676 struct dns_nameserver *nameserver;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200677 struct dns_requester *requester = NULL;
Erwan Velu5457eb42015-10-15 15:07:26 +0200678 int ret, bufsize, fd;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200679
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200680 /* nothing to do */
681 if (LIST_ISEMPTY(&resolution->requester.curr))
682 return 0;
683
684 requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list);
685
686 switch (obj_type(requester->requester)) {
687 case OBJ_TYPE_SERVER:
688 resolvers = objt_server(requester->requester)->resolvers;
689 break;
690 case OBJ_TYPE_NONE:
691 default:
692 return 0;
693 }
Baptiste Assmann42746372017-05-03 12:12:02 +0200694
695 if (!resolvers)
696 return 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200697
Baptiste Assmann325137d2015-04-13 23:40:55 +0200698 bufsize = dns_build_query(resolution->query_id, resolution->query_type, resolution->hostname_dn,
699 resolution->hostname_dn_len, trash.str, trash.size);
700
701 if (bufsize == -1)
702 return 0;
703
704 list_for_each_entry(nameserver, &resolvers->nameserver_list, list) {
705 fd = nameserver->dgram->t.sock.fd;
706 errno = 0;
707
708 ret = send(fd, trash.str, bufsize, 0);
709
710 if (ret > 0)
711 nameserver->counters.sent += 1;
712
713 if (ret == 0 || errno == EAGAIN) {
714 /* nothing written, let's update the poller that we wanted to send
715 * but we were not able to */
716 fd_want_send(fd);
717 fd_cant_send(fd);
718 }
719 }
720
721 /* update resolution */
Baptiste Assmann325137d2015-04-13 23:40:55 +0200722 resolution->nb_responses = 0;
723 resolution->last_sent_packet = now_ms;
724
725 return 1;
726}
727
728/*
729 * update a resolvers' task timeout for next wake up
730 */
731void dns_update_resolvers_timeout(struct dns_resolvers *resolvers)
732{
733 struct dns_resolution *resolution;
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200734 struct dns_requester *requester;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200735
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200736 if ((LIST_ISEMPTY(&resolvers->resolution.curr)) && (LIST_ISEMPTY(&resolvers->resolution.wait))) {
Baptiste Assmann325137d2015-04-13 23:40:55 +0200737 resolvers->t->expire = TICK_ETERNITY;
738 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200739 else if (!LIST_ISEMPTY(&resolvers->resolution.curr)) {
740 resolution = LIST_NEXT(&resolvers->resolution.curr, struct dns_resolution *, list);
741 if (!resolvers->t->expire || tick_is_le(resolvers->t->expire, tick_add(resolution->last_sent_packet, resolvers->timeout.retry))) {
742 resolvers->t->expire = tick_add(resolution->last_sent_packet, resolvers->timeout.retry);
743 }
Baptiste Assmann325137d2015-04-13 23:40:55 +0200744 }
Baptiste Assmann201c07f2017-05-22 15:17:15 +0200745 else if (!LIST_ISEMPTY(&resolvers->resolution.wait)) {
746 int valid_period, inter, need_wakeup;
747 struct dns_resolution *res_back;
748 need_wakeup = 0;
749 list_for_each_entry_safe(resolution, res_back, &resolvers->resolution.wait, list) {
750 valid_period = 0;
751 inter = 0;
752
753 requester = LIST_NEXT(&resolution->requester.wait, struct dns_requester *, list);
754
755 switch (obj_type(requester->requester)) {
756 case OBJ_TYPE_SERVER:
757 valid_period = objt_server(requester->requester)->check.inter;
758 break;
759 case OBJ_TYPE_NONE:
760 default:
761 continue;
762 }
763
764 if (resolvers->hold.valid < valid_period)
765 inter = resolvers->hold.valid;
766 else
767 inter = valid_period;
768
769 if (tick_is_expired(tick_add(resolution->last_resolution, inter), now_ms)) {
770 switch (obj_type(requester->requester)) {
771 case OBJ_TYPE_SERVER:
772 dns_trigger_resolution(objt_server(requester->requester)->resolution);
773 break;
774 case OBJ_TYPE_NONE:
775 default:
776 ;;
777 }
778 }
779 else {
780 need_wakeup = 1;
781 }
782 }
783 /* in such case, we wake up in 1s */
784 if (need_wakeup) {
785 int r = 1000;
786
787 resolution = LIST_NEXT(&resolvers->resolution.wait, struct dns_resolution *, list);
788 if (tick_is_le(resolvers->t->expire, tick_add(now_ms, r)))
789 resolvers->t->expire = tick_add(now_ms, r);
790 resolvers->t->expire = tick_add(now_ms, 1000);
791 }
792 }
793
794 task_queue(resolvers->t);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200795}
796
797/*
798 * Analyse, re-build and copy the name <name> from the DNS response packet <buffer>.
799 * <name> must point to the 'data_len' information or pointer 'c0' for compressed data.
800 * The result is copied into <dest>, ensuring we don't overflow using <dest_len>
801 * Returns the number of bytes the caller can move forward. If 0 it means an error occured
802 * while parsing the name.
803 * <offset> is the number of bytes the caller could move forward.
804 */
805int dns_read_name(unsigned char *buffer, unsigned char *bufend, unsigned char *name, char *destination, int dest_len, int *offset)
806{
807 int nb_bytes = 0, n = 0;
808 int label_len;
809 unsigned char *reader = name;
810 char *dest = destination;
811
812 while (1) {
813 /* name compression is in use */
814 if ((*reader & 0xc0) == 0xc0) {
815 /* a pointer must point BEFORE current position */
816 if ((buffer + reader[1]) > reader) {
817 goto out_error;
818 }
819
820 n = dns_read_name(buffer, bufend, buffer + reader[1], dest, dest_len - nb_bytes, offset);
821 if (n == 0)
822 goto out_error;
823
824 dest += n;
825 nb_bytes += n;
826 goto out;
827 }
828
829 label_len = *reader;
830 if (label_len == 0)
831 goto out;
832 /* Check if:
833 * - we won't read outside the buffer
834 * - there is enough place in the destination
835 */
836 if ((reader + label_len >= bufend) || (nb_bytes + label_len >= dest_len))
837 goto out_error;
838
839 /* +1 to take label len + label string */
840 label_len += 1;
841
842 memcpy(dest, reader, label_len);
843
844 dest += label_len;
845 nb_bytes += label_len;
846 reader += label_len;
847 }
848
849 out:
850 /* offset computation:
851 * parse from <name> until finding either NULL or a pointer "c0xx"
852 */
853 reader = name;
854 *offset = 0;
855 while (reader < bufend) {
856 if ((reader[0] & 0xc0) == 0xc0) {
857 *offset += 2;
858 break;
859 }
860 else if (*reader == 0) {
861 *offset += 1;
862 break;
863 }
864 *offset += 1;
865 ++reader;
866 }
867
868 return nb_bytes;
869
870 out_error:
871 return 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200872}
873
874/*
875 * Function to validate that the buffer DNS response provided in <resp> and
876 * finishing before <bufend> is valid from a DNS protocol point of view.
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200877 *
Baptiste Assmann729c9012017-05-22 15:13:10 +0200878 * The result is stored in <resolution>' response, buf_response, response_query_records
879 * and response_answer_records members.
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200880 *
881 * This function returns one of the DNS_RESP_* code to indicate the type of
882 * error found.
Baptiste Assmann325137d2015-04-13 23:40:55 +0200883 */
Baptiste Assmann729c9012017-05-22 15:13:10 +0200884int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend, struct dns_resolution *resolution)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200885{
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200886 unsigned char *reader;
887 char *previous_dname, tmpname[DNS_MAX_NAME_SIZE];
888 int len, flags, offset, ret;
889 int dns_query_record_id, dns_answer_record_id;
Baptiste Assmann69fce672017-05-04 08:37:45 +0200890 int nb_saved_records;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200891 struct dns_query_item *dns_query;
892 struct dns_answer_item *dns_answer_record;
Baptiste Assmann729c9012017-05-22 15:13:10 +0200893 struct dns_response_packet *dns_p;
894 struct chunk *dns_response_buffer;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200895
896 reader = resp;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200897 len = 0;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200898 previous_dname = NULL;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200899
Baptiste Assmann729c9012017-05-22 15:13:10 +0200900 /* initialization of response buffer and structure */
901 dns_p = &resolution->response;
902 dns_response_buffer = &resolution->response_buffer;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200903 memset(dns_p, '\0', sizeof(struct dns_response_packet));
Baptiste Assmann729c9012017-05-22 15:13:10 +0200904 chunk_reset(dns_response_buffer);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200905
906 /* query id */
907 if (reader + 2 >= bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200908 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200909 dns_p->header.id = reader[0] * 256 + reader[1];
910 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200911
912 /*
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200913 * flags and rcode are stored over 2 bytes
Baptiste Assmann3440f0d2015-09-02 22:08:38 +0200914 * First byte contains:
915 * - response flag (1 bit)
916 * - opcode (4 bits)
917 * - authoritative (1 bit)
918 * - truncated (1 bit)
919 * - recursion desired (1 bit)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200920 */
Baptiste Assmann3440f0d2015-09-02 22:08:38 +0200921 if (reader + 2 >= bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200922 return DNS_RESP_INVALID;
923
Baptiste Assmann3440f0d2015-09-02 22:08:38 +0200924 flags = reader[0] * 256 + reader[1];
925
926 if (flags & DNS_FLAG_TRUNCATED)
927 return DNS_RESP_TRUNCATED;
928
929 if ((flags & DNS_FLAG_REPLYCODE) != DNS_RCODE_NO_ERROR) {
930 if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_NX_DOMAIN)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200931 return DNS_RESP_NX_DOMAIN;
Baptiste Assmann3440f0d2015-09-02 22:08:38 +0200932 else if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_REFUSED)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200933 return DNS_RESP_REFUSED;
934
935 return DNS_RESP_ERROR;
936 }
937
Baptiste Assmann3440f0d2015-09-02 22:08:38 +0200938 /* move forward 2 bytes for flags */
939 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200940
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200941 /* 2 bytes for question count */
942 if (reader + 2 >= bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200943 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200944 dns_p->header.qdcount = reader[0] * 256 + reader[1];
945 /* (for now) we send one query only, so we expect only one in the response too */
946 if (dns_p->header.qdcount != 1)
947 return DNS_RESP_QUERY_COUNT_ERROR;
948 if (dns_p->header.qdcount > DNS_MAX_QUERY_RECORDS)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200949 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200950 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200951
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200952 /* 2 bytes for answer count */
953 if (reader + 2 >= bufend)
954 return DNS_RESP_INVALID;
955 dns_p->header.ancount = reader[0] * 256 + reader[1];
956 if (dns_p->header.ancount == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200957 return DNS_RESP_ANCOUNT_ZERO;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200958 /* check if too many records are announced */
959 if (dns_p->header.ancount > DNS_MAX_ANSWER_RECORDS)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200960 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200961 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200962
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200963 /* 2 bytes authority count */
964 if (reader + 2 >= bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200965 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200966 dns_p->header.nscount = reader[0] * 256 + reader[1];
967 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200968
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200969 /* 2 bytes additional count */
970 if (reader + 2 >= bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +0200971 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200972 dns_p->header.arcount = reader[0] * 256 + reader[1];
973 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +0200974
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200975 /* parsing dns queries */
976 LIST_INIT(&dns_p->query_list);
977 for (dns_query_record_id = 0; dns_query_record_id < dns_p->header.qdcount; dns_query_record_id++) {
978 /* use next pre-allocated dns_query_item after ensuring there is
979 * still one available.
980 * It's then added to our packet query list.
981 */
982 if (dns_query_record_id > DNS_MAX_QUERY_RECORDS)
983 return DNS_RESP_INVALID;
Baptiste Assmann729c9012017-05-22 15:13:10 +0200984 dns_query = &resolution->response_query_records[dns_query_record_id];
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200985 LIST_ADDQ(&dns_p->query_list, &dns_query->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +0200986
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200987 /* name is a NULL terminated string in our case, since we have
988 * one query per response and the first one can't be compressed
989 * (using the 0x0c format)
990 */
991 offset = 0;
992 len = dns_read_name(resp, bufend, reader, dns_query->name, DNS_MAX_NAME_SIZE, &offset);
Baptiste Assmann325137d2015-04-13 23:40:55 +0200993
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +0200994 if (len == 0)
995 return DNS_RESP_INVALID;
996
997 reader += offset;
998 previous_dname = dns_query->name;
999
1000 /* move forward 2 bytes for question type */
1001 if (reader + 2 >= bufend)
1002 return DNS_RESP_INVALID;
1003 dns_query->type = reader[0] * 256 + reader[1];
1004 reader += 2;
1005
1006 /* move forward 2 bytes for question class */
1007 if (reader + 2 >= bufend)
1008 return DNS_RESP_INVALID;
1009 dns_query->class = reader[0] * 256 + reader[1];
1010 reader += 2;
1011 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02001012
1013 /* now parsing response records */
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001014 LIST_INIT(&dns_p->answer_list);
Baptiste Assmann69fce672017-05-04 08:37:45 +02001015 nb_saved_records = 0;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001016 for (dns_answer_record_id = 0; dns_answer_record_id < dns_p->header.ancount; dns_answer_record_id++) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001017 if (reader >= bufend)
1018 return DNS_RESP_INVALID;
1019
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001020 /* pull next response record from the list, if still one available, then add it
1021 * to the record list */
1022 if (dns_answer_record_id > DNS_MAX_ANSWER_RECORDS)
1023 return DNS_RESP_INVALID;
Baptiste Assmann729c9012017-05-22 15:13:10 +02001024 dns_answer_record = &resolution->response_answer_records[dns_answer_record_id];
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001025 LIST_ADDQ(&dns_p->answer_list, &dns_answer_record->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001026
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001027 offset = 0;
1028 len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001029
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001030 if (len == 0)
1031 return DNS_RESP_INVALID;
1032
1033 /* check if the current record dname is valid.
1034 * previous_dname points either to queried dname or last CNAME target
1035 */
1036 if (memcmp(previous_dname, tmpname, len) != 0) {
1037 if (dns_answer_record_id == 0) {
1038 /* first record, means a mismatch issue between queried dname
1039 * and dname found in the first record */
Baptiste Assmann325137d2015-04-13 23:40:55 +02001040 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001041 } else {
1042 /* if not the first record, this means we have a CNAME resolution
1043 * error */
1044 return DNS_RESP_CNAME_ERROR;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001045 }
1046
Baptiste Assmann325137d2015-04-13 23:40:55 +02001047 }
1048
Baptiste Assmann729c9012017-05-22 15:13:10 +02001049 dns_answer_record->name = chunk_newstr(dns_response_buffer);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001050 if (dns_answer_record->name == NULL)
1051 return DNS_RESP_INVALID;
Baptiste Assmann5d681ba2015-10-15 15:23:28 +02001052
Baptiste Assmann729c9012017-05-22 15:13:10 +02001053 ret = chunk_strncat(dns_response_buffer, tmpname, len);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001054 if (ret == 0)
1055 return DNS_RESP_INVALID;
Baptiste Assmann2359ff12015-08-07 11:24:05 +02001056
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001057 reader += offset;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001058 if (reader >= bufend)
1059 return DNS_RESP_INVALID;
1060
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001061 if (reader >= bufend)
1062 return DNS_RESP_INVALID;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001063
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001064 /* 2 bytes for record type (A, AAAA, CNAME, etc...) */
Baptiste Assmann325137d2015-04-13 23:40:55 +02001065 if (reader + 2 > bufend)
1066 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001067 dns_answer_record->type = reader[0] * 256 + reader[1];
1068 reader += 2;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001069
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001070 /* 2 bytes for class (2) */
1071 if (reader + 2 > bufend)
1072 return DNS_RESP_INVALID;
1073 dns_answer_record->class = reader[0] * 256 + reader[1];
Baptiste Assmann325137d2015-04-13 23:40:55 +02001074 reader += 2;
1075
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001076 /* 4 bytes for ttl (4) */
1077 if (reader + 4 > bufend)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001078 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001079 dns_answer_record->ttl = reader[0] * 16777216 + reader[1] * 65536
1080 + reader[2] * 256 + reader[3];
1081 reader += 4;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001082
1083 /* now reading data len */
1084 if (reader + 2 > bufend)
1085 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001086 dns_answer_record->data_len = reader[0] * 256 + reader[1];
Baptiste Assmann325137d2015-04-13 23:40:55 +02001087
1088 /* move forward 2 bytes for data len */
1089 reader += 2;
1090
1091 /* analyzing record content */
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001092 switch (dns_answer_record->type) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001093 case DNS_RTYPE_A:
1094 /* ipv4 is stored on 4 bytes */
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001095 if (dns_answer_record->data_len != 4)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001096 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001097 dns_answer_record->address.sa_family = AF_INET;
1098 memcpy(&(((struct sockaddr_in *)&dns_answer_record->address)->sin_addr),
1099 reader, dns_answer_record->data_len);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001100 break;
1101
1102 case DNS_RTYPE_CNAME:
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001103 /* check if this is the last record and update the caller about the status:
1104 * no IP could be found and last record was a CNAME. Could be triggered
1105 * by a wrong query type
1106 *
1107 * + 1 because dns_answer_record_id starts at 0 while number of answers
1108 * is an integer and starts at 1.
1109 */
1110 if (dns_answer_record_id + 1 == dns_p->header.ancount)
1111 return DNS_RESP_CNAME_ERROR;
1112
1113 offset = 0;
1114 len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset);
1115
1116 if (len == 0)
1117 return DNS_RESP_INVALID;
1118
Baptiste Assmann729c9012017-05-22 15:13:10 +02001119 dns_answer_record->target = chunk_newstr(dns_response_buffer);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001120 if (dns_answer_record->target == NULL)
1121 return DNS_RESP_INVALID;
1122
Baptiste Assmann729c9012017-05-22 15:13:10 +02001123 ret = chunk_strncat(dns_response_buffer, tmpname, len);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001124 if (ret == 0)
1125 return DNS_RESP_INVALID;
1126
1127 previous_dname = dns_answer_record->target;
1128
Baptiste Assmann325137d2015-04-13 23:40:55 +02001129 break;
1130
1131 case DNS_RTYPE_AAAA:
1132 /* ipv6 is stored on 16 bytes */
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001133 if (dns_answer_record->data_len != 16)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001134 return DNS_RESP_INVALID;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001135 dns_answer_record->address.sa_family = AF_INET6;
1136 memcpy(&(((struct sockaddr_in6 *)&dns_answer_record->address)->sin6_addr),
1137 reader, dns_answer_record->data_len);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001138 break;
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001139
Baptiste Assmann325137d2015-04-13 23:40:55 +02001140 } /* switch (record type) */
1141
Baptiste Assmann69fce672017-05-04 08:37:45 +02001142 /* increment the counter for number of records saved into our local response */
1143 nb_saved_records += 1;
1144
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001145 /* move forward dns_answer_record->data_len for analyzing next record in the response */
1146 reader += dns_answer_record->data_len;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001147 } /* for i 0 to ancount */
1148
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001149 /* let's add a last \0 to close our last string */
Baptiste Assmann729c9012017-05-22 15:13:10 +02001150 ret = chunk_strncat(dns_response_buffer, "\0", 1);
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001151 if (ret == 0)
1152 return DNS_RESP_INVALID;
Baptiste Assmann96972bc2015-09-09 00:46:58 +02001153
Baptiste Assmann69fce672017-05-04 08:37:45 +02001154 /* save the number of records we really own */
1155 dns_p->header.ancount = nb_saved_records;
1156
Baptiste Assmann325137d2015-04-13 23:40:55 +02001157 return DNS_RESP_VALID;
1158}
1159
1160/*
1161 * search dn_name resolution in resp.
1162 * If existing IP not found, return the first IP matching family_priority,
1163 * otherwise, first ip found
1164 * The following tasks are the responsibility of the caller:
Baptiste Assmann3cf7f982016-04-17 22:43:26 +02001165 * - <dns_p> contains an error free DNS response
Baptiste Assmann325137d2015-04-13 23:40:55 +02001166 * For both cases above, dns_validate_dns_response is required
1167 * returns one of the DNS_UPD_* code
1168 */
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001169#define DNS_MAX_IP_REC 20
Baptiste Assmannfb7091e2017-05-03 15:43:12 +02001170int dns_get_ip_from_response(struct dns_response_packet *dns_p,
Baptiste Assmann42746372017-05-03 12:12:02 +02001171 struct dns_options *dns_opts, void *currentip,
Thierry Fournierada34842016-02-17 21:25:09 +01001172 short currentip_sin_family,
Baptiste Assmannfb7091e2017-05-03 15:43:12 +02001173 void **newip, short *newip_sin_family,
1174 void *owner)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001175{
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001176 struct dns_answer_item *record;
Thierry Fournierada34842016-02-17 21:25:09 +01001177 int family_priority;
Baptiste Assmann3cf7f982016-04-17 22:43:26 +02001178 int i, currentip_found;
1179 unsigned char *newip4, *newip6;
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001180 struct {
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001181 void *ip;
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001182 unsigned char type;
1183 } rec[DNS_MAX_IP_REC];
1184 int currentip_sel;
1185 int j;
1186 int rec_nb = 0;
1187 int score, max_score;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001188
Baptiste Assmann42746372017-05-03 12:12:02 +02001189 family_priority = dns_opts->family_prio;
Baptiste Assmann3cf7f982016-04-17 22:43:26 +02001190 *newip = newip4 = newip6 = NULL;
1191 currentip_found = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001192 *newip_sin_family = AF_UNSPEC;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001193
1194 /* now parsing response records */
Baptiste Assmann729c9012017-05-22 15:13:10 +02001195 list_for_each_entry(record, &dns_p->answer_list, list) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001196 /* analyzing record content */
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001197 switch (record->type) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001198 case DNS_RTYPE_A:
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001199 /* Store IPv4, only if some room is avalaible. */
1200 if (rec_nb < DNS_MAX_IP_REC) {
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001201 rec[rec_nb].ip = &(((struct sockaddr_in *)&record->address)->sin_addr);
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001202 rec[rec_nb].type = AF_INET;
1203 rec_nb++;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001204 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02001205 break;
1206
Baptiste Assmann3cf7f982016-04-17 22:43:26 +02001207 /* we're looking for IPs only. CNAME validation is done when
1208 * parsing the response buffer for the first time */
Baptiste Assmann325137d2015-04-13 23:40:55 +02001209 case DNS_RTYPE_CNAME:
Baptiste Assmann325137d2015-04-13 23:40:55 +02001210 break;
1211
1212 case DNS_RTYPE_AAAA:
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001213 /* Store IPv6, only if some room is avalaible. */
1214 if (rec_nb < DNS_MAX_IP_REC) {
Baptiste Assmannc1ce5f32016-05-14 11:26:22 +02001215 rec[rec_nb].ip = &(((struct sockaddr_in6 *)&record->address)->sin6_addr);
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001216 rec[rec_nb].type = AF_INET6;
1217 rec_nb++;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001218 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02001219 break;
1220
Baptiste Assmann325137d2015-04-13 23:40:55 +02001221 } /* switch (record type) */
Baptiste Assmannbcbd4912016-04-18 19:42:57 +02001222 } /* list for each record entries */
Baptiste Assmann325137d2015-04-13 23:40:55 +02001223
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001224 /* Select an IP regarding configuration preference.
1225 * Top priority is the prefered network ip version,
1226 * second priority is the prefered network.
1227 * the last priority is the currently used IP,
1228 *
1229 * For these three priorities, a score is calculated. The
1230 * weight are:
Baptistefc725902016-12-26 23:21:08 +01001231 * 8 - prefered netwok ip version.
1232 * 4 - prefered network.
1233 * 2 - if the ip in the record is not affected to any other server in the same backend (duplication)
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001234 * 1 - current ip.
1235 * The result with the biggest score is returned.
1236 */
1237 max_score = -1;
1238 for (i = 0; i < rec_nb; i++) {
Baptistefc725902016-12-26 23:21:08 +01001239 int record_ip_already_affected = 0;
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001240
1241 score = 0;
1242
1243 /* Check for prefered ip protocol. */
1244 if (rec[i].type == family_priority)
Baptistefc725902016-12-26 23:21:08 +01001245 score += 8;
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001246
1247 /* Check for prefered network. */
Baptiste Assmann42746372017-05-03 12:12:02 +02001248 for (j = 0; j < dns_opts->pref_net_nb; j++) {
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001249
1250 /* Compare only the same adresses class. */
Baptiste Assmann42746372017-05-03 12:12:02 +02001251 if (dns_opts->pref_net[j].family != rec[i].type)
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001252 continue;
1253
1254 if ((rec[i].type == AF_INET &&
Willy Tarreaueec1d382016-07-13 11:59:39 +02001255 in_net_ipv4(rec[i].ip,
Baptiste Assmann42746372017-05-03 12:12:02 +02001256 &dns_opts->pref_net[j].mask.in4,
1257 &dns_opts->pref_net[j].addr.in4)) ||
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001258 (rec[i].type == AF_INET6 &&
Willy Tarreaueec1d382016-07-13 11:59:39 +02001259 in_net_ipv6(rec[i].ip,
Baptiste Assmann42746372017-05-03 12:12:02 +02001260 &dns_opts->pref_net[j].mask.in6,
1261 &dns_opts->pref_net[j].addr.in6))) {
Baptistefc725902016-12-26 23:21:08 +01001262 score += 4;
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001263 break;
1264 }
1265 }
1266
Baptiste Assmannfb7091e2017-05-03 15:43:12 +02001267 /* Check if the IP found in the record is already affected to a member of a group.
1268 * If yes, the score should be incremented by 2.
1269 */
1270 if (owner) {
1271 if (snr_check_ip_callback(owner, rec[i].ip, &rec[i].type))
Baptistefc725902016-12-26 23:21:08 +01001272 record_ip_already_affected = 1;
Baptistefc725902016-12-26 23:21:08 +01001273 }
Baptiste Assmannfb7091e2017-05-03 15:43:12 +02001274 if (record_ip_already_affected == 0)
Baptistefc725902016-12-26 23:21:08 +01001275 score += 2;
1276
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001277 /* Check for current ip matching. */
1278 if (rec[i].type == currentip_sin_family &&
1279 ((currentip_sin_family == AF_INET &&
Willy Tarreaueec1d382016-07-13 11:59:39 +02001280 memcmp(rec[i].ip, currentip, 4) == 0) ||
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001281 (currentip_sin_family == AF_INET6 &&
1282 memcmp(rec[i].ip, currentip, 16) == 0))) {
1283 score += 1;
1284 currentip_sel = 1;
1285 } else
1286 currentip_sel = 0;
1287
Baptistefc725902016-12-26 23:21:08 +01001288
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001289 /* Keep the address if the score is better than the previous
Baptistefc725902016-12-26 23:21:08 +01001290 * score. The maximum score is 15, if this value is reached,
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001291 * we break the parsing. Implicitly, this score is reached
1292 * the ip selected is the current ip.
1293 */
1294 if (score > max_score) {
1295 if (rec[i].type == AF_INET)
1296 newip4 = rec[i].ip;
1297 else
1298 newip6 = rec[i].ip;
1299 currentip_found = currentip_sel;
Baptistefc725902016-12-26 23:21:08 +01001300 if (score == 15)
Thierry Fournierac88cfe2016-02-17 22:05:30 +01001301 return DNS_UPD_NO;
1302 max_score = score;
1303 }
1304 }
1305
Baptiste Assmann0453a1d2015-09-09 00:51:08 +02001306 /* no IP found in the response */
1307 if (!newip4 && !newip6) {
1308 return DNS_UPD_NO_IP_FOUND;
1309 }
1310
Baptiste Assmann325137d2015-04-13 23:40:55 +02001311 /* case when the caller looks first for an IPv4 address */
1312 if (family_priority == AF_INET) {
1313 if (newip4) {
1314 *newip = newip4;
1315 *newip_sin_family = AF_INET;
1316 if (currentip_found == 1)
1317 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001318 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001319 }
1320 else if (newip6) {
1321 *newip = newip6;
1322 *newip_sin_family = AF_INET6;
1323 if (currentip_found == 1)
1324 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001325 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001326 }
1327 }
1328 /* case when the caller looks first for an IPv6 address */
1329 else if (family_priority == AF_INET6) {
1330 if (newip6) {
1331 *newip = newip6;
1332 *newip_sin_family = AF_INET6;
1333 if (currentip_found == 1)
1334 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001335 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001336 }
1337 else if (newip4) {
1338 *newip = newip4;
1339 *newip_sin_family = AF_INET;
1340 if (currentip_found == 1)
1341 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001342 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001343 }
1344 }
1345 /* case when the caller have no preference (we prefer IPv6) */
1346 else if (family_priority == AF_UNSPEC) {
1347 if (newip6) {
1348 *newip = newip6;
1349 *newip_sin_family = AF_INET6;
1350 if (currentip_found == 1)
1351 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001352 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001353 }
1354 else if (newip4) {
1355 *newip = newip4;
1356 *newip_sin_family = AF_INET;
1357 if (currentip_found == 1)
1358 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001359 goto return_DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001360 }
1361 }
1362
1363 /* no reason why we should change the server's IP address */
1364 return DNS_UPD_NO;
Baptiste Assmann8ea0bcc2017-05-04 08:24:11 +02001365
1366 return_DNS_UPD_SRVIP_NOT_FOUND:
1367 list_for_each_entry(record, &dns_p->answer_list, list) {
1368 /* move the first record to the end of the list, for internal round robin */
1369 if (record) {
1370 LIST_DEL(&record->list);
1371 LIST_ADDQ(&dns_p->answer_list, &record->list);
1372 break;
1373 }
1374 }
1375 return DNS_UPD_SRVIP_NOT_FOUND;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001376}
1377
1378/*
1379 * returns the query id contained in a DNS response
1380 */
Thiago Farinab1af23e2016-01-20 23:46:34 +01001381unsigned short dns_response_get_query_id(unsigned char *resp)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001382{
1383 /* read the query id from the response */
1384 return resp[0] * 256 + resp[1];
1385}
1386
1387/*
1388 * used during haproxy's init phase
1389 * parses resolvers sections and initializes:
1390 * - task (time events) for each resolvers section
1391 * - the datagram layer (network IO events) for each nameserver
Baptiste Assmann5cd1b922017-02-02 22:44:15 +01001392 * It takes one argument:
1393 * - close_first takes 2 values: 0 or 1. If 1, the connection is closed first.
Baptiste Assmann325137d2015-04-13 23:40:55 +02001394 * returns:
1395 * 0 in case of error
1396 * 1 when no error
1397 */
Baptiste Assmann5cd1b922017-02-02 22:44:15 +01001398int dns_init_resolvers(int close_socket)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001399{
1400 struct dns_resolvers *curr_resolvers;
1401 struct dns_nameserver *curnameserver;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001402 struct dns_resolution *resolution, *res_back;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001403 struct dgram_conn *dgram;
1404 struct task *t;
1405 int fd;
1406
Baptiste Assmannfa4a6632017-05-04 09:05:00 +02001407 /* initialize our DNS resolution cache */
1408 dns_lru_tree = lru64_new(dns_cache_size);
1409
Baptiste Assmann325137d2015-04-13 23:40:55 +02001410 /* give a first random value to our dns query_id seed */
1411 dns_query_id_seed = random();
1412
1413 /* run through the resolvers section list */
1414 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
1415 /* create the task associated to the resolvers section */
1416 if ((t = task_new()) == NULL) {
1417 Alert("Starting [%s] resolvers: out of memory.\n", curr_resolvers->id);
1418 return 0;
1419 }
1420
1421 /* update task's parameters */
1422 t->process = dns_process_resolve;
1423 t->context = curr_resolvers;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001424 t->expire = 0;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001425
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001426 /* no need to keep the new task if one is already affected to our resolvers
1427 * section */
1428 if (!curr_resolvers->t)
1429 curr_resolvers->t = t;
1430 else
1431 task_free(t);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001432
1433 list_for_each_entry(curnameserver, &curr_resolvers->nameserver_list, list) {
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001434 dgram = NULL;
Baptiste Assmann5cd1b922017-02-02 22:44:15 +01001435
1436 if (close_socket == 1) {
1437 if (curnameserver->dgram) {
Frédéric Lécaille64920532017-05-12 09:57:15 +02001438 fd_delete(curnameserver->dgram->t.sock.fd);
Baptiste Assmann5cd1b922017-02-02 22:44:15 +01001439 memset(curnameserver->dgram, '\0', sizeof(*dgram));
1440 dgram = curnameserver->dgram;
1441 }
1442 }
1443
1444 /* allocate memory only if it has not already been allocated
1445 * by a previous call to this function */
1446 if (!dgram && (dgram = calloc(1, sizeof(*dgram))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001447 Alert("Starting [%s/%s] nameserver: out of memory.\n", curr_resolvers->id,
1448 curnameserver->id);
1449 return 0;
1450 }
1451 /* update datagram's parameters */
1452 dgram->owner = (void *)curnameserver;
1453 dgram->data = &resolve_dgram_cb;
1454
1455 /* create network UDP socket for this nameserver */
Frédéric Lécaille5e5bc9f2017-04-11 08:46:37 +02001456 if ((fd = socket(curnameserver->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001457 Alert("Starting [%s/%s] nameserver: can't create socket.\n", curr_resolvers->id,
1458 curnameserver->id);
1459 free(dgram);
1460 dgram = NULL;
1461 return 0;
1462 }
1463
1464 /* "connect" the UDP socket to the name server IP */
Baptiste Assmann8c62c472015-09-21 20:55:08 +02001465 if (connect(fd, (struct sockaddr*)&curnameserver->addr, get_addr_len(&curnameserver->addr)) == -1) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001466 Alert("Starting [%s/%s] nameserver: can't connect socket.\n", curr_resolvers->id,
1467 curnameserver->id);
1468 close(fd);
1469 free(dgram);
1470 dgram = NULL;
1471 return 0;
1472 }
1473
1474 /* make the socket non blocking */
1475 fcntl(fd, F_SETFL, O_NONBLOCK);
1476
1477 /* add the fd in the fd list and update its parameters */
1478 fd_insert(fd);
1479 fdtab[fd].owner = dgram;
1480 fdtab[fd].iocb = dgram_fd_handler;
1481 fd_want_recv(fd);
1482 dgram->t.sock.fd = fd;
1483
1484 /* update nameserver's datagram property */
1485 curnameserver->dgram = dgram;
1486
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001487 continue;
1488 }
1489
1490 if (close_socket == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001491 continue;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001492
1493 /* now, we can trigger DNS resolution */
1494 list_for_each_entry_safe(resolution, res_back, &curr_resolvers->resolution.wait, list) {
1495 /* if there is no requester in the wait queue, no need to trigger the resolution */
1496 if (LIST_ISEMPTY(&resolution->requester.wait))
1497 continue;
1498
1499 dns_trigger_resolution(resolution);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001500 }
1501
1502 /* task can be queued */
1503 task_queue(t);
1504 }
1505
1506 return 1;
1507}
1508
1509/*
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001510 * Allocate a pool of resolution to a resolvers section.
1511 * Each resolution is associated with a UUID.
1512 *
1513 * Return code:
1514 * - 0 if everything went smoothly
1515 * - -1 if an error occured
1516 */
1517int dns_alloc_resolution_pool(struct dns_resolvers *resolvers)
1518{
1519 int i;
1520 struct dns_resolution *resolution;
1521
1522 /* return if a pool has already been set for this resolvers */
1523 if (!LIST_ISEMPTY(&resolvers->resolution.pool)) {
1524 return 0;
1525 }
1526
1527 for (i = 0; i < resolvers->resolution_pool_size; i++) {
1528 resolution = dns_alloc_resolution();
1529 if (!resolution) {
1530 Alert("Starting [%s] resolvers: can't allocate memory for DNS resolution pool.\n", resolvers->id);
1531 return -1;
1532 }
1533 resolution->uuid = i;
1534 LIST_ADDQ(&resolvers->resolution.pool, &resolution->list);
1535 }
1536
1537 return 0;
1538}
1539
1540/*
Baptiste Assmann325137d2015-04-13 23:40:55 +02001541 * Forge a DNS query. It needs the following information from the caller:
1542 * - <query_id>: the DNS query id corresponding to this query
1543 * - <query_type>: DNS_RTYPE_* request DNS record type (A, AAAA, ANY, etc...)
1544 * - <hostname_dn>: hostname in domain name format
1545 * - <hostname_dn_len>: length of <hostname_dn>
1546 * To store the query, the caller must pass a buffer <buf> and its size <bufsize>
1547 *
1548 * the DNS query is stored in <buf>
1549 * returns:
1550 * -1 if <buf> is too short
1551 */
1552int dns_build_query(int query_id, int query_type, char *hostname_dn, int hostname_dn_len, char *buf, int bufsize)
1553{
1554 struct dns_header *dns;
Vincent Bernat9b7125c2016-04-08 22:17:45 +02001555 struct dns_question qinfo;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001556 char *ptr, *bufend;
1557
1558 memset(buf, '\0', bufsize);
1559 ptr = buf;
1560 bufend = buf + bufsize;
1561
1562 /* check if there is enough room for DNS headers */
1563 if (ptr + sizeof(struct dns_header) >= bufend)
1564 return -1;
1565
1566 /* set dns query headers */
1567 dns = (struct dns_header *)ptr;
1568 dns->id = (unsigned short) htons(query_id);
Nenad Merdanovic8ab79422016-07-13 14:03:43 +02001569 dns->flags = htons(0x0100); /* qr=0, opcode=0, aa=0, tc=0, rd=1, ra=0, z=0, rcode=0 */
Baptiste Assmann325137d2015-04-13 23:40:55 +02001570 dns->qdcount = htons(1); /* 1 question */
1571 dns->ancount = 0;
1572 dns->nscount = 0;
1573 dns->arcount = 0;
1574
1575 /* move forward ptr */
1576 ptr += sizeof(struct dns_header);
1577
1578 /* check if there is enough room for query hostname */
1579 if ((ptr + hostname_dn_len) >= bufend)
1580 return -1;
1581
1582 /* set up query hostname */
1583 memcpy(ptr, hostname_dn, hostname_dn_len);
1584 ptr[hostname_dn_len + 1] = '\0';
1585
1586 /* move forward ptr */
1587 ptr += (hostname_dn_len + 1);
1588
1589 /* check if there is enough room for query hostname*/
1590 if (ptr + sizeof(struct dns_question) >= bufend)
1591 return -1;
1592
1593 /* set up query info (type and class) */
Vincent Bernat9b7125c2016-04-08 22:17:45 +02001594 qinfo.qtype = htons(query_type);
1595 qinfo.qclass = htons(DNS_RCLASS_IN);
1596 memcpy(ptr, &qinfo, sizeof(qinfo));
Baptiste Assmann325137d2015-04-13 23:40:55 +02001597
1598 ptr += sizeof(struct dns_question);
1599
1600 return ptr - buf;
1601}
1602
1603/*
1604 * turn a string into domain name label:
1605 * www.haproxy.org into 3www7haproxy3org
1606 * if dn memory is pre-allocated, you must provide its size in dn_len
1607 * if dn memory isn't allocated, dn_len must be set to 0.
1608 * In the second case, memory will be allocated.
1609 * in case of error, -1 is returned, otherwise, number of bytes copied in dn
1610 */
Willy Tarreau2100b492015-07-22 16:42:43 +02001611char *dns_str_to_dn_label(const char *string, char *dn, int dn_len)
Baptiste Assmann325137d2015-04-13 23:40:55 +02001612{
1613 char *c, *d;
1614 int i, offset;
1615
1616 /* offset between string size and theorical dn size */
1617 offset = 1;
1618
1619 /*
1620 * first, get the size of the string turned into its domain name version
1621 * This function also validates the string respect the RFC
1622 */
1623 if ((i = dns_str_to_dn_label_len(string)) == -1)
1624 return NULL;
1625
1626 /* yes, so let's check there is enough memory */
1627 if (dn_len < i + offset)
1628 return NULL;
1629
Willy Tarreaud69d6f32015-07-22 16:45:36 +02001630 i = strlen(string);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001631 memcpy(dn + offset, string, i);
1632 dn[i + offset] = '\0';
1633 /* avoid a '\0' at the beginning of dn string which may prevent the for loop
1634 * below from working.
1635 * Actually, this is the reason of the offset. */
1636 dn[0] = '0';
1637
1638 for (c = dn; *c ; ++c) {
1639 /* c points to the first '0' char or a dot, which we don't want to read */
1640 d = c + offset;
1641 i = 0;
1642 while (*d != '.' && *d) {
1643 i++;
1644 d++;
1645 }
1646 *c = i;
1647
1648 c = d - 1; /* because of c++ of the for loop */
1649 }
1650
1651 return dn;
1652}
1653
1654/*
1655 * compute and return the length of <string> it it were translated into domain name
1656 * label:
1657 * www.haproxy.org into 3www7haproxy3org would return 16
1658 * NOTE: add +1 for '\0' when allocating memory ;)
1659 */
1660int dns_str_to_dn_label_len(const char *string)
1661{
1662 return strlen(string) + 1;
1663}
1664
1665/*
1666 * validates host name:
1667 * - total size
1668 * - each label size individually
1669 * returns:
1670 * 0 in case of error. If <err> is not NULL, an error message is stored there.
1671 * 1 when no error. <err> is left unaffected.
1672 */
1673int dns_hostname_validation(const char *string, char **err)
1674{
1675 const char *c, *d;
1676 int i;
1677
1678 if (strlen(string) > DNS_MAX_NAME_SIZE) {
1679 if (err)
1680 *err = DNS_TOO_LONG_FQDN;
1681 return 0;
1682 }
1683
1684 c = string;
1685 while (*c) {
1686 d = c;
1687
1688 i = 0;
1689 while (*d != '.' && *d && i <= DNS_MAX_LABEL_SIZE) {
1690 i++;
1691 if (!((*d == '-') || (*d == '_') ||
1692 ((*d >= 'a') && (*d <= 'z')) ||
1693 ((*d >= 'A') && (*d <= 'Z')) ||
1694 ((*d >= '0') && (*d <= '9')))) {
1695 if (err)
1696 *err = DNS_INVALID_CHARACTER;
1697 return 0;
1698 }
1699 d++;
1700 }
1701
1702 if ((i >= DNS_MAX_LABEL_SIZE) && (d[i] != '.')) {
1703 if (err)
1704 *err = DNS_LABEL_TOO_LONG;
1705 return 0;
1706 }
1707
1708 if (*d == '\0')
1709 goto out;
1710
1711 c = ++d;
1712 }
1713 out:
1714 return 1;
1715}
1716
1717/*
1718 * 2 bytes random generator to generate DNS query ID
1719 */
1720uint16_t dns_rnd16(void)
1721{
1722 dns_query_id_seed ^= dns_query_id_seed << 13;
1723 dns_query_id_seed ^= dns_query_id_seed >> 7;
1724 dns_query_id_seed ^= dns_query_id_seed << 17;
1725 return dns_query_id_seed;
1726}
1727
1728
1729/*
1730 * function called when a timeout occurs during name resolution process
1731 * if max number of tries is reached, then stop, otherwise, retry.
1732 */
1733struct task *dns_process_resolve(struct task *t)
1734{
1735 struct dns_resolvers *resolvers = t->context;
1736 struct dns_resolution *resolution, *res_back;
Baptiste Assmann060e5732016-01-06 02:01:59 +01001737 int res_preferred_afinet, res_preferred_afinet6;
Baptiste Assmann42746372017-05-03 12:12:02 +02001738 struct dns_options *dns_opts = NULL;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001739
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001740 /* if both there is no resolution in the run queue, we can re-schedule a wake up */
1741 if (LIST_ISEMPTY(&resolvers->resolution.curr)) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02001742 /* no first entry, so wake up was useless */
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001743 dns_update_resolvers_timeout(resolvers);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001744 return t;
1745 }
1746
1747 /* look for the first resolution which is not expired */
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001748 list_for_each_entry_safe(resolution, res_back, &resolvers->resolution.curr, list) {
1749 struct dns_requester *requester = NULL;
1750
Baptiste Assmann325137d2015-04-13 23:40:55 +02001751 /* when we find the first resolution in the future, then we can stop here */
1752 if (tick_is_le(now_ms, resolution->last_sent_packet))
1753 goto out;
1754
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001755 if (LIST_ISEMPTY(&resolution->requester.curr))
1756 goto out;
1757
Baptiste Assmann325137d2015-04-13 23:40:55 +02001758 /*
1759 * if current resolution has been tried too many times and finishes in timeout
1760 * we update its status and remove it from the list
1761 */
Baptiste Assmannf778bb42015-09-09 00:54:38 +02001762 if (resolution->try <= 0) {
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001763 struct dns_requester *tmprequester;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001764 /* clean up resolution information and remove from the list */
1765 dns_reset_resolution(resolution);
1766
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001767 LIST_DEL(&resolution->list);
1768 LIST_ADDQ(&resolvers->resolution.wait, &resolution->list);
1769
1770 if (resolution->status != RSLV_STATUS_TIMEOUT) {
1771 resolution->status = RSLV_STATUS_TIMEOUT;
1772 resolution->last_status_change = now_ms;
1773 }
1774
1775 /* notify the result to the requesters */
1776 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
1777 requester->requester_error_cb(requester, DNS_RESP_TIMEOUT);
1778 LIST_DEL(&requester->list);
1779 LIST_ADDQ(&resolution->requester.wait, &requester->list);
1780 }
Baptiste Assmann382824c2016-01-06 01:53:46 +01001781 goto out;
Baptiste Assmann325137d2015-04-13 23:40:55 +02001782 }
1783
Baptiste Assmannf778bb42015-09-09 00:54:38 +02001784 resolution->try -= 1;
1785
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001786 /* running queue is empty, nothing to do but wait */
1787 if (LIST_ISEMPTY(&resolution->requester.curr))
1788 goto out;
1789
1790 requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list);
1791
1792 switch (obj_type(requester->requester)) {
1793 case OBJ_TYPE_SERVER:
1794 dns_opts = &(objt_server(requester->requester)->dns_opts);
1795 break;
1796
1797 case OBJ_TYPE_NONE:
1798 default:
1799 /* clean up resolution information and remove from the list */
1800 dns_reset_resolution(resolution);
1801
1802 LIST_DEL(&resolution->list);
1803 LIST_ADDQ(&resolvers->resolution.wait, &resolution->list);
1804
1805 /* notify the result to the requester */
1806 requester->requester_error_cb(requester, DNS_RESP_INTERNAL);
1807 goto out;
1808 }
Baptiste Assmann42746372017-05-03 12:12:02 +02001809
1810 res_preferred_afinet = dns_opts->family_prio == AF_INET && resolution->query_type == DNS_RTYPE_A;
1811 res_preferred_afinet6 = dns_opts->family_prio == AF_INET6 && resolution->query_type == DNS_RTYPE_AAAA;
Baptiste Assmann060e5732016-01-06 02:01:59 +01001812
1813 /* let's change the query type if needed */
1814 if (res_preferred_afinet6) {
1815 /* fallback from AAAA to A */
1816 resolution->query_type = DNS_RTYPE_A;
1817 }
1818 else if (res_preferred_afinet) {
1819 /* fallback from A to AAAA */
1820 resolution->query_type = DNS_RTYPE_AAAA;
1821 }
1822
Baptiste Assmann382824c2016-01-06 01:53:46 +01001823 /* resend the DNS query */
1824 dns_send_query(resolution);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001825
Baptiste Assmann382824c2016-01-06 01:53:46 +01001826 /* check if we have more than one resolution in the list */
1827 if (dns_check_resolution_queue(resolvers) > 1) {
1828 /* move the rsolution to the end of the list */
1829 LIST_DEL(&resolution->list);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001830 LIST_ADDQ(&resolvers->resolution.curr, &resolution->list);
Baptiste Assmann325137d2015-04-13 23:40:55 +02001831 }
1832 }
1833
1834 out:
1835 dns_update_resolvers_timeout(resolvers);
1836 return t;
1837}
William Lallemand69e96442016-11-19 00:58:54 +01001838
Baptiste Assmannfa4a6632017-05-04 09:05:00 +02001839/*
1840 * build a dns cache key composed as follow:
1841 * <query type>#<hostname in domain name format>
1842 * and store it into <str>.
1843 * It's up to the caller to allocate <buf> and to reset it.
1844 * The function returns NULL in case of error (IE <buf> too small) or a pointer
1845 * to buf if successful
1846 */
1847struct chunk *
1848dns_cache_key(int query_type, char *hostname_dn, int hostname_dn_len, struct chunk *buf)
1849{
1850 int len, size;
1851 char *str;
1852
1853 str = buf->str;
1854 len = buf->len;
1855 size = buf->size;
1856
1857 switch (query_type) {
1858 case DNS_RTYPE_A:
1859 if (len + 1 > size)
1860 return NULL;
1861 memcpy(&str[len], "A", 1);
1862 len += 1;
1863 break;
1864 case DNS_RTYPE_AAAA:
1865 if (len + 4 > size)
1866 return NULL;
1867 memcpy(&str[len], "AAAA", 4);
1868 len += 4;
1869 break;
1870 default:
1871 return NULL;
1872 }
1873
1874 if (len + 1 > size)
1875 return NULL;
1876 memcpy(&str[len], "#", 1);
1877 len += 1;
1878
1879 if (len + hostname_dn_len + 1 > size) // +1 for trailing zero
1880 return NULL;
1881 memcpy(&str[len], hostname_dn, hostname_dn_len);
1882 len += hostname_dn_len;
1883 str[len] = '\0';
1884
1885 return buf;
1886}
1887
1888/*
1889 * returns a pointer to a cache entry which may still be considered as up to date
1890 * by the caller.
1891 * returns NULL if no entry can be found or if the data found is outdated.
1892 */
1893struct lru64 *
1894dns_cache_lookup(int query_type, char *hostname_dn, int hostname_dn_len, int valid_period, void *cache_domain) {
1895 struct lru64 *elem = NULL;
1896 struct dns_resolution *resolution = NULL;
1897 struct dns_resolvers *resolvers = NULL;
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001898 struct dns_requester *requester = NULL;
Baptiste Assmannfa4a6632017-05-04 09:05:00 +02001899 int inter = 0;
1900 struct chunk *buf = get_trash_chunk();
1901 struct chunk *tmp = NULL;
1902
1903 if (!dns_lru_tree)
1904 return NULL;
1905
1906 chunk_reset(buf);
1907 tmp = dns_cache_key(query_type, hostname_dn, hostname_dn_len, buf);
1908 if (tmp == NULL)
1909 return NULL;
1910
1911 elem = lru64_lookup(XXH64(buf->str, buf->len, 1), dns_lru_tree, cache_domain, 1);
1912
1913 if (!elem || !elem->data)
1914 return NULL;
1915
1916 resolution = elem->data;
1917
1918 /* since we can change the fqdn of a server at run time, it may happen that
1919 * we got an innacurate elem.
1920 * This is because resolution->hostname_dn points to (owner)->hostname_dn (which
1921 * may be changed at run time)
1922 */
1923 if ((hostname_dn_len == resolution->hostname_dn_len) &&
1924 (memcmp(hostname_dn, resolution->hostname_dn, hostname_dn_len) != 0)) {
1925 return NULL;
1926 }
1927
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001928 requester = LIST_NEXT(&resolution->requester.wait, struct dns_requester *, list);
1929
1930 switch (obj_type(requester->requester)) {
1931 case OBJ_TYPE_SERVER:
1932 resolvers = objt_server(requester->requester)->resolvers;
1933 break;
1934 case OBJ_TYPE_NONE:
1935 default:
1936 return NULL;
1937 }
Baptiste Assmannfa4a6632017-05-04 09:05:00 +02001938
1939 if (!resolvers)
1940 return NULL;
1941
1942 if (resolvers->hold.valid < valid_period)
1943 inter = resolvers->hold.valid;
1944 else
1945 inter = valid_period;
1946
1947 if (!tick_is_expired(tick_add(resolution->last_resolution, inter), now_ms))
1948 return elem;
1949
1950 return NULL;
1951}
1952
Willy Tarreau777b5602016-12-16 18:06:26 +01001953/* if an arg is found, it sets the resolvers section pointer into cli.p0 */
William Lallemand69e96442016-11-19 00:58:54 +01001954static int cli_parse_stat_resolvers(char **args, struct appctx *appctx, void *private)
1955{
1956 struct dns_resolvers *presolvers;
1957
1958 if (*args[3]) {
William Lallemand69e96442016-11-19 00:58:54 +01001959 list_for_each_entry(presolvers, &dns_resolvers, list) {
1960 if (strcmp(presolvers->id, args[3]) == 0) {
Willy Tarreau777b5602016-12-16 18:06:26 +01001961 appctx->ctx.cli.p0 = presolvers;
William Lallemand69e96442016-11-19 00:58:54 +01001962 break;
1963 }
1964 }
Willy Tarreau777b5602016-12-16 18:06:26 +01001965 if (appctx->ctx.cli.p0 == NULL) {
William Lallemand69e96442016-11-19 00:58:54 +01001966 appctx->ctx.cli.msg = "Can't find that resolvers section\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01001967 appctx->st0 = CLI_ST_PRINT;
William Lallemand69e96442016-11-19 00:58:54 +01001968 return 1;
1969 }
1970 }
Willy Tarreau3067bfa2016-12-05 14:50:15 +01001971 return 0;
William Lallemand69e96442016-11-19 00:58:54 +01001972}
1973
Baptiste Assmann201c07f2017-05-22 15:17:15 +02001974/*
1975 * if <resolution> is provided, then the function skips the memory allocation part.
1976 * It does the linking only.
1977 *
1978 * if <resolution> is NULL, the function links a dns resolution to a requester:
1979 * - it allocates memory for the struct requester used to link
1980 * the resolution to the requester
1981 * - it configures the resolution if this is the first requester to be linked to it
1982 * - it updates the requester with a pointer to the resolution
1983 *
1984 * Return code:
1985 * - 0 if everything happened smoothly
1986 * - -1 if an error occured. Of course, no resolution is linked to the requester
1987 */
1988int dns_link_resolution(void *requester, int requester_type, struct dns_resolution *resolution)
1989{
1990 struct dns_resolution *tmpresolution = NULL;
1991 struct dns_requester *tmprequester = NULL;
1992 struct dns_resolvers *resolvers = NULL;
1993 char *hostname_dn = NULL;
1994 int new_resolution;
1995
1996 if (!resolution) {
1997 tmprequester = calloc(1, sizeof(*tmprequester));
1998 if (!tmprequester)
1999 return -1;
2000
2001 switch (requester_type) {
2002 case OBJ_TYPE_SERVER:
2003 tmprequester->requester = &((struct server *)requester)->obj_type;
2004 hostname_dn = objt_server(tmprequester->requester)->hostname_dn;
2005 resolvers = objt_server(tmprequester->requester)->resolvers;
2006 switch (objt_server(tmprequester->requester)->dns_opts.family_prio) {
2007 case AF_INET:
2008 tmprequester->prefered_query_type = DNS_RTYPE_A;
2009 break;
2010 default:
2011 tmprequester->prefered_query_type = DNS_RTYPE_AAAA;
2012 }
2013
2014 break;
2015 case OBJ_TYPE_NONE:
2016 default:
2017 free(tmprequester);
2018 return -1;
2019 }
2020
2021 /* get a resolution from the resolvers' wait queue or pool */
2022 tmpresolution = dns_resolution_list_get(resolvers, hostname_dn, tmprequester->prefered_query_type);
2023 if (!tmpresolution) {
2024 free(tmprequester);
2025 return -1;
2026 }
2027 }
2028 else {
2029 tmpresolution = resolution;
2030
2031 switch (requester_type) {
2032 case OBJ_TYPE_SERVER:
2033 tmprequester = ((struct server *)requester)->dns_requester;
2034 resolvers = ((struct server *)requester)->resolvers;
2035 break;
2036 case OBJ_TYPE_NONE:
2037 default:
2038 return -1;
2039 }
2040 }
2041
2042 /* flag this resolution as NEW if applicable (not already linked to any requester).
2043 * this is required to decide which parameters we have to update on the resolution.
2044 * If new, it means we pulled up the resolution from the resolvers' pool.
2045 */
2046 if (LIST_ISEMPTY(&tmpresolution->requester.wait)) {
2047 new_resolution = 1;
2048 }
2049 else
2050 new_resolution = 0;
2051
2052 /* those parameters are related to the requester type */
2053 switch (obj_type(tmprequester->requester)) {
2054 case OBJ_TYPE_SERVER:
2055 /* some parameters should be set only if the resolution is brand new */
2056 if (new_resolution) {
2057 tmpresolution->query_type = tmprequester->prefered_query_type;
2058 tmpresolution->hostname_dn = objt_server(tmprequester->requester)->hostname_dn;
2059 tmpresolution->hostname_dn_len = objt_server(tmprequester->requester)->hostname_dn_len;
2060 }
2061
2062 /* update requester as well, only if we just allocated it */
2063 objt_server(tmprequester->requester)->resolution = tmpresolution;
2064 if (!resolution) {
2065 tmprequester->requester_cb = snr_resolution_cb;
2066 tmprequester->requester_error_cb = snr_resolution_error_cb;
2067 objt_server(tmprequester->requester)->dns_requester = tmprequester;
2068 }
2069 break;
2070 case OBJ_TYPE_NONE:
2071 default:
2072 free(tmprequester);
2073 return -1;
2074 }
2075
2076 /* update some parameters only if this is a brand new resolution */
2077 if (new_resolution) {
2078 /* move the resolution to the requesters' wait queue */
2079 LIST_DEL(&tmpresolution->list);
2080 LIST_ADDQ(&resolvers->resolution.wait, &tmpresolution->list);
2081
2082 tmpresolution->status = RSLV_STATUS_NONE;
2083 tmpresolution->step = RSLV_STEP_NONE;
2084 tmpresolution->revision = 1;
2085 }
2086
2087 /* add the requester to the resolution's wait queue */
2088 if (resolution)
2089 LIST_DEL(&tmprequester->list);
2090 LIST_ADDQ(&tmpresolution->requester.wait, &tmprequester->list);
2091
2092 return 0;
2093}
2094
2095/*
2096 * pick up an available resolution from the different resolution list associated to a resolvers section,
2097 * in this order:
2098 * 1. check in resolution.curr for the same hostname and query_type
2099 * 2. check in resolution.wait for the same hostname and query_type
2100 * 3. take an available resolution from resolution.pool
2101 *
2102 * return an available resolution, NULL if none found.
2103 */
2104struct dns_resolution *dns_resolution_list_get(struct dns_resolvers *resolvers, char *hostname_dn, int query_type)
2105{
2106 struct dns_resolution *resolution, *tmpresolution;
2107 struct dns_requester *requester;
2108
2109 /* search for same hostname and query type in resolution.curr */
2110 list_for_each_entry_safe(resolution, tmpresolution, &resolvers->resolution.curr, list) {
2111 requester = NULL;
2112
2113 if (!LIST_ISEMPTY(&resolution->requester.wait))
2114 requester = LIST_NEXT(&resolution->requester.wait, struct dns_requester *, list);
2115 else if (!LIST_ISEMPTY(&resolution->requester.curr))
2116 requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list);
2117
2118 if (!requester)
2119 continue;
2120
2121 if ((query_type == requester->prefered_query_type) &&
2122 (strcmp(hostname_dn, resolution->hostname_dn) == 0)) {
2123 return resolution;
2124 }
2125 }
2126
2127 /* search for same hostname and query type in resolution.wait */
2128 list_for_each_entry_safe(resolution, tmpresolution, &resolvers->resolution.wait, list) {
2129 requester = NULL;
2130
2131 if (!LIST_ISEMPTY(&resolution->requester.wait))
2132 requester = LIST_NEXT(&resolution->requester.wait, struct dns_requester *, list);
2133 else if (!LIST_ISEMPTY(&resolution->requester.curr))
2134 requester = LIST_NEXT(&resolution->requester.curr, struct dns_requester *, list);
2135
2136 if (!requester)
2137 continue;
2138
2139 if ((query_type == requester->prefered_query_type) &&
2140 (strcmp(hostname_dn, resolution->hostname_dn) == 0)) {
2141 return resolution;
2142 }
2143 }
2144
2145 /* take the first one (hopefully) from the pool */
2146 list_for_each_entry_safe(resolution, tmpresolution, &resolvers->resolution.pool, list) {
2147 if (LIST_ISEMPTY(&resolution->requester.wait)) {
2148 return resolution;
2149 }
2150 }
2151
2152 return NULL;
2153}
2154
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002155/* This function allocates memory for a DNS resolution structure.
2156 * It's up to the caller to set the parameters
2157 * Returns a pointer to the structure resolution or NULL if memory could
2158 * not be allocated.
2159 */
2160struct dns_resolution *dns_alloc_resolution(void)
2161{
2162 struct dns_resolution *resolution = NULL;
Baptiste Assmann729c9012017-05-22 15:13:10 +02002163 char *buffer = NULL;
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002164
2165 resolution = calloc(1, sizeof(*resolution));
Baptiste Assmann729c9012017-05-22 15:13:10 +02002166 buffer = calloc(1, global.tune.bufsize);
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002167
Baptiste Assmann729c9012017-05-22 15:13:10 +02002168 if (!resolution || !buffer) {
2169 free(buffer);
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002170 free(resolution);
2171 return NULL;
2172 }
2173
Baptiste Assmann729c9012017-05-22 15:13:10 +02002174 chunk_init(&resolution->response_buffer, buffer, global.tune.bufsize);
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002175 LIST_INIT(&resolution->requester.wait);
2176 LIST_INIT(&resolution->requester.curr);
Baptiste Assmann729c9012017-05-22 15:13:10 +02002177
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002178 return resolution;
2179}
2180
2181/* This function free the memory allocated to a DNS resolution */
2182void dns_free_resolution(struct dns_resolution *resolution)
2183{
Baptiste Assmann729c9012017-05-22 15:13:10 +02002184 chunk_destroy(&resolution->response_buffer);
Baptiste Assmann81ed1a02017-05-03 10:11:44 +02002185 free(resolution);
2186
2187 return;
2188}
2189
Baptiste Assmann201c07f2017-05-22 15:17:15 +02002190/* this function free a resolution from its requester(s) and move it back to the pool */
2191void dns_resolution_free(struct dns_resolvers *resolvers, struct dns_resolution *resolution)
2192{
2193 struct dns_requester *requester, *tmprequester;
2194
2195 /* clean up configuration */
2196 dns_reset_resolution(resolution);
2197 resolution->hostname_dn = NULL;
2198 resolution->hostname_dn_len = 0;
2199
2200 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.wait, list) {
2201 LIST_DEL(&requester->list);
2202 }
2203 list_for_each_entry_safe(requester, tmprequester, &resolution->requester.curr, list) {
2204 LIST_DEL(&requester->list);
2205 }
2206
2207 LIST_DEL(&resolution->list);
2208 LIST_ADDQ(&resolvers->resolution.pool, &resolution->list);
2209
2210 return;
2211}
2212
2213/*
2214 * this function remove a requester from a resolution
2215 * and takes care of all the consequences.
2216 * It also cleans up some parameters from the requester
2217 */
2218void dns_rm_requester_from_resolution(struct dns_requester *requester, struct dns_resolution *resolution)
2219{
2220 char *hostname_dn;
2221 struct dns_requester *tmprequester;
2222
2223 /* resolution is still used by other requesters, we need to move
2224 * some pointers to an other requester if needed
2225 */
2226 switch (obj_type(requester->requester)) {
2227 case OBJ_TYPE_SERVER:
2228 hostname_dn = objt_server(requester->requester)->hostname_dn;
2229 break;
2230 case OBJ_TYPE_NONE:
2231 default:
2232 hostname_dn = NULL;
2233 break;
2234 }
2235
2236 if (resolution->hostname_dn != hostname_dn)
2237 return;
2238
2239 /* First, we need to find this other requester */
2240 tmprequester = NULL;
2241 list_for_each_entry(tmprequester, &resolution->requester.wait, list) {
2242 if (tmprequester != requester)
2243 break;
2244 }
2245 if (!tmprequester) {
2246 /* if we can't find it in wait queue, let's get one in run queue */
2247 list_for_each_entry(tmprequester, &resolution->requester.curr, list) {
2248 if (tmprequester != requester)
2249 break;
2250 }
2251 }
2252
2253 /* move hostname_dn related pointers to the next requester */
2254 switch (obj_type(tmprequester->requester)) {
2255 case OBJ_TYPE_SERVER:
2256 resolution->hostname_dn = objt_server(tmprequester->requester)->hostname_dn;
2257 resolution->hostname_dn_len = objt_server(tmprequester->requester)->hostname_dn_len;
2258 break;
2259 case OBJ_TYPE_NONE:
2260 default:
2261 ;;
2262 }
2263
2264
2265 /* clean up the requester */
2266 LIST_DEL(&requester->list);
2267 switch (obj_type(requester->requester)) {
2268 case OBJ_TYPE_SERVER:
2269 objt_server(requester->requester)->resolution = NULL;
2270 break;
2271 case OBJ_TYPE_NONE:
2272 default:
2273 ;;
2274 }
2275}
2276
Willy Tarreau777b5602016-12-16 18:06:26 +01002277/* This function dumps counters from all resolvers section and associated name
2278 * servers. It returns 0 if the output buffer is full and it needs to be called
2279 * again, otherwise non-zero. It may limit itself to the resolver pointed to by
2280 * <cli.p0> if it's not null.
William Lallemand69e96442016-11-19 00:58:54 +01002281 */
2282static int cli_io_handler_dump_resolvers_to_buffer(struct appctx *appctx)
2283{
2284 struct stream_interface *si = appctx->owner;
2285 struct dns_resolvers *presolvers;
2286 struct dns_nameserver *pnameserver;
2287
2288 chunk_reset(&trash);
2289
2290 switch (appctx->st2) {
2291 case STAT_ST_INIT:
2292 appctx->st2 = STAT_ST_LIST; /* let's start producing data */
2293 /* fall through */
2294
2295 case STAT_ST_LIST:
2296 if (LIST_ISEMPTY(&dns_resolvers)) {
2297 chunk_appendf(&trash, "No resolvers found\n");
2298 }
2299 else {
2300 list_for_each_entry(presolvers, &dns_resolvers, list) {
Willy Tarreau777b5602016-12-16 18:06:26 +01002301 if (appctx->ctx.cli.p0 != NULL && appctx->ctx.cli.p0 != presolvers)
William Lallemand69e96442016-11-19 00:58:54 +01002302 continue;
2303
2304 chunk_appendf(&trash, "Resolvers section %s\n", presolvers->id);
2305 list_for_each_entry(pnameserver, &presolvers->nameserver_list, list) {
2306 chunk_appendf(&trash, " nameserver %s:\n", pnameserver->id);
2307 chunk_appendf(&trash, " sent: %ld\n", pnameserver->counters.sent);
2308 chunk_appendf(&trash, " valid: %ld\n", pnameserver->counters.valid);
2309 chunk_appendf(&trash, " update: %ld\n", pnameserver->counters.update);
2310 chunk_appendf(&trash, " cname: %ld\n", pnameserver->counters.cname);
2311 chunk_appendf(&trash, " cname_error: %ld\n", pnameserver->counters.cname_error);
2312 chunk_appendf(&trash, " any_err: %ld\n", pnameserver->counters.any_err);
2313 chunk_appendf(&trash, " nx: %ld\n", pnameserver->counters.nx);
2314 chunk_appendf(&trash, " timeout: %ld\n", pnameserver->counters.timeout);
2315 chunk_appendf(&trash, " refused: %ld\n", pnameserver->counters.refused);
2316 chunk_appendf(&trash, " other: %ld\n", pnameserver->counters.other);
2317 chunk_appendf(&trash, " invalid: %ld\n", pnameserver->counters.invalid);
2318 chunk_appendf(&trash, " too_big: %ld\n", pnameserver->counters.too_big);
2319 chunk_appendf(&trash, " truncated: %ld\n", pnameserver->counters.truncated);
2320 chunk_appendf(&trash, " outdated: %ld\n", pnameserver->counters.outdated);
2321 }
2322 }
2323 }
2324
2325 /* display response */
2326 if (bi_putchk(si_ic(si), &trash) == -1) {
2327 /* let's try again later from this session. We add ourselves into
2328 * this session's users so that it can remove us upon termination.
2329 */
2330 si->flags |= SI_FL_WAIT_ROOM;
2331 return 0;
2332 }
2333
2334 appctx->st2 = STAT_ST_FIN;
2335 /* fall through */
2336
2337 default:
2338 appctx->st2 = STAT_ST_FIN;
2339 return 1;
2340 }
2341}
2342
2343/* register cli keywords */
2344static struct cli_kw_list cli_kws = {{ },{
2345 { { "show", "stat", "resolvers", NULL }, "show stat resolvers [id]: dumps counters from all resolvers section and\n"
2346 " associated name servers",
2347 cli_parse_stat_resolvers, cli_io_handler_dump_resolvers_to_buffer },
2348 {{},}
2349}};
2350
2351
2352__attribute__((constructor))
2353static void __dns_init(void)
2354{
2355 cli_register_kw(&cli_kws);
2356}
2357