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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors