ipcache.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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 {
147 Flags() : negcached(false), fromhosts(false) {}
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);
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
230IpCacheLookupForwarder::finalCallback(const Dns::CachedIps * const possiblyEmptyAddrs, const Dns::LookupDetails &details)
231{
232 // TODO: Consider removing nil-supplying IpcacheStats.invalid code and refactoring accordingly.
233 // may be nil but is never empty
234 const auto addrs = (possiblyEmptyAddrs && possiblyEmptyAddrs->empty()) ? nullptr : possiblyEmptyAddrs;
235
236 debugs(14, 7, addrs << " " << details);
237 if (receiverObj.set()) {
238 if (auto receiver = receiverObj.valid())
239 receiver->noteIps(addrs, details);
241 } else if (receiverFun) {
242 if (receiverData.valid())
243 receiverFun(addrs, details, receiverData.validDone());
244 receiverFun = nullptr;
245 }
246}
247
250bool
252{
253 debugs(14, 7, ip);
254 if (receiverObj.set()) {
255 if (auto receiver = receiverObj.valid()) {
256 receiver->noteIp(ip);
257 return true;
258 }
259 return false;
260 }
261 // else do nothing: ReceiverFun does not do incremental notifications
262 return false;
263}
264
266void
268{
269 if (receiverObj.set()) {
270 for (const auto &ip: ips.good()) {
271 if (!forwardIp(ip))
272 break; // receiver gone
273 }
274 }
275 // else do nothing: ReceiverFun does not do incremental notifications
276}
277
278void
280{
281 // Lookups run concurrently, but HttpRequest::recordLookup() thinks they
282 // are sequential. Give it just the new, yet-unaccounted-for delay.
283 if (receiverObj.set()) {
284 if (auto receiver = receiverObj.valid()) {
285 receiver->noteLookup(Dns::LookupDetails(SBuf(error), additionalLookupDelay()));
287 }
288 }
289 // else do nothing: ReceiverFun gets no individual lookup notifications
290}
291
293inline int ipcacheCount() { return ip_table ? ip_table->count : 0; }
294
300static void
302{
303 if (!i) {
304 debugs(14, DBG_CRITICAL, "ipcacheRelease: Releasing entry with i=<NULL>");
305 return;
306 }
307
308 if (!i || !i->hash.key) {
309 debugs(14, DBG_CRITICAL, "ipcacheRelease: Releasing entry without hash link!");
310 return;
311 }
312
313 debugs(14, 3, "ipcacheRelease: Releasing entry for '" << (const char *) i->hash.key << "'");
314
316 dlinkDelete(&i->lru, &lru_list);
317 if (dofree)
319}
320
322static ipcache_entry *
323ipcache_get(const char *name)
324{
325 if (ip_table != nullptr)
326 return (ipcache_entry *) hash_lookup(ip_table, name);
327 else
328 return nullptr;
329}
330
332static int
334{
335 /* all static entries are locked, so this takes care of them too */
336
337 if (i->locks != 0)
338 return 0;
339
340 if (i->addrs.empty())
341 if (0 == i->flags.negcached)
342 return 1;
343
344 if (i->expires > squid_curtime)
345 return 0;
346
347 return 1;
348}
349
351void
353{
354 dlink_node *m;
355 dlink_node *prev = nullptr;
356 ipcache_entry *i;
357 int removed = 0;
358 eventAdd("ipcache_purgelru", ipcache_purgelru, nullptr, 10.0, 1);
359
360 for (m = lru_list.tail; m; m = prev) {
362 break;
363
364 prev = m->prev;
365
366 i = (ipcache_entry *)m->data;
367
368 if (i->locks != 0)
369 continue;
370
372
373 ++removed;
374 }
375
376 debugs(14, 9, "ipcache_purgelru: removed " << removed << " entries");
377}
378
384static void
386{
388 ipcache_entry *i = nullptr, *t;
389
390 while (m) {
391 if (i != nullptr) { /* need to delay deletion */
392 ipcacheRelease(i); /* we just override locks */
393 i = nullptr;
394 }
395
396 t = (ipcache_entry*)m->data;
397
398 if (t->flags.fromhosts)
399 i = t;
400
401 m = m->next;
402 }
403
404 if (i != nullptr)
406}
407
409 lastref(0),
410 expires(0),
411 error_message(nullptr),
412 locks(0) // XXX: use Lock type ?
413{
414 hash.key = xstrdup(aName);
415 Tolower(static_cast<char*>(hash.key));
417}
418
420static void
422{
424
425 if (nullptr != e) {
426 /* avoid collision */
427 ipcache_entry *q = (ipcache_entry *) e;
429 }
430
431 hash_join(ip_table, &i->hash);
432 dlinkAdd(i, &i->lru, &lru_list);
434}
435
441static void
442ipcacheCallback(ipcache_entry *i, const bool hit, const int wait)
443{
445
447
448 if (hit)
450 const Dns::LookupDetails details(SBuf(i->error_message), wait);
451 i->handler.finalCallback(&i->addrs, details);
452
454}
455
456void
458{
459 debugs(14, 3, "ERROR: DNS failure while resolving " << name() << ": " << text);
462}
463
464static void
465ipcacheParse(ipcache_entry *i, const rfc1035_rr * answers, int nr, const char *error_message)
466{
467 int k;
468
469 // XXX: Callers use zero ancount instead of -1 on errors!
470 if (nr < 0) {
471 i->latestError(error_message);
472 return;
473 }
474
475 if (nr == 0) {
476 i->latestError("No DNS records");
477 return;
478 }
479
480 debugs(14, 3, nr << " answers for " << i->name());
481 assert(answers);
482
483 for (k = 0; k < nr; ++k) {
484
485 if (Ip::EnableIpv6 && answers[k].type == RFC1035_TYPE_AAAA) {
486 static const RrSpecs<struct in6_addr> QuadA = { "IPv6", IpcacheStats.rr_aaaa };
487 i->addGood(answers[k], QuadA);
488 continue;
489 }
490
491 if (answers[k].type == RFC1035_TYPE_A) {
492 static const RrSpecs<struct in_addr> SingleA = { "IPv4", IpcacheStats.rr_a };
493 i->addGood(answers[k], SingleA);
494 continue;
495 }
496
497 /* With A and AAAA, the CNAME does not necessarily come with additional records to use. */
498 if (answers[k].type == RFC1035_TYPE_CNAME) {
499 i->sawCname = true;
501 continue;
502 }
503
504 // otherwise its an unknown RR. debug at level 9 since we usually want to ignore these and they are common.
505 debugs(14, 9, "Unknown RR type received: type=" << answers[k].type << " starting at " << &(answers[k]) );
506 }
507}
508
509template <class Specs>
510void
511ipcache_entry::addGood(const rfc1035_rr &rr, Specs &specs)
512{
513 typename Specs::DataType address;
514 if (rr.rdlength != sizeof(address)) {
515 debugs(14, DBG_IMPORTANT, "ERROR: Ignoring invalid " << specs.kind << " address record while resolving " << name());
516 return;
517 }
518
519 ++specs.recordCounter;
520
521 // Do not store more than 255 addresses (TODO: Why?)
522 if (addrs.raw().size() >= 255)
523 return;
524
525 memcpy(&address, rr.rdata, sizeof(address));
526 const Ip::Address ip = address;
527 if (addrs.have(ip)) {
528 debugs(14, 3, "refusing to add duplicate " << ip);
529 return;
530 }
531 addrs.pushUnique(address);
532
533 updateTtl(rr.ttl);
534
535 debugs(14, 3, name() << " #" << addrs.size() << " " << ip);
536 handler.forwardIp(ip); // we are only called with good IPs
537}
538
539void
540ipcache_entry::updateTtl(const unsigned int rrTtl)
541{
542 const time_t ttl = std::min(std::max(
543 Config.negativeDnsTtl, // smallest value allowed
544 static_cast<time_t>(rrTtl)),
545 Config.positiveDnsTtl); // largest value allowed
546
547 const time_t rrExpires = squid_curtime + ttl;
548 if (addrs.size() <= 1) {
549 debugs(14, 5, "use first " << ttl << " from RR TTL " << rrTtl);
550 expires = rrExpires;
551 } else if (rrExpires < expires) {
552 debugs(14, 5, "use smaller " << ttl << " from RR TTL " << rrTtl << "; was: " << (expires - squid_curtime));
553 expires = rrExpires;
554 } else {
555 debugs(14, 7, "ignore " << ttl << " from RR TTL " << rrTtl << "; keep: " << (expires - squid_curtime));
556 }
557}
558
560static void
561ipcacheHandleReply(void *data, const rfc1035_rr * answers, int na, const char *error_message, const bool lastAnswer)
562{
563 ipcache_entry *i = static_cast<ipcache_entry*>(data);
564
565 i->handler.forwardLookup(error_message);
566 ipcacheParse(i, answers, na, error_message);
567
568 if (!lastAnswer)
569 return;
570
572 const auto age = i->handler.totalResponseTime();
574
575 if (i->addrs.empty()) {
576 i->flags.negcached = true;
578
579 if (!i->error_message) {
580 i->latestError("No valid address records");
581 if (i->sawCname)
583 }
584 }
585
586 debugs(14, 3, "done with " << i->name() << ": " << i->addrs);
588 ipcacheCallback(i, false, age);
589}
590
607void
608ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData)
609{
610 debugs(14, 4, name);
612}
613
614void
615Dns::nbgethostbyname(const char *name, const CbcPointer<IpReceiver> &receiver)
616{
617 debugs(14, 4, name);
619}
620
622static void
624{
625 ipcache_entry *i = nullptr;
626 const ipcache_addrs *addrs = nullptr;
628
629 if (name == nullptr || name[0] == '\0') {
630 debugs(14, 4, "ipcache_nbgethostbyname: Invalid name!");
632 static const Dns::LookupDetails details(SBuf("Invalid hostname"), -1); // error, no lookup
633 handler.finalCallback(nullptr, details);
634 return;
635 }
636
637 if ((addrs = ipcacheCheckNumeric(name))) {
638 debugs(14, 4, "ipcache_nbgethostbyname: BYPASS for '" << name << "' (already numeric)");
639 handler.forwardHits(*addrs);
641 const Dns::LookupDetails details; // no error, no lookup
642 handler.finalCallback(addrs, details);
643 return;
644 }
645
646 i = ipcache_get(name);
647
648 if (nullptr == i) {
649 /* miss */
650 (void) 0;
651 } else if (ipcacheExpiredEntry(i)) {
652 /* hit, but expired -- bummer */
654 i = nullptr;
655 } else {
656 /* hit */
657 debugs(14, 4, "ipcache_nbgethostbyname: HIT for '" << name << "'");
658
659 if (i->flags.negcached)
661 else
663
664 i->handler = std::move(handler);
665 ipcacheCallback(i, true, -1); // no lookup
666
667 return;
668 }
669
670 debugs(14, 5, "ipcache_nbgethostbyname: MISS for '" << name << "'");
672 i = new ipcache_entry(name);
673 i->handler = std::move(handler);
676}
677
679static void
681{
682 Mgr::RegisterAction("ipcache",
683 "IP Cache Stats and Contents",
684 stat_ipcache_get, 0, 1);
685}
686
694void
696{
697 int n;
698 debugs(14, Important(24), "Initializing IP Cache...");
699 memset(&IpcacheStats, '\0', sizeof(IpcacheStats));
701
702 ipcache_high = (long) (((float) Config.ipcache.size *
703 (float) Config.ipcache.high) / (float) 100);
704 ipcache_low = (long) (((float) Config.ipcache.size *
705 (float) Config.ipcache.low) / (float) 100);
706 n = hashPrime(ipcache_high / 4);
707 ip_table = hash_create((HASHCMP *) strcmp, n, hash4);
708
710}
711
727const ipcache_addrs *
728ipcache_gethostbyname(const char *name, int flags)
729{
730 ipcache_entry *i = nullptr;
731 assert(name);
732 debugs(14, 3, "ipcache_gethostbyname: '" << name << "', flags=" << std::hex << flags);
734 i = ipcache_get(name);
735
736 if (nullptr == i) {
737 (void) 0;
738 } else if (ipcacheExpiredEntry(i)) {
740 i = nullptr;
741 } else if (i->flags.negcached) {
743 // ignore i->error_message: the caller just checks IP cache presence
744 return nullptr;
745 } else {
748 // ignore i->error_message: the caller just checks IP cache presence
749 return &i->addrs;
750 }
751
752 /* no entry [any more] */
753
754 if (const auto addrs = ipcacheCheckNumeric(name)) {
756 return addrs;
757 }
758
760
761 if (flags & IP_LOOKUP_IF_MISS)
762 ipcache_nbgethostbyname(name, nullptr, nullptr);
763
764 return nullptr;
765}
766
768static void
770{
771 char buf[MAX_IPSTRLEN];
772
773 if (!sentry) {
774 debugs(14, DBG_CRITICAL, "ERROR: sentry is NULL!");
775 return;
776 }
777
778 if (!i) {
779 debugs(14, DBG_CRITICAL, "ERROR: ipcache_entry is NULL!");
780 storeAppendPrintf(sentry, "CRITICAL ERROR\n");
781 return;
782 }
783
784 storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)",
785 hashKeyStr(&i->hash),
786 i->flags.fromhosts ? 'H' : ' ',
787 i->flags.negcached ? 'N' : ' ',
788 (int) (squid_curtime - i->lastref),
789 (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)),
790 static_cast<int>(i->addrs.size()),
791 static_cast<int>(i->addrs.badCount()));
792
795 if (i->flags.negcached) {
796 storeAppendPrintf(sentry, "\n");
797 return;
798 }
799
802 bool firstLine = true;
803 for (const auto &addr: i->addrs.raw()) {
804 /* Display tidy-up: IPv6 are so big make the list vertical */
805 const char *indent = firstLine ? "" : " ";
806 storeAppendPrintf(sentry, "%s %45.45s-%3s\n",
807 indent,
808 addr.ip.toStr(buf, MAX_IPSTRLEN),
809 addr.bad() ? "BAD" : "OK ");
810 firstLine = false;
811 }
812}
813
819void
821{
822 dlink_node *m;
823 assert(ip_table != nullptr);
824 storeAppendPrintf(sentry, "IP Cache Statistics:\n");
825 storeAppendPrintf(sentry, "IPcache Entries Cached: %d\n",
826 ipcacheCount());
827 storeAppendPrintf(sentry, "IPcache Requests: %d\n",
829 storeAppendPrintf(sentry, "IPcache Hits: %d\n",
831 storeAppendPrintf(sentry, "IPcache Negative Hits: %d\n",
833 storeAppendPrintf(sentry, "IPcache Numeric Hits: %d\n",
835 storeAppendPrintf(sentry, "IPcache Misses: %d\n",
837 storeAppendPrintf(sentry, "IPcache Retrieved A: %d\n",
839 storeAppendPrintf(sentry, "IPcache Retrieved AAAA: %d\n",
841 storeAppendPrintf(sentry, "IPcache Retrieved CNAME: %d\n",
843 storeAppendPrintf(sentry, "IPcache CNAME-Only Response: %d\n",
845 storeAppendPrintf(sentry, "IPcache Invalid Request: %d\n",
847 storeAppendPrintf(sentry, "\n\n");
848 storeAppendPrintf(sentry, "IP Cache Contents:\n\n");
849 storeAppendPrintf(sentry, " %-31.31s %3s %6s %6s %4s\n",
850 "Hostname",
851 "Flg",
852 "lstref",
853 "TTL",
854 "N(b)");
855
856 for (m = lru_list.head; m; m = m->next) {
857 assert( m->next != m );
858 ipcacheStatPrint((ipcache_entry *)m->data, sentry);
859 }
860}
861
863void
864ipcacheInvalidate(const char *name)
865{
866 ipcache_entry *i;
867
868 if ((i = ipcache_get(name)) == nullptr)
869 return;
870
872
873 /*
874 * NOTE, don't call ipcacheRelease here because we might be here due
875 * to a thread started from a callback.
876 */
877}
878
880void
882{
883 ipcache_entry *i;
884
885 if ((i = ipcache_get(name)) == nullptr)
886 return;
887
888 if (i->flags.negcached)
890
891 /*
892 * NOTE, don't call ipcacheRelease here because we might be here due
893 * to a thread started from a callback.
894 */
895}
896
898static const Dns::CachedIps *
899ipcacheCheckNumeric(const char *name)
900{
901 Ip::Address ip;
902 if (!ip.fromHost(name))
903 return nullptr;
904
905 debugs(14, 4, "HIT_BYPASS for " << name << "=" << ip);
906 static Dns::CachedIps static_addrs;
907 static_addrs.reset(ip);
908 return &static_addrs;
909}
910
912static void
914{
915 if (i->locks++ == 0) {
916 dlinkDelete(&i->lru, &lru_list);
917 dlinkAdd(i, &i->lru, &lru_list);
918 }
919}
920
922static void
924{
925 if (i->locks < 1) {
926 debugs(14, DBG_IMPORTANT, "WARNING: ipcacheEntry unlocked with no lock! locks=" << i->locks);
927 return;
928 }
929
930 -- i->locks;
931
932 if (ipcacheExpiredEntry(i))
934}
935
938bool
940{
941 // linear search!
942 for (size_t seen = 0; seen < ips.size(); ++seen) {
943 if (++goodPosition >= ips.size())
944 goodPosition = 0;
945 if (!ips[goodPosition].bad()) {
946 debugs(14, 3, "succeeded for " << name << ": " << *this);
947 return true;
948 }
949 }
950 goodPosition = ips.size();
951 debugs(14, 3, "failed for " << name << ": " << *this);
952 return false;
953}
954
955void
957{
958 ips.clear();
959 ips.emplace_back(ip);
960 goodPosition = 0;
961 // Assume that the given IP is good because CachedIps are designed to never
962 // run out of good IPs.
963 badCount_ = 0;
964}
965
967void
969{
970 if (badCount() >= size()) {
971 // There are no good IPs left. Clear all bad marks. This must help
972 // because we are called only after a good address was tested as bad.
973 for (auto &cachedIp: ips)
974 cachedIp.forgetMarking();
975 badCount_ = 0;
976 }
977 Must(seekNewGood(name));
978 debugs(14, 3, "cleared all IPs for " << name << "; now back to " << *this);
979}
980
981bool
982Dns::CachedIps::have(const Ip::Address &ip, size_t *positionOrNil) const
983{
984 // linear search!
985 size_t pos = 0;
986 for (const auto &cachedIp: ips) {
987 if (cachedIp.ip == ip) {
988 if (auto position = positionOrNil)
989 *position = pos;
990 debugs(14, 7, ip << " at " << pos << " in " << *this);
991 return true;
992 }
993 }
994 // no such address; leave *position as is
995 debugs(14, 7, " no " << ip << " in " << *this);
996 return false;
997}
998
999void
1001{
1002 assert(!have(ip));
1003 [[maybe_unused]] auto &cachedIp = ips.emplace_back(ip);
1004 assert(!cachedIp.bad());
1005}
1006
1007void
1008Dns::CachedIps::reportCurrent(std::ostream &os) const
1009{
1010 if (empty())
1011 os << "[no cached IPs]";
1012 else if (goodPosition == size())
1013 os << "[" << size() << " bad cached IPs]"; // could only be temporary
1014 else
1015 os << current() << " #" << (goodPosition+1) << "/" << ips.size() << "-" << badCount();
1016}
1017
1018void
1019Dns::CachedIps::markAsBad(const char *name, const Ip::Address &ip)
1020{
1021 size_t badPosition = 0;
1022 if (!have(ip, &badPosition))
1023 return; // no such address
1024
1025 auto &cachedIp = ips[badPosition];
1026 if (cachedIp.bad())
1027 return; // already marked correctly
1028
1029 cachedIp.markAsBad();
1030 ++badCount_;
1031 debugs(14, 2, ip << " of " << name);
1032
1033 if (goodPosition == badPosition)
1034 restoreGoodness(name);
1035 // else nothing to do: goodPositon still points to a good IP
1036}
1037
1038void
1039Dns::CachedIps::forgetMarking(const char *name, const Ip::Address &ip)
1040{
1041 if (!badCount_)
1042 return; // all IPs are already "good"
1043
1044 size_t badPosition = 0;
1045 if (!have(ip, &badPosition))
1046 return; // no such address
1047
1048 auto &cachedIp = ips[badPosition];
1049 if (!cachedIp.bad())
1050 return; // already marked correctly
1051
1052 cachedIp.forgetMarking();
1053 assert(!cachedIp.bad());
1054 --badCount_;
1055 debugs(14, 2, ip << " of " << name);
1056}
1057
1065void
1066ipcacheMarkBadAddr(const char *name, const Ip::Address &addr)
1067{
1068 if (auto cached = ipcache_get(name))
1069 cached->addrs.markAsBad(name, addr);
1070}
1071
1073void
1074ipcacheMarkGoodAddr(const char *name, const Ip::Address &addr)
1075{
1076 if (auto cached = ipcache_get(name))
1077 cached->addrs.forgetMarking(name, addr);
1078}
1079
1081static void
1083{
1084 ipcache_entry *i = (ipcache_entry *)data;
1085 delete i;
1086}
1087
1089{
1090 xfree(error_message);
1091 xfree(hash.key);
1092}
1093
1101void
1103{
1104 ipcache_high = (long) (((float) Config.ipcache.size *
1105 (float) Config.ipcache.high) / (float) 100);
1106 ipcache_low = (long) (((float) Config.ipcache.size *
1107 (float) Config.ipcache.low) / (float) 100);
1109}
1110
1122int
1123ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
1124{
1125 ipcache_entry *i;
1126
1127 Ip::Address ip;
1128
1129 if (!(ip = ipaddr)) {
1130 if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) {
1131 debugs(14, 3, "ipcacheAddEntryFromHosts: Skipping IPv6 address '" << ipaddr << "'");
1132 } else {
1133 debugs(14, DBG_IMPORTANT, "ERROR: ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr << "'");
1134 }
1135
1136 return 1;
1137 }
1138
1139 if (!Ip::EnableIpv6 && ip.isIPv6()) {
1140 debugs(14, 2, "skips IPv6 address in /etc/hosts because IPv6 support was disabled: " << ip);
1141 return 1;
1142 }
1143
1144 if ((i = ipcache_get(name))) {
1145 if (1 == i->flags.fromhosts) {
1147 } else if (i->locks > 0) {
1148 debugs(14, DBG_IMPORTANT, "ERROR: ipcacheAddEntryFromHosts: cannot add static entry for locked name '" << name << "'");
1149 return 1;
1150 } else {
1151 ipcacheRelease(i);
1152 }
1153 }
1154
1155 i = new ipcache_entry(name);
1156 i->addrs.pushUnique(ip);
1157 i->flags.fromhosts = true;
1158 ipcacheAddEntry(i);
1160 return 0;
1161}
1162
1163#if SQUID_SNMP
1171{
1172 variable_list *Answer = nullptr;
1173 MemBuf tmp;
1174 debugs(49, 5, "snmp_netIpFn: Processing request:" << snmpDebugOid(Var->name, Var->name_length, tmp));
1175 *ErrP = SNMP_ERR_NOERROR;
1176
1177 switch (Var->name[LEN_SQ_NET + 1]) {
1178
1179 case IP_ENT:
1180 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1181 ipcacheCount(),
1182 SMI_GAUGE32);
1183 break;
1184
1185 case IP_REQ:
1186 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1189 break;
1190
1191 case IP_HITS:
1192 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1195 break;
1196
1197 case IP_PENDHIT:
1198 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1199 0,
1200 SMI_GAUGE32);
1201 break;
1202
1203 case IP_NEGHIT:
1204 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1207 break;
1208
1209 case IP_MISS:
1210 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1213 break;
1214
1215 case IP_GHBN:
1216 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1217 0, /* deprecated */
1219 break;
1220
1221 case IP_LOC:
1222 Answer = snmp_var_new_integer(Var->name, Var->name_length,
1223 0, /* deprecated */
1225 break;
1226
1227 default:
1228 *ErrP = SNMP_ERR_NOSUCHNAME;
1229 assert(!Answer);
1230 }
1231
1232 return Answer;
1233}
1234
1235#endif /*SQUID_SNMP */
1236
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:75
void error(char *format,...)
#define assert(EX)
Definition: assert.h:17
#define LEN_SQ_NET
Definition: cache_snmp.h:49
int64_t snint
Definition: cache_snmp.h:14
@ 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
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:320
#define CBDATA_CLASS(type)
Definition: cbdata.h:289
an old-style void* callback parameter
Definition: cbdata.h:379
void * validDone()
Definition: cbdata.h:391
bool valid() const
Definition: cbdata.h:390
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:1019
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:956
void pushUnique(const Ip::Address &ip)
Definition: ipcache.cc:1000
bool have(const Ip::Address &ip, size_t *position=nullptr) const
Definition: ipcache.cc:982
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:1039
bool seekNewGood(const char *name)
Definition: ipcache.cc:939
IpsSelector< GoodIpsIterator > good() const
good IPs
Definition: ipcache.h:243
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:968
void reportCurrent(std::ostream &os) const
prints current IP and other debugging information
Definition: ipcache.cc:1008
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:23
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:267
IPH * receiverFun
gets final results
Definition: ipcache.cc:114
void forwardLookup(const char *error)
inform recipient of a finished lookup
Definition: ipcache.cc:279
bool forwardIp(const Ip::Address &ip)
Definition: ipcache.cc:251
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
Definition: SBuf.h:94
time_t negativeDnsTtl
Definition: SquidConfig.h:105
struct SquidConfig::@102 ipcache
time_t positiveDnsTtl
Definition: SquidConfig.h:106
StatHist svcTime
Definition: StatCounters.h:98
struct StatCounters::@127 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:511
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:408
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
const char * name() const
Definition: ipcache.cc:155
ipcache_addrs addrs
Definition: ipcache.cc:140
void latestError(const char *text)
remembers the last error seen, overwriting any previous errors
Definition: ipcache.cc:457
~ipcache_entry()
Definition: ipcache.cc:1088
void updateTtl(const unsigned int rrTtl)
Definition: ipcache.cc:540
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:93
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
#define DBG_CRITICAL
Definition: Stream.h:37
#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 *)
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:881
void ipcache_restart(void)
Definition: ipcache.cc:1102
const ipcache_addrs * ipcache_gethostbyname(const char *name, int flags)
Definition: ipcache.cc:728
void ipcache_init(void)
Definition: ipcache.cc:695
void ipcacheInvalidate(const char *name)
Definition: ipcache.cc:864
variable_list * snmp_netIpFn(variable_list *Var, snint *ErrP)
Definition: ipcache.cc:1170
void ipcache_purgelru(void *)
Definition: ipcache.cc:352
void ipcacheMarkGoodAddr(const char *name, const Ip::Address &addr)
Definition: ipcache.cc:1074
int ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
Definition: ipcache.cc:1123
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:608
static const Dns::CachedIps * ipcacheCheckNumeric(const char *name)
Definition: ipcache.cc:899
static void ipcacheUnlockEntry(ipcache_entry *)
Definition: ipcache.cc:923
static ipcache_entry * ipcache_get(const char *)
Definition: ipcache.cc:323
static hash_table * ip_table
Definition: ipcache.cc:206
static void ipcacheStatPrint(ipcache_entry *, StoreEntry *)
Definition: ipcache.cc:769
static void ipcacheLockEntry(ipcache_entry *)
Definition: ipcache.cc:913
static void purge_entries_fromhosts(void)
Definition: ipcache.cc:385
int ipcacheCount()
Definition: ipcache.cc:293
static struct _ipcache_stats IpcacheStats
static void ipcacheCallback(ipcache_entry *i, const bool hit, const int wait)
Definition: ipcache.cc:442
static void stat_ipcache_get(StoreEntry *)
Definition: ipcache.cc:820
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:301
static long ipcache_low
Definition: ipcache.cc:209
static void ipcacheRegisterWithCacheManager(void)
Definition: ipcache.cc:680
static void ipcacheAddEntry(ipcache_entry *i)
Definition: ipcache.cc:421
static int ipcacheExpiredEntry(ipcache_entry *)
Definition: ipcache.cc:333
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:1066
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:623
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:465
void IPH(const ipcache_addrs *, const Dns::LookupDetails &details, void *)
Definition: ipcache.h:227
void FREE(void *)
Definition: forward.h:37
void nbgethostbyname(const char *name, const CbcPointer< IpReceiver > &receiver)
initiate an (often) asynchronous DNS lookup; the receiver gets the results
Definition: ipcache.cc:615
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:858
#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:1056
#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:841
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
SBuf text("GET http://resource.com/path HTTP/1.1\r\n" "Host: resource.com\r\n" "Cookie: laijkpk3422r j1noin \r\n" "\r\n")
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