]> git.ipfire.org Git - thirdparty/squid.git/blob - src/dns_internal.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / dns_internal.cc
1 /*
2 * Copyright (C) 1996-2018 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 static void idnsCallbackOnEarlyError(IDNSCB *callback, void *cbdata, const char *error);
286
287 static void
288 idnsCheckMDNS(idns_query *q)
289 {
290 if (!Config.onoff.dns_mdns || q->permit_mdns)
291 return;
292
293 size_t slen = strlen(q->name);
294 if (slen > 6 && memcmp(q->name +(slen-6),".local", 6) == 0) {
295 q->permit_mdns = true;
296 }
297 }
298
299 static void
300 idnsAddMDNSNameservers()
301 {
302 nns_mdns_count=0;
303
304 // mDNS is disabled
305 if (!Config.onoff.dns_mdns)
306 return;
307
308 // mDNS resolver addresses are explicit multicast group IPs
309 if (Ip::EnableIpv6) {
310 idnsAddNameserver("FF02::FB");
311 nameservers[nns-1].S.port(5353);
312 nameservers[nns-1].mDNSResolver = true;
313 ++nns_mdns_count;
314 }
315
316 idnsAddNameserver("224.0.0.251");
317 nameservers[nns-1].S.port(5353);
318 nameservers[nns-1].mDNSResolver = true;
319
320 ++nns_mdns_count;
321 }
322
323 static void
324 idnsAddNameserver(const char *buf)
325 {
326 Ip::Address A;
327
328 if (!(A = buf)) {
329 debugs(78, DBG_CRITICAL, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address");
330 return;
331 }
332
333 if (A.isAnyAddr()) {
334 debugs(78, DBG_CRITICAL, "WARNING: Squid does not accept " << A << " in DNS server specifications.");
335 A.setLocalhost();
336 debugs(78, DBG_CRITICAL, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine");
337 }
338
339 if (!Ip::EnableIpv6 && !A.setIPv4()) {
340 debugs(78, DBG_IMPORTANT, "WARNING: IPv6 is disabled. Discarding " << A << " in DNS server specifications.");
341 return;
342 }
343
344 if (nns == nns_alloc) {
345 int oldalloc = nns_alloc;
346 ns *oldptr = nameservers;
347
348 if (nns_alloc == 0)
349 nns_alloc = 2;
350 else
351 nns_alloc <<= 1;
352
353 nameservers = (ns *)xcalloc(nns_alloc, sizeof(*nameservers));
354
355 if (oldptr && oldalloc)
356 memcpy(nameservers, oldptr, oldalloc * sizeof(*nameservers));
357
358 if (oldptr)
359 safe_free(oldptr);
360 }
361
362 assert(nns < nns_alloc);
363 A.port(NS_DEFAULTPORT);
364 nameservers[nns].S = A;
365 #if WHEN_EDNS_RESPONSES_ARE_PARSED
366 nameservers[nns].last_seen_edns = RFC1035_DEFAULT_PACKET_SZ;
367 // TODO generate a test packet to probe this NS from EDNS size and ability.
368 #endif
369 debugs(78, 3, "idnsAddNameserver: Added nameserver #" << nns << " (" << A << ")");
370 ++nns;
371 }
372
373 static void
374 idnsAddPathComponent(const char *buf)
375 {
376 if (npc == npc_alloc) {
377 int oldalloc = npc_alloc;
378 sp *oldptr = searchpath;
379
380 if (0 == npc_alloc)
381 npc_alloc = 2;
382 else
383 npc_alloc <<= 1;
384
385 searchpath = (sp *)xcalloc(npc_alloc, sizeof(*searchpath));
386
387 if (oldptr && oldalloc)
388 memcpy(searchpath, oldptr, oldalloc * sizeof(*searchpath));
389
390 if (oldptr)
391 safe_free(oldptr);
392 }
393
394 assert(npc < npc_alloc);
395 strncpy(searchpath[npc].domain, buf, sizeof(searchpath[npc].domain)-1);
396 searchpath[npc].domain[sizeof(searchpath[npc].domain)-1] = '\0';
397 Tolower(searchpath[npc].domain);
398 debugs(78, 3, "idnsAddPathComponent: Added domain #" << npc << ": " << searchpath[npc].domain);
399 ++npc;
400 }
401
402 static void
403 idnsFreeNameservers(void)
404 {
405 safe_free(nameservers);
406 nns = nns_alloc = 0;
407 }
408
409 static void
410 idnsFreeSearchpath(void)
411 {
412 safe_free(searchpath);
413 npc = npc_alloc = 0;
414 }
415
416 static bool
417 idnsParseNameservers(void)
418 {
419 bool result = false;
420 for (auto &i : Config.dns.nameservers) {
421 debugs(78, DBG_IMPORTANT, "Adding nameserver " << i << " from squid.conf");
422 idnsAddNameserver(i.c_str());
423 result = true;
424 }
425 return result;
426 }
427
428 static bool
429 idnsParseResolvConf(void)
430 {
431 bool result = false;
432 #if !_SQUID_WINDOWS_
433 FILE *fp = fopen(_PATH_RESCONF, "r");
434
435 if (!fp) {
436 int xerrno = errno;
437 debugs(78, DBG_IMPORTANT, "" << _PATH_RESCONF << ": " << xstrerr(xerrno));
438 return false;
439 }
440
441 char buf[RESOLV_BUFSZ];
442 const char *t = NULL;
443 while (fgets(buf, RESOLV_BUFSZ, fp)) {
444 t = strtok(buf, w_space);
445
446 if (NULL == t) {
447 continue;
448 } else if (strcmp(t, "nameserver") == 0) {
449 t = strtok(NULL, w_space);
450
451 if (NULL == t)
452 continue;
453
454 debugs(78, DBG_IMPORTANT, "Adding nameserver " << t << " from " << _PATH_RESCONF);
455
456 idnsAddNameserver(t);
457 result = true;
458 } else if (strcmp(t, "domain") == 0) {
459 idnsFreeSearchpath();
460 t = strtok(NULL, w_space);
461
462 if (NULL == t)
463 continue;
464
465 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
466
467 idnsAddPathComponent(t);
468 } else if (strcmp(t, "search") == 0) {
469 idnsFreeSearchpath();
470 while (NULL != t) {
471 t = strtok(NULL, w_space);
472
473 if (NULL == t)
474 continue;
475
476 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
477
478 idnsAddPathComponent(t);
479 }
480 } else if (strcmp(t, "options") == 0) {
481 while (NULL != t) {
482 t = strtok(NULL, w_space);
483
484 if (NULL == t)
485 continue;
486
487 if (strncmp(t, "ndots:", 6) == 0) {
488 ndots = atoi(t + 6);
489
490 if (ndots < 1)
491 ndots = 1;
492
493 debugs(78, DBG_IMPORTANT, "Adding ndots " << ndots << " from " << _PATH_RESCONF);
494 }
495 }
496 }
497 }
498 if (npc == 0 && (t = getMyHostname())) {
499 t = strchr(t, '.');
500 if (t)
501 idnsAddPathComponent(t+1);
502 }
503
504 fclose(fp);
505 #endif
506 return result;
507 }
508
509 #if _SQUID_WINDOWS_
510 static void
511 idnsParseWIN32SearchList(const char * Separator)
512 {
513 char *t;
514 char *token;
515 HKEY hndKey;
516
517 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
518 DWORD Type = 0;
519 DWORD Size = 0;
520 LONG Result;
521 Result = RegQueryValueEx(hndKey, "Domain", NULL, &Type, NULL, &Size);
522
523 if (Result == ERROR_SUCCESS && Size) {
524 t = (char *) xmalloc(Size);
525 RegQueryValueEx(hndKey, "Domain", NULL, &Type, (LPBYTE) t, &Size);
526 debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from Registry");
527 idnsAddPathComponent(t);
528 xfree(t);
529 }
530 Result = RegQueryValueEx(hndKey, "SearchList", NULL, &Type, NULL, &Size);
531
532 if (Result == ERROR_SUCCESS && Size) {
533 t = (char *) xmalloc(Size);
534 RegQueryValueEx(hndKey, "SearchList", NULL, &Type, (LPBYTE) t, &Size);
535 token = strtok(t, Separator);
536
537 while (token) {
538 idnsAddPathComponent(token);
539 debugs(78, DBG_IMPORTANT, "Adding domain " << token << " from Registry");
540 token = strtok(NULL, Separator);
541 }
542 xfree(t);
543 }
544
545 RegCloseKey(hndKey);
546 }
547 if (npc == 0 && (t = (char *) getMyHostname())) {
548 t = strchr(t, '.');
549 if (t)
550 idnsAddPathComponent(t + 1);
551 }
552 }
553
554 static bool
555 idnsParseWIN32Registry(void)
556 {
557 char *t;
558 char *token;
559 HKEY hndKey, hndKey2;
560 bool result = false;
561
562 switch (WIN32_OS_version) {
563
564 case _WIN_OS_WINNT:
565 /* get nameservers from the Windows NT registry */
566
567 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
568 DWORD Type = 0;
569 DWORD Size = 0;
570 LONG Result;
571 Result = RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, NULL, &Size);
572
573 if (Result == ERROR_SUCCESS && Size) {
574 t = (char *) xmalloc(Size);
575 RegQueryValueEx(hndKey, "DhcpNameServer", NULL, &Type, (LPBYTE) t, &Size);
576 token = strtok(t, ", ");
577
578 while (token) {
579 idnsAddNameserver(token);
580 result = true;
581 debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
582 token = strtok(NULL, ",");
583 }
584 xfree(t);
585 }
586
587 Result = RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size);
588
589 if (Result == ERROR_SUCCESS && Size) {
590 t = (char *) xmalloc(Size);
591 RegQueryValueEx(hndKey, "NameServer", NULL, &Type, (LPBYTE) t, &Size);
592 token = strtok(t, ", ");
593
594 while (token) {
595 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
596 idnsAddNameserver(token);
597 result = true;
598 token = strtok(NULL, ", ");
599 }
600 xfree(t);
601 }
602
603 RegCloseKey(hndKey);
604 }
605
606 idnsParseWIN32SearchList(" ");
607
608 break;
609
610 case _WIN_OS_WIN2K:
611
612 case _WIN_OS_WINXP:
613
614 case _WIN_OS_WINNET:
615
616 case _WIN_OS_WINLON:
617
618 case _WIN_OS_WIN7:
619 /* get nameservers from the Windows 2000 registry */
620 /* search all interfaces for DNS server addresses */
621
622 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_TCPIP_PARA_INTERFACES, 0, KEY_READ, &hndKey) == ERROR_SUCCESS) {
623 int i;
624 DWORD MaxSubkeyLen, InterfacesCount;
625 char *keyname;
626 FILETIME ftLastWriteTime;
627
628 if (RegQueryInfoKey(hndKey, NULL, NULL, NULL, &InterfacesCount, &MaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
629 keyname = (char *) xmalloc(++MaxSubkeyLen);
630 for (i = 0; i < (int) InterfacesCount; ++i) {
631 DWORD j;
632 j = MaxSubkeyLen;
633 if (RegEnumKeyEx(hndKey, i, keyname, &j, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) {
634 char *newkeyname;
635 newkeyname = (char *) xmalloc(sizeof(REG_TCPIP_PARA_INTERFACES) + j + 2);
636 strcpy(newkeyname, REG_TCPIP_PARA_INTERFACES);
637 strcat(newkeyname, "\\");
638 strcat(newkeyname, keyname);
639 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, newkeyname, 0, KEY_QUERY_VALUE, &hndKey2) == ERROR_SUCCESS) {
640 DWORD Type = 0;
641 DWORD Size = 0;
642 LONG Result;
643 Result = RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, &Type, NULL, &Size);
644 if (Result == ERROR_SUCCESS && Size) {
645 t = (char *) xmalloc(Size);
646 RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, &Type, (LPBYTE)t, &Size);
647 token = strtok(t, ", ");
648 while (token) {
649 debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
650 idnsAddNameserver(token);
651 result = true;
652 token = strtok(NULL, ", ");
653 }
654 xfree(t);
655 }
656
657 Result = RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, NULL, &Size);
658 if (Result == ERROR_SUCCESS && Size) {
659 t = (char *) xmalloc(Size);
660 RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, (LPBYTE)t, &Size);
661 token = strtok(t, ", ");
662 while (token) {
663 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
664 idnsAddNameserver(token);
665 result = true;
666 token = strtok(NULL, ", ");
667 }
668
669 xfree(t);
670 }
671
672 RegCloseKey(hndKey2);
673 }
674
675 xfree(newkeyname);
676 }
677 }
678
679 xfree(keyname);
680 }
681
682 RegCloseKey(hndKey);
683 }
684
685 idnsParseWIN32SearchList(", ");
686
687 break;
688
689 case _WIN_OS_WIN95:
690
691 case _WIN_OS_WIN98:
692
693 case _WIN_OS_WINME:
694 /* get nameservers from the Windows 9X registry */
695
696 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_VXD_MSTCP, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) {
697 DWORD Type = 0;
698 DWORD Size = 0;
699 LONG Result;
700 Result = RegQueryValueEx(hndKey, "NameServer", NULL, &Type, NULL, &Size);
701
702 if (Result == ERROR_SUCCESS && Size) {
703 t = (char *) xmalloc(Size);
704 RegQueryValueEx(hndKey, "NameServer", NULL, &Type, (LPBYTE) t, &Size);
705 token = strtok(t, ", ");
706
707 while (token) {
708 debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
709 idnsAddNameserver(token);
710 result = true;
711 token = strtok(NULL, ", ");
712 }
713 xfree(t);
714 }
715
716 RegCloseKey(hndKey);
717 }
718
719 break;
720
721 default:
722 debugs(78, DBG_IMPORTANT, "Failed to read nameserver from Registry: Unknown System Type.");
723 }
724
725 return result;
726 }
727
728 #endif
729
730 static void
731 idnsStats(StoreEntry * sentry)
732 {
733 dlink_node *n;
734 idns_query *q;
735 int i;
736 int j;
737 char buf[MAX_IPSTRLEN];
738 storeAppendPrintf(sentry, "Internal DNS Statistics:\n");
739 storeAppendPrintf(sentry, "\nThe Queue:\n");
740 storeAppendPrintf(sentry, " DELAY SINCE\n");
741 storeAppendPrintf(sentry, " ID SIZE SENDS FIRST SEND LAST SEND M FQDN\n");
742 storeAppendPrintf(sentry, "------ ---- ----- ---------- --------- - ----\n");
743
744 for (n = lru_list.head; n; n = n->next) {
745 q = (idns_query *)n->data;
746 storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f %c %s\n",
747 (int) q->query_id, (int) q->sz, q->nsends,
748 tvSubDsec(q->start_t, current_time),
749 tvSubDsec(q->sent_t, current_time),
750 (q->permit_mdns? 'M':' '),
751 q->name);
752 }
753
754 if (Config.dns.packet_max > 0)
755 storeAppendPrintf(sentry, "\nDNS jumbo-grams: %zd Bytes\n", Config.dns.packet_max);
756 else
757 storeAppendPrintf(sentry, "\nDNS jumbo-grams: not working\n");
758
759 storeAppendPrintf(sentry, "\nNameservers:\n");
760 storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES Type\n");
761 storeAppendPrintf(sentry, "---------------------------------------------- --------- --------- --------\n");
762
763 for (i = 0; i < nns; ++i) {
764 storeAppendPrintf(sentry, "%-45s %9d %9d %s\n", /* Let's take the maximum: (15 IPv4/45 IPv6) */
765 nameservers[i].S.toStr(buf,MAX_IPSTRLEN),
766 nameservers[i].nqueries,
767 nameservers[i].nreplies,
768 nameservers[i].mDNSResolver?"multicast":"recurse");
769 }
770
771 storeAppendPrintf(sentry, "\nRcode Matrix:\n");
772 storeAppendPrintf(sentry, "RCODE");
773
774 for (i = 0; i < MAX_ATTEMPT; ++i)
775 storeAppendPrintf(sentry, " ATTEMPT%d", i + 1);
776
777 storeAppendPrintf(sentry, " PROBLEM\n");
778
779 for (j = 0; j < MAX_RCODE; ++j) {
780 if (j > 10 && j < 16)
781 continue; // unassigned by IANA.
782
783 storeAppendPrintf(sentry, "%5d", j);
784
785 for (i = 0; i < MAX_ATTEMPT; ++i)
786 storeAppendPrintf(sentry, " %8d", RcodeMatrix[j][i]);
787
788 storeAppendPrintf(sentry, " : %s\n",Rcodes[j]);
789 }
790
791 if (npc) {
792 storeAppendPrintf(sentry, "\nSearch list:\n");
793
794 for (i=0; i < npc; ++i)
795 storeAppendPrintf(sentry, "%s\n", searchpath[i].domain);
796
797 storeAppendPrintf(sentry, "\n");
798 }
799 }
800
801 static void
802 idnsTickleQueue(void)
803 {
804 if (event_queued)
805 return;
806
807 if (NULL == lru_list.tail)
808 return;
809
810 const double when = min(Config.Timeout.idns_query, Config.Timeout.idns_retransmit)/1000.0;
811
812 eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, when, 1);
813
814 event_queued = 1;
815 }
816
817 static void
818 idnsSentQueryVC(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int, void *data)
819 {
820 nsvc * vc = (nsvc *)data;
821
822 if (flag == Comm::ERR_CLOSING)
823 return;
824
825 // XXX: irrelevant now that we have conn pointer?
826 if (!Comm::IsConnOpen(conn) || fd_table[conn->fd].closing())
827 return;
828
829 if (flag != Comm::OK || size <= 0) {
830 conn->close();
831 return;
832 }
833
834 vc->busy = 0;
835 idnsDoSendQueryVC(vc);
836 }
837
838 static void
839 idnsDoSendQueryVC(nsvc *vc)
840 {
841 if (vc->busy)
842 return;
843
844 if (vc->queue->contentSize() == 0)
845 return;
846
847 // if retrying after a TC UDP response, our close handler cb may be pending
848 if (fd_table[vc->conn->fd].closing())
849 return;
850
851 MemBuf *mb = vc->queue;
852
853 vc->queue = new MemBuf;
854
855 vc->busy = 1;
856
857 // Comm needs seconds but idnsCheckQueue() will check the exact timeout
858 const int timeout = (Config.Timeout.idns_query % 1000 ?
859 Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
860 AsyncCall::Pointer nil;
861
862 commSetConnTimeout(vc->conn, timeout, nil);
863
864 AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC",
865 CommIoCbPtrFun(&idnsSentQueryVC, vc));
866 Comm::Write(vc->conn, mb, call);
867
868 delete mb;
869 }
870
871 static void
872 idnsInitVCConnected(const Comm::ConnectionPointer &conn, Comm::Flag status, int, void *data)
873 {
874 nsvc * vc = (nsvc *)data;
875
876 if (status != Comm::OK || !conn) {
877 char buf[MAX_IPSTRLEN] = "";
878 if (vc->ns < nns)
879 nameservers[vc->ns].S.toStr(buf,MAX_IPSTRLEN);
880 debugs(78, DBG_IMPORTANT, HERE << "Failed to connect to nameserver " << buf << " using TCP.");
881 return;
882 }
883
884 vc->conn = conn;
885
886 comm_add_close_handler(conn->fd, idnsVCClosed, vc);
887 AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
888 CommIoCbPtrFun(idnsReadVCHeader, vc));
889 comm_read(conn, (char *)&vc->msglen, 2, call);
890 vc->busy = 0;
891 idnsDoSendQueryVC(vc);
892 }
893
894 static void
895 idnsVCClosed(const CommCloseCbParams &params)
896 {
897 nsvc * vc = (nsvc *)params.data;
898 delete vc;
899 }
900
901 nsvc::~nsvc()
902 {
903 delete queue;
904 delete msg;
905 if (ns < nns) // XXX: idnsShutdownAndFreeState may have freed nameservers[]
906 nameservers[ns].vc = NULL;
907 }
908
909 static void
910 idnsInitVC(int nsv)
911 {
912 nsvc *vc = new nsvc(nsv);
913 assert(nsv < nns);
914 assert(vc->conn == NULL); // MUST be NULL from the construction process!
915 nameservers[nsv].vc = vc;
916
917 Comm::ConnectionPointer conn = new Comm::Connection();
918
919 if (!Config.Addrs.udp_outgoing.isNoAddr())
920 conn->setAddrs(Config.Addrs.udp_outgoing, nameservers[nsv].S);
921 else
922 conn->setAddrs(Config.Addrs.udp_incoming, nameservers[nsv].S);
923
924 if (conn->remote.isIPv4())
925 conn->local.setIPv4();
926
927 AsyncCall::Pointer call = commCbCall(78,3, "idnsInitVCConnected", CommConnectCbPtrFun(idnsInitVCConnected, vc));
928
929 Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, Config.Timeout.connect);
930 cs->setHost("DNS TCP Socket");
931 AsyncJob::Start(cs);
932 }
933
934 static void
935 idnsSendQueryVC(idns_query * q, int nsn)
936 {
937 assert(nsn < nns);
938 if (nameservers[nsn].vc == NULL)
939 idnsInitVC(nsn);
940
941 nsvc *vc = nameservers[nsn].vc;
942
943 if (!vc) {
944 char buf[MAX_IPSTRLEN];
945 debugs(78, DBG_IMPORTANT, "idnsSendQuery: Failed to initiate TCP connection to nameserver " << nameservers[nsn].S.toStr(buf,MAX_IPSTRLEN) << "!");
946
947 return;
948 }
949
950 vc->queue->reset();
951
952 short head = htons(q->sz);
953
954 vc->queue->append((char *)&head, 2);
955
956 vc->queue->append(q->buf, q->sz);
957
958 idnsDoSendQueryVC(vc);
959 }
960
961 static void
962 idnsSendQuery(idns_query * q)
963 {
964 // XXX: DNS sockets get closed during reconfigure produces a race between
965 // any already active connections (or ones received between closing DNS
966 // sockets and server listening sockets) and the reconfigure completing
967 // (Runner syncConfig() being run). Transactions which loose this race will
968 // produce DNS timeouts (or whatever the caller set) as their queries never
969 // get queued to be re-tried after the DNS socekts are re-opened.
970
971 if (DnsSocketA < 0 && DnsSocketB < 0) {
972 debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS socket!");
973 return;
974 }
975
976 if (nns <= 0) {
977 debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS nameservers known!");
978 return;
979 }
980
981 assert(q->lru.next == NULL);
982
983 assert(q->lru.prev == NULL);
984
985 int x = -1, y = -1;
986 int nsn;
987
988 do {
989 // only use mDNS resolvers for mDNS compatible queries
990 if (!q->permit_mdns)
991 nsn = nns_mdns_count + q->nsends % (nns-nns_mdns_count);
992 else
993 nsn = q->nsends % nns;
994
995 if (q->need_vc) {
996 idnsSendQueryVC(q, nsn);
997 x = y = 0;
998 } else {
999 if (DnsSocketB >= 0 && nameservers[nsn].S.isIPv6())
1000 y = comm_udp_sendto(DnsSocketB, nameservers[nsn].S, q->buf, q->sz);
1001 else if (DnsSocketA >= 0)
1002 x = comm_udp_sendto(DnsSocketA, nameservers[nsn].S, q->buf, q->sz);
1003 }
1004 int xerrno = errno;
1005
1006 ++ q->nsends;
1007
1008 q->sent_t = current_time;
1009
1010 if (y < 0 && nameservers[nsn].S.isIPv6())
1011 debugs(50, DBG_IMPORTANT, MYNAME << "FD " << DnsSocketB << ": sendto: " << xstrerr(xerrno));
1012 if (x < 0 && nameservers[nsn].S.isIPv4())
1013 debugs(50, DBG_IMPORTANT, MYNAME << "FD " << DnsSocketA << ": sendto: " << xstrerr(xerrno));
1014
1015 } while ( (x<0 && y<0) && q->nsends % nns != 0);
1016
1017 if (y > 0) {
1018 fd_bytes(DnsSocketB, y, FD_WRITE);
1019 }
1020 if (x > 0) {
1021 fd_bytes(DnsSocketA, x, FD_WRITE);
1022 }
1023
1024 ++ nameservers[nsn].nqueries;
1025 q->queue_t = current_time;
1026 dlinkAdd(q, &q->lru, &lru_list);
1027 q->pending = 1;
1028 idnsTickleQueue();
1029 }
1030
1031 static int
1032 idnsFromKnownNameserver(Ip::Address const &from)
1033 {
1034 int i;
1035
1036 for (i = 0; i < nns; ++i) {
1037 if (nameservers[i].S != from)
1038 continue;
1039
1040 if (nameservers[i].S.port() != from.port())
1041 continue;
1042
1043 return i;
1044 }
1045
1046 return -1;
1047 }
1048
1049 static idns_query *
1050 idnsFindQuery(unsigned short id)
1051 {
1052 dlink_node *n;
1053 idns_query *q;
1054
1055 for (n = lru_list.tail; n; n = n->prev) {
1056 q = (idns_query*)n->data;
1057
1058 if (q->query_id == id)
1059 return q;
1060 }
1061
1062 return NULL;
1063 }
1064
1065 static unsigned short
1066 idnsQueryID()
1067 {
1068 // NP: apparently ranlux are faster, but not quite as "proven"
1069 static std::mt19937 mt(static_cast<uint32_t>(getCurrentTime() & 0xFFFFFFFF));
1070 unsigned short id = mt() & 0xFFFF;
1071 unsigned short first_id = id;
1072
1073 // ensure temporal uniqueness by looking for an existing use
1074 while (idnsFindQuery(id)) {
1075 ++id;
1076
1077 if (id == first_id) {
1078 debugs(78, DBG_IMPORTANT, "idnsQueryID: Warning, too many pending DNS requests");
1079 break;
1080 }
1081 }
1082
1083 return id;
1084 }
1085
1086 /// \returns whether master or associated queries are still waiting for replies
1087 static bool
1088 idnsStillPending(const idns_query *master)
1089 {
1090 assert(!master->master); // we were given the master transaction
1091 for (const idns_query *qi = master; qi; qi = qi->slave) {
1092 if (qi->pending)
1093 return true;
1094 }
1095 return false;
1096 }
1097
1098 static std::ostream &
1099 operator <<(std::ostream &os, const idns_query &answered)
1100 {
1101 if (answered.error)
1102 os << "error \"" << answered.error << "\"";
1103 else
1104 os << answered.ancount << " records";
1105 return os;
1106 }
1107
1108 static void
1109 idnsCallbackOnEarlyError(IDNSCB *callback, void *cbdata, const char *error)
1110 {
1111 // A cbdataReferenceValid() check asserts on unlocked cbdata: Early errors,
1112 // by definition, happen before we store/cbdataReference() cbdata.
1113 debugs(78, 6, "\"" << error << "\" for " << cbdata);
1114 callback(cbdata, nullptr, 0, "Internal error", true); // hide error details
1115 }
1116
1117 /// safely sends one set of DNS records (or an error) to the caller
1118 static bool
1119 idnsCallbackOneWithAnswer(IDNSCB *callback, void *cbdata, const idns_query &answered, const bool lastAnswer)
1120 {
1121 if (!cbdataReferenceValid(cbdata))
1122 return false;
1123 const rfc1035_rr *records = answered.message ? answered.message->answer : nullptr;
1124 debugs(78, 6, (lastAnswer ? "last " : "") << answered << " for " << cbdata);
1125 callback(cbdata, records, answered.ancount, answered.error, lastAnswer);
1126 return true;
1127 }
1128
1129 static void
1130 idnsCallbackNewCallerWithOldAnswers(IDNSCB *callback, void *cbdata, const idns_query * const master)
1131 {
1132 const bool lastAnswer = false;
1133 // iterate all queries to act on answered ones
1134 for (auto query = master; query; query = query->slave) {
1135 if (query->pending)
1136 continue; // no answer yet
1137 if (!idnsCallbackOneWithAnswer(callback, cbdata, *query, lastAnswer))
1138 break; // the caller disappeared
1139 }
1140 }
1141
1142 static void
1143 idnsCallbackAllCallersWithNewAnswer(const idns_query * const answered, const bool lastAnswer)
1144 {
1145 debugs(78, 8, (lastAnswer ? "last " : "") << *answered);
1146 const auto master = answered->master ? answered->master : answered;
1147 // iterate all queued lookup callers
1148 for (auto looker = master; looker; looker = looker->queue) {
1149 (void)idnsCallbackOneWithAnswer(looker->callback, looker->callback_data,
1150 *answered, lastAnswer);
1151 }
1152 }
1153
1154 static void
1155 idnsCallback(idns_query *q, const char *error)
1156 {
1157 if (error)
1158 q->error = error;
1159
1160 auto master = q->master ? q->master : q;
1161
1162 const bool lastAnswer = !idnsStillPending(master);
1163 idnsCallbackAllCallersWithNewAnswer(q, lastAnswer);
1164
1165 if (!lastAnswer)
1166 return; // wait for more answers
1167
1168 if (master->hash.key) {
1169 hash_remove_link(idns_lookup_hash, &master->hash);
1170 master->hash.key = nullptr;
1171 }
1172
1173 delete master;
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 // This check must follow cbdataReference() above because our callback code
1709 // needs a locked cbdata to call cbdataReferenceValid().
1710 if (idnsStillPending(old))
1711 idnsCallbackNewCallerWithOldAnswers(callback, data, old);
1712 // else: idns_lookup_hash is not a cache so no pending lookups means we are
1713 // in a reentrant lookup and will be called back when dequeued.
1714
1715 return 1;
1716 }
1717
1718 static void
1719 idnsStartQuery(idns_query *q, IDNSCB * callback, void *data)
1720 {
1721 q->start_t = current_time;
1722 q->callback = callback;
1723 q->callback_data = cbdataReference(data);
1724
1725 q->hash.key = q->orig;
1726 hash_join(idns_lookup_hash, &q->hash);
1727
1728 idnsSendQuery(q);
1729 }
1730
1731 static void
1732 idnsSendSlaveAAAAQuery(idns_query *master)
1733 {
1734 idns_query *q = new idns_query;
1735 memcpy(q->name, master->name, sizeof(q->name));
1736 memcpy(q->orig, master->orig, sizeof(q->orig));
1737 q->master = master;
1738 q->query_id = idnsQueryID();
1739 q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
1740
1741 debugs(78, 3, HERE << "buf is " << q->sz << " bytes for " << q->name <<
1742 ", id = 0x" << std::hex << q->query_id);
1743 if (!q->sz) {
1744 delete q;
1745 return;
1746 }
1747
1748 q->start_t = master->start_t;
1749 q->slave = master->slave;
1750
1751 idnsCheckMDNS(q);
1752 master->slave = q;
1753 idnsSendQuery(q);
1754 }
1755
1756 void
1757 idnsALookup(const char *name, IDNSCB * callback, void *data)
1758 {
1759 size_t nameLength = strlen(name);
1760
1761 // Prevent buffer overflow on q->name
1762 if (nameLength > NS_MAXDNAME) {
1763 debugs(23, DBG_IMPORTANT, "SECURITY ALERT: DNS name too long to perform lookup: '" << name << "'. see access.log for details.");
1764 idnsCallbackOnEarlyError(callback, data, "huge name");
1765 return;
1766 }
1767
1768 if (idnsCachedLookup(name, callback, data))
1769 return;
1770
1771 idns_query *q = new idns_query;
1772 q->query_id = idnsQueryID();
1773
1774 int nd = 0;
1775 for (unsigned int i = 0; i < nameLength; ++i)
1776 if (name[i] == '.')
1777 ++nd;
1778
1779 if (Config.onoff.res_defnames && npc > 0 && name[nameLength-1] != '.') {
1780 q->do_searchpath = 1;
1781 } else {
1782 q->do_searchpath = 0;
1783 }
1784
1785 strcpy(q->orig, name);
1786 strcpy(q->name, q->orig);
1787
1788 if (q->do_searchpath && nd < ndots) {
1789 q->domain = 0;
1790 strcat(q->name, ".");
1791 strcat(q->name, searchpath[q->domain].domain);
1792 debugs(78, 3, "idnsALookup: searchpath used for " << q->name);
1793 }
1794
1795 // see EDNS notes at top of file why this sends 0
1796 q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
1797
1798 if (q->sz < 0) {
1799 /* problem with query data -- query not sent */
1800 idnsCallbackOnEarlyError(callback, data, "rfc3596BuildAQuery error");
1801 delete q;
1802 return;
1803 }
1804
1805 debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
1806 ", id = 0x" << std::hex << q->query_id);
1807
1808 idnsCheckMDNS(q);
1809 idnsStartQuery(q, callback, data);
1810
1811 if (Ip::EnableIpv6)
1812 idnsSendSlaveAAAAQuery(q);
1813 }
1814
1815 void
1816 idnsPTRLookup(const Ip::Address &addr, IDNSCB * callback, void *data)
1817 {
1818 char ip[MAX_IPSTRLEN];
1819
1820 addr.toStr(ip,MAX_IPSTRLEN);
1821
1822 idns_query *q = new idns_query;
1823 q->query_id = idnsQueryID();
1824
1825 if (addr.isIPv6()) {
1826 struct in6_addr addr6;
1827 addr.getInAddr(addr6);
1828 q->sz = rfc3596BuildPTRQuery6(addr6, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
1829 } else {
1830 struct in_addr addr4;
1831 addr.getInAddr(addr4);
1832 // see EDNS notes at top of file why this sends 0
1833 q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
1834 }
1835
1836 if (q->sz < 0) {
1837 /* problem with query data -- query not sent */
1838 idnsCallbackOnEarlyError(callback, data, "rfc3596BuildPTRQuery error");
1839 delete q;
1840 return;
1841 }
1842
1843 if (idnsCachedLookup(q->query.name, callback, data)) {
1844 delete q;
1845 return;
1846 }
1847
1848 debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
1849 ", id = 0x" << std::hex << q->query_id);
1850
1851 q->permit_mdns = Config.onoff.dns_mdns;
1852 idnsStartQuery(q, callback, data);
1853 }
1854
1855 #if SQUID_SNMP
1856 /*
1857 * The function to return the DNS via SNMP
1858 */
1859 variable_list *
1860 snmp_netDnsFn(variable_list * Var, snint * ErrP)
1861 {
1862 int i, n = 0;
1863 variable_list *Answer = NULL;
1864 MemBuf tmp;
1865 debugs(49, 5, "snmp_netDnsFn: Processing request: " << snmpDebugOid(Var->name, Var->name_length, tmp));
1866 *ErrP = SNMP_ERR_NOERROR;
1867
1868 switch (Var->name[LEN_SQ_NET + 1]) {
1869
1870 case DNS_REQ:
1871
1872 for (i = 0; i < nns; ++i)
1873 n += nameservers[i].nqueries;
1874
1875 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1876 n,
1877 SMI_COUNTER32);
1878
1879 break;
1880
1881 case DNS_REP:
1882 for (i = 0; i < nns; ++i)
1883 n += nameservers[i].nreplies;
1884
1885 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1886 n,
1887 SMI_COUNTER32);
1888
1889 break;
1890
1891 case DNS_SERVERS:
1892 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1893 nns,
1894 SMI_COUNTER32);
1895
1896 break;
1897
1898 default:
1899 *ErrP = SNMP_ERR_NOSUCHNAME;
1900
1901 break;
1902 }
1903
1904 return Answer;
1905 }
1906
1907 #endif /*SQUID_SNMP */
1908