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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors