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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors