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