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