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