72template <
class Content>
156 const char *
name()
const {
return static_cast<const char*
>(
hash.
key); }
164 template <
class Specs>
171 void updateTtl(
const unsigned int rrTtl);
214#if LIBRESOLV_DNS_TTL_HACK
221 receiverObj(receiver)
226 receiverFun(fun), receiverData(data)
235 const auto addrs = (possiblyEmptyAddrs && possiblyEmptyAddrs->
empty()) ?
nullptr : possiblyEmptyAddrs;
237 debugs(14, 7, addrs <<
" " << details);
240 receiver->noteIps(addrs, details);
257 receiver->noteIp(ip);
271 for (
const auto &ip: ips.
good()) {
314 debugs(14, 3,
"ipcacheRelease: Releasing entry for '" << (
const char *) i->
hash.
key <<
"'");
377 debugs(14, 9,
"ipcache_purgelru: removed " << removed <<
" entries");
399 if (t->flags.fromhosts)
412 error_message(nullptr),
460 debugs(14, 3,
"ERROR: DNS failure while resolving " <<
name() <<
": " <<
text);
481 debugs(14, 3, nr <<
" answers for " << i->
name());
484 for (k = 0; k < nr; ++k) {
494 i->
addGood(answers[k], SingleA);
506 debugs(14, 9,
"Unknown RR type received: type=" << answers[k].type <<
" starting at " << &(answers[k]) );
510template <
class Specs>
514 typename Specs::DataType address;
515 if (rr.
rdlength !=
sizeof(address)) {
516 debugs(14,
DBG_IMPORTANT,
"ERROR: Ignoring invalid " << specs.kind <<
" address record while resolving " <<
name());
520 ++specs.recordCounter;
526 memcpy(&address, rr.
rdata,
sizeof(address));
529 debugs(14, 3,
"refusing to add duplicate " << ip);
543 const time_t ttl = std::min(std::max(
545 static_cast<time_t
>(rrTtl)),
550 debugs(14, 5,
"use first " << ttl <<
" from RR TTL " << rrTtl);
552 }
else if (rrExpires <
expires) {
630 if (name ==
nullptr || name[0] ==
'\0') {
631 debugs(14, 4,
"ipcache_nbgethostbyname: Invalid name!");
639 debugs(14, 4,
"ipcache_nbgethostbyname: BYPASS for '" << name <<
"' (already numeric)");
658 debugs(14, 4,
"ipcache_nbgethostbyname: HIT for '" << name <<
"'");
665 i->
handler = std::move(handler);
671 debugs(14, 5,
"ipcache_nbgethostbyname: MISS for '" << name <<
"'");
674 i->
handler = std::move(handler);
684 "IP Cache Stats and Contents",
733 debugs(14, 3,
"'" << name <<
"', flags=" <<
asHex(flags));
803 bool firstLine =
true;
804 for (
const auto &addr: i->
addrs.
raw()) {
806 const char *indent = firstLine ?
"" :
" ";
810 addr.bad() ?
"BAD" :
"OK ");
906 debugs(14, 4,
"HIT_BYPASS for " << name <<
"=" << ip);
908 static_addrs.
reset(ip);
909 return &static_addrs;
916 if (i->
locks++ == 0) {
943 for (
size_t seen = 0; seen <
ips.size(); ++seen) {
947 debugs(14, 3,
"succeeded for " << name <<
": " << *
this);
952 debugs(14, 3,
"failed for " << name <<
": " << *
this);
960 ips.emplace_back(ip);
971 if (badCount() >=
size()) {
974 for (
auto &cachedIp: ips)
975 cachedIp.forgetMarking();
977 debugs(14, 3,
"cleared all " <<
size() <<
" bad IPs for " << name);
980 Must(seekNewGood(name));
988 for (
const auto &cachedIp: ips) {
989 if (cachedIp.ip == ip) {
990 if (
auto position = positionOrNil)
992 debugs(14, 7, ip <<
" at " << pos <<
" in " << *
this);
998 debugs(14, 7,
" no " << ip <<
" in " << *
this);
1006 [[maybe_unused]]
auto &cachedIp = ips.emplace_back(ip);
1014 os <<
"[no cached IPs]";
1015 else if (goodPosition ==
size())
1016 os <<
"[" <<
size() <<
" bad cached IPs]";
1018 os << current() <<
" #" << (goodPosition+1) <<
"/" << ips.size() <<
"-" << badCount();
1024 size_t badPosition = 0;
1025 if (!have(ip, &badPosition))
1028 auto &cachedIp = ips[badPosition];
1032 cachedIp.markAsBad();
1034 debugs(14, 2, ip <<
" of " << name);
1036 if (goodPosition == badPosition)
1037 restoreGoodness(name);
1047 size_t badPosition = 0;
1048 if (!have(ip, &badPosition))
1051 auto &cachedIp = ips[badPosition];
1052 if (!cachedIp.bad())
1055 cachedIp.forgetMarking();
1058 debugs(14, 2, ip <<
" of " << name);
1072 cached->addrs.markAsBad(name, addr);
1080 cached->addrs.forgetMarking(name, addr);
1093 xfree(error_message);
1132 if (!(ip = ipaddr)) {
1133 if (strchr(ipaddr,
':') && strspn(ipaddr,
"0123456789abcdefABCDEF:") == strlen(ipaddr)) {
1134 debugs(14, 3,
"ipcacheAddEntryFromHosts: Skipping IPv6 address '" << ipaddr <<
"'");
1136 debugs(14,
DBG_IMPORTANT,
"ERROR: ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr <<
"'");
1142 if (!Ip::EnableIpv6 && ip.
isIPv6()) {
1143 debugs(14, 2,
"skips IPv6 address in /etc/hosts because IPv6 support was disabled: " << ip);
1150 }
else if (i->
locks > 0) {
1151 debugs(14,
DBG_IMPORTANT,
"ERROR: ipcacheAddEntryFromHosts: cannot add static entry for locked name '" << name <<
"'");
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
void error(char *format,...)
#define CBDATA_CLASS_INIT(type)
#define CBDATA_CLASS(type)
an old-style void* callback parameter
Cbc * valid() const
was set and is valid
void clear()
make pointer not set; does not invalidate cbdata
bool set() const
was set but may be invalid
void markAsBad(const char *name, const Ip::Address &ip)
size_t goodPosition
position of the IP returned by current()
void reset(const Ip::Address &ip)
replace all info with the given (presumed good) IP address
void pushUnique(const Ip::Address &ip)
bool have(const Ip::Address &ip, size_t *position=nullptr) const
const Storage & raw() const
all cached entries
size_t size() const noexcept
all cached IPs
void forgetMarking(const char *name, const Ip::Address &ip)
undo successful markAsBad()
bool seekNewGood(const char *name)
IpsSelector< GoodIpsIterator > good() const
good IPs
Storage ips
good and bad IPs
void restoreGoodness(const char *name)
makes current() calls possible after a successful markAsBad()
void reportCurrent(std::ostream &os) const
prints current IP and other debugging information
size_t badCount() const noexcept
bad IPs
bool empty() const noexcept
whether we cached no IPs at all
encapsulates DNS lookup results
forwards non-blocking IP cache lookup results to either IPH or IpReciever
void forwardHits(const Dns::CachedIps &ips)
convenience wrapper to safely forwardIp() for each IP in the container
IPH * receiverFun
gets final results
void forwardLookup(const char *error)
inform recipient of a finished lookup
bool forwardIp(const Ip::Address &ip)
void finalCallback(const Dns::CachedIps *addrs, const Dns::LookupDetails &details)
forwards notification about the end of the lookup; last method to be called
CbcPointer< Dns::IpReceiver > receiverObj
gets incremental and final results
void lookupsStarting()
initialize lookup timestamps for Dns::LookupDetails delay calculation
int totalResponseTime() const
CallbackData receiverData
caller-specific data for the handler (optional)
int additionalLookupDelay() const
bool fromHost(const char *hostWithoutPort)
metadata for parsing DNS A and AAAA records
const char * kind
human-friendly record type description
int & recordCounter
where this kind of records are counted (for stats)
Content DataType
actual RR DATA type
struct SquidConfig::@86 ipcache
struct StatCounters::@109 dns
void addGood(const rfc1035_rr &rr, Specs &specs)
adds the contents of a "good" DNS A or AAAA record to stored IPs
IpCacheLookupForwarder handler
struct ipcache_entry::Flags flags
ipcache_entry(const char *)
int additionalLookupDelay() const
milliseconds since the last lookup start or -1 if there were no lookups
int totalResponseTime() const
milliseconds since the first lookup start or -1 if there were no lookups
const char * name() const
void latestError(const char *text)
remembers the last error seen, overwriting any previous errors
void updateTtl(const unsigned int rrTtl)
#define debugs(SECTION, LEVEL, CONTENT)
#define IP_LOOKUP_IF_MISS
void dlinkDelete(dlink_node *m, dlink_list *list)
void dlinkAdd(void *data, dlink_node *m, dlink_list *list)
void IDNSCB(void *cbdata, const rfc1035_rr *answer, const int recordsInAnswer, const char *error, bool lastAnswer)
void idnsALookup(const char *, IDNSCB *, void *)
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
static void purge_entries_fromhosts(void)
void ipcacheInvalidateNegative(const char *name)
void ipcache_restart(void)
const ipcache_addrs * ipcache_gethostbyname(const char *name, int flags)
void ipcacheInvalidate(const char *name)
variable_list * snmp_netIpFn(variable_list *Var, snint *ErrP)
void ipcache_purgelru(void *)
void ipcacheMarkGoodAddr(const char *name, const Ip::Address &addr)
int ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
static const Dns::CachedIps * ipcacheCheckNumeric(const char *name)
static void ipcacheUnlockEntry(ipcache_entry *)
static ipcache_entry * ipcache_get(const char *)
static hash_table * ip_table
static void ipcacheStatPrint(ipcache_entry *, StoreEntry *)
static void ipcacheLockEntry(ipcache_entry *)
static void purge_entries_fromhosts(void)
static struct _ipcache_stats IpcacheStats
static void ipcacheCallback(ipcache_entry *i, const bool hit, const int wait)
static void stat_ipcache_get(StoreEntry *)
static dlink_list lru_list
static void ipcacheRelease(ipcache_entry *, bool dofree=true)
static void ipcacheRegisterWithCacheManager(void)
static void ipcacheAddEntry(ipcache_entry *i)
static int ipcacheExpiredEntry(ipcache_entry *)
hash_link * hash_lookup(hash_table *, const void *)
hash_table * hash_create(HASHCMP *, int, HASHHASH *)
int HASHCMP(const void *, const void *)
void hash_join(hash_table *, hash_link *)
void hash_remove_link(hash_table *, hash_link *)
const char * hashKeyStr(const hash_link *)
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
void ipcacheMarkBadAddr(const char *name, const Ip::Address &addr)
static FREE ipcacheFreeEntry
static void ipcache_nbgethostbyname_(const char *name, IpCacheLookupForwarder handler)
implements ipcache_nbgethostbyname() and Dns::nbgethostbyname() APIs
static IDNSCB ipcacheHandleReply
static void ipcacheParse(ipcache_entry *i, const rfc1035_rr *answers, int nr, const char *error_message)
void IPH(const ipcache_addrs *, const Dns::LookupDetails &details, void *)
void nbgethostbyname(const char *name, const CbcPointer< IpReceiver > &receiver)
initiate an (often) asynchronous DNS lookup; the receiver gets the results
void RegisterAction(char const *action, char const *desc, OBJH *handler, Protected, Atomic, Format)
#define RFC1035_TYPE_CNAME
#define RFC1035_TYPE_AAAA
const char * snmpDebugOid(oid *Name, snint Len, MemBuf &outbuf)
#define SNMP_ERR_NOSUCHNAME
struct variable_list * snmp_var_new_integer(oid *, int, int, unsigned char)
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
time of the idnsALookup() call
time of the last noteLookup() call
SBuf text("GET http://resource.com/path HTTP/1.1\r\n" "Host: resource.com\r\n" "Cookie: laijkpk3422r j1noin \r\n" "\r\n")
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
int tvSubMsec(struct timeval t1, struct timeval t2)