1 /*
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/cfgparse.h>
23 #include <common/errors.h>
24 #include <common/initcall.h>
25 #include <common/time.h>
26 #include <common/ticks.h>
27 #include <common/net_helper.h>
28 
29 #include <types/applet.h>
30 #include <types/cli.h>
31 #include <types/global.h>
32 #include <types/dns.h>
33 #include <types/stats.h>
34 
35 #include <proto/channel.h>
36 #include <proto/cli.h>
37 #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>
44 #include <proto/proxy.h>
45 #include <proto/stream_interface.h>
46 
47 struct list dns_resolvers  = LIST_HEAD_INIT(dns_resolvers);
48 struct list dns_srvrq_list = LIST_HEAD_INIT(dns_srvrq_list);
49 
50 static THREAD_LOCAL uint64_t dns_query_id_seed = 0; /* random seed */
51 
52 DECLARE_STATIC_POOL(dns_answer_item_pool, "dns_answer_item", sizeof(struct dns_answer_item));
53 DECLARE_STATIC_POOL(dns_resolution_pool,  "dns_resolution",  sizeof(struct dns_resolution));
54 
55 static unsigned int resolution_uuid = 1;
56 
57 /* Returns a pointer to the resolvers matching the id <id>. NULL is returned if
58  * no match is found.
59  */
find_resolvers_by_id(const char * id)60 struct dns_resolvers *find_resolvers_by_id(const char *id)
61 {
62 	struct dns_resolvers *res;
63 
64 	list_for_each_entry(res, &dns_resolvers, list) {
65 		if (!strcmp(res->id, id))
66 			return res;
67 	}
68 	return NULL;
69 }
70 
71 /* Returns a pointer on the SRV request matching the name <name> for the proxy
72  * <px>. NULL is returned if no match is found.
73  */
find_srvrq_by_name(const char * name,struct proxy * px)74 struct dns_srvrq *find_srvrq_by_name(const char *name, struct proxy *px)
75 {
76 	struct dns_srvrq *srvrq;
77 
78 	list_for_each_entry(srvrq, &dns_srvrq_list, list) {
79 		if (srvrq->proxy == px && !strcmp(srvrq->name, name))
80 			return srvrq;
81 	}
82 	return NULL;
83 }
84 
85 /* Allocates a new SRVRQ for the given server with the name <fqdn>. It returns
86  * NULL if an error occurred. */
new_dns_srvrq(struct server * srv,char * fqdn)87 struct dns_srvrq *new_dns_srvrq(struct server *srv, char *fqdn)
88 {
89 	struct proxy     *px    = srv->proxy;
90 	struct dns_srvrq *srvrq = NULL;
91 	int fqdn_len, hostname_dn_len;
92 
93 	fqdn_len = strlen(fqdn);
94 	hostname_dn_len = dns_str_to_dn_label(fqdn, fqdn_len + 1, trash.area,
95 					      trash.size);
96 	if (hostname_dn_len == -1) {
97 		ha_alert("config : %s '%s', server '%s': failed to parse FQDN '%s'\n",
98 			 proxy_type_str(px), px->id, srv->id, fqdn);
99 		goto err;
100 	}
101 
102 	if ((srvrq = calloc(1, sizeof(*srvrq))) == NULL) {
103 		ha_alert("config : %s '%s', server '%s': out of memory\n",
104 			 proxy_type_str(px), px->id, srv->id);
105 		goto err;
106 	}
107 	srvrq->obj_type        = OBJ_TYPE_SRVRQ;
108 	srvrq->proxy           = px;
109 	srvrq->name            = strdup(fqdn);
110 	srvrq->hostname_dn     = strdup(trash.area);
111 	srvrq->hostname_dn_len = hostname_dn_len;
112 	if (!srvrq->name || !srvrq->hostname_dn) {
113 		ha_alert("config : %s '%s', server '%s': out of memory\n",
114 			 proxy_type_str(px), px->id, srv->id);
115 		goto err;
116 	}
117 	LIST_ADDQ(&dns_srvrq_list, &srvrq->list);
118 	return srvrq;
119 
120   err:
121 	if (srvrq) {
122 		free(srvrq->name);
123 		free(srvrq->hostname_dn);
124 		free(srvrq);
125 	}
126 	return NULL;
127 }
128 
129 
130 /* 2 bytes random generator to generate DNS query ID */
dns_rnd16(void)131 static inline uint16_t dns_rnd16(void)
132 {
133 	if (!dns_query_id_seed)
134 		dns_query_id_seed = now_ms;
135 	dns_query_id_seed ^= dns_query_id_seed << 13;
136 	dns_query_id_seed ^= dns_query_id_seed >> 7;
137 	dns_query_id_seed ^= dns_query_id_seed << 17;
138 	return dns_query_id_seed;
139 }
140 
141 
dns_resolution_timeout(struct dns_resolution * res)142 static inline int dns_resolution_timeout(struct dns_resolution *res)
143 {
144 	return res->resolvers->timeout.resolve;
145 }
146 
147 /* Updates a resolvers' task timeout for next wake up and queue it */
dns_update_resolvers_timeout(struct dns_resolvers * resolvers)148 static void dns_update_resolvers_timeout(struct dns_resolvers *resolvers)
149 {
150 	struct dns_resolution *res;
151 	int next;
152 
153 	next = tick_add(now_ms, resolvers->timeout.resolve);
154 	if (!LIST_ISEMPTY(&resolvers->resolutions.curr)) {
155 		res  = LIST_NEXT(&resolvers->resolutions.curr, struct dns_resolution *, list);
156 		next = MIN(next, tick_add(res->last_query, resolvers->timeout.retry));
157 	}
158 
159 	list_for_each_entry(res, &resolvers->resolutions.wait, list)
160 		next = MIN(next, tick_add(res->last_resolution, dns_resolution_timeout(res)));
161 
162 	resolvers->t->expire = next;
163 	task_queue(resolvers->t);
164 }
165 
166 /* Opens an UDP socket on the namesaver's IP/Port, if required. Returns 0 on
167  * success, -1 otherwise.
168  */
dns_connect_namesaver(struct dns_nameserver * ns)169 static int dns_connect_namesaver(struct dns_nameserver *ns)
170 {
171 	struct dgram_conn *dgram = ns->dgram;
172 	int fd;
173 
174 	/* Already connected */
175 	if (dgram->t.sock.fd != -1)
176 		return 0;
177 
178 	/* Create an UDP socket and connect it on the nameserver's IP/Port */
179 	if ((fd = socket(ns->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
180 		send_log(NULL, LOG_WARNING,
181 			 "DNS : resolvers '%s': can't create socket for nameserver '%s'.\n",
182 			 ns->resolvers->id, ns->id);
183 		return -1;
184 	}
185 	if (connect(fd, (struct sockaddr*)&ns->addr, get_addr_len(&ns->addr)) == -1) {
186 		send_log(NULL, LOG_WARNING,
187 			 "DNS : resolvers '%s': can't connect socket for nameserver '%s'.\n",
188 			 ns->resolvers->id, ns->id);
189 		close(fd);
190 		return -1;
191 	}
192 
193 	/* Make the socket non blocking */
194 	fcntl(fd, F_SETFL, O_NONBLOCK);
195 
196 	/* Add the fd in the fd list and update its parameters */
197 	dgram->t.sock.fd = fd;
198 	fd_insert(fd, dgram, dgram_fd_handler, MAX_THREADS_MASK);
199 	fd_want_recv(fd);
200 	return 0;
201 }
202 
203 /* Forges a DNS query. It needs the following information from the caller:
204  *  - <query_id>        : the DNS query id corresponding to this query
205  *  - <query_type>      : DNS_RTYPE_* request DNS record type (A, AAAA, ANY...)
206  *  - <hostname_dn>     : hostname in domain name format
207  *  - <hostname_dn_len> : length of <hostname_dn>
208  *
209  * To store the query, the caller must pass a buffer <buf> and its size
210  * <bufsize>. It returns the number of written bytes in success, -1 if <buf> is
211  * too short.
212  */
dns_build_query(int query_id,int query_type,unsigned int accepted_payload_size,char * hostname_dn,int hostname_dn_len,char * buf,int bufsize)213 static int dns_build_query(int query_id, int query_type, unsigned int accepted_payload_size,
214 			   char *hostname_dn, int hostname_dn_len, char *buf, int bufsize)
215 {
216 	struct dns_header            dns_hdr;
217 	struct dns_question          qinfo;
218 	struct dns_additional_record edns;
219 	char *p = buf;
220 
221 	if (sizeof(dns_hdr) + sizeof(qinfo) +  sizeof(edns) + hostname_dn_len >= bufsize)
222 		return -1;
223 
224 	memset(buf, 0, bufsize);
225 
226 	/* Set dns query headers */
227 	dns_hdr.id      = (unsigned short) htons(query_id);
228 	dns_hdr.flags   = htons(0x0100); /* qr=0, opcode=0, aa=0, tc=0, rd=1, ra=0, z=0, rcode=0 */
229 	dns_hdr.qdcount = htons(1);      /* 1 question */
230 	dns_hdr.ancount = 0;
231 	dns_hdr.nscount = 0;
232 	dns_hdr.arcount = htons(1);
233 	memcpy(p, &dns_hdr, sizeof(dns_hdr));
234 	p += sizeof(dns_hdr);
235 
236 	/* Set up query hostname */
237 	memcpy(p, hostname_dn, hostname_dn_len);
238 	p += hostname_dn_len;
239 	*p++ = 0;
240 
241 	/* Set up query info (type and class) */
242 	qinfo.qtype  = htons(query_type);
243 	qinfo.qclass = htons(DNS_RCLASS_IN);
244 	memcpy(p, &qinfo, sizeof(qinfo));
245 	p += sizeof(qinfo);
246 
247 	/* Set the DNS extension */
248 	edns.name             = 0;
249 	edns.type             = htons(DNS_RTYPE_OPT);
250 	edns.udp_payload_size = htons(accepted_payload_size);
251 	edns.extension        = 0;
252 	edns.data_length      = 0;
253 	memcpy(p, &edns, sizeof(edns));
254 	p += sizeof(edns);
255 
256 	return (p - buf);
257 }
258 
259 /* Sends a DNS query to resolvers associated to a resolution. It returns 0 on
260  * success, -1 otherwise.
261  */
dns_send_query(struct dns_resolution * resolution)262 static int dns_send_query(struct dns_resolution *resolution)
263 {
264 	struct dns_resolvers  *resolvers = resolution->resolvers;
265 	struct dns_nameserver *ns;
266 
267 	list_for_each_entry(ns, &resolvers->nameservers, list) {
268 		int fd = ns->dgram->t.sock.fd;
269 		if (fd == -1) {
270 			if (dns_connect_namesaver(ns) == -1)
271 				continue;
272 			fd = ns->dgram->t.sock.fd;
273 			resolvers->nb_nameservers++;
274 		}
275 		fd_want_send(fd);
276 	}
277 
278 	/* Update resolution */
279 	resolution->nb_queries   = 0;
280 	resolution->nb_responses = 0;
281 	resolution->last_query   = now_ms;
282 
283 	/* Push the resolution at the end of the active list */
284 	LIST_DEL(&resolution->list);
285 	LIST_ADDQ(&resolvers->resolutions.curr, &resolution->list);
286 	return 0;
287 }
288 
289 /* Prepares and sends a DNS resolution. It returns 1 if the query was sent, 0 if
290  * skipped and -1 if an error occurred.
291  */
292 static int
dns_run_resolution(struct dns_resolution * resolution)293 dns_run_resolution(struct dns_resolution *resolution)
294 {
295 	struct dns_resolvers  *resolvers = resolution->resolvers;
296 	int query_id, i;
297 
298 	/* Avoid sending requests for resolutions that don't yet have an
299 	 * hostname, ie resolutions linked to servers that do not yet have an
300 	 * fqdn */
301 	if (!resolution->hostname_dn)
302 		return 0;
303 
304 	/* Check if a resolution has already been started for this server return
305 	 * directly to avoid resolution pill up. */
306 	if (resolution->step != RSLV_STEP_NONE)
307 		return 0;
308 
309 	/* Generates a new query id. We try at most 100 times to find a free
310 	 * query id */
311 	for (i = 0; i < 100; ++i) {
312 		query_id = dns_rnd16();
313 		if (!eb32_lookup(&resolvers->query_ids, query_id))
314 			break;
315 		query_id = -1;
316 	}
317 	if (query_id == -1) {
318 		send_log(NULL, LOG_NOTICE,
319 			 "could not generate a query id for %s, in resolvers %s.\n",
320 			 resolution->hostname_dn, resolvers->id);
321 		return -1;
322 	}
323 
324 	/* Update resolution parameters */
325 	resolution->query_id     = query_id;
326 	resolution->qid.key      = query_id;
327 	resolution->step         = RSLV_STEP_RUNNING;
328 	resolution->query_type   = resolution->prefered_query_type;
329 	resolution->try          = resolvers->resolve_retries;
330 	eb32_insert(&resolvers->query_ids, &resolution->qid);
331 
332 	/* Send the DNS query */
333 	resolution->try -= 1;
334 	dns_send_query(resolution);
335 	return 1;
336 }
337 
338 /* Performs a name resolution for the requester <req> */
dns_trigger_resolution(struct dns_requester * req)339 void dns_trigger_resolution(struct dns_requester *req)
340 {
341 	struct dns_resolvers  *resolvers;
342 	struct dns_resolution *res;
343 	int exp;
344 
345 	if (!req || !req->resolution)
346 		return;
347 	res       = req->resolution;
348 	resolvers = res->resolvers;
349 
350 	/* The resolution must not be triggered yet. Use the cached response, if
351 	 * valid */
352 	exp = tick_add(res->last_resolution, resolvers->hold.valid);
353 	if (resolvers->t && (res->status != RSLV_STATUS_VALID ||
354 	    !tick_isset(res->last_resolution) || tick_is_expired(exp, now_ms)))
355 		task_wakeup(resolvers->t, TASK_WOKEN_OTHER);
356 }
357 
358 
359 /* Resets some resolution parameters to initial values and also delete the query
360  * ID from the resolver's tree.
361  */
dns_reset_resolution(struct dns_resolution * resolution)362 static void dns_reset_resolution(struct dns_resolution *resolution)
363 {
364 	/* update resolution status */
365 	resolution->step            = RSLV_STEP_NONE;
366 	resolution->try             = 0;
367 	resolution->last_resolution = now_ms;
368 	resolution->nb_queries      = 0;
369 	resolution->nb_responses    = 0;
370 	resolution->query_type      = resolution->prefered_query_type;
371 
372 	/* clean up query id */
373 	eb32_delete(&resolution->qid);
374 	resolution->query_id = 0;
375 	resolution->qid.key   = 0;
376 }
377 
378 /* Returns the query id contained in a DNS response */
dns_response_get_query_id(unsigned char * resp)379 static inline unsigned short dns_response_get_query_id(unsigned char *resp)
380 {
381 	return resp[0] * 256 + resp[1];
382 }
383 
384 
385 /* Analyses, re-builds and copies the name <name> from the DNS response packet
386  * <buffer>.  <name> must point to the 'data_len' information or pointer 'c0'
387  * for compressed data.  The result is copied into <dest>, ensuring we don't
388  * overflow using <dest_len> Returns the number of bytes the caller can move
389  * forward. If 0 it means an error occurred while parsing the name. <offset> is
390  * the number of bytes the caller could move forward.
391  */
dns_read_name(unsigned char * buffer,unsigned char * bufend,unsigned char * name,char * destination,int dest_len,int * offset,unsigned int depth)392 int dns_read_name(unsigned char *buffer, unsigned char *bufend,
393 		  unsigned char *name, char *destination, int dest_len,
394 		  int *offset, unsigned int depth)
395 {
396 	int nb_bytes = 0, n = 0;
397 	int label_len;
398 	unsigned char *reader = name;
399 	char *dest = destination;
400 
401 	while (1) {
402 		if (reader >= bufend)
403 			goto err;
404 
405 		/* Name compression is in use */
406 		if ((*reader & 0xc0) == 0xc0) {
407 			if (reader + 1 >= bufend)
408 				goto err;
409 
410 			/* Must point BEFORE current position */
411 			if ((buffer + reader[1]) > reader)
412 				goto err;
413 
414 			if (depth++ > 100)
415 				goto err;
416 
417 			n = dns_read_name(buffer, bufend, buffer + (*reader & 0x3f)*256 + reader[1],
418 					  dest, dest_len - nb_bytes, offset, depth);
419 			if (n == 0)
420 				goto err;
421 
422 			dest     += n;
423 			nb_bytes += n;
424 			goto out;
425 		}
426 
427 		label_len = *reader;
428 		if (label_len == 0)
429 			goto out;
430 
431 		/* Check if:
432 		 *  - we won't read outside the buffer
433 		 *  - there is enough place in the destination
434 		 */
435 		if ((reader + label_len >= bufend) || (nb_bytes + label_len >= dest_len))
436 			goto err;
437 
438 		/* +1 to take label len + label string */
439 		label_len++;
440 
441 		memcpy(dest, reader, label_len);
442 
443 		dest     += label_len;
444 		nb_bytes += label_len;
445 		reader   += label_len;
446 	}
447 
448   out:
449 	/* offset computation:
450 	 * parse from <name> until finding either NULL or a pointer "c0xx"
451 	 */
452 	reader  = name;
453 	*offset = 0;
454 	while (reader < bufend) {
455 		if ((reader[0] & 0xc0) == 0xc0) {
456 			*offset += 2;
457 			break;
458 		}
459 		else if (*reader == 0) {
460 			*offset += 1;
461 			break;
462 		}
463 		*offset += 1;
464 		++reader;
465 	}
466 	return nb_bytes;
467 
468   err:
469 	return 0;
470 }
471 
472 /* Checks for any obsolete record, also identify any SRV request, and try to
473  * find a corresponding server.
474 */
dns_check_dns_response(struct dns_resolution * res)475 static void dns_check_dns_response(struct dns_resolution *res)
476 {
477 	struct dns_resolvers   *resolvers = res->resolvers;
478 	struct dns_requester   *req, *reqback;
479 	struct dns_answer_item *item, *itemback;
480 	struct server          *srv;
481 	struct dns_srvrq       *srvrq;
482 
483 	list_for_each_entry_safe(item, itemback, &res->response.answer_list, list) {
484 
485 		/* Remove obsolete items */
486 		if ((item->last_seen + resolvers->hold.obsolete / 1000) < now.tv_sec) {
487 			if (item->type != DNS_RTYPE_SRV)
488 				goto rm_obselete_item;
489 
490 			list_for_each_entry_safe(req, reqback, &res->requesters, list) {
491 				if ((srvrq = objt_dns_srvrq(req->owner)) == NULL)
492 					continue;
493 
494 				/* Remove any associated server */
495 				for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
496 					HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
497 					if (srv->srvrq == srvrq && srv->svc_port == item->port &&
498 					    item->data_len == srv->hostname_dn_len &&
499 					    !memcmp(srv->hostname_dn, item->target, item->data_len)) {
500 						snr_update_srv_status(srv, 1);
501 						free(srv->hostname);
502 						free(srv->hostname_dn);
503 						srv->hostname        = NULL;
504 						srv->hostname_dn     = NULL;
505 						srv->hostname_dn_len = 0;
506 						dns_unlink_resolution(srv->dns_requester);
507 					}
508 					HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
509 				}
510 			}
511 
512 		  rm_obselete_item:
513 			LIST_DEL(&item->list);
514 			pool_free(dns_answer_item_pool, item);
515 			continue;
516 		}
517 
518 		if (item->type != DNS_RTYPE_SRV)
519 			continue;
520 
521 		/* Now process SRV records */
522 		list_for_each_entry_safe(req, reqback, &res->requesters, list) {
523 			if ((srvrq = objt_dns_srvrq(req->owner)) == NULL)
524 				continue;
525 
526 			/* Check if a server already uses that hostname */
527 			for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
528 				HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
529 				if (srv->srvrq == srvrq && srv->svc_port == item->port &&
530 				    item->data_len == srv->hostname_dn_len &&
531 				    !memcmp(srv->hostname_dn, item->target, item->data_len)) {
532 					int ha_weight;
533 
534 					/* DNS weight range if from 0 to 65535
535 					 * HAProxy weight is from 0 to 256
536 					 * The rule below ensures that weight 0 is well respected
537 					 * while allowing a "mapping" from DNS weight into HAProxy's one.
538 					 */
539 					ha_weight = (item->weight + 255) / 256;
540 					if (srv->uweight != ha_weight) {
541 						char weight[9];
542 
543 						snprintf(weight, sizeof(weight), "%d", ha_weight);
544 						server_parse_weight_change_request(srv, weight);
545 					}
546 					HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
547 					break;
548 				}
549 				HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
550 			}
551 			if (srv)
552 				continue;
553 
554 			/* If not, try to find a server with undefined hostname */
555 			for (srv = srvrq->proxy->srv; srv != NULL; srv = srv->next) {
556 				HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
557 				if (srv->srvrq == srvrq && !srv->hostname_dn)
558 					break;
559 				HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
560 			}
561 			/* And update this server, if found */
562 			if (srv) {
563 				const char *msg = NULL;
564 				char weight[9];
565 				int ha_weight;
566 				char hostname[DNS_MAX_NAME_SIZE];
567 
568 				if (dns_dn_label_to_str(item->target, item->data_len+1,
569 							hostname, DNS_MAX_NAME_SIZE) == -1) {
570 					HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
571 					continue;
572 				}
573 				msg = update_server_fqdn(srv, hostname, "SRV record", 1);
574 				if (msg)
575 					send_log(srv->proxy, LOG_NOTICE, "%s", msg);
576 
577 				srv->svc_port = item->port;
578 				srv->flags   &= ~SRV_F_MAPPORTS;
579 				if ((srv->check.state & CHK_ST_CONFIGURED) &&
580 				    !(srv->flags & SRV_F_CHECKPORT))
581 					srv->check.port = item->port;
582 
583 				/* DNS weight range if from 0 to 65535
584 				 * HAProxy weight is from 0 to 256
585 				 * The rule below ensures that weight 0 is well respected
586 				 * while allowing a "mapping" from DNS weight into HAProxy's one.
587 				 */
588 				ha_weight = (item->weight + 255) / 256;
589 
590 				snprintf(weight, sizeof(weight), "%d", ha_weight);
591 				server_parse_weight_change_request(srv, weight);
592 				HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
593 			}
594 		}
595 	}
596 }
597 
598 /* Validates that the buffer DNS response provided in <resp> and finishing
599  * before <bufend> is valid from a DNS protocol point of view.
600  *
601  * The result is stored in <resolution>' response, buf_response,
602  * response_query_records and response_answer_records members.
603  *
604  * This function returns one of the DNS_RESP_* code to indicate the type of
605  * error found.
606  */
dns_validate_dns_response(unsigned char * resp,unsigned char * bufend,struct dns_resolution * resolution,int max_answer_records)607 static int dns_validate_dns_response(unsigned char *resp, unsigned char *bufend,
608 				     struct dns_resolution *resolution, int max_answer_records)
609 {
610 	unsigned char *reader;
611 	char *previous_dname, tmpname[DNS_MAX_NAME_SIZE];
612 	int len, flags, offset;
613 	int dns_query_record_id;
614 	int nb_saved_records;
615 	struct dns_query_item *dns_query;
616 	struct dns_answer_item *dns_answer_record, *tmp_record;
617 	struct dns_response_packet *dns_p;
618 	int i, found = 0;
619 
620 	reader         = resp;
621 	len            = 0;
622 	previous_dname = NULL;
623 	dns_query      = NULL;
624 
625 	/* Initialization of response buffer and structure */
626 	dns_p = &resolution->response;
627 
628 	/* query id */
629 	if (reader + 2 >= bufend)
630 		return DNS_RESP_INVALID;
631 	dns_p->header.id = reader[0] * 256 + reader[1];
632 	reader += 2;
633 
634 	/* Flags and rcode are stored over 2 bytes
635 	 * First byte contains:
636 	 *  - response flag (1 bit)
637 	 *  - opcode (4 bits)
638 	 *  - authoritative (1 bit)
639 	 *  - truncated (1 bit)
640 	 *  - recursion desired (1 bit)
641 	 */
642 	if (reader + 2 >= bufend)
643 		return DNS_RESP_INVALID;
644 
645 	flags = reader[0] * 256 + reader[1];
646 
647 	if ((flags & DNS_FLAG_REPLYCODE) != DNS_RCODE_NO_ERROR) {
648 		if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_NX_DOMAIN)
649 			return DNS_RESP_NX_DOMAIN;
650 		else if ((flags & DNS_FLAG_REPLYCODE) == DNS_RCODE_REFUSED)
651 			return DNS_RESP_REFUSED;
652 		return DNS_RESP_ERROR;
653 	}
654 
655 	/* Move forward 2 bytes for flags */
656 	reader += 2;
657 
658 	/* 2 bytes for question count */
659 	if (reader + 2 >= bufend)
660 		return DNS_RESP_INVALID;
661 	dns_p->header.qdcount = reader[0] * 256 + reader[1];
662 	/* (for now) we send one query only, so we expect only one in the
663 	 * response too */
664 	if (dns_p->header.qdcount != 1)
665 		return DNS_RESP_QUERY_COUNT_ERROR;
666 	if (dns_p->header.qdcount > DNS_MAX_QUERY_RECORDS)
667 		return DNS_RESP_INVALID;
668 	reader += 2;
669 
670 	/* 2 bytes for answer count */
671 	if (reader + 2 >= bufend)
672 		return DNS_RESP_INVALID;
673 	dns_p->header.ancount = reader[0] * 256 + reader[1];
674 	if (dns_p->header.ancount == 0)
675 		return DNS_RESP_ANCOUNT_ZERO;
676 	/* Check if too many records are announced */
677 	if (dns_p->header.ancount > max_answer_records)
678 		return DNS_RESP_INVALID;
679 	reader += 2;
680 
681 	/* 2 bytes authority count */
682 	if (reader + 2 >= bufend)
683 		return DNS_RESP_INVALID;
684 	dns_p->header.nscount = reader[0] * 256 + reader[1];
685 	reader += 2;
686 
687 	/* 2 bytes additional count */
688 	if (reader + 2 >= bufend)
689 		return DNS_RESP_INVALID;
690 	dns_p->header.arcount = reader[0] * 256 + reader[1];
691 	reader += 2;
692 
693 	/* Parsing dns queries */
694 	LIST_INIT(&dns_p->query_list);
695 	for (dns_query_record_id = 0; dns_query_record_id < dns_p->header.qdcount; dns_query_record_id++) {
696 		/* Use next pre-allocated dns_query_item after ensuring there is
697 		 * still one available.
698 		 * It's then added to our packet query list. */
699 		if (dns_query_record_id > DNS_MAX_QUERY_RECORDS)
700 			return DNS_RESP_INVALID;
701 		dns_query = &resolution->response_query_records[dns_query_record_id];
702 		LIST_ADDQ(&dns_p->query_list, &dns_query->list);
703 
704 		/* Name is a NULL terminated string in our case, since we have
705 		 * one query per response and the first one can't be compressed
706 		 * (using the 0x0c format) */
707 		offset = 0;
708 		len = dns_read_name(resp, bufend, reader, dns_query->name, DNS_MAX_NAME_SIZE, &offset, 0);
709 
710 		if (len == 0)
711 			return DNS_RESP_INVALID;
712 
713 		reader += offset;
714 		previous_dname = dns_query->name;
715 
716 		/* move forward 2 bytes for question type */
717 		if (reader + 2 >= bufend)
718 			return DNS_RESP_INVALID;
719 		dns_query->type = reader[0] * 256 + reader[1];
720 		reader += 2;
721 
722 		/* move forward 2 bytes for question class */
723 		if (reader + 2 >= bufend)
724 			return DNS_RESP_INVALID;
725 		dns_query->class = reader[0] * 256 + reader[1];
726 		reader += 2;
727 	}
728 
729 	/* TRUNCATED flag must be checked after we could read the query type
730 	 * because a TRUNCATED SRV query type response can still be exploited */
731 	if (dns_query->type != DNS_RTYPE_SRV && flags & DNS_FLAG_TRUNCATED)
732 		return DNS_RESP_TRUNCATED;
733 
734 	/* now parsing response records */
735 	nb_saved_records = 0;
736 	for (i = 0; i < dns_p->header.ancount; i++) {
737 		if (reader >= bufend)
738 			return DNS_RESP_INVALID;
739 
740 		dns_answer_record = pool_alloc(dns_answer_item_pool);
741 		if (dns_answer_record == NULL)
742 			return (DNS_RESP_INVALID);
743 
744 		offset = 0;
745 		len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0);
746 
747 		if (len == 0) {
748 			pool_free(dns_answer_item_pool, dns_answer_record);
749 			return DNS_RESP_INVALID;
750 		}
751 
752 		/* Check if the current record dname is valid.  previous_dname
753 		 * points either to queried dname or last CNAME target */
754 		if (dns_query->type != DNS_RTYPE_SRV && memcmp(previous_dname, tmpname, len) != 0) {
755 			pool_free(dns_answer_item_pool, dns_answer_record);
756 			if (i == 0) {
757 				/* First record, means a mismatch issue between
758 				 * queried dname and dname found in the first
759 				 * record */
760 				return DNS_RESP_INVALID;
761 			}
762 			else {
763 				/* If not the first record, this means we have a
764 				 * CNAME resolution error */
765 				return DNS_RESP_CNAME_ERROR;
766 			}
767 
768 		}
769 
770 		memcpy(dns_answer_record->name, tmpname, len);
771 		dns_answer_record->name[len] = 0;
772 
773 		reader += offset;
774 		if (reader >= bufend) {
775 			pool_free(dns_answer_item_pool, dns_answer_record);
776 			return DNS_RESP_INVALID;
777 		}
778 
779 		/* 2 bytes for record type (A, AAAA, CNAME, etc...) */
780 		if (reader + 2 > bufend) {
781 			pool_free(dns_answer_item_pool, dns_answer_record);
782 			return DNS_RESP_INVALID;
783 		}
784 		dns_answer_record->type = reader[0] * 256 + reader[1];
785 		reader += 2;
786 
787 		/* 2 bytes for class (2) */
788 		if (reader + 2 > bufend) {
789 			pool_free(dns_answer_item_pool, dns_answer_record);
790 			return DNS_RESP_INVALID;
791 		}
792 		dns_answer_record->class = reader[0] * 256 + reader[1];
793 		reader += 2;
794 
795 		/* 4 bytes for ttl (4) */
796 		if (reader + 4 > bufend) {
797 			pool_free(dns_answer_item_pool, dns_answer_record);
798 			return DNS_RESP_INVALID;
799 		}
800 		dns_answer_record->ttl =   reader[0] * 16777216 + reader[1] * 65536
801 			                 + reader[2] * 256 + reader[3];
802 		reader += 4;
803 
804 		/* Now reading data len */
805 		if (reader + 2 > bufend) {
806 			pool_free(dns_answer_item_pool, dns_answer_record);
807 			return DNS_RESP_INVALID;
808 		}
809 		dns_answer_record->data_len = reader[0] * 256 + reader[1];
810 
811 		/* Move forward 2 bytes for data len */
812 		reader += 2;
813 
814 		if (reader + dns_answer_record->data_len > bufend) {
815 			pool_free(dns_answer_item_pool, dns_answer_record);
816 			return DNS_RESP_INVALID;
817 		}
818 
819 		/* Analyzing record content */
820 		switch (dns_answer_record->type) {
821 			case DNS_RTYPE_A:
822 				/* ipv4 is stored on 4 bytes */
823 				if (dns_answer_record->data_len != 4) {
824 					pool_free(dns_answer_item_pool, dns_answer_record);
825 					return DNS_RESP_INVALID;
826 				}
827 				dns_answer_record->address.sa_family = AF_INET;
828 				memcpy(&(((struct sockaddr_in *)&dns_answer_record->address)->sin_addr),
829 						reader, dns_answer_record->data_len);
830 				break;
831 
832 			case DNS_RTYPE_CNAME:
833 				/* Check if this is the last record and update the caller about the status:
834 				 * no IP could be found and last record was a CNAME. Could be triggered
835 				 * by a wrong query type
836 				 *
837 				 * + 1 because dns_answer_record_id starts at 0
838 				 * while number of answers is an integer and
839 				 * starts at 1.
840 				 */
841 				if (i + 1 == dns_p->header.ancount) {
842 					pool_free(dns_answer_item_pool, dns_answer_record);
843 					return DNS_RESP_CNAME_ERROR;
844 				}
845 
846 				offset = 0;
847 				len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0);
848 				if (len == 0) {
849 					pool_free(dns_answer_item_pool, dns_answer_record);
850 					return DNS_RESP_INVALID;
851 				}
852 
853 				memcpy(dns_answer_record->target, tmpname, len);
854 				dns_answer_record->target[len] = 0;
855 				previous_dname = dns_answer_record->target;
856 				break;
857 
858 
859 			case DNS_RTYPE_SRV:
860 				/* Answer must contain :
861 				 * - 2 bytes for the priority
862 				 * - 2 bytes for the weight
863 				 * - 2 bytes for the port
864 				 * - the target hostname
865 				 */
866 				if (dns_answer_record->data_len <= 6) {
867 					pool_free(dns_answer_item_pool, dns_answer_record);
868 					return DNS_RESP_INVALID;
869 				}
870 				dns_answer_record->priority = read_n16(reader);
871 				reader += sizeof(uint16_t);
872 				dns_answer_record->weight = read_n16(reader);
873 				reader += sizeof(uint16_t);
874 				dns_answer_record->port = read_n16(reader);
875 				reader += sizeof(uint16_t);
876 				offset = 0;
877 				len = dns_read_name(resp, bufend, reader, tmpname, DNS_MAX_NAME_SIZE, &offset, 0);
878 				if (len == 0) {
879 					pool_free(dns_answer_item_pool, dns_answer_record);
880 					return DNS_RESP_INVALID;
881 				}
882 				dns_answer_record->data_len = len;
883 				memcpy(dns_answer_record->target, tmpname, len);
884 				dns_answer_record->target[len] = 0;
885 				break;
886 
887 			case DNS_RTYPE_AAAA:
888 				/* ipv6 is stored on 16 bytes */
889 				if (dns_answer_record->data_len != 16) {
890 					pool_free(dns_answer_item_pool, dns_answer_record);
891 					return DNS_RESP_INVALID;
892 				}
893 				dns_answer_record->address.sa_family = AF_INET6;
894 				memcpy(&(((struct sockaddr_in6 *)&dns_answer_record->address)->sin6_addr),
895 						reader, dns_answer_record->data_len);
896 				break;
897 
898 		} /* switch (record type) */
899 
900 		/* Increment the counter for number of records saved into our
901 		 * local response */
902 		nb_saved_records++;
903 
904 		/* Move forward dns_answer_record->data_len for analyzing next
905 		 * record in the response */
906 		reader += ((dns_answer_record->type == DNS_RTYPE_SRV)
907 			   ? offset
908 			   : dns_answer_record->data_len);
909 
910 		/* Lookup to see if we already had this entry */
911 		found = 0;
912 		list_for_each_entry(tmp_record, &dns_p->answer_list, list) {
913 			if (tmp_record->type != dns_answer_record->type)
914 				continue;
915 
916 			switch(tmp_record->type) {
917 				case DNS_RTYPE_A:
918 					if (!memcmp(&((struct sockaddr_in *)&dns_answer_record->address)->sin_addr,
919 						    &((struct sockaddr_in *)&tmp_record->address)->sin_addr,
920 						    sizeof(in_addr_t)))
921 						found = 1;
922 					break;
923 
924 				case DNS_RTYPE_AAAA:
925 					if (!memcmp(&((struct sockaddr_in6 *)&dns_answer_record->address)->sin6_addr,
926 						    &((struct sockaddr_in6 *)&tmp_record->address)->sin6_addr,
927 						    sizeof(struct in6_addr)))
928 						found = 1;
929 					break;
930 
931 			case DNS_RTYPE_SRV:
932                                 if (dns_answer_record->data_len == tmp_record->data_len &&
933 				    !memcmp(dns_answer_record->target, tmp_record->target, dns_answer_record->data_len) &&
934 				    dns_answer_record->port == tmp_record->port) {
935 					tmp_record->weight = dns_answer_record->weight;
936                                         found = 1;
937 				}
938                                 break;
939 
940 			default:
941 				break;
942 			}
943 
944 			if (found == 1)
945 				break;
946 		}
947 
948 		if (found == 1) {
949 			tmp_record->last_seen = now.tv_sec;
950 			pool_free(dns_answer_item_pool, dns_answer_record);
951 		}
952 		else {
953 			dns_answer_record->last_seen = now.tv_sec;
954 			LIST_ADDQ(&dns_p->answer_list, &dns_answer_record->list);
955 		}
956 	} /* for i 0 to ancount */
957 
958 	/* Save the number of records we really own */
959 	dns_p->header.ancount = nb_saved_records;
960 	dns_check_dns_response(resolution);
961 	return DNS_RESP_VALID;
962 }
963 
964 /* Searches dn_name resolution in resp.
965  * If existing IP not found, return the first IP matching family_priority,
966  * otherwise, first ip found
967  * The following tasks are the responsibility of the caller:
968  *   - <dns_p> contains an error free DNS response
969  * For both cases above, dns_validate_dns_response is required
970  * returns one of the DNS_UPD_* code
971  */
dns_get_ip_from_response(struct dns_response_packet * dns_p,struct dns_options * dns_opts,void * currentip,short currentip_sin_family,void ** newip,short * newip_sin_family,void * owner)972 int dns_get_ip_from_response(struct dns_response_packet *dns_p,
973                              struct dns_options *dns_opts, void *currentip,
974                              short currentip_sin_family,
975                              void **newip, short *newip_sin_family,
976                              void *owner)
977 {
978 	struct dns_answer_item *record;
979 	int family_priority;
980 	int currentip_found;
981 	unsigned char *newip4, *newip6;
982 	int currentip_sel;
983 	int j;
984 	int score, max_score;
985 	int allowed_duplicated_ip;
986 
987 	family_priority   = dns_opts->family_prio;
988 	allowed_duplicated_ip = dns_opts->accept_duplicate_ip;
989 	*newip = newip4   = newip6 = NULL;
990 	currentip_found   = 0;
991 	*newip_sin_family = AF_UNSPEC;
992 	max_score         = -1;
993 
994 	/* Select an IP regarding configuration preference.
995 	 * Top priority is the preferred network ip version,
996 	 * second priority is the preferred network.
997 	 * the last priority is the currently used IP,
998 	 *
999 	 * For these three priorities, a score is calculated. The
1000 	 * weight are:
1001 	 *  8 - preferred ip version.
1002 	 *  4 - preferred network.
1003 	 *  2 - if the ip in the record is not affected to any other server in the same backend (duplication)
1004 	 *  1 - current ip.
1005 	 * The result with the biggest score is returned.
1006 	 */
1007 
1008 	list_for_each_entry(record, &dns_p->answer_list, list) {
1009 		void *ip;
1010 		unsigned char ip_type;
1011 
1012 		if (record->type == DNS_RTYPE_A) {
1013 			ip = &(((struct sockaddr_in *)&record->address)->sin_addr);
1014 			ip_type = AF_INET;
1015 		}
1016 		else if (record->type == DNS_RTYPE_AAAA) {
1017 			ip_type = AF_INET6;
1018 			ip = &(((struct sockaddr_in6 *)&record->address)->sin6_addr);
1019 		}
1020 		else
1021 			continue;
1022 		score = 0;
1023 
1024 		/* Check for preferred ip protocol. */
1025 		if (ip_type == family_priority)
1026 			score += 8;
1027 
1028 		/* Check for preferred network. */
1029 		for (j = 0; j < dns_opts->pref_net_nb; j++) {
1030 
1031 			/* Compare only the same adresses class. */
1032 			if (dns_opts->pref_net[j].family != ip_type)
1033 				continue;
1034 
1035 			if ((ip_type == AF_INET &&
1036 			     in_net_ipv4(ip,
1037 			                 &dns_opts->pref_net[j].mask.in4,
1038 			                 &dns_opts->pref_net[j].addr.in4)) ||
1039 			    (ip_type == AF_INET6 &&
1040 			     in_net_ipv6(ip,
1041 			                 &dns_opts->pref_net[j].mask.in6,
1042 			                 &dns_opts->pref_net[j].addr.in6))) {
1043 				score += 4;
1044 				break;
1045 			}
1046 		}
1047 
1048 		/* Check if the IP found in the record is already affected to a
1049 		 * member of a group.  If not, the score should be incremented
1050 		 * by 2. */
1051 		if (owner && snr_check_ip_callback(owner, ip, &ip_type)) {
1052 			if (!allowed_duplicated_ip) {
1053 				continue;
1054 			}
1055 		} else {
1056 			score += 2;
1057 		}
1058 
1059 		/* Check for current ip matching. */
1060 		if (ip_type == currentip_sin_family &&
1061 		    ((currentip_sin_family == AF_INET &&
1062 		      !memcmp(ip, currentip, 4)) ||
1063 		     (currentip_sin_family == AF_INET6 &&
1064 		      !memcmp(ip, currentip, 16)))) {
1065 			score++;
1066 			currentip_sel = 1;
1067 		}
1068 		else
1069 			currentip_sel = 0;
1070 
1071 		/* Keep the address if the score is better than the previous
1072 		 * score. The maximum score is 15, if this value is reached, we
1073 		 * break the parsing. Implicitly, this score is reached the ip
1074 		 * selected is the current ip. */
1075 		if (score > max_score) {
1076 			if (ip_type == AF_INET)
1077 				newip4 = ip;
1078 			else
1079 				newip6 = ip;
1080 			currentip_found = currentip_sel;
1081 			if (score == 15)
1082 				return DNS_UPD_NO;
1083 			max_score = score;
1084 		}
1085 	} /* list for each record entries */
1086 
1087 	/* No IP found in the response */
1088 	if (!newip4 && !newip6)
1089 		return DNS_UPD_NO_IP_FOUND;
1090 
1091 	/* Case when the caller looks first for an IPv4 address */
1092 	if (family_priority == AF_INET) {
1093 		if (newip4) {
1094 			*newip = newip4;
1095 			*newip_sin_family = AF_INET;
1096 		}
1097 		else if (newip6) {
1098 			*newip = newip6;
1099 			*newip_sin_family = AF_INET6;
1100 		}
1101 		if (!currentip_found)
1102 			goto not_found;
1103 	}
1104 	/* Case when the caller looks first for an IPv6 address */
1105 	else if (family_priority == AF_INET6) {
1106 		if (newip6) {
1107 			*newip = newip6;
1108 			*newip_sin_family = AF_INET6;
1109 		}
1110 		else if (newip4) {
1111 			*newip = newip4;
1112 			*newip_sin_family = AF_INET;
1113 		}
1114 		if (!currentip_found)
1115 			goto not_found;
1116 	}
1117 	/* Case when the caller have no preference (we prefer IPv6) */
1118 	else if (family_priority == AF_UNSPEC) {
1119 		if (newip6) {
1120 			*newip = newip6;
1121 			*newip_sin_family = AF_INET6;
1122 		}
1123 		else if (newip4) {
1124 			*newip = newip4;
1125 			*newip_sin_family = AF_INET;
1126 		}
1127 		if (!currentip_found)
1128 			goto not_found;
1129 	}
1130 
1131 	/* No reason why we should change the server's IP address */
1132 	return DNS_UPD_NO;
1133 
1134  not_found:
1135 	list_for_each_entry(record, &dns_p->answer_list, list) {
1136 		/* Move the first record to the end of the list, for internal
1137 		 * round robin */
1138 		LIST_DEL(&record->list);
1139 		LIST_ADDQ(&dns_p->answer_list, &record->list);
1140 		break;
1141 	}
1142 	return DNS_UPD_SRVIP_NOT_FOUND;
1143 }
1144 
1145 /* Turns a domain name label into a string.
1146  *
1147  * <dn> must be a null-terminated string. <dn_len> must include the terminating
1148  * null byte. <str> must be allocated and its size must be passed in <str_len>.
1149  *
1150  *  In case of error, -1 is returned, otherwise, the number of bytes copied in
1151  * <str> (including the terminating null byte).
1152  */
dns_dn_label_to_str(const char * dn,int dn_len,char * str,int str_len)1153 int dns_dn_label_to_str(const char *dn, int dn_len, char *str, int str_len)
1154 {
1155 	char *ptr;
1156 	int i, sz;
1157 
1158 	if (str_len < dn_len - 1)
1159 		return -1;
1160 
1161 	ptr = str;
1162 	for (i = 0; i < dn_len-1; ++i) {
1163 		sz = dn[i];
1164 		if (i)
1165 			*ptr++ = '.';
1166 		memcpy(ptr, dn+i+1, sz);
1167 		ptr += sz;
1168 		i   += sz;
1169 	}
1170 	*ptr++ = '\0';
1171 	return (ptr - str);
1172 }
1173 
1174 /* Turns a string into domain name label: www.haproxy.org into 3www7haproxy3org
1175  *
1176  * <str> must be a null-terminated string. <str_len> must include the
1177  * terminating null byte. <dn> buffer must be allocated and its size must be
1178  * passed in <dn_len>.
1179  *
1180  *  In case of error, -1 is returned, otherwise, the number of bytes copied in
1181  * <dn> (excluding the terminating null byte).
1182  */
dns_str_to_dn_label(const char * str,int str_len,char * dn,int dn_len)1183 int dns_str_to_dn_label(const char *str, int str_len, char *dn, int dn_len)
1184 {
1185 	int i, offset;
1186 
1187 	if (dn_len < str_len + 1)
1188 		return -1;
1189 
1190 	/* First byte of dn will be used to store the length of the first
1191 	 * label */
1192 	offset = 0;
1193 	for (i = 0; i < str_len; ++i) {
1194 		if (str[i] == '.') {
1195 			/* 2 or more consecutive dots is invalid */
1196 			if (i == offset)
1197 				return -1;
1198 
1199 			/* ignore trailing dot */
1200 			if (i + 2 == str_len) {
1201 				i++;
1202 				break;
1203 			}
1204 
1205 			dn[offset] = (i - offset);
1206 			offset = i+1;
1207 			continue;
1208 		}
1209 		dn[i+1] = str[i];
1210 	}
1211 	dn[offset] = (i - offset - 1);
1212 	dn[i] = '\0';
1213 	return i;
1214 }
1215 
1216 /* Validates host name:
1217  *  - total size
1218  *  - each label size individually
1219  * returns:
1220  *  0 in case of error. If <err> is not NULL, an error message is stored there.
1221  *  1 when no error. <err> is left unaffected.
1222  */
dns_hostname_validation(const char * string,char ** err)1223 int dns_hostname_validation(const char *string, char **err)
1224 {
1225 	int i;
1226 
1227 	if (strlen(string) > DNS_MAX_NAME_SIZE) {
1228 		if (err)
1229 			*err = DNS_TOO_LONG_FQDN;
1230 		return 0;
1231 	}
1232 
1233 	while (*string) {
1234 		i = 0;
1235 		while (*string && *string != '.' && i < DNS_MAX_LABEL_SIZE) {
1236 			if (!(*string == '-' || *string == '_' ||
1237 			      (*string >= 'a' && *string <= 'z') ||
1238 			      (*string >= 'A' && *string <= 'Z') ||
1239 			      (*string >= '0' && *string <= '9'))) {
1240 				if (err)
1241 					*err = DNS_INVALID_CHARACTER;
1242 				return 0;
1243 			}
1244 			i++;
1245 			string++;
1246 		}
1247 
1248 		if (!(*string))
1249 			break;
1250 
1251 		if (*string != '.' && i >= DNS_MAX_LABEL_SIZE) {
1252 			if (err)
1253 				*err = DNS_LABEL_TOO_LONG;
1254 			return 0;
1255 		}
1256 
1257 		string++;
1258 	}
1259 	return 1;
1260 }
1261 
1262 /* Picks up an available resolution from the different resolution list
1263  * associated to a resolvers section, in this order:
1264  *   1. check in resolutions.curr for the same hostname and query_type
1265  *   2. check in resolutions.wait for the same hostname and query_type
1266  *   3. Get a new resolution from resolution pool
1267  *
1268  * Returns an available resolution, NULL if none found.
1269  */
dns_pick_resolution(struct dns_resolvers * resolvers,char ** hostname_dn,int hostname_dn_len,int query_type)1270 static struct dns_resolution *dns_pick_resolution(struct dns_resolvers *resolvers,
1271 						  char **hostname_dn, int hostname_dn_len,
1272 						  int query_type)
1273 {
1274 	struct dns_resolution *res;
1275 
1276 	if (!*hostname_dn)
1277 		goto from_pool;
1278 
1279 	/* Search for same hostname and query type in resolutions.curr */
1280 	list_for_each_entry(res, &resolvers->resolutions.curr, list) {
1281 		if (!res->hostname_dn)
1282 			continue;
1283 		if ((query_type == res->prefered_query_type) &&
1284 		    hostname_dn_len == res->hostname_dn_len  &&
1285 		    !memcmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
1286 			return res;
1287 	}
1288 
1289 	/* Search for same hostname and query type in resolutions.wait */
1290 	list_for_each_entry(res, &resolvers->resolutions.wait, list) {
1291 		if (!res->hostname_dn)
1292 			continue;
1293 		if ((query_type == res->prefered_query_type) &&
1294 		    hostname_dn_len == res->hostname_dn_len  &&
1295 		    !memcmp(*hostname_dn, res->hostname_dn, hostname_dn_len))
1296 			return res;
1297 	}
1298 
1299   from_pool:
1300 	/* No resolution could be found, so let's allocate a new one */
1301 	res = pool_alloc(dns_resolution_pool);
1302 	if (res) {
1303 		memset(res, 0, sizeof(*res));
1304 		res->resolvers  = resolvers;
1305 		res->uuid       = resolution_uuid;
1306 		res->status     = RSLV_STATUS_NONE;
1307 		res->step       = RSLV_STEP_NONE;
1308 		res->last_valid = now_ms;
1309 
1310 		LIST_INIT(&res->requesters);
1311 		LIST_INIT(&res->response.answer_list);
1312 
1313 		res->prefered_query_type = query_type;
1314 		res->query_type          = query_type;
1315 		res->hostname_dn         = *hostname_dn;
1316 		res->hostname_dn_len     = hostname_dn_len;
1317 
1318 		++resolution_uuid;
1319 
1320 		/* Move the resolution to the resolvers wait queue */
1321 		LIST_ADDQ(&resolvers->resolutions.wait, &res->list);
1322 	}
1323 	return res;
1324 }
1325 
1326 /* Releases a resolution from its requester(s) and move it back to the pool */
dns_free_resolution(struct dns_resolution * resolution)1327 static void dns_free_resolution(struct dns_resolution *resolution)
1328 {
1329 	struct dns_requester *req, *reqback;
1330 	struct dns_answer_item *item, *itemback;
1331 
1332 	/* clean up configuration */
1333 	dns_reset_resolution(resolution);
1334 	resolution->hostname_dn = NULL;
1335 	resolution->hostname_dn_len = 0;
1336 
1337 	list_for_each_entry_safe(req, reqback, &resolution->requesters, list) {
1338 		LIST_DEL(&req->list);
1339 		req->resolution = NULL;
1340 	}
1341 
1342 	list_for_each_entry_safe(item, itemback, &resolution->response.answer_list, list) {
1343 		LIST_DEL(&item->list);
1344 		pool_free(dns_answer_item_pool, item);
1345 	}
1346 
1347 	LIST_DEL(&resolution->list);
1348 	pool_free(dns_resolution_pool, resolution);
1349 }
1350 
1351 /* Links a requester (a server or a dns_srvrq) with a resolution. It returns 0
1352  * on success, -1 otherwise.
1353  */
dns_link_resolution(void * requester,int requester_type,int requester_locked)1354 int dns_link_resolution(void *requester, int requester_type, int requester_locked)
1355 {
1356 	struct dns_resolution *res = NULL;
1357 	struct dns_requester  *req;
1358 	struct dns_resolvers  *resolvers;
1359 	struct server         *srv   = NULL;
1360 	struct dns_srvrq      *srvrq = NULL;
1361 	char **hostname_dn;
1362 	int   hostname_dn_len, query_type;
1363 
1364 	switch (requester_type) {
1365 		case OBJ_TYPE_SERVER:
1366 			srv             = (struct server *)requester;
1367 			hostname_dn     = &srv->hostname_dn;
1368 			hostname_dn_len = srv->hostname_dn_len;
1369 			resolvers       = srv->resolvers;
1370 			query_type      = ((srv->dns_opts.family_prio == AF_INET)
1371 					   ? DNS_RTYPE_A
1372 					   : DNS_RTYPE_AAAA);
1373 			break;
1374 
1375 		case OBJ_TYPE_SRVRQ:
1376 			srvrq           = (struct dns_srvrq *)requester;
1377 			hostname_dn     = &srvrq->hostname_dn;
1378 			hostname_dn_len = srvrq->hostname_dn_len;
1379 			resolvers       = srvrq->resolvers;
1380 			query_type      = DNS_RTYPE_SRV;
1381 			break;
1382 
1383 		default:
1384 			goto err;
1385 	}
1386 
1387 	/* Get a resolution from the resolvers' wait queue or pool */
1388 	if ((res = dns_pick_resolution(resolvers, hostname_dn, hostname_dn_len, query_type)) == NULL)
1389 		goto err;
1390 
1391 	if (srv) {
1392 		if (!requester_locked)
1393 			HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1394 		if (srv->dns_requester == NULL) {
1395 			if ((req = calloc(1, sizeof(*req))) == NULL) {
1396 				if (!requester_locked)
1397 					HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1398 				goto err;
1399 			}
1400 			req->owner         = &srv->obj_type;
1401 			srv->dns_requester = req;
1402 		}
1403 		else
1404 			req = srv->dns_requester;
1405 		if (!requester_locked)
1406 			HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1407 	}
1408 	else if (srvrq) {
1409 		if (srvrq->dns_requester == NULL) {
1410 			if ((req = calloc(1, sizeof(*req))) == NULL)
1411 				goto err;
1412 			req->owner           = &srvrq->obj_type;
1413 			srvrq->dns_requester = req;
1414 		}
1415 		else
1416 			req = srvrq->dns_requester;
1417 	}
1418 	else
1419 		goto err;
1420 
1421 	req->resolution         = res;
1422 	req->requester_cb       = snr_resolution_cb;
1423 	req->requester_error_cb = snr_resolution_error_cb;
1424 
1425 	LIST_ADDQ(&res->requesters, &req->list);
1426 	return 0;
1427 
1428   err:
1429 	if (res && LIST_ISEMPTY(&res->requesters))
1430 		dns_free_resolution(res);
1431 	return -1;
1432 }
1433 
1434 /* Removes a requester from a DNS resoltion. It takes takes care of all the
1435  * consequences. It also cleans up some parameters from the requester.
1436  */
dns_unlink_resolution(struct dns_requester * requester)1437 void dns_unlink_resolution(struct dns_requester *requester)
1438 {
1439 	struct dns_resolution *res;
1440 	struct dns_requester  *req;
1441 
1442 	/* Nothing to do */
1443 	if (!requester || !requester->resolution)
1444 		return;
1445 	res = requester->resolution;
1446 
1447 	/* Clean up the requester */
1448 	LIST_DEL(&requester->list);
1449 	requester->resolution = NULL;
1450 
1451 	/* We need to find another requester linked on this resolution */
1452 	if (!LIST_ISEMPTY(&res->requesters))
1453 		req = LIST_NEXT(&res->requesters, struct dns_requester *, list);
1454 	else {
1455 		dns_free_resolution(res);
1456 		return;
1457 	}
1458 
1459 	/* Move hostname_dn related pointers to the next requester */
1460 	switch (obj_type(req->owner)) {
1461 		case OBJ_TYPE_SERVER:
1462 			res->hostname_dn     = __objt_server(req->owner)->hostname_dn;
1463 			res->hostname_dn_len = __objt_server(req->owner)->hostname_dn_len;
1464 			break;
1465 		case OBJ_TYPE_SRVRQ:
1466 			res->hostname_dn     = __objt_dns_srvrq(req->owner)->hostname_dn;
1467 			res->hostname_dn_len = __objt_dns_srvrq(req->owner)->hostname_dn_len;
1468 			break;
1469 		default:
1470 			res->hostname_dn     = NULL;
1471 			res->hostname_dn_len = 0;
1472 			break;
1473 	}
1474 }
1475 
1476 /* Called when a network IO is generated on a name server socket for an incoming
1477  * packet. It performs the following actions:
1478  *  - check if the packet requires processing (not outdated resolution)
1479  *  - ensure the DNS packet received is valid and call requester's callback
1480  *  - call requester's error callback if invalid response
1481  *  - check the dn_name in the packet against the one sent
1482  */
dns_resolve_recv(struct dgram_conn * dgram)1483 static void dns_resolve_recv(struct dgram_conn *dgram)
1484 {
1485 	struct dns_nameserver *ns, *tmpns;
1486 	struct dns_resolvers  *resolvers;
1487 	struct dns_resolution *res;
1488 	struct dns_query_item *query;
1489 	unsigned char  buf[DNS_MAX_UDP_MESSAGE + 1];
1490 	unsigned char *bufend;
1491 	int fd, buflen, dns_resp;
1492 	int max_answer_records;
1493 	unsigned short query_id;
1494 	struct eb32_node *eb;
1495 	struct dns_requester *req;
1496 
1497 	fd = dgram->t.sock.fd;
1498 
1499 	/* check if ready for reading */
1500 	if (!fd_recv_ready(fd))
1501 		return;
1502 
1503 	/* no need to go further if we can't retrieve the nameserver */
1504 	if ((ns = dgram->owner) == NULL) {
1505 		HA_ATOMIC_AND(&fdtab[fd].ev, ~(FD_POLL_HUP|FD_POLL_ERR));
1506 		fd_stop_recv(fd);
1507 		return;
1508 	}
1509 
1510 	resolvers = ns->resolvers;
1511 	HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
1512 
1513 	/* process all pending input messages */
1514 	while (fd_recv_ready(fd)) {
1515 		/* read message received */
1516 		memset(buf, '\0', resolvers->accepted_payload_size + 1);
1517 		if ((buflen = recv(fd, (char*)buf , resolvers->accepted_payload_size + 1, 0)) < 0) {
1518 			/* FIXME : for now we consider EAGAIN only, but at
1519 			 * least we purge sticky errors that would cause us to
1520 			 * be called in loops.
1521 			 */
1522 			HA_ATOMIC_AND(&fdtab[fd].ev, ~(FD_POLL_HUP|FD_POLL_ERR));
1523 			fd_cant_recv(fd);
1524 			break;
1525 		}
1526 
1527 		/* message too big */
1528 		if (buflen > resolvers->accepted_payload_size) {
1529 			ns->counters.too_big++;
1530 			continue;
1531 		}
1532 
1533 		/* initializing variables */
1534 		bufend = buf + buflen;	/* pointer to mark the end of the buffer */
1535 
1536 		/* read the query id from the packet (16 bits) */
1537 		if (buf + 2 > bufend) {
1538 			ns->counters.invalid++;
1539 			continue;
1540 		}
1541 		query_id = dns_response_get_query_id(buf);
1542 
1543 		/* search the query_id in the pending resolution tree */
1544 		eb = eb32_lookup(&resolvers->query_ids, query_id);
1545 		if (eb == NULL) {
1546 			/* unknown query id means an outdated response and can be safely ignored */
1547 			ns->counters.outdated++;
1548 			continue;
1549 		}
1550 
1551 		/* known query id means a resolution in prgress */
1552 		res = eb32_entry(eb, struct dns_resolution, qid);
1553 		if (!res) {
1554 			ns->counters.outdated++;
1555 			continue;
1556 		}
1557 
1558 		/* number of responses received */
1559 		res->nb_responses++;
1560 
1561 		max_answer_records = (resolvers->accepted_payload_size - DNS_HEADER_SIZE) / DNS_MIN_RECORD_SIZE;
1562 		dns_resp = dns_validate_dns_response(buf, bufend, res, max_answer_records);
1563 
1564 		switch (dns_resp) {
1565 			case DNS_RESP_VALID:
1566 				break;
1567 
1568 			case DNS_RESP_INVALID:
1569 			case DNS_RESP_QUERY_COUNT_ERROR:
1570 			case DNS_RESP_WRONG_NAME:
1571 				res->status = RSLV_STATUS_INVALID;
1572 				ns->counters.invalid++;
1573 				break;
1574 
1575 			case DNS_RESP_NX_DOMAIN:
1576 				res->status = RSLV_STATUS_NX;
1577 				ns->counters.nx++;
1578 				break;
1579 
1580 			case DNS_RESP_REFUSED:
1581 				res->status = RSLV_STATUS_REFUSED;
1582 				ns->counters.refused++;
1583 				break;
1584 
1585 			case DNS_RESP_ANCOUNT_ZERO:
1586 				res->status = RSLV_STATUS_OTHER;
1587 				ns->counters.any_err++;
1588 				break;
1589 
1590 			case DNS_RESP_CNAME_ERROR:
1591 				res->status = RSLV_STATUS_OTHER;
1592 				ns->counters.cname_error++;
1593 				break;
1594 
1595 			case DNS_RESP_TRUNCATED:
1596 				res->status = RSLV_STATUS_OTHER;
1597 				ns->counters.truncated++;
1598 				break;
1599 
1600 			case DNS_RESP_NO_EXPECTED_RECORD:
1601 			case DNS_RESP_ERROR:
1602 			case DNS_RESP_INTERNAL:
1603 				res->status = RSLV_STATUS_OTHER;
1604 				ns->counters.other++;
1605 				break;
1606 		}
1607 
1608 		/* Wait all nameservers response to handle errors */
1609 		if (dns_resp != DNS_RESP_VALID && res->nb_responses < resolvers->nb_nameservers)
1610 			continue;
1611 
1612 		/* Process error codes */
1613 		if (dns_resp != DNS_RESP_VALID)  {
1614 			if (res->prefered_query_type != res->query_type) {
1615 				/* The fallback on the query type was already performed,
1616 				 * so check the try counter. If it falls to 0, we can
1617 				 * report an error. Else, wait the next attempt. */
1618 				if (!res->try)
1619 					goto report_res_error;
1620 			}
1621 			else {
1622 				/* Fallback from A to AAAA or the opposite and re-send
1623 				 * the resolution immediately. try counter is not
1624 				 * decremented. */
1625 				if (res->prefered_query_type == DNS_RTYPE_A) {
1626 					res->query_type = DNS_RTYPE_AAAA;
1627 					dns_send_query(res);
1628 				}
1629 				else if (res->prefered_query_type == DNS_RTYPE_AAAA) {
1630 					res->query_type = DNS_RTYPE_A;
1631 					dns_send_query(res);
1632 				}
1633 			}
1634 			continue;
1635 		}
1636 
1637 		/* Now let's check the query's dname corresponds to the one we
1638 		 * sent. We can check only the first query of the list. We send
1639 		 * one query at a time so we get one query in the response */
1640 		query = LIST_NEXT(&res->response.query_list, struct dns_query_item *, list);
1641 		if (query && memcmp(query->name, res->hostname_dn, res->hostname_dn_len) != 0) {
1642 			dns_resp = DNS_RESP_WRONG_NAME;
1643 			ns->counters.other++;
1644 			goto report_res_error;
1645 		}
1646 
1647 		/* So the resolution succeeded */
1648 		res->status     = RSLV_STATUS_VALID;
1649 		res->last_valid = now_ms;
1650 		ns->counters.valid++;
1651 		goto report_res_success;
1652 
1653 	report_res_error:
1654 		list_for_each_entry(req, &res->requesters, list)
1655 			req->requester_error_cb(req, dns_resp);
1656 		dns_reset_resolution(res);
1657 		LIST_DEL(&res->list);
1658 		LIST_ADDQ(&resolvers->resolutions.wait, &res->list);
1659 		continue;
1660 
1661 	report_res_success:
1662 		/* Only the 1rst requester s managed by the server, others are
1663 		 * from the cache */
1664 		tmpns = ns;
1665 		list_for_each_entry(req, &res->requesters, list) {
1666 			struct server *s = objt_server(req->owner);
1667 
1668 			if (s)
1669 				HA_SPIN_LOCK(SERVER_LOCK, &s->lock);
1670 			req->requester_cb(req, tmpns);
1671 			if (s)
1672 				HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
1673 			tmpns = NULL;
1674 		}
1675 
1676 		dns_reset_resolution(res);
1677 		LIST_DEL(&res->list);
1678 		LIST_ADDQ(&resolvers->resolutions.wait, &res->list);
1679 		continue;
1680 	}
1681 	dns_update_resolvers_timeout(resolvers);
1682 	HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
1683 }
1684 
1685 /* Called when a resolvers network socket is ready to send data */
dns_resolve_send(struct dgram_conn * dgram)1686 static void dns_resolve_send(struct dgram_conn *dgram)
1687 {
1688 	struct dns_resolvers  *resolvers;
1689 	struct dns_nameserver *ns;
1690 	struct dns_resolution *res;
1691 	int fd;
1692 
1693 	fd = dgram->t.sock.fd;
1694 
1695 	/* check if ready for sending */
1696 	if (!fd_send_ready(fd))
1697 		return;
1698 
1699 	/* we don't want/need to be waked up any more for sending */
1700 	fd_stop_send(fd);
1701 
1702 	/* no need to go further if we can't retrieve the nameserver */
1703 	if ((ns = dgram->owner) == NULL)
1704 		return;
1705 
1706 	resolvers = ns->resolvers;
1707 	HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
1708 
1709 	list_for_each_entry(res, &resolvers->resolutions.curr, list) {
1710 		int ret, len;
1711 
1712 		if (res->nb_queries == resolvers->nb_nameservers)
1713 			continue;
1714 
1715 		len = dns_build_query(res->query_id, res->query_type,
1716 		                      resolvers->accepted_payload_size,
1717 		                      res->hostname_dn, res->hostname_dn_len,
1718 		                      trash.area, trash.size);
1719 		if (len == -1)
1720 			goto snd_error;
1721 
1722 		ret = send(fd, trash.area, len, 0);
1723 		if (ret != len)
1724 			goto snd_error;
1725 
1726 		ns->counters.sent++;
1727 		res->nb_queries++;
1728 		continue;
1729 
1730 	  snd_error:
1731 		ns->counters.snd_error++;
1732 		res->nb_queries++;
1733 	}
1734 	HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
1735 }
1736 
1737 /* Processes DNS resolution. First, it checks the active list to detect expired
1738  * resolutions and retry them if possible. Else a timeout is reported. Then, it
1739  * checks the wait list to trigger new resolutions.
1740  */
dns_process_resolvers(struct task * t,void * context,unsigned short state)1741 static struct task *dns_process_resolvers(struct task *t, void *context, unsigned short state)
1742 {
1743 	struct dns_resolvers  *resolvers = context;
1744 	struct dns_resolution *res, *resback;
1745 	int exp;
1746 
1747 	HA_SPIN_LOCK(DNS_LOCK, &resolvers->lock);
1748 
1749 	/* Handle all expired resolutions from the active list */
1750 	list_for_each_entry_safe(res, resback, &resolvers->resolutions.curr, list) {
1751 		/* When we find the first resolution in the future, then we can
1752 		 * stop here */
1753 		exp = tick_add(res->last_query, resolvers->timeout.retry);
1754 		if (!tick_is_expired(exp, now_ms))
1755 			break;
1756 
1757 		/* If current resolution has been tried too many times and
1758 		 * finishes in timeout we update its status and remove it from
1759 		 * the list */
1760 		if (!res->try) {
1761 			struct dns_requester *req;
1762 
1763 			/* Notify the result to the requesters */
1764 			if (!res->nb_responses)
1765 				res->status = RSLV_STATUS_TIMEOUT;
1766 			list_for_each_entry(req, &res->requesters, list)
1767 				req->requester_error_cb(req, res->status);
1768 
1769 			/* Clean up resolution info and remove it from the
1770 			 * current list */
1771 			dns_reset_resolution(res);
1772 			LIST_DEL(&res->list);
1773 			LIST_ADDQ(&resolvers->resolutions.wait, &res->list);
1774 		}
1775 		else {
1776 			/* Otherwise resend the DNS query and requeue the resolution */
1777 			if (!res->nb_responses || res->prefered_query_type != res->query_type) {
1778 				/* No response received (a real timeout) or fallback already done */
1779 				res->query_type = res->prefered_query_type;
1780 				res->try--;
1781 			}
1782 			else {
1783 				/* Fallback from A to AAAA or the opposite and re-send
1784 				 * the resolution immediately. try counter is not
1785 				 * decremented. */
1786 				if (res->prefered_query_type == DNS_RTYPE_A)
1787 					res->query_type = DNS_RTYPE_AAAA;
1788 				else if (res->prefered_query_type == DNS_RTYPE_AAAA)
1789 					res->query_type = DNS_RTYPE_A;
1790 				else
1791 					res->try--;
1792 			}
1793 			dns_send_query(res);
1794 		}
1795 	}
1796 
1797 	/* Handle all resolutions in the wait list */
1798 	list_for_each_entry_safe(res, resback, &resolvers->resolutions.wait, list) {
1799 		exp = tick_add(res->last_resolution, dns_resolution_timeout(res));
1800 		if (tick_isset(res->last_resolution) && !tick_is_expired(exp, now_ms))
1801 			continue;
1802 
1803 		if (dns_run_resolution(res) != 1) {
1804 			res->last_resolution = now_ms;
1805 			LIST_DEL(&res->list);
1806 			LIST_ADDQ(&resolvers->resolutions.wait, &res->list);
1807 		}
1808 	}
1809 
1810 	dns_update_resolvers_timeout(resolvers);
1811 	HA_SPIN_UNLOCK(DNS_LOCK, &resolvers->lock);
1812 	return t;
1813 }
1814 
1815 /* proto_udp callback functions for a DNS resolution */
1816 struct dgram_data_cb resolve_dgram_cb = {
1817 	.recv = dns_resolve_recv,
1818 	.send = dns_resolve_send,
1819 };
1820 
1821 /* Release memory allocated by DNS */
dns_deinit(void)1822 static void dns_deinit(void)
1823 {
1824 	struct dns_resolvers  *resolvers, *resolversback;
1825 	struct dns_nameserver *ns, *nsback;
1826 	struct dns_resolution *res, *resback;
1827 	struct dns_requester  *req, *reqback;
1828 	struct dns_srvrq      *srvrq, *srvrqback;
1829 
1830 	list_for_each_entry_safe(resolvers, resolversback, &dns_resolvers, list) {
1831 		list_for_each_entry_safe(ns, nsback, &resolvers->nameservers, list) {
1832 			free(ns->id);
1833 			free((char *)ns->conf.file);
1834 			if (ns->dgram && ns->dgram->t.sock.fd != -1)
1835 				fd_delete(ns->dgram->t.sock.fd);
1836 			free(ns->dgram);
1837 			LIST_DEL(&ns->list);
1838 			free(ns);
1839 		}
1840 
1841 		list_for_each_entry_safe(res, resback, &resolvers->resolutions.curr, list) {
1842 			list_for_each_entry_safe(req, reqback, &res->requesters, list) {
1843 				LIST_DEL(&req->list);
1844 				free(req);
1845 			}
1846 			dns_free_resolution(res);
1847 		}
1848 
1849 		list_for_each_entry_safe(res, resback, &resolvers->resolutions.wait, list) {
1850 			list_for_each_entry_safe(req, reqback, &res->requesters, list) {
1851 				LIST_DEL(&req->list);
1852 				free(req);
1853 			}
1854 			dns_free_resolution(res);
1855 		}
1856 
1857 		free(resolvers->id);
1858 		free((char *)resolvers->conf.file);
1859 		task_delete(resolvers->t);
1860 		task_free(resolvers->t);
1861 		LIST_DEL(&resolvers->list);
1862 		free(resolvers);
1863 	}
1864 
1865 	list_for_each_entry_safe(srvrq, srvrqback, &dns_srvrq_list, list) {
1866 		free(srvrq->name);
1867 		free(srvrq->hostname_dn);
1868 		LIST_DEL(&srvrq->list);
1869 		free(srvrq);
1870 	}
1871 }
1872 
1873 /* Finalizes the DNS configuration by allocating required resources and checking
1874  * live parameters.
1875  * Returns 0 on success, ERR_* flags otherwise.
1876  */
dns_finalize_config(void)1877 static int dns_finalize_config(void)
1878 {
1879 	struct dns_resolvers *resolvers;
1880 	struct proxy	     *px;
1881 	int err_code = 0;
1882 
1883 	/* allocate pool of resolution per resolvers */
1884 	list_for_each_entry(resolvers, &dns_resolvers, list) {
1885 		struct dns_nameserver *ns;
1886 		struct task           *t;
1887 
1888 		/* Check if we can create the socket with nameservers info */
1889 		list_for_each_entry(ns, &resolvers->nameservers, list) {
1890 			struct dgram_conn *dgram = NULL;
1891 			int fd;
1892 
1893 			/* Check nameserver info */
1894 			if ((fd = socket(ns->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
1895 				ha_alert("config : resolvers '%s': can't create socket for nameserver '%s'.\n",
1896 					 resolvers->id, ns->id);
1897 				err_code |= (ERR_ALERT|ERR_ABORT);
1898 				continue;
1899 			}
1900 			if (connect(fd, (struct sockaddr*)&ns->addr, get_addr_len(&ns->addr)) == -1) {
1901 				ha_alert("config : resolvers '%s': can't connect socket for nameserver '%s'.\n",
1902 					 resolvers->id, ns->id);
1903 				close(fd);
1904 				err_code |= (ERR_ALERT|ERR_ABORT);
1905 				continue;
1906 			}
1907 			close(fd);
1908 
1909 			/* Create dgram structure that will hold the UPD socket
1910 			 * and attach it on the current nameserver */
1911 			if ((dgram = calloc(1, sizeof(*dgram))) == NULL) {
1912 				ha_alert("config: resolvers '%s' : out of memory.\n",
1913 					 resolvers->id);
1914 				err_code |= (ERR_ALERT|ERR_ABORT);
1915 				goto err;
1916 			}
1917 
1918 			/* Leave dgram partially initialized, no FD attached for
1919 			 * now. */
1920 			dgram->owner     = ns;
1921 			dgram->data      = &resolve_dgram_cb;
1922 			dgram->t.sock.fd = -1;
1923 			ns->dgram        = dgram;
1924 		}
1925 
1926 		/* Create the task associated to the resolvers section */
1927 		if ((t = task_new(MAX_THREADS_MASK)) == NULL) {
1928 			ha_alert("config : resolvers '%s' : out of memory.\n", resolvers->id);
1929 			err_code |= (ERR_ALERT|ERR_ABORT);
1930 			goto err;
1931 		}
1932 
1933 		/* Update task's parameters */
1934 		t->process   = dns_process_resolvers;
1935 		t->context   = resolvers;
1936 		resolvers->t = t;
1937 		task_wakeup(t, TASK_WOKEN_INIT);
1938 	}
1939 
1940 	for (px = proxies_list; px; px = px->next) {
1941 		struct server *srv;
1942 
1943 		for (srv = px->srv; srv; srv = srv->next) {
1944 			struct dns_resolvers *resolvers;
1945 
1946 			if (!srv->resolvers_id)
1947 				continue;
1948 
1949 			if ((resolvers = find_resolvers_by_id(srv->resolvers_id)) == NULL) {
1950 				ha_alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
1951 					 proxy_type_str(px), px->id, srv->id, srv->resolvers_id);
1952 				err_code |= (ERR_ALERT|ERR_ABORT);
1953 				continue;
1954 			}
1955 			srv->resolvers = resolvers;
1956 
1957 			if (srv->srvrq && !srv->srvrq->resolvers) {
1958 				srv->srvrq->resolvers = srv->resolvers;
1959 				if (dns_link_resolution(srv->srvrq, OBJ_TYPE_SRVRQ, 0) == -1) {
1960 					ha_alert("config : %s '%s' : unable to set DNS resolution for server '%s'.\n",
1961 						 proxy_type_str(px), px->id, srv->id);
1962 					err_code |= (ERR_ALERT|ERR_ABORT);
1963 					continue;
1964 				}
1965 			}
1966 			if (dns_link_resolution(srv, OBJ_TYPE_SERVER, 0) == -1) {
1967 				ha_alert("config : %s '%s', unable to set DNS resolution for server '%s'.\n",
1968 					 proxy_type_str(px), px->id, srv->id);
1969 				err_code |= (ERR_ALERT|ERR_ABORT);
1970 				continue;
1971 			}
1972 		}
1973 	}
1974 
1975 	if (err_code & (ERR_ALERT|ERR_ABORT))
1976 		goto err;
1977 
1978 	return err_code;
1979   err:
1980 	dns_deinit();
1981 	return err_code;
1982 
1983 }
1984 
1985 /* if an arg is found, it sets the resolvers section pointer into cli.p0 */
cli_parse_stat_resolvers(char ** args,char * payload,struct appctx * appctx,void * private)1986 static int cli_parse_stat_resolvers(char **args, char *payload, struct appctx *appctx, void *private)
1987 {
1988 	struct dns_resolvers *presolvers;
1989 
1990 	if (*args[2]) {
1991 		list_for_each_entry(presolvers, &dns_resolvers, list) {
1992 			if (strcmp(presolvers->id, args[2]) == 0) {
1993 				appctx->ctx.cli.p0 = presolvers;
1994 				break;
1995 			}
1996 		}
1997 		if (appctx->ctx.cli.p0 == NULL) {
1998 			appctx->ctx.cli.severity = LOG_ERR;
1999 			appctx->ctx.cli.msg = "Can't find that resolvers section\n";
2000 			appctx->st0 = CLI_ST_PRINT;
2001 			return 1;
2002 		}
2003 	}
2004 	return 0;
2005 }
2006 
2007 /* Dumps counters from all resolvers section and associated name servers. It
2008  * returns 0 if the output buffer is full and it needs to be called again,
2009  * otherwise non-zero. It may limit itself to the resolver pointed to by
2010  * <cli.p0> if it's not null.
2011  */
cli_io_handler_dump_resolvers_to_buffer(struct appctx * appctx)2012 static int cli_io_handler_dump_resolvers_to_buffer(struct appctx *appctx)
2013 {
2014 	struct stream_interface *si = appctx->owner;
2015 	struct dns_resolvers    *resolvers;
2016 	struct dns_nameserver   *ns;
2017 
2018 	chunk_reset(&trash);
2019 
2020 	switch (appctx->st2) {
2021 	case STAT_ST_INIT:
2022 		appctx->st2 = STAT_ST_LIST; /* let's start producing data */
2023 		/* fall through */
2024 
2025 	case STAT_ST_LIST:
2026 		if (LIST_ISEMPTY(&dns_resolvers)) {
2027 			chunk_appendf(&trash, "No resolvers found\n");
2028 		}
2029 		else {
2030 			list_for_each_entry(resolvers, &dns_resolvers, list) {
2031 				if (appctx->ctx.cli.p0 != NULL && appctx->ctx.cli.p0 != resolvers)
2032 					continue;
2033 
2034 				chunk_appendf(&trash, "Resolvers section %s\n", resolvers->id);
2035 				list_for_each_entry(ns, &resolvers->nameservers, list) {
2036 					chunk_appendf(&trash, " nameserver %s:\n", ns->id);
2037 					chunk_appendf(&trash, "  sent:        %lld\n", ns->counters.sent);
2038 					chunk_appendf(&trash, "  snd_error:   %lld\n", ns->counters.snd_error);
2039 					chunk_appendf(&trash, "  valid:       %lld\n", ns->counters.valid);
2040 					chunk_appendf(&trash, "  update:      %lld\n", ns->counters.update);
2041 					chunk_appendf(&trash, "  cname:       %lld\n", ns->counters.cname);
2042 					chunk_appendf(&trash, "  cname_error: %lld\n", ns->counters.cname_error);
2043 					chunk_appendf(&trash, "  any_err:     %lld\n", ns->counters.any_err);
2044 					chunk_appendf(&trash, "  nx:          %lld\n", ns->counters.nx);
2045 					chunk_appendf(&trash, "  timeout:     %lld\n", ns->counters.timeout);
2046 					chunk_appendf(&trash, "  refused:     %lld\n", ns->counters.refused);
2047 					chunk_appendf(&trash, "  other:       %lld\n", ns->counters.other);
2048 					chunk_appendf(&trash, "  invalid:     %lld\n", ns->counters.invalid);
2049 					chunk_appendf(&trash, "  too_big:     %lld\n", ns->counters.too_big);
2050 					chunk_appendf(&trash, "  truncated:   %lld\n", ns->counters.truncated);
2051 					chunk_appendf(&trash, "  outdated:    %lld\n",  ns->counters.outdated);
2052 				}
2053 				chunk_appendf(&trash, "\n");
2054 			}
2055 		}
2056 
2057 		/* display response */
2058 		if (ci_putchk(si_ic(si), &trash) == -1) {
2059 			/* let's try again later from this session. We add ourselves into
2060 			 * this session's users so that it can remove us upon termination.
2061 			 */
2062 			si_rx_room_blk(si);
2063 			return 0;
2064 		}
2065 		/* fall through */
2066 
2067 	default:
2068 		appctx->st2 = STAT_ST_FIN;
2069 		return 1;
2070 	}
2071 }
2072 
2073 /* register cli keywords */
2074 static struct cli_kw_list cli_kws = {{ }, {
2075 		{ { "show", "resolvers", NULL }, "show resolvers [id]: dumps counters from all resolvers section and\n"
2076 		  "                     associated name servers",
2077 		  cli_parse_stat_resolvers, cli_io_handler_dump_resolvers_to_buffer },
2078 		{{},}
2079 	}
2080 };
2081 
2082 INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
2083 
2084 REGISTER_POST_DEINIT(dns_deinit);
2085 REGISTER_CONFIG_POSTPARSER("dns runtime resolver", dns_finalize_config);
2086