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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors