]> git.ipfire.org Git - thirdparty/squid.git/blob - src/dns_internal.cc
Cleanup: convert main DNS classes to C++11 initialization
[thirdparty/squid.git] / src / dns_internal.cc
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 78 DNS lookups; interacts with dns/rfc1035.cc */
10
11 #include "squid.h"
12 #include "base/InstanceId.h"
13 #include "base/RunnersRegistry.h"
14 #include "comm.h"
15 #include "comm/Connection.h"
16 #include "comm/ConnOpener.h"
17 #include "comm/Loops.h"
18 #include "comm/Read.h"
19 #include "comm/Write.h"
20 #include "dlink.h"
21 #include "dns/forward.h"
22 #include "dns/rfc3596.h"
23 #include "event.h"
24 #include "fd.h"
25 #include "fde.h"
26 #include "ip/tools.h"
27 #include "MemBuf.h"
28 #include "mgr/Registration.h"
29 #include "SquidConfig.h"
30 #include "SquidTime.h"
31 #include "Store.h"
32 #include "tools.h"
33 #include "util.h"
34 #include "wordlist.h"
35
36 #if SQUID_SNMP
37 #include "snmp_core.h"
38 #endif
39
40 #if HAVE_ARPA_NAMESER_H
41 #include <arpa/nameser.h>
42 #endif
43 #include <cerrno>
44 #include <random>
45 #if HAVE_RESOLV_H
46 #include <resolv.h>
47 #endif
48
49 #if _SQUID_WINDOWS_
50 #define REG_TCPIP_PARA_INTERFACES "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
51 #define REG_TCPIP_PARA "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
52 #define REG_VXD_MSTCP "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP"
53 #endif
54 #ifndef _PATH_RESCONF
55 #define _PATH_RESCONF "/etc/resolv.conf"
56 #endif
57 #ifndef NS_DEFAULTPORT
58 #define NS_DEFAULTPORT 53
59 #endif
60
61 #ifndef NS_MAXDNAME
62 #define NS_MAXDNAME 1025
63 #endif
64
65 #ifndef MAXDNSRCH
66 #define MAXDNSRCH 6
67 #endif
68
69 /* The buffer size required to store the maximum allowed search path */
70 #ifndef RESOLV_BUFSZ
71 #define RESOLV_BUFSZ NS_MAXDNAME * MAXDNSRCH + sizeof("search ") + 1
72 #endif
73
74 #define IDNS_MAX_TRIES 20
75 #define MAX_RCODE 17
76 #define MAX_ATTEMPT 3
77 static int RcodeMatrix[MAX_RCODE][MAX_ATTEMPT];
78 // NP: see http://www.iana.org/assignments/dns-parameters
79 static const char *Rcodes[] = {
80 /* RFC 1035 */
81 "Success",
82 "Packet Format Error",
83 "DNS Server Failure",
84 "Non-Existent Domain",
85 "Not Implemented",
86 "Query Refused",
87 /* RFC 2136 */
88 "Name Exists when it should not",
89 "RR Set Exists when it should not",
90 "RR Set that should exist does not",
91 "Server Not Authoritative for zone",
92 "Name not contained in zone",
93 /* unassigned */
94 "","","","","",
95 /* RFC 2671 */
96 "Bad OPT Version or TSIG Signature Failure"
97 };
98
99 typedef struct _ns ns;
100
101 typedef struct _sp sp;
102
103 class idns_query
104 {
105 CBDATA_CLASS(idns_query);
106
107 public:
108 idns_query() {
109 callback = nullptr;
110 memset(&query, 0, sizeof(query));
111 *buf = 0;
112 *name = 0;
113 *orig = 0;
114 memset(&start_t, 0, sizeof(start_t));
115 memset(&sent_t, 0, sizeof(sent_t));
116 memset(&queue_t, 0, sizeof(queue_t));
117 }
118
119 ~idns_query() {
120 if (message)
121 rfc1035MessageDestroy(&message);
122 delete queue;
123 delete slave;
124 // master is just a back-reference
125 cbdataReferenceDone(callback_data);
126 }
127
128 hash_link hash;
129 rfc1035_query query;
130 char buf[RESOLV_BUFSZ];
131 char name[NS_MAXDNAME + 1];
132 char orig[NS_MAXDNAME + 1];
133 ssize_t sz = 0;
134 unsigned short query_id = 0; ///< random query ID sent to server; changes with every query sent
135 InstanceId<idns_query> xact_id; ///< identifies our "transaction", stays constant when query is retried
136
137 int nsends = 0;
138 int need_vc = 0;
139 bool permit_mdns = false;
140 int pending = 0;
141
142 struct timeval start_t;
143 struct timeval sent_t;
144 struct timeval queue_t;
145 dlink_node lru;
146 IDNSCB *callback;
147 void *callback_data = nullptr;
148 int attempt = 0;
149 int rcode = 0;
150 idns_query *queue = nullptr;
151 idns_query *slave = nullptr; // single linked list
152 idns_query *master = nullptr; // single pointer to a shared master
153 unsigned short domain = 0;
154 unsigned short do_searchpath = 0;
155 rfc1035_message *message = nullptr;
156 int ancount = 0;
157 const char *error = nullptr;
158 };
159
160 InstanceIdDefinitions(idns_query, "dns");
161
162 CBDATA_CLASS_INIT(idns_query);
163
164 class nsvc
165 {
166 CBDATA_CLASS(nsvc);
167
168 public:
169 explicit nsvc(int nsv) : ns(nsv), msg(new MemBuf()), queue(new MemBuf()) {}
170 ~nsvc();
171
172 int ns = 0;
173 Comm::ConnectionPointer conn;
174 unsigned short msglen = 0;
175 int read_msglen = 0;
176 MemBuf *msg = nullptr;
177 MemBuf *queue = nullptr;
178 bool busy = true;
179 };
180
181 CBDATA_CLASS_INIT(nsvc);
182
183 struct _ns {
184 Ip::Address S;
185 int nqueries;
186 int nreplies;
187 #if WHEN_EDNS_RESPONSES_ARE_PARSED
188 int last_seen_edns;
189 #endif
190 bool mDNSResolver;
191 nsvc *vc;
192 };
193
194 namespace Dns
195 {
196
197 /// manage DNS internal component
198 class ConfigRr : public RegisteredRunner
199 {
200 public:
201 /* RegisteredRunner API */
202 virtual void startReconfigure() override;
203 virtual void endingShutdown() override;
204 };
205
206 RunnerRegistrationEntry(ConfigRr);
207
208 } // namespace Dns
209
210 struct _sp {
211 char domain[NS_MAXDNAME];
212 int queries;
213 };
214
215 static ns *nameservers = NULL;
216 static sp *searchpath = NULL;
217 static int nns = 0;
218 static int nns_alloc = 0;
219 static int nns_mdns_count = 0;
220 static int npc = 0;
221 static int npc_alloc = 0;
222 static int ndots = 1;
223 static dlink_list lru_list;
224 static int event_queued = 0;
225 static hash_table *idns_lookup_hash = NULL;
226
227 /*
228 * Notes on EDNS:
229 *
230 * IPv4:
231 * EDNS as specified may be sent as an additional record for any request.
232 * early testing has revealed that it works on common devices, but cannot
233 * be reliably used on any A or PTR requet done for IPv4 addresses.
234 *
235 * As such the IPv4 packets are still hard-coded not to contain EDNS (0)
236 *
237 * Squid design:
238 * Squid is optimized to generate one packet and re-send it to all NS
239 * due to this we cannot customize the EDNS size per NS.
240 *
241 * As such we take the configuration option value as fixed.
242 *
243 * FUTURE TODO:
244 * This may not be worth doing, but if/when additional-records are parsed
245 * we will be able to recover the OPT value specific to any one NS and
246 * cache it. Effectively automating the tuning of EDNS advertised to the
247 * size our active NS are capable.
248 * Default would need to start with 512 bytes RFC1035 says every NS must accept.
249 * Responses from the configured NS may cause this to be raised or turned off.
250 */
251 #if WHEN_EDNS_RESPONSES_ARE_PARSED
252 static int max_shared_edns = RFC1035_DEFAULT_PACKET_SZ;
253 #endif
254
255 static OBJH idnsStats;
256 static void idnsAddNameserver(const char *buf);
257 static void idnsAddMDNSNameservers();
258 static void idnsAddPathComponent(const char *buf);
259 static void idnsFreeNameservers(void);
260 static void idnsFreeSearchpath(void);
261 static bool idnsParseNameservers(void);
262 static bool idnsParseResolvConf(void);
263 #if _SQUID_WINDOWS_
264 static bool idnsParseWIN32Registry(void);
265 static void idnsParseWIN32SearchList(const char *);
266 #endif
267 static void idnsStartQuery(idns_query * q, IDNSCB * callback, void *data);
268 static void idnsSendQuery(idns_query * q);
269 static IOCB idnsReadVCHeader;
270 static void idnsDoSendQueryVC(nsvc *vc);
271 static CNCB idnsInitVCConnected;
272 static IOCB idnsReadVC;
273 static IOCB idnsSentQueryVC;
274
275 static int idnsFromKnownNameserver(Ip::Address const &from);
276 static idns_query *idnsFindQuery(unsigned short id);
277 static void idnsGrokReply(const char *buf, size_t sz, int from_ns);
278 static PF idnsRead;
279 static EVH idnsCheckQueue;
280 static void idnsTickleQueue(void);
281 static void idnsRcodeCount(int, int);
282 static CLCB idnsVCClosed;
283 static unsigned short idnsQueryID(void);
284 static void idnsSendSlaveAAAAQuery(idns_query *q);
285
286 static void
287 idnsCheckMDNS(idns_query *q)
288 {
289 if (!Config.onoff.dns_mdns || q->permit_mdns)
290 return;
291
292 size_t slen = strlen(q->name);
293 if (slen > 6 && memcmp(q->name +(slen-6),".local", 6) == 0) {
294 q->permit_mdns = true;
295 }
296 }
297
298 static void
299 idnsAddMDNSNameservers()
300 {
301 nns_mdns_count=0;
302
303 // mDNS is disabled
304 if (!Config.onoff.dns_mdns)
305 return;
306
307 // mDNS resolver addresses are explicit multicast group IPs
308 if (Ip::EnableIpv6) {
309 idnsAddNameserver("FF02::FB");
310 nameservers[nns-1].S.port(5353);
311 nameservers[nns-1].mDNSResolver = true;
312 ++nns_mdns_count;
313 }
314
315 idnsAddNameserver("224.0.0.251");
316 nameservers[nns-1].S.port(5353);
317 nameservers[nns-1].mDNSResolver = true;
318
319 ++nns_mdns_count;
320 }
321
322 static void
323 idnsAddNameserver(const char *buf)
324 {
325 Ip::Address A;
326
327 if (!(A = buf)) {
328 debugs(78, DBG_CRITICAL, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address");
329 return;
330 }
331
332 if (A.isAnyAddr()) {
333 debugs(78, DBG_CRITICAL, "WARNING: Squid does not accept " << A << " in DNS server specifications.");
334 A.setLocalhost();
335 debugs(78, DBG_CRITICAL, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine");
336 }
337
338 if (!Ip::EnableIpv6 && !A.setIPv4()) {
339 debugs(78, DBG_IMPORTANT, "WARNING: IPv6 is disabled. Discarding " << A << " in DNS server specifications.");
340 return;
341 }
342
343 if (nns == nns_alloc) {
344 int oldalloc = nns_alloc;
345 ns *oldptr = nameservers;
346
347 if (nns_alloc == 0)
348 nns_alloc = 2;
349 else
350 nns_alloc <<= 1;
351
352 nameservers = (ns *)xcalloc(nns_alloc, sizeof(*nameservers));
353
354 if (oldptr && oldalloc)
355 memcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers));
356
357 if (oldptr)
358 safe_free(oldptr);
359 }
360
361 assert(nns < nns_alloc);
362 A.port(NS_DEFAULTPORT);
363 nameservers[nns].S = A;
364 #if WHEN_EDNS_RESPONSES_ARE_PARSED
365 nameservers[nns].last_seen_edns = RFC1035_DEFAULT_PACKET_SZ;
366 // TODO generate a test packet to probe this NS from EDNS size and ability.
367 #endif
368 debugs(78, 3, "idnsAddNameserver: Added nameserver #" << nns << " (" << A << ")");
369 ++nns;
370 }
371
372 static void
373 idnsAddPathComponent(const char *buf)
374 {
375 if (npc == npc_alloc) {
376 int oldalloc = npc_alloc;
377 sp *oldptr = searchpath;
378
379 if (0 == npc_alloc)
380 npc_alloc = 2;
381 else
382 npc_alloc <<= 1;
383
384 searchpath = (sp *)xcalloc(npc_alloc, sizeof(*searchpath));
385
386 if (oldptr && oldalloc)
387 memcpy(searchpath, oldptr, oldalloc * sizeof(*searchpath));
388
389 if (oldptr)
390 safe_free(oldptr);
391 }
392
393 assert(npc < npc_alloc);
394 strncpy(searchpath[npc].domain, buf, sizeof(searchpath[npc].domain)-1);
395 searchpath[npc].domain[sizeof(searchpath[npc].domain)-1] = '\0';
396 Tolower(searchpath[npc].domain);
397 debugs(78, 3, "idnsAddPathComponent: Added domain #" << npc << ": " << searchpath[npc].domain);
398 ++npc;
399 }
400
401 static void
402 idnsFreeNameservers(void)
403 {
404 safe_free(nameservers);
405 nns = nns_alloc = 0;
406 }
407
408 static void
409 idnsFreeSearchpath(void)
410 {
411 safe_free(searchpath);
412 npc = npc_alloc = 0;
413 }
414
415 static bool
416 idnsParseNameservers(void)
417 {
418 bool result = false;
419 for (wordlist *w = Config.dns_nameservers; w; w = w->next) {
420 debugs(78, DBG_IMPORTANT, "Adding nameserver " << w->key << " from squid.conf");
421 idnsAddNameserver(w->key);
422 result = true;
423 }
424 return result;
425 }
426
427 static bool
428 idnsParseResolvConf(void)
429 {
430 bool result = false;
431 #if !_SQUID_WINDOWS_
432 FILE *fp = fopen(_PATH_RESCONF, "r");
433
434 if (!fp) {
435 int xerrno = errno;
436 debugs(78, DBG_IMPORTANT, "" << _PATH_RESCONF << ": " << xstrerr(xerrno));
437 return false;
438 }
439
440 char buf[RESOLV_BUFSZ];
441 const char *t = NULL;
442 while (fgets(buf, RESOLV_BUFSZ, fp)) {
443 t = strtok(buf, w_space);
444
445 if (NULL == t) {
446 continue;
447 } else if (strcmp(t, "nameserver") == 0) {
448 t = strtok(NULL, w_space);
449
450 if (NULL == t)
451 continue;
452
453 debugs(78, DBG_IMPORTANT, "Adding nameserver " << t << " from " << _PATH_RESCONF);
454
455 idnsAddNameserver(t);
456 result = true;
457 } else if (strcmp(t, "domain") == 0) {
458 idnsFreeSearchpath();
459 t = strtok(NULL, w_space);
460
461 if (NULL == t)
462 continue;
463
464 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
465
466 idnsAddPathComponent(t);
467 } else if (strcmp(t, "search") == 0) {
468 idnsFreeSearchpath();
469 while (NULL != t) {
470 t = strtok(NULL, w_space);
471
472 if (NULL == t)
473 continue;
474
475 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
476
477 idnsAddPathComponent(t);
478 }
479 } else if (strcmp(t, "options") == 0) {
480 while (NULL != t) {
481 t = strtok(NULL, w_space);
482
483 if (NULL == t)
484 continue;
485
486 if (strncmp(t, "ndots:", 6) == 0) {
487 ndots = atoi(t + 6);
488
489 if (ndots < 1)
490 ndots = 1;
491
492 debugs(78, DBG_IMPORTANT, "Adding ndots " << ndots << " from " << _PATH_RESCONF);
493 }
494 }
495 }
496 }
497 if (npc == 0 && (t = getMyHostname())) {
498 t = strchr(t, '.');
499 if (t)
500 idnsAddPathComponent(t+1);
501 }
502
503 fclose(fp);
504 #endif
505 return result;
506 }
507
508 #if _SQUID_WINDOWS_
509 static void
510 idnsParseWIN32SearchList(const char * Separator)
511 {
512 char *t;
513 char *token;
514 HKEY hndKey;
515
516 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
517 DWORD Type = 0;
518 DWORD Size = 0;
519 LONG Result;
520 Result = RegQueryValueEx(hndKey, "Domain", NULL, &Type, NULL, &Size);
521
522 if (Result == ERROR_SUCCESS && Size) {
523 t = (char *) xmalloc(Size);
524 RegQueryValueEx(hndKey, "Domain", NULL, &Type, (LPBYTE) t, &Size);
525 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from Registry");
526 idnsAddPathComponent(t);
527 xfree(t);
528 }
529 Result = RegQueryValueEx(hndKey, "SearchList", NULL, &Type, NULL, &Size);
530
531 if (Result == ERROR_SUCCESS && Size) {
532 t = (char *) xmalloc(Size);
533 RegQueryValueEx(hndKey, "SearchList", NULL, &Type, (LPBYTE) t, &Size);
534 token = strtok(t, Separator);
535
536 while (token) {
537 idnsAddPathComponent(token);
538 debugs(78, DBG_IMPORTANT, "Adding domain " << token << " from Registry");
539 token = strtok(NULL, Separator);
540 }
541 xfree(t);
542 }
543
544 RegCloseKey(hndKey);
545 }
546 if (npc == 0 && (t = (char *) getMyHostname())) {
547 t = strchr(t, '.');
548 if (t)
549 idnsAddPathComponent(t + 1);
550 }
551 }
552
553 static bool
554 idnsParseWIN32Registry(void)
555 {
556 char *t;
557 char *token;
558 HKEY hndKey, hndKey2;
559 bool result = false;
560
561 switch (WIN32_OS_version) {
562
563 case _WIN_OS_WINNT:
564 /* get nameservers from the Windows NT registry */
565
566 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
567 DWORD Type = 0;
568 DWORD Size = 0;
569 LONG Result;
570 Result = RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, NULL, &Size);
571
572 if (Result == ERROR_SUCCESS && Size) {
573 t = (char *) xmalloc(Size);
574 RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, (LPBYTE) t, &Size);
575 token = strtok(t, ", ");
576
577 while (token) {
578 idnsAddNameserver(token);
579 result = true;
580 debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
581 token = strtok(NULL, ",");
582 }
583 xfree(t);
584 }
585
586 Result = RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size);
587
588 if (Result == ERROR_SUCCESS && Size) {
589 t = (char *) xmalloc(Size);
590 RegQueryValueEx(hndKey, "NameServer", NULL, &Type, (LPBYTE) t, &Size);
591 token = strtok(t, ", ");
592
593 while (token) {
594 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
595 idnsAddNameserver(token);
596 result = true;
597 token = strtok(NULL, ", ");
598 }
599 xfree(t);
600 }
601
602 RegCloseKey(hndKey);
603 }
604
605 idnsParseWIN32SearchList(" ");
606
607 break;
608
609 case _WIN_OS_WIN2K:
610
611 case _WIN_OS_WINXP:
612
613 case _WIN_OS_WINNET:
614
615 case _WIN_OS_WINLON:
616
617 case _WIN_OS_WIN7:
618 /* get nameservers from the Windows 2000 registry */
619 /* search all interfaces for DNS server addresses */
620
621 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA_INTERFACES, 0, KEY_READ, &hndKey) == ERROR_SUCCESS) {
622 int i;
623 DWORD MaxSubkeyLen, InterfacesCount;
624 char *keyname;
625 FILETIME ftLastWriteTime;
626
627 if (RegQueryInfoKey(hndKey, NULL, NULL, NULL, &InterfacesCount, &MaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
628 keyname = (char *) xmalloc(++MaxSubkeyLen);
629 for (i = 0; i < (int) InterfacesCount; ++i) {
630 DWORD j;
631 j = MaxSubkeyLen;
632 if (RegEnumKeyEx(hndKey, i, keyname, &j, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) {
633 char *newkeyname;
634 newkeyname = (char *) xmalloc(sizeof(REG_TCPIP_PARA_INTERFACES) + j + 2);
635 strcpy(newkeyname, REG_TCPIP_PARA_INTERFACES);
636 strcat(newkeyname, "\\");
637 strcat(newkeyname, keyname);
638 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newkeyname, 0, KEY_QUERY_VALUE, &hndKey2) == ERROR_SUCCESS) {
639 DWORD Type = 0;
640 DWORD Size = 0;
641 LONG Result;
642 Result = RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, &Type, NULL, &Size);
643 if (Result == ERROR_SUCCESS && Size) {
644 t = (char *) xmalloc(Size);
645 RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, &Type, (LPBYTE)t, &Size);
646 token = strtok(t, ", ");
647 while (token) {
648 debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
649 idnsAddNameserver(token);
650 result = true;
651 token = strtok(NULL, ", ");
652 }
653 xfree(t);
654 }
655
656 Result = RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, NULL, &Size);
657 if (Result == ERROR_SUCCESS && Size) {
658 t = (char *) xmalloc(Size);
659 RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, (LPBYTE)t, &Size);
660 token = strtok(t, ", ");
661 while (token) {
662 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
663 idnsAddNameserver(token);
664 result = true;
665 token = strtok(NULL, ", ");
666 }
667
668 xfree(t);
669 }
670
671 RegCloseKey(hndKey2);
672 }
673
674 xfree(newkeyname);
675 }
676 }
677
678 xfree(keyname);
679 }
680
681 RegCloseKey(hndKey);
682 }
683
684 idnsParseWIN32SearchList(", ");
685
686 break;
687
688 case _WIN_OS_WIN95:
689
690 case _WIN_OS_WIN98:
691
692 case _WIN_OS_WINME:
693 /* get nameservers from the Windows 9X registry */
694
695 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_VXD_MSTCP, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
696 DWORD Type = 0;
697 DWORD Size = 0;
698 LONG Result;
699 Result = RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size);
700
701 if (Result == ERROR_SUCCESS && Size) {
702 t = (char *) xmalloc(Size);
703 RegQueryValueEx(hndKey, "NameServer", NULL, &Type, (LPBYTE) t, &Size);
704 token = strtok(t, ", ");
705
706 while (token) {
707 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
708 idnsAddNameserver(token);
709 result = true;
710 token = strtok(NULL, ", ");
711 }
712 xfree(t);
713 }
714
715 RegCloseKey(hndKey);
716 }
717
718 break;
719
720 default:
721 debugs(78, DBG_IMPORTANT, "Failed to read nameserver from Registry: Unknown System Type.");
722 }
723
724 return result;
725 }
726
727 #endif
728
729 static void
730 idnsStats(StoreEntry * sentry)
731 {
732 dlink_node *n;
733 idns_query *q;
734 int i;
735 int j;
736 char buf[MAX_IPSTRLEN];
737 storeAppendPrintf(sentry, "Internal DNS Statistics:\n");
738 storeAppendPrintf(sentry, "\nThe Queue:\n");
739 storeAppendPrintf(sentry, " DELAY SINCE\n");
740 storeAppendPrintf(sentry, " ID SIZE SENDS FIRST SEND LAST SEND M FQDN\n");
741 storeAppendPrintf(sentry, "------ ---- ----- ---------- --------- - ----\n");
742
743 for (n = lru_list.head; n; n = n->next) {
744 q = (idns_query *)n->data;
745 storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f %c %s\n",
746 (int) q->query_id, (int) q->sz, q->nsends,
747 tvSubDsec(q->start_t, current_time),
748 tvSubDsec(q->sent_t, current_time),
749 (q->permit_mdns? 'M':' '),
750 q->name);
751 }
752
753 if (Config.dns.packet_max > 0)
754 storeAppendPrintf(sentry, "\nDNS jumbo-grams: %zd Bytes\n", Config.dns.packet_max);
755 else
756 storeAppendPrintf(sentry, "\nDNS jumbo-grams: not working\n");
757
758 storeAppendPrintf(sentry, "\nNameservers:\n");
759 storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES Type\n");
760 storeAppendPrintf(sentry, "---------------------------------------------- --------- --------- --------\n");
761
762 for (i = 0; i < nns; ++i) {
763 storeAppendPrintf(sentry, "%-45s %9d %9d %s\n", /* Let's take the maximum: (15 IPv4/45 IPv6) */
764 nameservers[i].S.toStr(buf,MAX_IPSTRLEN),
765 nameservers[i].nqueries,
766 nameservers[i].nreplies,
767 nameservers[i].mDNSResolver?"multicast":"recurse");
768 }
769
770 storeAppendPrintf(sentry, "\nRcode Matrix:\n");
771 storeAppendPrintf(sentry, "RCODE");
772
773 for (i = 0; i < MAX_ATTEMPT; ++i)
774 storeAppendPrintf(sentry, " ATTEMPT%d", i + 1);
775
776 storeAppendPrintf(sentry, " PROBLEM\n");
777
778 for (j = 0; j < MAX_RCODE; ++j) {
779 if (j > 10 && j < 16)
780 continue; // unassigned by IANA.
781
782 storeAppendPrintf(sentry, "%5d", j);
783
784 for (i = 0; i < MAX_ATTEMPT; ++i)
785 storeAppendPrintf(sentry, " %8d", RcodeMatrix[j][i]);
786
787 storeAppendPrintf(sentry, " : %s\n",Rcodes[j]);
788 }
789
790 if (npc) {
791 storeAppendPrintf(sentry, "\nSearch list:\n");
792
793 for (i=0; i < npc; ++i)
794 storeAppendPrintf(sentry, "%s\n", searchpath[i].domain);
795
796 storeAppendPrintf(sentry, "\n");
797 }
798 }
799
800 static void
801 idnsTickleQueue(void)
802 {
803 if (event_queued)
804 return;
805
806 if (NULL == lru_list.tail)
807 return;
808
809 const double when = min(Config.Timeout.idns_query, Config.Timeout.idns_retransmit)/1000.0;
810
811 eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, when, 1);
812
813 event_queued = 1;
814 }
815
816 static void
817 idnsSentQueryVC(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int, void *data)
818 {
819 nsvc * vc = (nsvc *)data;
820
821 if (flag == Comm::ERR_CLOSING)
822 return;
823
824 // XXX: irrelevant now that we have conn pointer?
825 if (!Comm::IsConnOpen(conn) || fd_table[conn->fd].closing())
826 return;
827
828 if (flag != Comm::OK || size <= 0) {
829 conn->close();
830 return;
831 }
832
833 vc->busy = 0;
834 idnsDoSendQueryVC(vc);
835 }
836
837 static void
838 idnsDoSendQueryVC(nsvc *vc)
839 {
840 if (vc->busy)
841 return;
842
843 if (vc->queue->contentSize() == 0)
844 return;
845
846 // if retrying after a TC UDP response, our close handler cb may be pending
847 if (fd_table[vc->conn->fd].closing())
848 return;
849
850 MemBuf *mb = vc->queue;
851
852 vc->queue = new MemBuf;
853
854 vc->busy = 1;
855
856 // Comm needs seconds but idnsCheckQueue() will check the exact timeout
857 const int timeout = (Config.Timeout.idns_query % 1000 ?
858 Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
859 AsyncCall::Pointer nil;
860
861 commSetConnTimeout(vc->conn, timeout, nil);
862
863 AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC",
864 CommIoCbPtrFun(&idnsSentQueryVC, vc));
865 Comm::Write(vc->conn, mb, call);
866
867 delete mb;
868 }
869
870 static void
871 idnsInitVCConnected(const Comm::ConnectionPointer &conn, Comm::Flag status, int, void *data)
872 {
873 nsvc * vc = (nsvc *)data;
874
875 if (status != Comm::OK || !conn) {
876 char buf[MAX_IPSTRLEN] = "";
877 if (vc->ns < nns)
878 nameservers[vc->ns].S.toStr(buf,MAX_IPSTRLEN);
879 debugs(78, DBG_IMPORTANT, HERE << "Failed to connect to nameserver " << buf << " using TCP.");
880 return;
881 }
882
883 vc->conn = conn;
884
885 comm_add_close_handler(conn->fd, idnsVCClosed, vc);
886 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
887 CommIoCbPtrFun(idnsReadVCHeader, vc));
888 comm_read(conn, (char *)&vc->msglen, 2, call);
889 vc->busy = 0;
890 idnsDoSendQueryVC(vc);
891 }
892
893 static void
894 idnsVCClosed(const CommCloseCbParams &params)
895 {
896 nsvc * vc = (nsvc *)params.data;
897 delete vc;
898 }
899
900 nsvc::~nsvc()
901 {
902 delete queue;
903 delete msg;
904 if (ns < nns) // XXX: idnsShutdownAndFreeState may have freed nameservers[]
905 nameservers[ns].vc = NULL;
906 }
907
908 static void
909 idnsInitVC(int nsv)
910 {
911 nsvc *vc = new nsvc(nsv);
912 assert(nsv < nns);
913 assert(vc->conn == NULL); // MUST be NULL from the construction process!
914 nameservers[nsv].vc = vc;
915
916 Comm::ConnectionPointer conn = new Comm::Connection();
917
918 if (!Config.Addrs.udp_outgoing.isNoAddr())
919 conn->setAddrs(Config.Addrs.udp_outgoing, nameservers[nsv].S);
920 else
921 conn->setAddrs(Config.Addrs.udp_incoming, nameservers[nsv].S);
922
923 if (conn->remote.isIPv4())
924 conn->local.setIPv4();
925
926 AsyncCall::Pointer call = commCbCall(78,3, "idnsInitVCConnected", CommConnectCbPtrFun(idnsInitVCConnected, vc));
927
928 Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, Config.Timeout.connect);
929 cs->setHost("DNS TCP Socket");
930 AsyncJob::Start(cs);
931 }
932
933 static void
934 idnsSendQueryVC(idns_query * q, int nsn)
935 {
936 assert(nsn < nns);
937 if (nameservers[nsn].vc == NULL)
938 idnsInitVC(nsn);
939
940 nsvc *vc = nameservers[nsn].vc;
941
942 if (!vc) {
943 char buf[MAX_IPSTRLEN];
944 debugs(78, DBG_IMPORTANT, "idnsSendQuery: Failed to initiate TCP connection to nameserver " << nameservers[nsn].S.toStr(buf,MAX_IPSTRLEN) << "!");
945
946 return;
947 }
948
949 vc->queue->reset();
950
951 short head = htons(q->sz);
952
953 vc->queue->append((char *)&head, 2);
954
955 vc->queue->append(q->buf, q->sz);
956
957 idnsDoSendQueryVC(vc);
958 }
959
960 static void
961 idnsSendQuery(idns_query * q)
962 {
963 // XXX: DNS sockets get closed during reconfigure produces a race between
964 // any already active connections (or ones received between closing DNS
965 // sockets and server listening sockets) and the reconfigure completing
966 // (Runner syncConfig() being run). Transactions which loose this race will
967 // produce DNS timeouts (or whatever the caller set) as their queries never
968 // get queued to be re-tried after the DNS socekts are re-opened.
969
970 if (DnsSocketA < 0 && DnsSocketB < 0) {
971 debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS socket!");
972 return;
973 }
974
975 if (nns <= 0) {
976 debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS nameservers known!");
977 return;
978 }
979
980 assert(q->lru.next == NULL);
981
982 assert(q->lru.prev == NULL);
983
984 int x = -1, y = -1;
985 int nsn;
986
987 do {
988 // only use mDNS resolvers for mDNS compatible queries
989 if (!q->permit_mdns)
990 nsn = nns_mdns_count + q->nsends % (nns-nns_mdns_count);
991 else
992 nsn = q->nsends % nns;
993
994 if (q->need_vc) {
995 idnsSendQueryVC(q, nsn);
996 x = y = 0;
997 } else {
998 if (DnsSocketB >= 0 && nameservers[nsn].S.isIPv6())
999 y = comm_udp_sendto(DnsSocketB, nameservers[nsn].S, q->buf, q->sz);
1000 else if (DnsSocketA >= 0)
1001 x = comm_udp_sendto(DnsSocketA, nameservers[nsn].S, q->buf, q->sz);
1002 }
1003 int xerrno = errno;
1004
1005 ++ q->nsends;
1006
1007 q->sent_t = current_time;
1008
1009 if (y < 0 && nameservers[nsn].S.isIPv6())
1010 debugs(50, DBG_IMPORTANT, MYNAME << "FD " << DnsSocketB << ": sendto: " << xstrerr(xerrno));
1011 if (x < 0 && nameservers[nsn].S.isIPv4())
1012 debugs(50, DBG_IMPORTANT, MYNAME << "FD " << DnsSocketA << ": sendto: " << xstrerr(xerrno));
1013
1014 } while ( (x<0 && y<0) && q->nsends % nns != 0);
1015
1016 if (y > 0) {
1017 fd_bytes(DnsSocketB, y, FD_WRITE);
1018 }
1019 if (x > 0) {
1020 fd_bytes(DnsSocketA, x, FD_WRITE);
1021 }
1022
1023 ++ nameservers[nsn].nqueries;
1024 q->queue_t = current_time;
1025 dlinkAdd(q, &q->lru, &lru_list);
1026 q->pending = 1;
1027 idnsTickleQueue();
1028 }
1029
1030 static int
1031 idnsFromKnownNameserver(Ip::Address const &from)
1032 {
1033 int i;
1034
1035 for (i = 0; i < nns; ++i) {
1036 if (nameservers[i].S != from)
1037 continue;
1038
1039 if (nameservers[i].S.port() != from.port())
1040 continue;
1041
1042 return i;
1043 }
1044
1045 return -1;
1046 }
1047
1048 static idns_query *
1049 idnsFindQuery(unsigned short id)
1050 {
1051 dlink_node *n;
1052 idns_query *q;
1053
1054 for (n = lru_list.tail; n; n = n->prev) {
1055 q = (idns_query*)n->data;
1056
1057 if (q->query_id == id)
1058 return q;
1059 }
1060
1061 return NULL;
1062 }
1063
1064 static unsigned short
1065 idnsQueryID()
1066 {
1067 // NP: apparently ranlux are faster, but not quite as "proven"
1068 static std::mt19937 mt(static_cast<uint32_t>(getCurrentTime() & 0xFFFFFFFF));
1069 unsigned short id = mt() & 0xFFFF;
1070 unsigned short first_id = id;
1071
1072 // ensure temporal uniqueness by looking for an existing use
1073 while (idnsFindQuery(id)) {
1074 ++id;
1075
1076 if (id == first_id) {
1077 debugs(78, DBG_IMPORTANT, "idnsQueryID: Warning, too many pending DNS requests");
1078 break;
1079 }
1080 }
1081
1082 return id;
1083 }
1084
1085 static void
1086 idnsCallback(idns_query *q, const char *error)
1087 {
1088 IDNSCB *callback;
1089 void *cbdata;
1090
1091 if (error)
1092 q->error = error;
1093
1094 if (q->master)
1095 q = q->master;
1096
1097 // If any of our subqueries are still pending then wait for them to complete before continuing
1098 for (idns_query *q2 = q; q2; q2 = q2->slave) {
1099 if (q2->pending) {
1100 return;
1101 }
1102 }
1103
1104 /* Merge results */
1105 rfc1035_message *message = q->message;
1106 q->message = NULL;
1107 int n = q->ancount;
1108 error = q->error;
1109
1110 while ( idns_query *q2 = q->slave ) {
1111 debugs(78, 6, HERE << "Merging DNS results " << q->name << " A has " << n << " RR, AAAA has " << q2->ancount << " RR");
1112 q->slave = q2->slave;
1113 q2->slave = NULL;
1114 if ( !q2->error ) {
1115 if (n > 0) {
1116 // two sets of RR need merging
1117 rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q2->ancount) );
1118 if (Config.dns.v4_first) {
1119 memcpy(result, message->answer, (sizeof(rfc1035_rr)*n) );
1120 memcpy(result+n, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
1121 } else {
1122 memcpy(result, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
1123 memcpy(result+q2->ancount, message->answer, (sizeof(rfc1035_rr)*n) );
1124 }
1125 n += q2->ancount;
1126 // HACK WARNING, the answer rr:s have been copied in-place to
1127 // result, do not free them here
1128 safe_free(message->answer);
1129 safe_free(q2->message->answer);
1130 message->answer = result;
1131 message->ancount += q2->message->ancount;
1132 } else {
1133 // first response empty or failed, just use the second
1134 rfc1035MessageDestroy(&message);
1135 message = q2->message;
1136 q2->message = NULL;
1137 n = q2->ancount;
1138 error = NULL;
1139 }
1140 }
1141 delete q2;
1142 }
1143
1144 debugs(78, 6, HERE << "Sending " << n << " (" << (error ? error : "OK") << ") DNS results to caller.");
1145
1146 callback = q->callback;
1147 q->callback = NULL;
1148 const rfc1035_rr *answers = message ? message->answer : NULL;
1149
1150 if (cbdataReferenceValidDone(q->callback_data, &cbdata))
1151 callback(cbdata, answers, n, error);
1152
1153 while (q->queue) {
1154 idns_query *q2 = q->queue;
1155 q->queue = q2->queue;
1156 q2->queue = NULL;
1157
1158 callback = q2->callback;
1159 q2->callback = NULL;
1160
1161 if (cbdataReferenceValidDone(q2->callback_data, &cbdata))
1162 callback(cbdata, answers, n, error);
1163
1164 delete q2;
1165 }
1166
1167 if (q->hash.key) {
1168 hash_remove_link(idns_lookup_hash, &q->hash);
1169 q->hash.key = NULL;
1170 }
1171
1172 rfc1035MessageDestroy(&message);
1173 delete q;
1174 }
1175
1176 static void
1177 idnsGrokReply(const char *buf, size_t sz, int /*from_ns*/)
1178 {
1179 rfc1035_message *message = NULL;
1180
1181 int n = rfc1035MessageUnpack(buf, sz, &message);
1182
1183 if (message == NULL) {
1184 debugs(78, DBG_IMPORTANT, "idnsGrokReply: Malformed DNS response");
1185 return;
1186 }
1187
1188 debugs(78, 3, "idnsGrokReply: QID 0x" << std::hex << message->id << ", " << std::dec << n << " answers");
1189
1190 idns_query *q = idnsFindQuery(message->id);
1191
1192 if (q == NULL) {
1193 debugs(78, 3, "idnsGrokReply: Late response");
1194 rfc1035MessageDestroy(&message);
1195 return;
1196 }
1197
1198 if (rfc1035QueryCompare(&q->query, message->query) != 0) {
1199 debugs(78, 3, "idnsGrokReply: Query mismatch (" << q->query.name << " != " << message->query->name << ")");
1200 rfc1035MessageDestroy(&message);
1201 return;
1202 }
1203
1204 #if WHEN_EDNS_RESPONSES_ARE_PARSED
1205 // TODO: actually gr the message right here.
1206 // pull out the DNS meta data we need (A records, AAAA records and EDNS OPT) and store in q
1207 // this is overall better than force-feeding A response with AAAA an section later anyway.
1208 // AND allows us to merge AN+AR sections from both responses (one day)
1209
1210 if (q->edns_seen >= 0) {
1211 if (max_shared_edns == nameservers[from_ns].last_seen_edns && max_shared_edns < q->edns_seen) {
1212 nameservers[from_ns].last_seen_edns = q->edns_seen;
1213 // the altered NS was limiting the whole group.
1214 max_shared_edns = q->edns_seen;
1215 // may be limited by one of the others still
1216 for (int i = 0; i < nns; ++i)
1217 max_shared_edns = min(max_shared_edns, nameservers[i].last_seen_edns);
1218 } else {
1219 nameservers[from_ns].last_seen_edns = q->edns_seen;
1220 // maybe reduce the global limit downwards to accomodate this NS
1221 max_shared_edns = min(max_shared_edns, q->edns_seen);
1222 }
1223 if (max_shared_edns < RFC1035_DEFAULT_PACKET_SZ)
1224 max_shared_edns = -1;
1225 }
1226 #endif
1227
1228 dlinkDelete(&q->lru, &lru_list);
1229 q->pending = 0;
1230
1231 if (message->tc) {
1232 debugs(78, 3, HERE << "Resolver requested TC (" << q->query.name << ")");
1233 rfc1035MessageDestroy(&message);
1234
1235 if (!q->need_vc) {
1236 q->need_vc = 1;
1237 -- q->nsends;
1238 idnsSendQuery(q);
1239 } else {
1240 // Strange: A TCP DNS response with the truncation bit (TC) set.
1241 // Return an error and cleanup; no point in trying TCP again.
1242 debugs(78, 3, HERE << "TCP DNS response");
1243 idnsCallback(q, "Truncated TCP DNS response");
1244 }
1245
1246 return;
1247 }
1248
1249 idnsRcodeCount(n, q->attempt);
1250
1251 if (n < 0) {
1252 q->rcode = -n;
1253 debugs(78, 3, "idnsGrokReply: error " << rfc1035ErrorMessage(n) << " (" << q->rcode << ")");
1254
1255 if (q->rcode == 2 && (++ q->attempt) < MAX_ATTEMPT) {
1256 /*
1257 * RCODE 2 is "Server failure - The name server was
1258 * unable to process this query due to a problem with
1259 * the name server."
1260 */
1261 debugs(78, 3, "idnsGrokReply: Query result: SERV_FAIL");
1262 rfc1035MessageDestroy(&message);
1263 idnsSendQuery(q);
1264 return;
1265 }
1266
1267 // Do searchpath processing on the master A query only to keep
1268 // things simple. NXDOMAIN is authorative for the label, not
1269 // the record type.
1270 if (q->rcode == 3 && !q->master && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
1271 assert(NULL == message->answer);
1272 strcpy(q->name, q->orig);
1273
1274 debugs(78, 3, "idnsGrokReply: Query result: NXDOMAIN - " << q->name );
1275
1276 if (q->domain < npc) {
1277 strcat(q->name, ".");
1278 strcat(q->name, searchpath[q->domain].domain);
1279 debugs(78, 3, "idnsGrokReply: searchpath used for " << q->name);
1280 ++ q->domain;
1281 } else {
1282 ++ q->attempt;
1283 }
1284
1285 rfc1035MessageDestroy(&message);
1286
1287 // cleanup slave AAAA query
1288 while (idns_query *slave = q->slave) {
1289 dlinkDelete(&slave->lru, &lru_list);
1290 q->slave = slave->slave;
1291 slave->slave = NULL;
1292 delete slave;
1293 }
1294
1295 // Build new query
1296 q->query_id = idnsQueryID();
1297 debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name);
1298 // see EDNS notes at top of file why this sends 0
1299 q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
1300 if (q->sz < 0) {
1301 /* problem with query data -- query not sent */
1302 idnsCallback(q, "Internal error");
1303 return;
1304 }
1305
1306 q->nsends = 0;
1307
1308 idnsCheckMDNS(q);
1309 idnsSendQuery(q);
1310 if (Ip::EnableIpv6)
1311 idnsSendSlaveAAAAQuery(q);
1312 return;
1313 }
1314 }
1315
1316 q->message = message;
1317 q->ancount = n;
1318
1319 if (n >= 0)
1320 idnsCallback(q, NULL);
1321 else
1322 idnsCallback(q, rfc1035ErrorMessage(q->rcode));
1323
1324 }
1325
1326 static void
1327 idnsRead(int fd, void *)
1328 {
1329 int *N = &incoming_sockets_accepted;
1330 int len;
1331 int max = INCOMING_DNS_MAX;
1332 static char rbuf[SQUID_UDP_SO_RCVBUF];
1333 Ip::Address from;
1334
1335 debugs(78, 3, "idnsRead: starting with FD " << fd);
1336
1337 // Always keep reading. This stops (or at least makes harder) several
1338 // attacks on the DNS client.
1339 Comm::SetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0);
1340
1341 /* BUG (UNRESOLVED)
1342 * two code lines after returning from comm_udprecvfrom()
1343 * something overwrites the memory behind the from parameter.
1344 * NO matter where in the stack declaration list above it is placed
1345 * The cause of this is still unknown, however copying the data appears
1346 * to allow it to be passed further without this erasure.
1347 */
1348 Ip::Address bugbypass;
1349
1350 while (max) {
1351 --max;
1352 len = comm_udp_recvfrom(fd, rbuf, SQUID_UDP_SO_RCVBUF, 0, bugbypass);
1353
1354 from = bugbypass; // BUG BYPASS. see notes above.
1355
1356 if (len == 0)
1357 break;
1358
1359 if (len < 0) {
1360 int xerrno = errno;
1361 if (ignoreErrno(xerrno))
1362 break;
1363
1364 #if _SQUID_LINUX_
1365 /* Some Linux systems seem to set the FD for reading and then
1366 * return ECONNREFUSED when sendto() fails and generates an ICMP
1367 * port unreachable message. */
1368 /* or maybe an EHOSTUNREACH "No route to host" message */
1369 if (xerrno != ECONNREFUSED && xerrno != EHOSTUNREACH)
1370 #endif
1371 debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << " recvfrom: " << xstrerr(xerrno));
1372
1373 break;
1374 }
1375
1376 fd_bytes(fd, len, FD_READ);
1377
1378 assert(N);
1379 ++(*N);
1380
1381 debugs(78, 3, "idnsRead: FD " << fd << ": received " << len << " bytes from " << from);
1382
1383 /* BUG: see above. Its here that it becomes apparent that the content of bugbypass is gone. */
1384 int nsn = idnsFromKnownNameserver(from);
1385
1386 if (nsn >= 0) {
1387 ++ nameservers[nsn].nreplies;
1388 }
1389
1390 // Before unknown_nameservers check to avoid flooding cache.log on attacks,
1391 // but after the ++ above to keep statistics right.
1392 if (!lru_list.head)
1393 continue; // Don't process replies if there is no pending query.
1394
1395 if (nsn < 0 && Config.onoff.ignore_unknown_nameservers) {
1396 static time_t last_warning = 0;
1397
1398 if (squid_curtime - last_warning > 60) {
1399 debugs(78, DBG_IMPORTANT, "WARNING: Reply from unknown nameserver " << from);
1400 last_warning = squid_curtime;
1401 } else {
1402 debugs(78, DBG_IMPORTANT, "WARNING: Reply from unknown nameserver " << from << " (retrying..." << (squid_curtime-last_warning) << "<=60)" );
1403 }
1404 continue;
1405 }
1406
1407 idnsGrokReply(rbuf, len, nsn);
1408 }
1409 }
1410
1411 static void
1412 idnsCheckQueue(void *)
1413 {
1414 dlink_node *n;
1415 dlink_node *p = NULL;
1416 idns_query *q;
1417 event_queued = 0;
1418
1419 if (0 == nns)
1420 /* name servers went away; reconfiguring or shutting down */
1421 return;
1422
1423 for (n = lru_list.tail; n; n = p) {
1424
1425 p = n->prev;
1426 q = static_cast<idns_query*>(n->data);
1427
1428 /* Anything to process in the queue? */
1429 if ((time_msec_t)tvSubMsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit )
1430 break;
1431
1432 /* Query timer still running? */
1433 if ((time_msec_t)tvSubMsec(q->sent_t, current_time) < (Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns))) {
1434 dlinkDelete(&q->lru, &lru_list);
1435 q->queue_t = current_time;
1436 dlinkAdd(q, &q->lru, &lru_list);
1437 continue;
1438 }
1439
1440 debugs(78, 3, "idnsCheckQueue: ID " << q->xact_id <<
1441 " QID 0x" << std::hex << std::setfill('0') <<
1442 std::setw(4) << q->query_id << ": timeout" );
1443
1444 dlinkDelete(&q->lru, &lru_list);
1445 q->pending = 0;
1446
1447 if ((time_msec_t)tvSubMsec(q->start_t, current_time) < Config.Timeout.idns_query) {
1448 idnsSendQuery(q);
1449 } else {
1450 debugs(78, 2, "idnsCheckQueue: ID " << q->xact_id <<
1451 " QID 0x" << std::hex << q->query_id <<
1452 " : giving up after " << std::dec << q->nsends << " tries and " <<
1453 std::setw(5)<< std::setprecision(2) << tvSubDsec(q->start_t, current_time) << " seconds");
1454
1455 if (q->rcode != 0)
1456 idnsCallback(q, rfc1035ErrorMessage(q->rcode));
1457 else
1458 idnsCallback(q, "Timeout");
1459 }
1460 }
1461
1462 idnsTickleQueue();
1463 }
1464
1465 static void
1466 idnsReadVC(const Comm::ConnectionPointer &conn, char *buf, size_t len, Comm::Flag flag, int, void *data)
1467 {
1468 nsvc * vc = (nsvc *)data;
1469
1470 if (flag == Comm::ERR_CLOSING)
1471 return;
1472
1473 if (flag != Comm::OK || len <= 0) {
1474 if (Comm::IsConnOpen(conn))
1475 conn->close();
1476 return;
1477 }
1478
1479 vc->msg->size += len; // XXX should not access -> size directly
1480
1481 if (vc->msg->contentSize() < vc->msglen) {
1482 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVC",
1483 CommIoCbPtrFun(idnsReadVC, vc));
1484 comm_read(conn, buf+len, vc->msglen - vc->msg->contentSize(), call);
1485 return;
1486 }
1487
1488 assert(vc->ns < nns);
1489 debugs(78, 3, HERE << conn << ": received " << vc->msg->contentSize() << " bytes via TCP from " << nameservers[vc->ns].S << ".");
1490
1491 idnsGrokReply(vc->msg->buf, vc->msg->contentSize(), vc->ns);
1492 vc->msg->clean();
1493 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
1494 CommIoCbPtrFun(idnsReadVCHeader, vc));
1495 comm_read(conn, (char *)&vc->msglen, 2, call);
1496 }
1497
1498 static void
1499 idnsReadVCHeader(const Comm::ConnectionPointer &conn, char *buf, size_t len, Comm::Flag flag, int, void *data)
1500 {
1501 nsvc * vc = (nsvc *)data;
1502
1503 if (flag == Comm::ERR_CLOSING)
1504 return;
1505
1506 if (flag != Comm::OK || len <= 0) {
1507 if (Comm::IsConnOpen(conn))
1508 conn->close();
1509 return;
1510 }
1511
1512 vc->read_msglen += len;
1513
1514 assert(vc->read_msglen <= 2);
1515
1516 if (vc->read_msglen < 2) {
1517 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
1518 CommIoCbPtrFun(idnsReadVCHeader, vc));
1519 comm_read(conn, buf+len, 2 - vc->read_msglen, call);
1520 return;
1521 }
1522
1523 vc->read_msglen = 0;
1524
1525 vc->msglen = ntohs(vc->msglen);
1526
1527 if (!vc->msglen) {
1528 if (Comm::IsConnOpen(conn))
1529 conn->close();
1530 return;
1531 }
1532
1533 vc->msg->init(vc->msglen, vc->msglen);
1534 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVC",
1535 CommIoCbPtrFun(idnsReadVC, vc));
1536 comm_read(conn, vc->msg->buf, vc->msglen, call);
1537 }
1538
1539 /*
1540 * rcode < 0 indicates an error, rocde >= 0 indicates success
1541 */
1542 static void
1543 idnsRcodeCount(int rcode, int attempt)
1544 {
1545 if (rcode > 0)
1546 rcode = 0;
1547 else if (rcode < 0)
1548 rcode = -rcode;
1549
1550 if (rcode < MAX_RCODE)
1551 if (attempt < MAX_ATTEMPT)
1552 ++ RcodeMatrix[rcode][attempt];
1553 }
1554
1555 void
1556 Dns::Init(void)
1557 {
1558 static int init = 0;
1559
1560 if (DnsSocketA < 0 && DnsSocketB < 0) {
1561 Ip::Address addrV6; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
1562
1563 if (!Config.Addrs.udp_outgoing.isNoAddr())
1564 addrV6 = Config.Addrs.udp_outgoing;
1565 else
1566 addrV6 = Config.Addrs.udp_incoming;
1567
1568 Ip::Address addrV4 = addrV6;
1569 addrV4.setIPv4();
1570
1571 if (Ip::EnableIpv6 && addrV6.isIPv6()) {
1572 debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV6);
1573 DnsSocketB = comm_open_listener(SOCK_DGRAM,
1574 IPPROTO_UDP,
1575 addrV6,
1576 COMM_NONBLOCKING,
1577 "DNS Socket IPv6");
1578 }
1579
1580 if (addrV4.isIPv4()) {
1581 debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV4);
1582 DnsSocketA = comm_open_listener(SOCK_DGRAM,
1583 IPPROTO_UDP,
1584 addrV4,
1585 COMM_NONBLOCKING,
1586 "DNS Socket IPv4");
1587 }
1588
1589 if (DnsSocketA < 0 && DnsSocketB < 0)
1590 fatal("Could not create a DNS socket");
1591
1592 /* Ouch... we can't call functions using debug from a debug
1593 * statement. Doing so messes up the internal Debug::level
1594 */
1595 if (DnsSocketB >= 0) {
1596 comm_local_port(DnsSocketB);
1597 debugs(78, DBG_IMPORTANT, "DNS Socket created at " << addrV6 << ", FD " << DnsSocketB);
1598 Comm::SetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
1599 }
1600 if (DnsSocketA >= 0) {
1601 comm_local_port(DnsSocketA);
1602 debugs(78, DBG_IMPORTANT, "DNS Socket created at " << addrV4 << ", FD " << DnsSocketA);
1603 Comm::SetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
1604 }
1605 }
1606
1607 assert(0 == nns);
1608 idnsAddMDNSNameservers();
1609 bool nsFound = idnsParseNameservers();
1610
1611 if (!nsFound)
1612 nsFound = idnsParseResolvConf();
1613
1614 #if _SQUID_WINDOWS_
1615 if (!nsFound)
1616 nsFound = idnsParseWIN32Registry();
1617 #endif
1618
1619 if (!nsFound) {
1620 debugs(78, DBG_IMPORTANT, "Warning: Could not find any nameservers. Trying to use localhost");
1621 #if _SQUID_WINDOWS_
1622 debugs(78, DBG_IMPORTANT, "Please check your TCP-IP settings or /etc/resolv.conf file");
1623 #else
1624 debugs(78, DBG_IMPORTANT, "Please check your /etc/resolv.conf file");
1625 #endif
1626
1627 debugs(78, DBG_IMPORTANT, "or use the 'dns_nameservers' option in squid.conf.");
1628 if (Ip::EnableIpv6)
1629 idnsAddNameserver("::1");
1630 idnsAddNameserver("127.0.0.1");
1631 }
1632
1633 if (!init) {
1634 memset(RcodeMatrix, '\0', sizeof(RcodeMatrix));
1635 idns_lookup_hash = hash_create((HASHCMP *) strcmp, 103, hash_string);
1636 ++init;
1637 }
1638
1639 #if WHEN_EDNS_RESPONSES_ARE_PARSED
1640 if (Config.onoff.ignore_unknown_nameservers && max_shared_edns > 0) {
1641 debugs(0, DBG_IMPORTANT, "ERROR: cannot negotiate EDNS with unknown nameservers. Disabling");
1642 max_shared_edns = -1; // disable if we might receive random replies.
1643 }
1644 #endif
1645
1646 Mgr::RegisterAction("idns", "Internal DNS Statistics", idnsStats, 0, 1);
1647 }
1648
1649 static void
1650 idnsShutdownAndFreeState(const char *reason)
1651 {
1652 if (DnsSocketA < 0 && DnsSocketB < 0)
1653 return;
1654
1655 debugs(78, 2, reason << ": Closing DNS sockets");
1656
1657 if (DnsSocketA >= 0 ) {
1658 comm_close(DnsSocketA);
1659 DnsSocketA = -1;
1660 }
1661
1662 if (DnsSocketB >= 0 ) {
1663 comm_close(DnsSocketB);
1664 DnsSocketB = -1;
1665 }
1666
1667 for (int i = 0; i < nns; ++i) {
1668 if (nsvc *vc = nameservers[i].vc) {
1669 if (Comm::IsConnOpen(vc->conn))
1670 vc->conn->close();
1671 }
1672 }
1673
1674 // XXX: vcs are not closed/freed yet and may try to access nameservers[]
1675 idnsFreeNameservers();
1676 idnsFreeSearchpath();
1677 }
1678
1679 void
1680 Dns::ConfigRr::endingShutdown()
1681 {
1682 idnsShutdownAndFreeState("Shutdown");
1683 }
1684
1685 void
1686 Dns::ConfigRr::startReconfigure()
1687 {
1688 idnsShutdownAndFreeState("Reconfigure");
1689 }
1690
1691 static int
1692 idnsCachedLookup(const char *key, IDNSCB * callback, void *data)
1693 {
1694 idns_query *old = (idns_query *) hash_lookup(idns_lookup_hash, key);
1695
1696 if (!old)
1697 return 0;
1698
1699 idns_query *q = new idns_query;
1700 // no query_id on this instance.
1701
1702 q->callback = callback;
1703 q->callback_data = cbdataReference(data);
1704
1705 q->queue = old->queue;
1706 old->queue = q;
1707
1708 return 1;
1709 }
1710
1711 static void
1712 idnsStartQuery(idns_query *q, IDNSCB * callback, void *data)
1713 {
1714 q->start_t = current_time;
1715 q->callback = callback;
1716 q->callback_data = cbdataReference(data);
1717
1718 q->hash.key = q->orig;
1719 hash_join(idns_lookup_hash, &q->hash);
1720
1721 idnsSendQuery(q);
1722 }
1723
1724 static void
1725 idnsSendSlaveAAAAQuery(idns_query *master)
1726 {
1727 idns_query *q = new idns_query;
1728 memcpy(q->name, master->name, sizeof(q->name));
1729 memcpy(q->orig, master->orig, sizeof(q->orig));
1730 q->master = master;
1731 q->query_id = idnsQueryID();
1732 q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
1733
1734 debugs(78, 3, HERE << "buf is " << q->sz << " bytes for " << q->name <<
1735 ", id = 0x" << std::hex << q->query_id);
1736 if (!q->sz) {
1737 delete q;
1738 return;
1739 }
1740
1741 q->start_t = master->start_t;
1742 q->slave = master->slave;
1743
1744 idnsCheckMDNS(q);
1745 master->slave = q;
1746 idnsSendQuery(q);
1747 }
1748
1749 void
1750 idnsALookup(const char *name, IDNSCB * callback, void *data)
1751 {
1752 size_t nameLength = strlen(name);
1753
1754 // Prevent buffer overflow on q->name
1755 if (nameLength > NS_MAXDNAME) {
1756 debugs(23, DBG_IMPORTANT, "SECURITY ALERT: DNS name too long to perform lookup: '" << name << "'. see access.log for details.");
1757 callback(data, NULL, 0, "Internal error");
1758 return;
1759 }
1760
1761 if (idnsCachedLookup(name, callback, data))
1762 return;
1763
1764 idns_query *q = new idns_query;
1765 q->query_id = idnsQueryID();
1766
1767 int nd = 0;
1768 for (unsigned int i = 0; i < nameLength; ++i)
1769 if (name[i] == '.')
1770 ++nd;
1771
1772 if (Config.onoff.res_defnames && npc > 0 && name[nameLength-1] != '.') {
1773 q->do_searchpath = 1;
1774 } else {
1775 q->do_searchpath = 0;
1776 }
1777
1778 strcpy(q->orig, name);
1779 strcpy(q->name, q->orig);
1780
1781 if (q->do_searchpath && nd < ndots) {
1782 q->domain = 0;
1783 strcat(q->name, ".");
1784 strcat(q->name, searchpath[q->domain].domain);
1785 debugs(78, 3, "idnsALookup: searchpath used for " << q->name);
1786 }
1787
1788 // see EDNS notes at top of file why this sends 0
1789 q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
1790
1791 if (q->sz < 0) {
1792 /* problem with query data -- query not sent */
1793 callback(data, NULL, 0, "Internal error");
1794 delete q;
1795 return;
1796 }
1797
1798 debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
1799 ", id = 0x" << std::hex << q->query_id);
1800
1801 idnsCheckMDNS(q);
1802 idnsStartQuery(q, callback, data);
1803
1804 if (Ip::EnableIpv6)
1805 idnsSendSlaveAAAAQuery(q);
1806 }
1807
1808 void
1809 idnsPTRLookup(const Ip::Address &addr, IDNSCB * callback, void *data)
1810 {
1811 char ip[MAX_IPSTRLEN];
1812
1813 addr.toStr(ip,MAX_IPSTRLEN);
1814
1815 idns_query *q = new idns_query;
1816 q->query_id = idnsQueryID();
1817
1818 if (addr.isIPv6()) {
1819 struct in6_addr addr6;
1820 addr.getInAddr(addr6);
1821 q->sz = rfc3596BuildPTRQuery6(addr6, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
1822 } else {
1823 struct in_addr addr4;
1824 addr.getInAddr(addr4);
1825 // see EDNS notes at top of file why this sends 0
1826 q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
1827 }
1828
1829 if (q->sz < 0) {
1830 /* problem with query data -- query not sent */
1831 callback(data, NULL, 0, "Internal error");
1832 delete q;
1833 return;
1834 }
1835
1836 if (idnsCachedLookup(q->query.name, callback, data)) {
1837 delete q;
1838 return;
1839 }
1840
1841 debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
1842 ", id = 0x" << std::hex << q->query_id);
1843
1844 q->permit_mdns = Config.onoff.dns_mdns;
1845 idnsStartQuery(q, callback, data);
1846 }
1847
1848 #if SQUID_SNMP
1849 /*
1850 * The function to return the DNS via SNMP
1851 */
1852 variable_list *
1853 snmp_netDnsFn(variable_list * Var, snint * ErrP)
1854 {
1855 int i, n = 0;
1856 variable_list *Answer = NULL;
1857 MemBuf tmp;
1858 debugs(49, 5, "snmp_netDnsFn: Processing request: " << snmpDebugOid(Var->name, Var->name_length, tmp));
1859 *ErrP = SNMP_ERR_NOERROR;
1860
1861 switch (Var->name[LEN_SQ_NET + 1]) {
1862
1863 case DNS_REQ:
1864
1865 for (i = 0; i < nns; ++i)
1866 n += nameservers[i].nqueries;
1867
1868 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1869 n,
1870 SMI_COUNTER32);
1871
1872 break;
1873
1874 case DNS_REP:
1875 for (i = 0; i < nns; ++i)
1876 n += nameservers[i].nreplies;
1877
1878 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1879 n,
1880 SMI_COUNTER32);
1881
1882 break;
1883
1884 case DNS_SERVERS:
1885 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1886 nns,
1887 SMI_COUNTER32);
1888
1889 break;
1890
1891 default:
1892 *ErrP = SNMP_ERR_NOSUCHNAME;
1893
1894 break;
1895 }
1896
1897 return Answer;
1898 }
1899
1900 #endif /*SQUID_SNMP */
1901