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