*/
#include "squid.h"
+#include "base/InstanceId.h"
+#include "comm/Connection.h"
+#include "comm/ConnOpener.h"
#include "comm.h"
#include "comm/Loops.h"
#include "comm/Write.h"
#include "event.h"
-#include "SquidTime.h"
-#include "Store.h"
#include "fde.h"
#include "ip/tools.h"
#include "MemBuf.h"
#include "mgr/Registration.h"
+#include "protos.h"
+#include "rfc3596.h"
+#include "SquidTime.h"
+#include "Store.h"
#include "util.h"
#include "wordlist.h"
-#include "base/InstanceId.h"
#if HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#if HAVE_RESOLV_H
#include <resolv.h>
#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
/* MS Visual Studio Projects are monolithic, so we need the following
#ifndef to exclude the internal DNS code from compile process when
using external DNS process.
*/
-#if !USE_DNSSERVERS
+#if !USE_DNSHELPER
#if _SQUID_WINDOWS_
#include "squid_windows.h"
#define REG_TCPIP_PARA_INTERFACES "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"
char buf[RESOLV_BUFSZ];
char name[NS_MAXDNAME + 1];
char orig[NS_MAXDNAME + 1];
- size_t sz;
- unsigned short msg_id; /// random query ID sent to server; changes with every query sent
+ ssize_t sz;
+ unsigned short query_id; /// random query ID sent to server; changes with every query sent
InstanceId<idns_query> xact_id; /// identifies our "transaction", stays constant when query is retried
int nsends;
int need_vc;
+ int pending;
struct timeval start_t;
struct timeval sent_t;
int attempt;
int rcode;
idns_query *queue;
+ idns_query *slave; // single linked list
+ idns_query *master; // single pointer to a shared master
unsigned short domain;
unsigned short do_searchpath;
- bool need_A;
- struct {
- int count;
- rfc1035_rr *answers;
- } initial_AAAA;
+ rfc1035_message *message;
+ int ancount;
+ const char *error;
};
InstanceIdDefinitions(idns_query, "dns");
struct _nsvc {
int ns;
- int fd;
+ Comm::ConnectionPointer conn;
unsigned short msglen;
int read_msglen;
MemBuf *msg;
static void idnsFreeNameservers(void);
static void idnsFreeSearchpath(void);
static void idnsParseNameservers(void);
-#ifndef _SQUID_MSWIN_
+#if !_SQUID_MSWIN_
static void idnsParseResolvConf(void);
#endif
#if _SQUID_WINDOWS_
static void idnsParseWIN32Registry(void);
static void idnsParseWIN32SearchList(const char *);
#endif
-static void idnsCacheQuery(idns_query * q);
+static void idnsStartQuery(idns_query * q, IDNSCB * callback, void *data);
static void idnsSendQuery(idns_query * q);
static IOCB idnsReadVCHeader;
static void idnsDoSendQueryVC(nsvc *vc);
+static CNCB idnsInitVCConnected;
+static IOCB idnsReadVC;
+static IOCB idnsSentQueryVC;
static int idnsFromKnownNameserver(Ip::Address const &from);
static idns_query *idnsFindQuery(unsigned short id);
static EVH idnsCheckQueue;
static void idnsTickleQueue(void);
static void idnsRcodeCount(int, int);
+static CLCB idnsVCClosed;
static unsigned short idnsQueryID(void);
+static void idnsSendSlaveAAAAQuery(idns_query *q);
static void
idnsAddNameserver(const char *buf)
Ip::Address A;
if (!(A = buf)) {
- debugs(78, 0, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address");
+ debugs(78, DBG_CRITICAL, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address");
return;
}
if (A.IsAnyAddr()) {
- debugs(78, 0, "WARNING: Squid does not accept " << A << " in DNS server specifications.");
+ debugs(78, DBG_CRITICAL, "WARNING: Squid does not accept " << A << " in DNS server specifications.");
A.SetLocalhost();
- debugs(78, 0, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine");
+ debugs(78, DBG_CRITICAL, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine");
}
if (!Ip::EnableIpv6 && !A.SetIPv4()) {
// TODO generate a test packet to probe this NS from EDNS size and ability.
#endif
debugs(78, 3, "idnsAddNameserver: Added nameserver #" << nns << " (" << A << ")");
- nns++;
+ ++nns;
}
static void
strcpy(searchpath[npc].domain, buf);
Tolower(searchpath[npc].domain);
debugs(78, 3, "idnsAddPathComponent: Added domain #" << npc << ": " << searchpath[npc].domain);
- npc++;
+ ++npc;
}
-
static void
idnsFreeNameservers(void)
{
npc = npc_alloc = 0;
}
-
-
static void
idnsParseNameservers(void)
{
wordlist *w;
for (w = Config.dns_nameservers; w; w = w->next) {
- debugs(78, 1, "Adding nameserver " << w->key << " from squid.conf");
+ debugs(78, DBG_IMPORTANT, "Adding nameserver " << w->key << " from squid.conf");
idnsAddNameserver(w->key);
}
}
-#ifndef _SQUID_MSWIN_
+#if !_SQUID_MSWIN_
static void
idnsParseResolvConf(void)
{
fp = fopen(_PATH_RESCONF, "r");
if (fp == NULL) {
- debugs(78, 1, "" << _PATH_RESCONF << ": " << xstrerror());
+ debugs(78, DBG_IMPORTANT, "" << _PATH_RESCONF << ": " << xstrerror());
return;
}
if (NULL == t)
continue;
- debugs(78, 1, "Adding nameserver " << t << " from " << _PATH_RESCONF);
+ debugs(78, DBG_IMPORTANT, "Adding nameserver " << t << " from " << _PATH_RESCONF);
idnsAddNameserver(t);
} else if (strcasecmp(t, "domain") == 0) {
if (NULL == t)
continue;
- debugs(78, 1, "Adding domain " << t << " from " << _PATH_RESCONF);
+ debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
idnsAddPathComponent(t);
} else if (strcasecmp(t, "search") == 0) {
if (NULL == t)
continue;
- debugs(78, 1, "Adding domain " << t << " from " << _PATH_RESCONF);
+ debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from " << _PATH_RESCONF);
idnsAddPathComponent(t);
}
if (ndots < 1)
ndots = 1;
- debugs(78, 1, "Adding ndots " << ndots << " from " << _PATH_RESCONF);
+ debugs(78, DBG_IMPORTANT, "Adding ndots " << ndots << " from " << _PATH_RESCONF);
}
}
}
if (Result == ERROR_SUCCESS && Size) {
t = (char *) xmalloc(Size);
RegQueryValueEx(hndKey, "Domain", NULL, &Type, (LPBYTE) t, &Size);
- debugs(78, 1, "Adding domain " << t << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding domain " << t << " from Registry");
idnsAddPathComponent(t);
xfree(t);
}
while (token) {
idnsAddPathComponent(token);
- debugs(78, 1, "Adding domain " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding domain " << token << " from Registry");
token = strtok(NULL, Separator);
}
xfree(t);
while (token) {
idnsAddNameserver(token);
- debugs(78, 1, "Adding DHCP nameserver " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
token = strtok(NULL, ",");
}
xfree(t);
token = strtok(t, ", ");
while (token) {
- debugs(78, 1, "Adding nameserver " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
idnsAddNameserver(token);
token = strtok(NULL, ", ");
}
if (RegQueryInfoKey(hndKey, NULL, NULL, NULL, &InterfacesCount, &MaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
keyname = (char *) xmalloc(++MaxSubkeyLen);
- for (i = 0; i < (int) InterfacesCount; i++) {
+ for (i = 0; i < (int) InterfacesCount; ++i) {
DWORD j;
j = MaxSubkeyLen;
if (RegEnumKeyEx(hndKey, i, keyname, &j, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) {
RegQueryValueEx(hndKey2, "DhcpNameServer", NULL, &Type, (LPBYTE)t, &Size);
token = strtok(t, ", ");
while (token) {
- debugs(78, 1, "Adding DHCP nameserver " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " << token << " from Registry");
idnsAddNameserver(token);
token = strtok(NULL, ", ");
}
RegQueryValueEx(hndKey2, "NameServer", NULL, &Type, (LPBYTE)t, &Size);
token = strtok(t, ", ");
while (token) {
- debugs(78, 1, "Adding nameserver " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
idnsAddNameserver(token);
token = strtok(NULL, ", ");
}
token = strtok(t, ", ");
while (token) {
- debugs(78, 1, "Adding nameserver " << token << " from Registry");
+ debugs(78, DBG_IMPORTANT, "Adding nameserver " << token << " from Registry");
idnsAddNameserver(token);
token = strtok(NULL, ", ");
}
break;
default:
- debugs(78, 1, "Failed to read nameserver from Registry: Unknown System Type.");
+ debugs(78, DBG_IMPORTANT, "Failed to read nameserver from Registry: Unknown System Type.");
return;
}
}
for (n = lru_list.head; n; n = n->next) {
q = (idns_query *)n->data;
storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f\n",
- (int) q->msg_id, (int) q->sz, q->nsends,
+ (int) q->query_id, (int) q->sz, q->nsends,
tvSubDsec(q->start_t, current_time),
tvSubDsec(q->sent_t, current_time));
}
if (Config.dns.packet_max > 0)
- storeAppendPrintf(sentry, "DNS jumbo-grams: %Zd Bytes\n", Config.dns.packet_max);
+ storeAppendPrintf(sentry, "DNS jumbo-grams: %zd Bytes\n", Config.dns.packet_max);
else
storeAppendPrintf(sentry, "DNS jumbo-grams: not working\n");
storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES\n");
storeAppendPrintf(sentry, "---------------------------------------------- --------- ---------\n");
- for (i = 0; i < nns; i++) {
+ for (i = 0; i < nns; ++i) {
storeAppendPrintf(sentry, "%-45s %9d %9d\n", /* Let's take the maximum: (15 IPv4/45 IPv6) */
nameservers[i].S.NtoA(buf,MAX_IPSTRLEN),
nameservers[i].nqueries,
storeAppendPrintf(sentry, "\nRcode Matrix:\n");
storeAppendPrintf(sentry, "RCODE");
- for (i = 0; i < MAX_ATTEMPT; i++)
+ for (i = 0; i < MAX_ATTEMPT; ++i)
storeAppendPrintf(sentry, " ATTEMPT%d", i + 1);
storeAppendPrintf(sentry, " PROBLEM\n");
- for (j = 0; j < MAX_RCODE; j++) {
+ for (j = 0; j < MAX_RCODE; ++j) {
if (j > 10 && j < 16)
continue; // unassigned by IANA.
storeAppendPrintf(sentry, "%5d", j);
- for (i = 0; i < MAX_ATTEMPT; i++)
+ for (i = 0; i < MAX_ATTEMPT; ++i)
storeAppendPrintf(sentry, " %8d", RcodeMatrix[j][i]);
storeAppendPrintf(sentry, " : %s\n",Rcodes[j]);
if (npc) {
storeAppendPrintf(sentry, "\nSearch list:\n");
- for (i=0; i < npc; i++)
+ for (i=0; i < npc; ++i)
storeAppendPrintf(sentry, "%s\n", searchpath[i].domain);
storeAppendPrintf(sentry, "\n");
if (NULL == lru_list.tail)
return;
- eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, 1.0, 1);
+ const double when = min(Config.Timeout.idns_query, Config.Timeout.idns_retransmit)/1000.0;
+
+ eventAdd("idnsCheckQueue", idnsCheckQueue, NULL, when, 1);
event_queued = 1;
}
static void
-idnsSentQueryVC(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
+idnsSentQueryVC(const Comm::ConnectionPointer &conn, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
{
nsvc * vc = (nsvc *)data;
if (flag == COMM_ERR_CLOSING)
return;
- if (fd_table[fd].closing())
+ // XXX: irrelevant now that we have conn pointer?
+ if (!Comm::IsConnOpen(conn) || fd_table[conn->fd].closing())
return;
if (flag != COMM_OK || size <= 0) {
- comm_close(fd);
+ conn->close();
return;
}
if (vc->queue->contentSize() == 0)
return;
+ // if retrying after a TC UDP response, our close handler cb may be pending
+ if (fd_table[vc->conn->fd].closing())
+ return;
+
MemBuf *mb = vc->queue;
vc->queue = new MemBuf;
vc->busy = 1;
- commSetTimeout(vc->fd, Config.Timeout.idns_query, NULL, NULL);
+ // Comm needs seconds but idnsCheckQueue() will check the exact timeout
+ const int timeout = (Config.Timeout.idns_query % 1000 ?
+ Config.Timeout.idns_query + 1000 : Config.Timeout.idns_query) / 1000;
+ AsyncCall::Pointer nil;
+
+ commSetConnTimeout(vc->conn, timeout, nil);
AsyncCall::Pointer call = commCbCall(78, 5, "idnsSentQueryVC",
CommIoCbPtrFun(&idnsSentQueryVC, vc));
-
- Comm::Write(vc->fd, mb, call);
+ Comm::Write(vc->conn, mb, call);
delete mb;
}
static void
-idnsInitVCConnected(int fd, const DnsLookupDetails &details, comm_err_t status, int xerrno, void *data)
+idnsInitVCConnected(const Comm::ConnectionPointer &conn, comm_err_t status, int xerrno, void *data)
{
nsvc * vc = (nsvc *)data;
- if (status != COMM_OK) {
+ if (status != COMM_OK || !conn) {
char buf[MAX_IPSTRLEN] = "";
if (vc->ns < nns)
nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN);
- debugs(78, 1, HERE << "Failed to connect to nameserver " << buf << " using TCP: " << details);
- comm_close(fd);
+ debugs(78, DBG_IMPORTANT, HERE << "Failed to connect to nameserver " << buf << " using TCP.");
return;
}
- comm_read(fd, (char *)&vc->msglen, 2 , idnsReadVCHeader, vc);
+ vc->conn = conn;
+
+ comm_add_close_handler(conn->fd, idnsVCClosed, vc);
+ AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
+ CommIoCbPtrFun(idnsReadVCHeader, vc));
+ comm_read(conn, (char *)&vc->msglen, 2, call);
vc->busy = 0;
idnsDoSendQueryVC(vc);
}
static void
-idnsVCClosed(int fd, void *data)
+idnsVCClosed(const CommCloseCbParams ¶ms)
{
- nsvc * vc = (nsvc *)data;
+ nsvc * vc = (nsvc *)params.data;
delete vc->queue;
delete vc->msg;
- if (vc->ns < nns) // XXX: idnsShutdown may have freed nameservers[]
+ vc->conn = NULL;
+ if (vc->ns < nns) // XXX: dnsShutdown may have freed nameservers[]
nameservers[vc->ns].vc = NULL;
cbdataFree(vc);
}
static void
idnsInitVC(int ns)
{
- char buf[MAX_IPSTRLEN];
-
nsvc *vc = cbdataAlloc(nsvc);
assert(ns < nns);
+ assert(vc->conn == NULL); // MUST be NULL from the construction process!
nameservers[ns].vc = vc;
vc->ns = ns;
+ vc->queue = new MemBuf;
+ vc->msg = new MemBuf;
+ vc->busy = 1;
- Ip::Address addr;
+ Comm::ConnectionPointer conn = new Comm::Connection();
if (!Config.Addrs.udp_outgoing.IsNoAddr())
- addr = Config.Addrs.udp_outgoing;
+ conn->local = Config.Addrs.udp_outgoing;
else
- addr = Config.Addrs.udp_incoming;
-
- if (nameservers[ns].S.IsIPv4() && !addr.SetIPv4()) {
- debugs(31, DBG_CRITICAL, "ERROR: Cannot contact DNS nameserver " << nameservers[ns].S << " from " << addr);
- addr.SetAnyAddr();
- addr.SetIPv4();
- }
+ conn->local = Config.Addrs.udp_incoming;
- vc->queue = new MemBuf;
-
- vc->msg = new MemBuf;
+ conn->remote = nameservers[ns].S;
- vc->fd = comm_open(SOCK_STREAM,
- IPPROTO_TCP,
- addr,
- COMM_NONBLOCKING,
- "DNS TCP Socket");
-
- if (vc->fd < 0)
- fatal("Could not create a DNS socket");
-
- comm_add_close_handler(vc->fd, idnsVCClosed, vc);
+ if (conn->remote.IsIPv4()) {
+ conn->local.SetIPv4();
+ }
- vc->busy = 1;
+ AsyncCall::Pointer call = commCbCall(78,3, "idnsInitVCConnected", CommConnectCbPtrFun(idnsInitVCConnected, vc));
- commConnectStart(vc->fd, nameservers[ns].S.NtoA(buf,MAX_IPSTRLEN), nameservers[ns].S.GetPort(), idnsInitVCConnected, vc);
+ Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, Config.Timeout.connect);
+ cs->setHost("DNS TCP Socket");
+ AsyncJob::Start(cs);
}
static void
if (!vc) {
char buf[MAX_IPSTRLEN];
- debugs(78, 1, "idnsSendQuery: Failed to initiate TCP connection to nameserver " << nameservers[ns].S.NtoA(buf,MAX_IPSTRLEN) << "!");
+ debugs(78, DBG_IMPORTANT, "idnsSendQuery: Failed to initiate TCP connection to nameserver " << nameservers[ns].S.NtoA(buf,MAX_IPSTRLEN) << "!");
return;
}
idnsSendQuery(idns_query * q)
{
if (DnsSocketA < 0 && DnsSocketB < 0) {
- debugs(78, 1, "WARNING: idnsSendQuery: Can't send query, no DNS socket!");
+ debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS socket!");
return;
}
if (nns <= 0) {
- debugs(78, 1, "WARNING: idnsSendQuery: Can't send query, no DNS nameservers known!");
+ debugs(78, DBG_IMPORTANT, "WARNING: idnsSendQuery: Can't send query, no DNS nameservers known!");
return;
}
int x = -1, y = -1;
int ns;
- q->start_t = current_time;
- q->msg_id = idnsQueryID();
- rfc1035SetQueryID(q->buf, q->msg_id);
-
do {
ns = q->nsends % nns;
} else {
if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6())
y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz);
- else if (DnsSocketA)
+ else if (DnsSocketA >= 0)
x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz);
}
- q->nsends++;
+ ++ q->nsends;
- q->queue_t = q->sent_t = current_time;
+ q->sent_t = current_time;
if (y < 0 && nameservers[ns].S.IsIPv6())
- debugs(50, 1, "idnsSendQuery: FD " << DnsSocketB << ": sendto: " << xstrerror());
+ debugs(50, DBG_IMPORTANT, "idnsSendQuery: FD " << DnsSocketB << ": sendto: " << xstrerror());
if (x < 0 && nameservers[ns].S.IsIPv4())
- debugs(50, 1, "idnsSendQuery: FD " << DnsSocketA << ": sendto: " << xstrerror());
+ debugs(50, DBG_IMPORTANT, "idnsSendQuery: FD " << DnsSocketA << ": sendto: " << xstrerror());
} while ( (x<0 && y<0) && q->nsends % nns != 0);
fd_bytes(DnsSocketA, x, FD_WRITE);
}
- nameservers[ns].nqueries++;
+ ++ nameservers[ns].nqueries;
q->queue_t = current_time;
dlinkAdd(q, &q->lru, &lru_list);
+ q->pending = 1;
idnsTickleQueue();
}
{
int i;
- for (i = 0; i < nns; i++) {
+ for (i = 0; i < nns; ++i) {
if (nameservers[i].S != from)
continue;
for (n = lru_list.tail; n; n = n->prev) {
q = (idns_query*)n->data;
- if (q->msg_id == id)
+ if (q->query_id == id)
return q;
}
unsigned short first_id = id;
while (idnsFindQuery(id)) {
- id++;
+ ++id;
if (id == first_id) {
- debugs(78, 1, "idnsQueryID: Warning, too many pending DNS requests");
+ debugs(78, DBG_IMPORTANT, "idnsQueryID: Warning, too many pending DNS requests");
break;
}
}
}
static void
-idnsCallback(idns_query *q, rfc1035_rr *answers, int n, const char *error)
+idnsCallback(idns_query *q, const char *error)
{
IDNSCB *callback;
void *cbdata;
+ if (error)
+ q->error = error;
+
+ if (q->master)
+ q = q->master;
+
+ idns_query *q2;
+ // If any of our subqueries are still pending then wait for them to complete before continuing
+ for ( q2 = q; q2; q2 = q2->slave) {
+ if (q2->pending) {
+ return;
+ }
+ }
+
+ /* Merge results */
+ rfc1035_message *message = q->message;
+ q->message = NULL;
+ int n = q->ancount;
+ error = q->error;
+
+ while ( (q2 = q->slave) ) {
+ debugs(78, 6, HERE << "Merging DNS results " << q->name << " A has " << n << " RR, AAAA has " << q2->ancount << " RR");
+ q->slave = q2->slave;
+ if ( !q2->error ) {
+ if (n > 0) {
+ // two sets of RR need merging
+ rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q2->ancount) );
+ if (Config.dns.v4_first) {
+ memcpy(result, message->answer, (sizeof(rfc1035_rr)*n) );
+ memcpy(result+n, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+ } else {
+ memcpy(result, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+ memcpy(result+q2->ancount, message->answer, (sizeof(rfc1035_rr)*n) );
+ }
+ n += q2->ancount;
+ // HACK WARNING, the answer rr:s have been copied in-place to
+ // result, do not free them here
+ safe_free(message->answer);
+ safe_free(q2->message->answer);
+ message->answer = result;
+ message->ancount += q2->message->ancount;
+ } else {
+ // first response empty or failed, just use the second
+ rfc1035MessageDestroy(&message);
+ message = q2->message;
+ q2->message = NULL;
+ n = q2->ancount;
+ error = NULL;
+ }
+ }
+ rfc1035MessageDestroy(&q2->message);
+ cbdataFree(q2);
+ }
+
+ debugs(78, 6, HERE << "Sending " << n << " (" << (error ? error : "OK") << ") DNS results to caller.");
+
callback = q->callback;
q->callback = NULL;
+ const rfc1035_rr *answers = message ? message->answer : NULL;
if (cbdataReferenceValidDone(q->callback_data, &cbdata))
callback(cbdata, answers, n, error);
hash_remove_link(idns_lookup_hash, &q->hash);
q->hash.key = NULL;
}
-}
-void
-idnsDropMessage(rfc1035_message *message, idns_query *q)
-{
rfc1035MessageDestroy(&message);
- if (q->hash.key) {
- hash_remove_link(idns_lookup_hash, &q->hash);
- q->hash.key = NULL;
- }
+ cbdataFree(q);
}
static void
n = rfc1035MessageUnpack(buf, sz, &message);
if (message == NULL) {
- debugs(78, 1, "idnsGrokReply: Malformed DNS response");
+ debugs(78, DBG_IMPORTANT, "idnsGrokReply: Malformed DNS response");
return;
}
// the altered NS was limiting the whole group.
max_shared_edns = q->edns_seen;
// may be limited by one of the others still
- for (int i = 0; i < nns; i++)
+ for (int i = 0; i < nns; ++i)
max_shared_edns = min(max_shared_edns, nameservers[i].last_seen_edns);
} else {
nameservers[from_ns].last_seen_edns = q->edns_seen;
}
#endif
+ dlinkDelete(&q->lru, &lru_list);
+ q->pending = 0;
+
if (message->tc) {
debugs(78, 3, HERE << "Resolver requested TC (" << q->query.name << ")");
- dlinkDelete(&q->lru, &lru_list);
rfc1035MessageDestroy(&message);
if (!q->need_vc) {
q->need_vc = 1;
- q->nsends--;
+ -- q->nsends;
idnsSendQuery(q);
} else {
// Strange: A TCP DNS response with the truncation bit (TC) set.
// Return an error and cleanup; no point in trying TCP again.
debugs(78, 3, HERE << "TCP DNS response");
- idnsCallback(q, NULL, 0, "Truncated TCP DNS response");
- cbdataFree(q);
+ idnsCallback(q, "Truncated TCP DNS response");
}
return;
}
- dlinkDelete(&q->lru, &lru_list);
idnsRcodeCount(n, q->attempt);
if (n < 0) {
q->rcode = -n;
debugs(78, 3, "idnsGrokReply: error " << rfc1035ErrorMessage(n) << " (" << q->rcode << ")");
- if (q->rcode == 2 && ++q->attempt < MAX_ATTEMPT) {
+ if (q->rcode == 2 && (++ q->attempt) < MAX_ATTEMPT) {
/*
* RCODE 2 is "Server failure - The name server was
* unable to process this query due to a problem with
return;
}
- if (q->rcode == 3 && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
+ // Do searchpath processing on the master A query only to keep
+ // things simple. NXDOMAIN is authorative for the label, not
+ // the record type.
+ if (q->rcode == 3 && !q->master && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
assert(NULL == message->answer);
strcpy(q->name, q->orig);
strcat(q->name, ".");
strcat(q->name, searchpath[q->domain].domain);
debugs(78, 3, "idnsGrokReply: searchpath used for " << q->name);
- q->domain++;
+ ++ q->domain;
} else {
- q->attempt++;
+ ++ q->attempt;
}
- idnsDropMessage(message, q);
+ rfc1035MessageDestroy(&message);
- if (Ip::EnableIpv6 && q->query.qtype == RFC1035_TYPE_AAAA) {
- debugs(78, 3, "idnsGrokReply: Trying AAAA Query for " << q->name);
- q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, Config.dns.packet_max);
- } else {
- debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name);
- // see EDNS notes at top of file why this sends 0
- q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
+ // cleanup slave AAAA query
+ while (idns_query *slave = q->slave) {
+ dlinkDelete(&slave->lru, &lru_list);
+ q->slave = slave->slave;
+ rfc1035MessageDestroy(&slave->message);
+ cbdataFree(slave);
+ }
+
+ // Build new query
+ q->query_id = idnsQueryID();
+ debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name);
+ // see EDNS notes at top of file why this sends 0
+ q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
+ if (q->sz < 0) {
+ /* problem with query data -- query not sent */
+ idnsCallback(q, "Internal error");
+ return;
}
- idnsCacheQuery(q);
+
+ q->nsends = 0;
+
idnsSendQuery(q);
+ if (Ip::EnableIpv6)
+ idnsSendSlaveAAAAQuery(q);
return;
}
}
- if (q->need_A && (Config.onoff.dns_require_A == 1 || n <= 0 ) ) {
- /* ERROR or NO AAAA exist. Failover to A records. */
- /* Apparently its also a good idea to lookup and store the A records
- * just in case the AAAA are not available when we need them.
- * This could occur due to number of network failings beyond our control
- * thus the || above allowing the user to request always both.
- */
-
- if (n == 0)
- debugs(78, 3, "idnsGrokReply: " << q->name << " has no AAAA records. Looking up A record instead.");
- else if (q->need_A && n <= 0)
- debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query failed. Trying A now instead.");
- else // admin requested this.
- debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query done. Configured to retrieve A now also.");
-
- // move the initial message results into the failover query for merging later.
- if (n > 0) {
- q->initial_AAAA.count = message->ancount;
- q->initial_AAAA.answers = message->answer;
- message->answer = NULL;
- }
-
- // remove the hashed query info
- idnsDropMessage(message, q);
-
- // reset the query as an A query
- q->nsends = 0;
- // see EDNS notes at top of file why this sends 0
- q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
- q->need_A = false;
- idnsCacheQuery(q);
- idnsSendQuery(q);
- return;
- }
+ q->message = message;
+ q->ancount = n;
- /** If there are two result sets from preceeding AAAA and A lookups merge them with a preference for AAAA */
- if (q->initial_AAAA.count > 0 && n > 0) {
- /* two sets of RR need merging */
- rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q->initial_AAAA.count) );
- rfc1035_rr *tmp = result;
-
- debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR");
-
- memcpy(tmp, q->initial_AAAA.answers, (sizeof(rfc1035_rr)*(q->initial_AAAA.count)) );
- tmp += q->initial_AAAA.count;
- /* free the RR object without freeing its child strings (they are now taken by the copy above) */
- safe_free(q->initial_AAAA.answers);
-
- memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) );
- /* free the RR object without freeing its child strings (they are now taken by the copy above) */
- safe_free(message->answer);
-
- message->answer = result;
- message->ancount += q->initial_AAAA.count;
- n += q->initial_AAAA.count;
- q->initial_AAAA.count=0;
- } else if (q->initial_AAAA.count > 0 && n <= 0) {
- /* initial of dual queries was the only result set. */
- debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR");
- rfc1035RRDestroy(&(message->answer), n);
- message->answer = q->initial_AAAA.answers;
- n = q->initial_AAAA.count;
- }
- /* else initial results were empty. just use the final set as authoritative */
+ if (n >= 0)
+ idnsCallback(q, NULL);
+ else
+ idnsCallback(q, rfc1035ErrorMessage(q->rcode));
- debugs(78, 6, HERE << "Sending " << n << " DNS results to caller.");
- idnsCallback(q, message->answer, n, rfc1035ErrorMessage(n));
- rfc1035MessageDestroy(&message);
- cbdataFree(q);
}
static void
*/
Ip::Address bugbypass;
- while (max--) {
+ while (max) {
+ --max;
len = comm_udp_recvfrom(fd, rbuf, SQUID_UDP_SO_RCVBUF, 0, bugbypass);
from = bugbypass; // BUG BYPASS. see notes above.
if (ignoreErrno(errno))
break;
-#ifdef _SQUID_LINUX_
+#if _SQUID_LINUX_
/* Some Linux systems seem to set the FD for reading and then
* return ECONNREFUSED when sendto() fails and generates an ICMP
* port unreachable message. */
if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
#endif
- debugs(50, 1, "idnsRead: FD " << fd << " recvfrom: " << xstrerror());
+ debugs(50, DBG_IMPORTANT, "idnsRead: FD " << fd << " recvfrom: " << xstrerror());
break;
}
fd_bytes(fd, len, FD_READ);
assert(N);
- (*N)++;
+ ++(*N);
debugs(78, 3, "idnsRead: FD " << fd << ": received " << len << " bytes from " << from);
ns = idnsFromKnownNameserver(from);
if (ns >= 0) {
- nameservers[ns].nreplies++;
+ ++ nameservers[ns].nreplies;
}
// Before unknown_nameservers check to avoid flooding cache.log on attacks,
static time_t last_warning = 0;
if (squid_curtime - last_warning > 60) {
- debugs(78, 1, "WARNING: Reply from unknown nameserver " << from);
+ debugs(78, DBG_IMPORTANT, "WARNING: Reply from unknown nameserver " << from);
last_warning = squid_curtime;
} else {
- debugs(78, 1, "WARNING: Reply from unknown nameserver " << from << " (retrying..." << (squid_curtime-last_warning) << "<=60)" );
+ debugs(78, DBG_IMPORTANT, "WARNING: Reply from unknown nameserver " << from << " (retrying..." << (squid_curtime-last_warning) << "<=60)" );
}
continue;
}
q = static_cast<idns_query*>(n->data);
/* Anything to process in the queue? */
- if (tvSubDsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit )
+ if ((time_msec_t)tvSubMsec(q->queue_t, current_time) < Config.Timeout.idns_retransmit )
break;
- /* Query timer expired? */
- if (tvSubDsec(q->sent_t, current_time) < Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns)) {
+ /* Query timer still running? */
+ if ((time_msec_t)tvSubMsec(q->sent_t, current_time) < (Config.Timeout.idns_retransmit * 1 << ((q->nsends - 1) / nns))) {
dlinkDelete(&q->lru, &lru_list);
q->queue_t = current_time;
dlinkAdd(q, &q->lru, &lru_list);
debugs(78, 3, "idnsCheckQueue: ID " << q->xact_id <<
" QID 0x" << std::hex << std::setfill('0') <<
- std::setw(4) << q->msg_id << ": timeout" );
+ std::setw(4) << q->query_id << ": timeout" );
dlinkDelete(&q->lru, &lru_list);
+ q->pending = 0;
- if (tvSubDsec(q->start_t, current_time) < Config.Timeout.idns_query) {
+ if ((time_msec_t)tvSubMsec(q->start_t, current_time) < Config.Timeout.idns_query) {
idnsSendQuery(q);
} else {
debugs(78, 2, "idnsCheckQueue: ID " << q->xact_id <<
- " QID 0x" << std::hex << q->msg_id <<
+ " QID 0x" << std::hex << q->query_id <<
" : giving up after " << std::dec << q->nsends << " tries and " <<
std::setw(5)<< std::setprecision(2) << tvSubDsec(q->start_t, current_time) << " seconds");
if (q->rcode != 0)
- idnsCallback(q, NULL, -q->rcode, rfc1035ErrorMessage(q->rcode));
+ idnsCallback(q, rfc1035ErrorMessage(q->rcode));
else
- idnsCallback(q, NULL, -16, "Timeout");
-
- cbdataFree(q);
+ idnsCallback(q, "Timeout");
}
}
}
static void
-idnsReadVC(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
+idnsReadVC(const Comm::ConnectionPointer &conn, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
{
nsvc * vc = (nsvc *)data;
return;
if (flag != COMM_OK || len <= 0) {
- comm_close(fd);
+ if (Comm::IsConnOpen(conn))
+ conn->close();
return;
}
vc->msg->size += len; // XXX should not access -> size directly
if (vc->msg->contentSize() < vc->msglen) {
- comm_read(fd, buf + len, vc->msglen - vc->msg->contentSize(), idnsReadVC, vc);
+ AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVC",
+ CommIoCbPtrFun(idnsReadVC, vc));
+ comm_read(conn, buf+len, vc->msglen - vc->msg->contentSize(), call);
return;
}
assert(vc->ns < nns);
- debugs(78, 3, "idnsReadVC: FD " << fd << ": received " <<
- (int) vc->msg->contentSize() << " bytes via tcp from " <<
- nameservers[vc->ns].S << ".");
+ debugs(78, 3, HERE << conn << ": received " << vc->msg->contentSize() << " bytes via TCP from " << nameservers[vc->ns].S << ".");
idnsGrokReply(vc->msg->buf, vc->msg->contentSize(), vc->ns);
vc->msg->clean();
- comm_read(fd, (char *)&vc->msglen, 2 , idnsReadVCHeader, vc);
+ AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
+ CommIoCbPtrFun(idnsReadVCHeader, vc));
+ comm_read(conn, (char *)&vc->msglen, 2, call);
}
static void
-idnsReadVCHeader(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
+idnsReadVCHeader(const Comm::ConnectionPointer &conn, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
{
nsvc * vc = (nsvc *)data;
return;
if (flag != COMM_OK || len <= 0) {
- comm_close(fd);
+ if (Comm::IsConnOpen(conn))
+ conn->close();
return;
}
assert(vc->read_msglen <= 2);
if (vc->read_msglen < 2) {
- comm_read(fd, buf + len, 2 - vc->read_msglen, idnsReadVCHeader, vc);
+ AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVCHeader",
+ CommIoCbPtrFun(idnsReadVCHeader, vc));
+ comm_read(conn, buf+len, 2 - vc->read_msglen, call);
return;
}
vc->msglen = ntohs(vc->msglen);
vc->msg->init(vc->msglen, vc->msglen);
- comm_read(fd, vc->msg->buf, vc->msglen, idnsReadVC, vc);
+ AsyncCall::Pointer call = commCbCall(5,4, "idnsReadVC",
+ CommIoCbPtrFun(idnsReadVC, vc));
+ comm_read(conn, vc->msg->buf, vc->msglen, call);
}
/*
if (rcode < MAX_RCODE)
if (attempt < MAX_ATTEMPT)
- RcodeMatrix[rcode][attempt]++;
+ ++ RcodeMatrix[rcode][attempt];
}
/* ====================================================================== */
}
void
-idnsInit(void)
+dnsInit(void)
{
static int init = 0;
CBDATA_INIT_TYPE(idns_query);
if (DnsSocketA < 0 && DnsSocketB < 0) {
- int port;
-
- Ip::Address addrA; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
+ Ip::Address addrV6; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
if (!Config.Addrs.udp_outgoing.IsNoAddr())
- addrA = Config.Addrs.udp_outgoing;
+ addrV6 = Config.Addrs.udp_outgoing;
else
- addrA = Config.Addrs.udp_incoming;
+ addrV6 = Config.Addrs.udp_incoming;
- Ip::Address addrB = addrA;
- addrA.SetIPv4();
+ Ip::Address addrV4 = addrV6;
+ addrV4.SetIPv4();
- if (Ip::EnableIpv6 && (addrB.IsAnyAddr() || addrB.IsIPv6())) {
- debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrB);
+ if (Ip::EnableIpv6 && addrV6.IsIPv6()) {
+ debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV6);
DnsSocketB = comm_open_listener(SOCK_DGRAM,
IPPROTO_UDP,
- addrB,
+ addrV6,
COMM_NONBLOCKING,
"DNS Socket IPv6");
}
- if (addrA.IsAnyAddr() || addrA.IsIPv4()) {
- debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrA);
+ if (addrV4.IsIPv4()) {
+ debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV4);
DnsSocketA = comm_open_listener(SOCK_DGRAM,
IPPROTO_UDP,
- addrA,
+ addrV4,
COMM_NONBLOCKING,
"DNS Socket IPv4");
}
* statement. Doing so messes up the internal Debug::level
*/
if (DnsSocketB >= 0) {
- port = comm_local_port(DnsSocketB);
- debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB);
+ comm_local_port(DnsSocketB);
+ debugs(78, DBG_IMPORTANT, "DNS Socket created at " << addrV6 << ", FD " << DnsSocketB);
Comm::SetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
}
if (DnsSocketA >= 0) {
- port = comm_local_port(DnsSocketA);
- debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA);
+ comm_local_port(DnsSocketA);
+ debugs(78, DBG_IMPORTANT, "DNS Socket created at " << addrV4 << ", FD " << DnsSocketA);
Comm::SetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
}
}
assert(0 == nns);
idnsParseNameservers();
-#ifndef _SQUID_MSWIN_
+#if !_SQUID_MSWIN_
if (0 == nns)
idnsParseResolvConf();
#endif
if (0 == nns) {
- debugs(78, 1, "Warning: Could not find any nameservers. Trying to use localhost");
+ debugs(78, DBG_IMPORTANT, "Warning: Could not find any nameservers. Trying to use localhost");
#if _SQUID_WINDOWS_
- debugs(78, 1, "Please check your TCP-IP settings or /etc/resolv.conf file");
+ debugs(78, DBG_IMPORTANT, "Please check your TCP-IP settings or /etc/resolv.conf file");
#else
- debugs(78, 1, "Please check your /etc/resolv.conf file");
+ debugs(78, DBG_IMPORTANT, "Please check your /etc/resolv.conf file");
#endif
- debugs(78, 1, "or use the 'dns_nameservers' option in squid.conf.");
+ debugs(78, DBG_IMPORTANT, "or use the 'dns_nameservers' option in squid.conf.");
idnsAddNameserver("127.0.0.1");
}
memDataInit(MEM_IDNS_QUERY, "idns_query", sizeof(idns_query), 0);
memset(RcodeMatrix, '\0', sizeof(RcodeMatrix));
idns_lookup_hash = hash_create((HASHCMP *) strcmp, 103, hash_string);
- init++;
+ ++init;
}
#if WHEN_EDNS_RESPONSES_ARE_PARSED
}
void
-idnsShutdown(void)
+dnsShutdown(void)
{
if (DnsSocketA < 0 && DnsSocketB < 0)
return;
DnsSocketB = -1;
}
- for (int i = 0; i < nns; i++) {
+ for (int i = 0; i < nns; ++i) {
if (nsvc *vc = nameservers[i].vc) {
- if (vc->fd >= 0)
- comm_close(vc->fd);
+ if (Comm::IsConnOpen(vc->conn))
+ vc->conn->close();
}
}
q = cbdataAlloc(idns_query);
// idns_query is POD so no constructors are called after allocation
q->xact_id.change();
+ // no query_id on this instance.
q->callback = callback;
}
static void
-idnsCacheQuery(idns_query *q)
+idnsStartQuery(idns_query *q, IDNSCB * callback, void *data)
{
- q->hash.key = q->query.name;
+ q->start_t = current_time;
+ q->callback = callback;
+ q->callback_data = cbdataReference(data);
+
+ q->hash.key = q->orig;
hash_join(idns_lookup_hash, &q->hash);
+
+ idnsSendQuery(q);
+}
+
+static void
+idnsSendSlaveAAAAQuery(idns_query *master)
+{
+ idns_query *q = cbdataAlloc(idns_query);
+ memcpy(q->name, master->name, sizeof(q->name));
+ memcpy(q->orig, master->orig, sizeof(q->orig));
+ q->master = master;
+ q->query_id = idnsQueryID();
+ q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
+ q->start_t = master->start_t;
+ q->slave = master->slave;
+
+ debugs(78, 3, HERE << "buf is " << q->sz << " bytes for " << q->name <<
+ ", id = 0x" << std::hex << q->query_id);
+ if (!q->sz) {
+ cbdataFree(q);
+ return;
+ }
+ master->slave = q;
+ idnsSendQuery(q);
}
void
q = cbdataAlloc(idns_query);
// idns_query is POD so no constructors are called after allocation
q->xact_id.change();
+ q->query_id = idnsQueryID();
- for (i = 0; i < strlen(name); i++)
+ for (i = 0; i < strlen(name); ++i)
if (name[i] == '.')
- nd++;
+ ++nd;
if (Config.onoff.res_defnames && npc > 0 && name[strlen(name)-1] != '.') {
q->do_searchpath = 1;
debugs(78, 3, "idnsALookup: searchpath used for " << q->name);
}
- if (Ip::EnableIpv6) {
- q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, Config.dns.packet_max);
- q->need_A = true;
- } else {
- // see EDNS notes at top of file why this sends 0
- q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
- q->need_A = false;
- }
+ // see EDNS notes at top of file why this sends 0
+ q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
if (q->sz < 0) {
/* problem with query data -- query not sent */
}
debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
- ", id = 0x" << std::hex << q->msg_id);
+ ", id = 0x" << std::hex << q->query_id);
- q->callback = callback;
- q->callback_data = cbdataReference(data);
+ idnsStartQuery(q, callback, data);
+
+ if (Ip::EnableIpv6)
+ idnsSendSlaveAAAAQuery(q);
- idnsCacheQuery(q);
- idnsSendQuery(q);
}
void
// idns_query is POD so no constructors are called after allocation
q->xact_id.change();
+ q->query_id = idnsQueryID();
- if (Ip::EnableIpv6 && addr.IsIPv6()) {
+ if (addr.IsIPv6()) {
struct in6_addr addr6;
addr.GetInAddr(addr6);
- q->sz = rfc3596BuildPTRQuery6(addr6, q->buf, sizeof(q->buf), 0, &q->query, Config.dns.packet_max);
+ q->sz = rfc3596BuildPTRQuery6(addr6, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
} else {
struct in_addr addr4;
addr.GetInAddr(addr4);
// see EDNS notes at top of file why this sends 0
- q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), 0, &q->query, 0);
+ q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
}
- /* PTR does not do inbound A/AAAA */
- q->need_A = false;
-
if (q->sz < 0) {
/* problem with query data -- query not sent */
callback(data, NULL, 0, "Internal error");
}
debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
- ", id = 0x" << std::hex << q->msg_id);
-
- q->callback = callback;
- q->callback_data = cbdataReference(data);
+ ", id = 0x" << std::hex << q->query_id);
- idnsCacheQuery(q);
- idnsSendQuery(q);
+ idnsStartQuery(q, callback, data);
}
#if SQUID_SNMP
* The function to return the DNS via SNMP
*/
variable_list *
-snmp_netIdnsFn(variable_list * Var, snint * ErrP)
+snmp_netDnsFn(variable_list * Var, snint * ErrP)
{
int i, n = 0;
variable_list *Answer = NULL;
case DNS_REQ:
- for (i = 0; i < nns; i++)
+ for (i = 0; i < nns; ++i)
n += nameservers[i].nqueries;
Answer = snmp_var_new_integer(Var->name, Var->name_length,
break;
case DNS_REP:
- for (i = 0; i < nns; i++)
+ for (i = 0; i < nns; ++i)
n += nameservers[i].nreplies;
Answer = snmp_var_new_integer(Var->name, Var->name_length,
}
#endif /*SQUID_SNMP */
-#endif /* USE_DNSSERVERS */
+#endif /* USE_DNSHELPER */