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