ipcache.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 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 14 IP Cache */
10
11#include "squid.h"
12#include "CacheManager.h"
13#include "cbdata.h"
14#include "debug/Messages.h"
15#include "dlink.h"
16#include "dns/LookupDetails.h"
17#include "dns/rfc3596.h"
18#include "event.h"
19#include "ip/Address.h"
20#include "ip/tools.h"
21#include "ipcache.h"
22#include "mgr/Registration.h"
23#include "snmp_agent.h"
24#include "SquidConfig.h"
25#include "StatCounters.h"
26#include "Store.h"
27#include "util.h"
28#include "wordlist.h"
29
30#if SQUID_SNMP
31#include "snmp_core.h"
32#endif
33
71template <class Content>
73{
74public:
75 typedef Content DataType;
76 const char *kind;
78};
79
82{
83public:
86 IpCacheLookupForwarder(IPH *fun, void *data);
87
89 void finalCallback(const Dns::CachedIps *addrs, const Dns::LookupDetails &details);
90
93 bool forwardIp(const Ip::Address &ip);
94
96 void forwardHits(const Dns::CachedIps &ips);
97
100
102 void forwardLookup(const char *error);
103
106
107protected:
110
111private:
112 /* receiverObj and receiverFun are mutually exclusive */
114 IPH *receiverFun = nullptr;
116
117 struct timeval firstLookupStart {0,0};
118 struct timeval lastLookupEnd {0,0};
119};
120
130{
132
133public:
134 ipcache_entry(const char *);
136
137 hash_link hash; /* must be first */
138 time_t lastref;
139 time_t expires;
143
145 unsigned short locks;
146 struct Flags {
148
152
153 bool sawCname = false;
154
155 const char *name() const { return static_cast<const char*>(hash.key); }
156
158 int totalResponseTime() const;
161
163 template <class Specs>
164 void addGood(const rfc1035_rr &rr, Specs &specs);
165
167 void latestError(const char *text, const int debugLevel = 3);
168
169protected:
170 void updateTtl(const unsigned int rrTtl);
171};
172
174static struct _ipcache_stats {
177 int hits;
181 int rr_a;
187
190
191// forward-decls
192static void stat_ipcache_get(StoreEntry *);
193
197static ipcache_entry *ipcache_get(const char *);
198static void ipcacheLockEntry(ipcache_entry *);
200static void ipcacheUnlockEntry(ipcache_entry *);
201static void ipcacheRelease(ipcache_entry *, bool dofree = true);
202static const Dns::CachedIps *ipcacheCheckNumeric(const char *name);
203static void ipcache_nbgethostbyname_(const char *name, IpCacheLookupForwarder handler);
204
206static hash_table *ip_table = nullptr;
207
209static long ipcache_low = 180;
211static long ipcache_high = 200;
212
213#if LIBRESOLV_DNS_TTL_HACK
214extern int _dns_ttl_;
215#endif
216
218
220 receiverObj(receiver)
221{
222}
223
225 receiverFun(fun), receiverData(data)
226{
227}
228
229void
231{
232 debugs(14, 7, addrs << " " << details);
233 if (receiverObj.set()) {
234 if (auto receiver = receiverObj.valid())
235 receiver->noteIps(addrs, details);
237 } else if (receiverFun) {
238 if (receiverData.valid()) {
239 const Dns::CachedIps *emptyIsNil = (addrs && !addrs->empty()) ? addrs : nullptr;
240 receiverFun(emptyIsNil, details, receiverData.validDone());
241 }
242 receiverFun = nullptr;
243 }
244}
245
248bool
250{
251 debugs(14, 7, ip);
252 if (receiverObj.set()) {
253 if (auto receiver = receiverObj.valid()) {
254 receiver->noteIp(ip);
255 return true;
256 }
257 return false;
258 }
259 // else do nothing: ReceiverFun does not do incremental notifications
260 return false;
261}
262
264void
266{
267 if (receiverObj.set()) {
268 for (const auto &ip: ips.good()) {
269 if (!forwardIp(ip))
270 break; // receiver gone
271 }
272 }
273 // else do nothing: ReceiverFun does not do incremental notifications
274}
275
276void
278{
279 // Lookups run concurrently, but HttpRequest::recordLookup() thinks they
280 // are sequential. Give it just the new, yet-unaccounted-for delay.
281 if (receiverObj.set()) {
282 if (auto receiver = receiverObj.valid()) {
283 receiver->noteLookup(Dns::LookupDetails(error, additionalLookupDelay()));
285 }
286 }
287 // else do nothing: ReceiverFun gets no individual lookup notifications
288}
289
291inline int ipcacheCount() { return ip_table ? ip_table->count : 0; }
292
298static void
300{
301 if (!i) {
302 debugs(14, DBG_CRITICAL, "ipcacheRelease: Releasing entry with i=<NULL>");
303 return;
304 }
305
306 if (!i || !i->hash.key) {
307 debugs(14, DBG_CRITICAL, "ipcacheRelease: Releasing entry without hash link!");
308 return;
309 }
310
311 debugs(14, 3, "ipcacheRelease: Releasing entry for '" << (const char *) i->hash.key << "'");
312
314 dlinkDelete(&i->lru, &lru_list);
315 if (dofree)
317}
318
320static ipcache_entry *
321ipcache_get(const char *name)
322{
323 if (ip_table != nullptr)
324 return (ipcache_entry *) hash_lookup(ip_table, name);
325 else
326 return nullptr;
327}
328
330static int
332{
333 /* all static entries are locked, so this takes care of them too */
334
335 if (i->locks != 0)
336 return 0;
337
338 if (i->addrs.empty())
339 if (0 == i->flags.negcached)
340 return 1;
341
342 if (i->expires > squid_curtime)
343 return 0;
344
345 return 1;
346}
347
349void
351{
352 dlink_node *m;
353 dlink_node *prev = nullptr;
354 ipcache_entry *i;
355 int removed = 0;
356 eventAdd("ipcache_purgelru", ipcache_purgelru, nullptr, 10.0, 1);
357
358 for (m = lru_list.tail; m; m = prev) {
360 break;
361
362 prev = m->prev;
363
364 i = (ipcache_entry *)m->data;
365
366 if (i->locks != 0)
367 continue;
368
370
371 ++removed;
372 }
373
374 debugs(14, 9, "ipcache_purgelru: removed " << removed << " entries");
375}
376
382static void
384{
386 ipcache_entry *i = nullptr, *t;
387
388 while (m) {
389 if (i != nullptr) { /* need to delay deletion */
390 ipcacheRelease(i); /* we just override locks */
391 i = nullptr;
392 }
393
394 t = (ipcache_entry*)m->data;
395
396 if (t->flags.fromhosts)
397 i = t;
398
399 m = m->next;
400 }
401
402 if (i != nullptr)
404}
405
407 lastref(0),
408 expires(0),
409 error_message(nullptr),
410 locks(0) // XXX: use Lock type ?
411{
412 hash.key = xstrdup(aName);
413 Tolower(static_cast<char*>(hash.key));
415}
416
418static void
420{
422
423 if (nullptr != e) {
424 /* avoid collision */
425 ipcache_entry *q = (ipcache_entry *) e;
427 }
428
429 hash_join(ip_table, &i->hash);
430 dlinkAdd(i, &i->lru, &lru_list);
432}
433
439static void
440ipcacheCallback(ipcache_entry *i, const bool hit, const int wait)
441{
443
445
446 if (hit)
448 const Dns::LookupDetails details(i->error_message, wait);
449 i->handler.finalCallback(&i->addrs, details);
450
452}
453
454void
455ipcache_entry::latestError(const char *text, const int debugLevel)
456{
457 debugs(14, debugLevel, "ERROR: DNS failure while resolving " << name() << ": " << text);
460}
461
462static void
463ipcacheParse(ipcache_entry *i, const rfc1035_rr * answers, int nr, const char *error_message)
464{
465 int k;
466
467 // XXX: Callers use zero ancount instead of -1 on errors!
468 if (nr < 0) {
469 i->latestError(error_message);
470 return;
471 }
472
473 if (nr == 0) {
474 i->latestError("No DNS records");
475 return;
476 }
477
478 debugs(14, 3, nr << " answers for " << i->name());
479 assert(answers);
480
481 for (k = 0; k < nr; ++k) {
482
483 if (Ip::EnableIpv6 && answers[k].type == RFC1035_TYPE_AAAA) {
484 static const RrSpecs<struct in6_addr> QuadA = { "IPv6", IpcacheStats.rr_aaaa };
485 i->addGood(answers[k], QuadA);
486 continue;
487 }
488
489 if (answers[k].type == RFC1035_TYPE_A) {
490 static const RrSpecs<struct in_addr> SingleA = { "IPv4", IpcacheStats.rr_a };
491 i->addGood(answers[k], SingleA);
492 continue;
493 }
494
495 /* With A and AAAA, the CNAME does not necessarily come with additional records to use. */
496 if (answers[k].type == RFC1035_TYPE_CNAME) {
497 i->sawCname = true;
499 continue;
500 }
501
502 // otherwise its an unknown RR. debug at level 9 since we usually want to ignore these and they are common.
503 debugs(14, 9, "Unknown RR type received: type=" << answers[k].type << " starting at " << &(answers[k]) );
504 }
505}
506
507template <class Specs>
508void
509ipcache_entry::addGood(const rfc1035_rr &rr, Specs &specs)
510{
511 typename Specs::DataType address;
512 if (rr.rdlength != sizeof(address)) {
513 debugs(14, DBG_IMPORTANT, "ERROR: Ignoring invalid " << specs.kind << " address record while resolving " << name());
514 return;
515 }
516
517 ++specs.recordCounter;
518
519 // Do not store more than 255 addresses (TODO: Why?)
520 if (addrs.raw().size() >= 255)
521 return;
522
523 memcpy(&address, rr.rdata, sizeof(address));
524 const Ip::Address ip = address;
525 if (addrs.have(ip)) {
526 debugs(14, 3, "refusing to add duplicate " << ip);
527 return;
528 }
529 addrs.pushUnique(address);
530
531 updateTtl(rr.ttl);
532
533 debugs(14, 3, name() << " #" << addrs.size() << " " << ip);
534 handler.forwardIp(ip); // we are only called with good IPs
535}
536
537void
538ipcache_entry::updateTtl(const unsigned int rrTtl)
539{
540 const time_t ttl = std::min(std::max(
541 Config.negativeDnsTtl, // smallest value allowed
542 static_cast<time_t>(rrTtl)),
543 Config.positiveDnsTtl); // largest value allowed
544
545 const time_t rrExpires = squid_curtime + ttl;
546 if (rrExpires < expires)
547 expires = rrExpires;
548}
549
551static void
552ipcacheHandleReply(void *data, const rfc1035_rr * answers, int na, const char *error_message, const bool lastAnswer)
553{
554 ipcache_entry *i = static_cast<ipcache_entry*>(data);
555
556 i->handler.forwardLookup(error_message);
557 ipcacheParse(i, answers, na, error_message);
558
559 if (!lastAnswer)
560 return;
561
563 const auto age = i->handler.totalResponseTime();
565
566 if (i->addrs.empty()) {
567 i->flags.negcached = true;
569
570 if (!i->error_message) {
571 i->latestError("No valid address records", DBG_IMPORTANT);
572 if (i->sawCname)
574 }
575 }
576
577 debugs(14, 3, "done with " << i->name() << ": " << i->addrs);
579 ipcacheCallback(i, false, age);
580}
581
598void
599ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData)
600{
601 debugs(14, 4, name);
603}
604
605void
606Dns::nbgethostbyname(const char *name, const CbcPointer<IpReceiver> &receiver)
607{
608 debugs(14, 4, name);
610}
611
613static void
615{
616 ipcache_entry *i = nullptr;
617 const ipcache_addrs *addrs = nullptr;
619
620 if (name == nullptr || name[0] == '\0') {
621 debugs(14, 4, "ipcache_nbgethostbyname: Invalid name!");
623 const Dns::LookupDetails details("Invalid hostname", -1); // error, no lookup
624 handler.finalCallback(nullptr, details);
625 return;
626 }
627
628 if ((addrs = ipcacheCheckNumeric(name))) {
629 debugs(14, 4, "ipcache_nbgethostbyname: BYPASS for '" << name << "' (already numeric)");
630 handler.forwardHits(*addrs);
632 const Dns::LookupDetails details; // no error, no lookup
633 handler.finalCallback(addrs, details);
634 return;
635 }
636
637 i = ipcache_get(name);
638
639 if (nullptr == i) {
640 /* miss */
641 (void) 0;
642 } else if (ipcacheExpiredEntry(i)) {
643 /* hit, but expired -- bummer */
645 i = nullptr;
646 } else {
647 /* hit */
648 debugs(14, 4, "ipcache_nbgethostbyname: HIT for '" << name << "'");
649
650 if (i->flags.negcached)
652 else
654
655 i->handler = std::move(handler);
656 ipcacheCallback(i, true, -1); // no lookup
657
658 return;
659 }
660
661 debugs(14, 5, "ipcache_nbgethostbyname: MISS for '" << name << "'");
663 i = new ipcache_entry(name);
664 i->handler = std::move(handler);
667}
668
670static void
672{
673 Mgr::RegisterAction("ipcache",
674 "IP Cache Stats and Contents",
675 stat_ipcache_get, 0, 1);
676}
677
685void
687{
688 int n;
689 debugs(14, Important(24), "Initializing IP Cache...");
690 memset(&IpcacheStats, '\0', sizeof(IpcacheStats));
692
693 ipcache_high = (long) (((float) Config.ipcache.size *
694 (float) Config.ipcache.high) / (float) 100);
695 ipcache_low = (long) (((float) Config.ipcache.size *
696 (float) Config.ipcache.low) / (float) 100);
697 n = hashPrime(ipcache_high / 4);
698 ip_table = hash_create((HASHCMP *) strcmp, n, hash4);
699
701}
702
718const ipcache_addrs *
719ipcache_gethostbyname(const char *name, int flags)
720{
721 ipcache_entry *i = nullptr;
722 assert(name);
723 debugs(14, 3, "ipcache_gethostbyname: '" << name << "', flags=" << std::hex << flags);
725 i = ipcache_get(name);
726
727 if (nullptr == i) {
728 (void) 0;
729 } else if (ipcacheExpiredEntry(i)) {
731 i = nullptr;
732 } else if (i->flags.negcached) {
734 // ignore i->error_message: the caller just checks IP cache presence
735 return nullptr;
736 } else {
739 // ignore i->error_message: the caller just checks IP cache presence
740 return &i->addrs;
741 }
742
743 /* no entry [any more] */
744
745 if (const auto addrs = ipcacheCheckNumeric(name)) {
747 return addrs;
748 }
749
751
752 if (flags & IP_LOOKUP_IF_MISS)
753 ipcache_nbgethostbyname(name, nullptr, nullptr);
754
755 return nullptr;
756}
757
759static void
761{
762 char buf[MAX_IPSTRLEN];
763
764 if (!sentry) {
765 debugs(14, DBG_CRITICAL, "ERROR: sentry is NULL!");
766 return;
767 }
768
769 if (!i) {
770 debugs(14, DBG_CRITICAL, "ERROR: ipcache_entry is NULL!");
771 storeAppendPrintf(sentry, "CRITICAL ERROR\n");
772 return;
773 }
774
775 storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)",
776 hashKeyStr(&i->hash),
777 i->flags.fromhosts ? 'H' : ' ',
778 i->flags.negcached ? 'N' : ' ',
779 (int) (squid_curtime - i->lastref),
780 (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)),
781 static_cast<int>(i->addrs.size()),
782 static_cast<int>(i->addrs.badCount()));
783
786 if (i->flags.negcached) {
787 storeAppendPrintf(sentry, "\n");
788 return;
789 }
790
793 bool firstLine = true;
794 for (const auto &addr: i->addrs.raw()) {
795 /* Display tidy-up: IPv6 are so big make the list vertical */
796 const char *indent = firstLine ? "" : " ";
797 storeAppendPrintf(sentry, "%s %45.45s-%3s\n",
798 indent,
799 addr.ip.toStr(buf, MAX_IPSTRLEN),
800 addr.bad() ? "BAD" : "OK ");
801 firstLine = false;
802 }
803}
804
810void
812{
813 dlink_node *m;
814 assert(ip_table != nullptr);
815 storeAppendPrintf(sentry, "IP Cache Statistics:\n");
816 storeAppendPrintf(sentry, "IPcache Entries Cached: %d\n",
817 ipcacheCount());
818 storeAppendPrintf(sentry, "IPcache Requests: %d\n",
820 storeAppendPrintf(sentry, "IPcache Hits: %d\n",
822 storeAppendPrintf(sentry, "IPcache Negative Hits: %d\n",
824 storeAppendPrintf(sentry, "IPcache Numeric Hits: %d\n",
826 storeAppendPrintf(sentry, "IPcache Misses: %d\n",
828 storeAppendPrintf(sentry, "IPcache Retrieved A: %d\n",
830 storeAppendPrintf(sentry, "IPcache Retrieved AAAA: %d\n",
832 storeAppendPrintf(sentry, "IPcache Retrieved CNAME: %d\n",
834 storeAppendPrintf(sentry, "IPcache CNAME-Only Response: %d\n",
836 storeAppendPrintf(sentry, "IPcache Invalid Request: %d\n",
838 storeAppendPrintf(sentry, "\n\n");
839 storeAppendPrintf(sentry, "IP Cache Contents:\n\n");
840 storeAppendPrintf(sentry, " %-31.31s %3s %6s %6s %4s\n",
841 "Hostname",
842 "Flg",
843 "lstref",
844 "TTL",
845 "N(b)");
846
847 for (m = lru_list.head; m; m = m->next) {
848 assert( m->next != m );
849 ipcacheStatPrint((ipcache_entry *)m->data, sentry);
850 }
851}
852
854void
855ipcacheInvalidate(const char *name)
856{
857 ipcache_entry *i;
858
859 if ((i = ipcache_get(name)) == nullptr)
860 return;
861
863
864 /*
865 * NOTE, don't call ipcacheRelease here because we might be here due
866 * to a thread started from a callback.
867 */
868}
869
871void
873{
874 ipcache_entry *i;
875
876 if ((i = ipcache_get(name)) == nullptr)
877 return;
878
879 if (i->flags.negcached)
881
882 /*
883 * NOTE, don't call ipcacheRelease here because we might be here due
884 * to a thread started from a callback.
885 */
886}
887
889static const Dns::CachedIps *
890ipcacheCheckNumeric(const char *name)
891{
892 Ip::Address ip;
893 if (!ip.fromHost(name))
894 return nullptr;
895
896 debugs(14, 4, "HIT_BYPASS for " << name << "=" << ip);
897 static Dns::CachedIps static_addrs;
898 static_addrs.reset(ip);
899 return &static_addrs;
900}
901
903static void
905{
906 if (i->locks++ == 0) {
907 dlinkDelete(&i->lru, &lru_list);
908 dlinkAdd(i, &i->lru, &lru_list);
909 }
910}
911
913static void
915{
916 if (i->locks < 1) {
917 debugs(14, DBG_IMPORTANT, "WARNING: ipcacheEntry unlocked with no lock! locks=" << i->locks);
918 return;
919 }
920
921 -- i->locks;
922
923 if (ipcacheExpiredEntry(i))
925}
926
929bool
931{
932 // linear search!
933 for (size_t seen = 0; seen < ips.size(); ++seen) {
934 if (++goodPosition >= ips.size())
935 goodPosition = 0;
936 if (!ips[goodPosition].bad()) {
937 debugs(14, 3, "succeeded for " << name << ": " << *this);
938 return true;
939 }
940 }
941 goodPosition = ips.size();
942 debugs(14, 3, "failed for " << name << ": " << *this);
943 return false;
944}
945
946void
948{
949 ips.clear();
950 ips.emplace_back(ip);
951 goodPosition = 0;
952 // Assume that the given IP is good because CachedIps are designed to never
953 // run out of good IPs.
954 badCount_ = 0;
955}
956
958void
960{
961 if (badCount() >= size()) {
962 // There are no good IPs left. Clear all bad marks. This must help
963 // because we are called only after a good address was tested as bad.
964 for (auto &cachedIp: ips)
965 cachedIp.forgetMarking();
966 badCount_ = 0;
967 }
968 Must(seekNewGood(name));
969 debugs(14, 3, "cleared all IPs for " << name << "; now back to " << *this);
970}
971
972bool
973Dns::CachedIps::have(const Ip::Address &ip, size_t *positionOrNil) const
974{
975 // linear search!
976 size_t pos = 0;
977 for (const auto &cachedIp: ips) {
978 if (cachedIp.ip == ip) {
979 if (auto position = positionOrNil)
980 *position = pos;
981 debugs(14, 7, ip << " at " << pos << " in " << *this);
982 return true;
983 }
984 }
985 // no such address; leave *position as is
986 debugs(14, 7, " no " << ip << " in " << *this);
987 return false;
988}
989
990void
992{
993 assert(!have(ip));
994 ips.emplace_back(ip);
995 assert(!raw().back().bad());
996}
997
998void
999Dns::CachedIps::reportCurrent(std::ostream &os) const
1000{
1001 if (empty())
1002 os << "[no cached IPs]";
1003 else if (goodPosition == size())
1004 os << "[" << size() << " bad cached IPs]"; // could only be temporary
1005 else
1006 os << current() << " #" << (goodPosition+1) << "/" << ips.size() << "-" << badCount();
1007}
1008
1009void
1010Dns::CachedIps::markAsBad(const char *name, const Ip::Address &ip)
1011{
1012 size_t badPosition = 0;
1013 if (!have(ip, &badPosition))
1014 return; // no such address
1015
1016 auto &cachedIp = ips[badPosition];
1017 if (cachedIp.bad())
1018 return; // already marked correctly
1019
1020 cachedIp.markAsBad();
1021 ++badCount_;
1022 debugs(14, 2, ip << " of " << name);
1023
1024 if (goodPosition == badPosition)
1025 restoreGoodness(name);
1026 // else nothing to do: goodPositon still points to a good IP
1027}
1028
1029void
1030Dns::CachedIps::forgetMarking(const char *name, const Ip::Address &ip)
1031{
1032 if (!badCount_)
1033 return; // all IPs are already "good"
1034
1035 size_t badPosition = 0;
1036 if (!have(ip, &badPosition))
1037 return; // no such address
1038
1039 auto &cachedIp = ips[badPosition];
1040 if (!cachedIp.bad())
1041 return; // already marked correctly
1042
1043 cachedIp.forgetMarking();
1044 assert(!cachedIp.bad());
1045 --badCount_;
1046 debugs(14, 2, ip << " of " << name);
1047}
1048
1056void
1057ipcacheMarkBadAddr(const char *name, const Ip::Address &addr)
1058{
1059 if (auto cached = ipcache_get(name))
1060 cached->addrs.markAsBad(name, addr);
1061}
1062
1064void
1065ipcacheMarkGoodAddr(const char *name, const Ip::Address &addr)
1066{
1067 if (auto cached = ipcache_get(name))
1068 cached->addrs.forgetMarking(name, addr);
1069}
1070
1072static void
1074{
1075 ipcache_entry *i = (ipcache_entry *)data;
1076 delete i;
1077}
1078
1080{
1081 xfree(error_message);
1082 xfree(hash.key);
1083}
1084
1092void
1094{
1095 ipcache_high = (long) (((float) Config.ipcache.size *
1096 (float) Config.ipcache.high) / (float) 100);
1097 ipcache_low = (long) (((float) Config.ipcache.size *
1098 (float) Config.ipcache.low) / (float) 100);
1100}
1101
1113int
1114ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
1115{
1116 ipcache_entry *i;
1117
1118 Ip::Address ip;
1119
1120 if (!(ip = ipaddr)) {
1121 if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) {
1122 debugs(14, 3, "ipcacheAddEntryFromHosts: Skipping IPv6 address '" << ipaddr << "'");
1123 } else {
1124 debugs(14, DBG_IMPORTANT, "ERROR: ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr << "'");
1125 }
1126
1127 return 1;
1128 }
1129
1130 if (!Ip::EnableIpv6 && ip.isIPv6()) {
1131 debugs(14, 2, "skips IPv6 address in /etc/hosts because IPv6 support was disabled: " << ip);
1132 return 1;
1133 }
1134
1135 if ((i = ipcache_get(name))) {
1136 if (1 == i->flags.fromhosts) {
1138 } else if (i->locks > 0) {
1139 debugs(14, DBG_IMPORTANT, "ERROR: ipcacheAddEntryFromHosts: cannot add static entry for locked name '" << name << "'");
1140 return 1;
1141 } else {
1142 ipcacheRelease(i);
1143 }
1144 }
1145
1146 i = new ipcache_entry(name);
1147 i->addrs.pushUnique(ip);
1148 i->flags.fromhosts = true;
1149 ipcacheAddEntry(i);
1151 return 0;
1152}
1153
1154#if SQUID_SNMP
1162{
1163 variable_list *Answer = nullptr;
1164 MemBuf tmp;
1165 debugs(49, 5, "snmp_netIpFn: Processing request:" << snmpDebugOid(Var->name, Var->name_length, tmp));
1166 *ErrP = SNMP_ERR_NOERROR;
1167
1168 switch (Var->name[LEN_SQ_NET + 1]) {
1169
1170 case IP_ENT:
1171 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1172 ipcacheCount(),
1173 SMI_GAUGE32);
1174 break;
1175
1176 case IP_REQ:
1177 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1180 break;
1181
1182 case IP_HITS:
1183 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1186 break;
1187
1188 case IP_PENDHIT:
1189 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1190 0,
1191 SMI_GAUGE32);
1192 break;
1193
1194 case IP_NEGHIT:
1195 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1198 break;
1199
1200 case IP_MISS:
1201 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1204 break;
1205
1206 case IP_GHBN:
1207 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1208 0, /* deprecated */
1210 break;
1211
1212 case IP_LOC:
1213 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1214 0, /* deprecated */
1216 break;
1217
1218 default:
1219 *ErrP = SNMP_ERR_NOSUCHNAME;
1220 assert(!Answer);
1221 }
1222
1223 return Answer;
1224}
1225
1226#endif /*SQUID_SNMP */
1227
#define false
Definition: GnuRegex.c:240
int size
Definition: ModDevPoll.cc:75
time_t squid_curtime
Definition: stub_libtime.cc:20
class SquidConfig Config
Definition: SquidConfig.cc:12
StatCounters statCounter
Definition: StatCounters.cc:12
#define Must(condition)
Definition: TextException.h:71
void error(char *format,...)
#define assert(EX)
Definition: assert.h:19
#define LEN_SQ_NET
Definition: cache_snmp.h:49
@ IP_HITS
Definition: cache_snmp.h:191
@ IP_REQ
Definition: cache_snmp.h:190
@ IP_ENT
Definition: cache_snmp.h:189
@ IP_MISS
Definition: cache_snmp.h:194
@ IP_NEGHIT
Definition: cache_snmp.h:193
@ IP_GHBN
Definition: cache_snmp.h:195
@ IP_LOC
Definition: cache_snmp.h:196
@ IP_PENDHIT
Definition: cache_snmp.h:192
int64_t snint
Definition: cache_snmp.h:14
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
#define CBDATA_CLASS(type)
Definition: cbdata.h:302
an old-style void* callback parameter
Definition: cbdata.h:377
void * validDone()
Definition: cbdata.h:389
bool valid() const
Definition: cbdata.h:388
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
void clear()
make pointer not set; does not invalidate cbdata
Definition: CbcPointer.h:144
bool set() const
was set but may be invalid
Definition: CbcPointer.h:40
void markAsBad(const char *name, const Ip::Address &ip)
Definition: ipcache.cc:1010
size_t goodPosition
position of the IP returned by current()
Definition: ipcache.h:100
void reset(const Ip::Address &ip)
replace all info with the given (presumed good) IP address
Definition: ipcache.cc:947
void pushUnique(const Ip::Address &ip)
Definition: ipcache.cc:991
bool have(const Ip::Address &ip, size_t *position=nullptr) const
Definition: ipcache.cc:973
const Storage & raw() const
all cached entries
Definition: ipcache.h:69
size_t size() const noexcept
all cached IPs
Definition: ipcache.h:62
void forgetMarking(const char *name, const Ip::Address &ip)
undo successful markAsBad()
Definition: ipcache.cc:1030
bool seekNewGood(const char *name)
Definition: ipcache.cc:930
IpsSelector< GoodIpsIterator > good() const
good IPs
Definition: ipcache.h:242
Storage ips
good and bad IPs
Definition: ipcache.h:97
void restoreGoodness(const char *name)
makes current() calls possible after a successful markAsBad()
Definition: ipcache.cc:959
void reportCurrent(std::ostream &os) const
prints current IP and other debugging information
Definition: ipcache.cc:999
size_t badCount() const noexcept
bad IPs
Definition: ipcache.h:63
bool empty() const noexcept
whether we cached no IPs at all
Definition: ipcache.h:61
encapsulates DNS lookup results
Definition: LookupDetails.h:21
forwards non-blocking IP cache lookup results to either IPH or IpReciever
Definition: ipcache.cc:82
void forwardHits(const Dns::CachedIps &ips)
convenience wrapper to safely forwardIp() for each IP in the container
Definition: ipcache.cc:265
IPH * receiverFun
gets final results
Definition: ipcache.cc:114
void forwardLookup(const char *error)
inform recipient of a finished lookup
Definition: ipcache.cc:277
bool forwardIp(const Ip::Address &ip)
Definition: ipcache.cc:249
void finalCallback(const Dns::CachedIps *addrs, const Dns::LookupDetails &details)
forwards notification about the end of the lookup; last method to be called
Definition: ipcache.cc:230
CbcPointer< Dns::IpReceiver > receiverObj
gets incremental and final results
Definition: ipcache.cc:113
void lookupsStarting()
initialize lookup timestamps for Dns::LookupDetails delay calculation
Definition: ipcache.cc:99
int totalResponseTime() const
Definition: ipcache.cc:105
CallbackData receiverData
caller-specific data for the handler (optional)
Definition: ipcache.cc:115
int additionalLookupDelay() const
Definition: ipcache.cc:109
bool fromHost(const char *hostWithoutPort)
Definition: Address.cc:898
bool isIPv6() const
Definition: Address.cc:164
Definition: MemBuf.h:24
metadata for parsing DNS A and AAAA records
Definition: ipcache.cc:73
const char * kind
human-friendly record type description
Definition: ipcache.cc:76
int & recordCounter
where this kind of records are counted (for stats)
Definition: ipcache.cc:77
Content DataType
actual RR DATA type
Definition: ipcache.cc:75
time_t negativeDnsTtl
Definition: SquidConfig.h:103
struct SquidConfig::@107 ipcache
time_t positiveDnsTtl
Definition: SquidConfig.h:104
StatHist svcTime
Definition: StatCounters.h:98
struct StatCounters::@133 dns
void count(double val)
Definition: StatHist.cc:55
int count
Definition: hash.h:31
Definition: ipcache.cc:130
void addGood(const rfc1035_rr &rr, Specs &specs)
adds the contents of a "good" DNS A or AAAA record to stored IPs
Definition: ipcache.cc:509
time_t lastref
Definition: ipcache.cc:138
IpCacheLookupForwarder handler
Definition: ipcache.cc:141
struct ipcache_entry::Flags flags
char * error_message
Definition: ipcache.cc:142
time_t expires
Definition: ipcache.cc:139
unsigned short locks
Definition: ipcache.cc:145
hash_link hash
Definition: ipcache.cc:137
ipcache_entry(const char *)
Definition: ipcache.cc:406
bool sawCname
Definition: ipcache.cc:153
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
void latestError(const char *text, const int debugLevel=3)
remembers the last error seen, overwriting any previous errors
Definition: ipcache.cc:455
const char * name() const
Definition: ipcache.cc:155
ipcache_addrs addrs
Definition: ipcache.cc:140
~ipcache_entry()
Definition: ipcache.cc:1079
void updateTtl(const unsigned int rrTtl)
Definition: ipcache.cc:538
dlink_node lru
Definition: ipcache.cc:144
char * rdata
Definition: rfc1035.h:44
unsigned short rdlength
Definition: rfc1035.h:43
unsigned int ttl
Definition: rfc1035.h:42
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define Important(id)
Definition: Messages.h:91
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
#define DBG_CRITICAL
Definition: Stream.h:40
#define IP_LOOKUP_IF_MISS
Definition: defines.h:39
void IDNSCB(void *cbdata, const rfc1035_rr *answer, const int recordsInAnswer, const char *error, bool lastAnswer)
Definition: forward.h:16
void idnsALookup(const char *, IDNSCB *, void *)
const char * text
Definition: errorpage.cc:153
int type
Definition: errorpage.cc:152
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
void ipcacheInvalidateNegative(const char *name)
Definition: ipcache.cc:872
void ipcache_restart(void)
Definition: ipcache.cc:1093
const ipcache_addrs * ipcache_gethostbyname(const char *name, int flags)
Definition: ipcache.cc:719
void ipcache_init(void)
Definition: ipcache.cc:686
void ipcacheInvalidate(const char *name)
Definition: ipcache.cc:855
variable_list * snmp_netIpFn(variable_list *Var, snint *ErrP)
Definition: ipcache.cc:1161
void ipcache_purgelru(void *)
Definition: ipcache.cc:350
void ipcacheMarkGoodAddr(const char *name, const Ip::Address &addr)
Definition: ipcache.cc:1065
int ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
Definition: ipcache.cc:1114
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:599
static const Dns::CachedIps * ipcacheCheckNumeric(const char *name)
Definition: ipcache.cc:890
static void ipcacheUnlockEntry(ipcache_entry *)
Definition: ipcache.cc:914
static ipcache_entry * ipcache_get(const char *)
Definition: ipcache.cc:321
static hash_table * ip_table
Definition: ipcache.cc:206
static void ipcacheStatPrint(ipcache_entry *, StoreEntry *)
Definition: ipcache.cc:760
static void ipcacheLockEntry(ipcache_entry *)
Definition: ipcache.cc:904
static void purge_entries_fromhosts(void)
Definition: ipcache.cc:383
int ipcacheCount()
Definition: ipcache.cc:291
static struct _ipcache_stats IpcacheStats
static void ipcacheCallback(ipcache_entry *i, const bool hit, const int wait)
Definition: ipcache.cc:440
static void stat_ipcache_get(StoreEntry *)
Definition: ipcache.cc:811
static long ipcache_high
Definition: ipcache.cc:211
static dlink_list lru_list
Definition: ipcache.cc:189
static void ipcacheRelease(ipcache_entry *, bool dofree=true)
Definition: ipcache.cc:299
static long ipcache_low
Definition: ipcache.cc:209
static void ipcacheRegisterWithCacheManager(void)
Definition: ipcache.cc:671
static void ipcacheAddEntry(ipcache_entry *i)
Definition: ipcache.cc:419
static int ipcacheExpiredEntry(ipcache_entry *)
Definition: ipcache.cc:331
SQUIDCEXTERN hash_table * hash_create(HASHCMP *, int, HASHHASH *)
Definition: hash.cc:108
SQUIDCEXTERN void hash_join(hash_table *, hash_link *)
Definition: hash.cc:131
SQUIDCEXTERN int hashPrime(int n)
Definition: hash.cc:293
int HASHCMP(const void *, const void *)
Definition: hash.h:13
SQUIDCEXTERN void hash_remove_link(hash_table *, hash_link *)
Definition: hash.cc:220
SQUIDCEXTERN HASHHASH hash4
Definition: hash.h:46
SQUIDCEXTERN const char * hashKeyStr(const hash_link *)
Definition: hash.cc:313
SQUIDCEXTERN hash_link * hash_lookup(hash_table *, const void *)
Definition: hash.cc:146
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
void ipcacheMarkBadAddr(const char *name, const Ip::Address &addr)
Definition: ipcache.cc:1057
static FREE ipcacheFreeEntry
Definition: ipcache.cc:194
static void ipcache_nbgethostbyname_(const char *name, IpCacheLookupForwarder handler)
implements ipcache_nbgethostbyname() and Dns::nbgethostbyname() APIs
Definition: ipcache.cc:614
static IDNSCB ipcacheHandleReply
Definition: ipcache.cc:195
static void ipcacheParse(ipcache_entry *i, const rfc1035_rr *answers, int nr, const char *error_message)
Definition: ipcache.cc:463
void IPH(const ipcache_addrs *, const Dns::LookupDetails &details, void *)
Definition: ipcache.h:219
void FREE(void *)
Definition: forward.h:36
void nbgethostbyname(const char *name, const CbcPointer< IpReceiver > &receiver)
initiate an (often) asynchronous DNS lookup; the receiver gets the results
Definition: ipcache.cc:606
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
#define xfree
#define xstrdup
static void handler(int signo)
Definition: purge.cc:854
#define RFC1035_TYPE_A
Definition: rfc1035.h:93
#define RFC1035_TYPE_CNAME
Definition: rfc1035.h:94
#define RFC1035_TYPE_AAAA
Definition: rfc3596.h:53
const char * snmpDebugOid(oid *Name, snint Len, MemBuf &outbuf)
Definition: snmp_core.cc:1052
#define SNMP_ERR_NOERROR
Definition: snmp_error.h:42
#define SNMP_ERR_NOSUCHNAME
Definition: snmp_error.h:44
#define SMI_GAUGE32
Definition: snmp_vars.h:77
#define SMI_COUNTER32
Definition: snmp_vars.h:76
struct variable_list * snmp_var_new_integer(oid *, int, int, unsigned char)
Definition: snmp_vars.c:151
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:828
time of the idnsALookup() call
Definition: ipcache.cc:117
time of the last noteLookup() call
Definition: ipcache.cc:118
int EnableIpv6
Whether IPv6 is supported and type of support.
Definition: tools.h:25
int numeric_hits
Definition: ipcache.cc:180
int negative_hits
Definition: ipcache.cc:179
Definition: ipcache.cc:146
Flags()
Definition: ipcache.cc:147
bool fromhosts
Definition: ipcache.cc:150
bool negcached
Definition: ipcache.cc:149
int name_length
Definition: snmp_vars.h:47
oid * name
Definition: snmp_vars.h:46
static hash_table * hash
Definition: text_backend.cc:41
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition: gadgets.cc:17
int tvSubMsec(struct timeval t1, struct timeval t2)
Definition: gadgets.cc:51
SQUIDCEXTERN void Tolower(char *)
Definition: util.c:28
#define safe_free(x)
Definition: xalloc.h:73

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors