]> git.ipfire.org Git - thirdparty/squid.git/blame - src/fqdncache.cc
Document the 'carp' cache_peer option
[thirdparty/squid.git] / src / fqdncache.cc
CommitLineData
f88bb09c 1
2/*
998adf71 3 * $Id: fqdncache.cc,v 1.154 2003/02/13 20:47:53 wessels Exp $
f88bb09c 4 *
7cf620a9 5 * DEBUG: section 35 FQDN Cache
f88bb09c 6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
f88bb09c 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
f88bb09c 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
f88bb09c 34 */
35
36#include "squid.h"
e6ccf245 37#include "Store.h"
f88bb09c 38
f88bb09c 39#define FQDN_LOW_WATER 90
40#define FQDN_HIGH_WATER 95
f88bb09c 41
add5d21f 42typedef struct _fqdncache_entry fqdncache_entry;
43
44struct _fqdncache_entry {
186477c1 45 hash_link hash; /* must be first */
add5d21f 46 time_t lastref;
47 time_t expires;
48 unsigned char name_count;
49 char *names[FQDN_MAX_NAMES + 1];
50 FQDNH *handler;
51 void *handlerData;
52 char *error_message;
53 struct timeval request_time;
54 dlink_node lru;
ac06f720 55 unsigned short locks;
add5d21f 56 struct {
57 unsigned int negcached:1;
0e70aa1e 58 unsigned int fromhosts:1;
add5d21f 59 } flags;
60};
61
f88bb09c 62static struct {
63 int requests;
64 int replies;
65 int hits;
66 int misses;
f88bb09c 67 int negative_hits;
f88bb09c 68} FqdncacheStats;
69
4bc76d59 70static dlink_list lru_list;
71
59f34d62 72#if USE_DNSSERVERS
74addf6c 73static HLPCB fqdncacheHandleReply;
74static fqdncache_entry *fqdncacheParse(const char *buf);
59f34d62 75#else
76static IDNSCB fqdncacheHandleReply;
77static fqdncache_entry *fqdncacheParse(rfc1035_rr *, int);
78#endif
add5d21f 79static void fqdncacheRelease(fqdncache_entry *);
80static fqdncache_entry *fqdncacheCreateEntry(const char *name);
81static void fqdncacheCallback(fqdncache_entry *);
f5b8bbc4 82static fqdncache_entry *fqdncache_get(const char *);
348b2031 83static FQDNH dummy_handler;
f5b8bbc4 84static int fqdncacheExpiredEntry(const fqdncache_entry *);
f5b8bbc4 85static void fqdncacheLockEntry(fqdncache_entry * f);
86static void fqdncacheUnlockEntry(fqdncache_entry * f);
ec878047 87static FREE fqdncacheFreeEntry;
add5d21f 88static void fqdncacheAddEntry(fqdncache_entry * f);
f88bb09c 89
365e5b34 90static hash_table *fqdn_table = NULL;
f88bb09c 91
24382924 92static long fqdncache_low = 180;
93static long fqdncache_high = 200;
f88bb09c 94
f88bb09c 95/* removes the given fqdncache entry */
b8d8561b 96static void
add5d21f 97fqdncacheRelease(fqdncache_entry * f)
f88bb09c 98{
f88bb09c 99 int k;
3fda0827 100 hash_remove_link(fqdn_table, (hash_link *) f);
add5d21f 101 for (k = 0; k < (int) f->name_count; k++)
102 safe_free(f->names[k]);
103 debug(35, 5) ("fqdncacheRelease: Released FQDN record for '%s'.\n",
186477c1 104 hashKeyStr(&f->hash));
4bc76d59 105 dlinkDelete(&f->lru, &lru_list);
186477c1 106 safe_free(f->hash.key);
429fdbec 107 safe_free(f->error_message);
db1cd23c 108 memFree(f, MEM_FQDNCACHE_ENTRY);
f88bb09c 109}
110
111/* return match for given name */
b8d8561b 112static fqdncache_entry *
0ee4272b 113fqdncache_get(const char *name)
f88bb09c 114{
115 hash_link *e;
116 static fqdncache_entry *f;
f88bb09c 117 f = NULL;
118 if (fqdn_table) {
e6ccf245 119 if ((e = (hash_link *)hash_lookup(fqdn_table, name)) != NULL)
f88bb09c 120 f = (fqdncache_entry *) e;
121 }
122 return f;
123}
124
b8d8561b 125static int
fe4e214f 126fqdncacheExpiredEntry(const fqdncache_entry * f)
f88bb09c 127{
0e70aa1e 128 /* all static entries are locked, so this takes care of them too */
429fdbec 129 if (f->locks != 0)
130 return 0;
e84703ad 131 if (f->expires > squid_curtime)
f88bb09c 132 return 0;
133 return 1;
134}
135
59c4d35b 136void
137fqdncache_purgelru(void *notused)
f88bb09c 138{
4bc76d59 139 dlink_node *m;
140 dlink_node *prev = NULL;
141 fqdncache_entry *f;
f88bb09c 142 int removed = 0;
52040193 143 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 10.0, 1);
4bc76d59 144 for (m = lru_list.tail; m; m = prev) {
59c4d35b 145 if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low)
4bc76d59 146 break;
147 prev = m->prev;
e6ccf245 148 f = (fqdncache_entry *)m->data;
4bc76d59 149 if (f->locks != 0)
150 continue;
add5d21f 151 fqdncacheRelease(f);
f88bb09c 152 removed++;
153 }
ac750329 154 debug(35, 9) ("fqdncache_purgelru: removed %d entries\n", removed);
f88bb09c 155}
156
0e70aa1e 157static void
158purge_entries_fromhosts(void)
159{
160 dlink_node *m = lru_list.head;
161 fqdncache_entry *i = NULL;
162 fqdncache_entry *t;
163 while (m) {
164 if (i != NULL) { /* need to delay deletion */
165 fqdncacheRelease(i); /* we just override locks */
166 i = NULL;
167 }
e6ccf245 168 t = (fqdncache_entry *)m->data;
0e70aa1e 169 if (t->flags.fromhosts)
170 i = t;
171 m = m->next;
172 }
173 if (i != NULL)
174 fqdncacheRelease(i);
175}
176
f88bb09c 177/* create blank fqdncache_entry */
b8d8561b 178static fqdncache_entry *
add5d21f 179fqdncacheCreateEntry(const char *name)
f88bb09c 180{
4bc76d59 181 static fqdncache_entry *f;
e6ccf245 182 f = (fqdncache_entry *)memAllocate(MEM_FQDNCACHE_ENTRY);
186477c1 183 f->hash.key = xstrdup(name);
4bc76d59 184 f->expires = squid_curtime + Config.negativeDnsTtl;
4bc76d59 185 return f;
f88bb09c 186}
187
b8d8561b 188static void
add5d21f 189fqdncacheAddEntry(fqdncache_entry * f)
f88bb09c 190{
e6ccf245 191 hash_link *e = (hash_link *)hash_lookup(fqdn_table, f->hash.key);
add5d21f 192 if (NULL != e) {
193 /* avoid colission */
194 fqdncache_entry *q = (fqdncache_entry *) e;
195 fqdncacheRelease(q);
429fdbec 196 }
186477c1 197 hash_join(fqdn_table, &f->hash);
add5d21f 198 dlinkAdd(f, &f->lru, &lru_list);
429fdbec 199 f->lastref = squid_curtime;
f88bb09c 200}
201
202/* walks down the pending list, calling handlers */
b8d8561b 203static void
add5d21f 204fqdncacheCallback(fqdncache_entry * f)
f88bb09c 205{
fa80a8ef 206 FQDNH *callback;
207 void *cbdata;
f88bb09c 208 f->lastref = squid_curtime;
fa80a8ef 209 if (!f->handler)
add5d21f 210 return;
5a2aa048 211 fqdncacheLockEntry(f);
fa80a8ef 212 callback = f->handler;
add5d21f 213 f->handler = NULL;
fa80a8ef 214 if (cbdataReferenceValidDone(f->handlerData, &cbdata)) {
add5d21f 215 dns_error_message = f->error_message;
fa80a8ef 216 callback(f->flags.negcached ? NULL : f->names[0], cbdata);
f88bb09c 217 }
429fdbec 218 fqdncacheUnlockEntry(f);
f88bb09c 219}
220
b8d8561b 221static fqdncache_entry *
b18baa48 222#if USE_DNSSERVERS
74addf6c 223fqdncacheParse(const char *inbuf)
f88bb09c 224{
bd34f258 225 LOCAL_ARRAY(char, buf, DNS_INBUF_SZ);
e84703ad 226 char *token;
227 static fqdncache_entry f;
bd34f258 228 int ttl;
f6c6cd66 229 memset(&f, '\0', sizeof(f));
bd34f258 230 f.expires = squid_curtime;
add5d21f 231 f.flags.negcached = 1;
c68e9c6b 232 if (inbuf == NULL) {
233 debug(35, 1) ("fqdncacheParse: Got <NULL> reply\n");
234 return &f;
235 }
c579f632 236 xstrncpy(buf, inbuf, DNS_INBUF_SZ);
237 debug(35, 5) ("fqdncacheParse: parsing: {%s}\n", buf);
bd34f258 238 token = strtok(buf, w_space);
239 if (NULL == token) {
6a78c18e 240 debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting '$name'\n");
bd34f258 241 return &f;
242 }
243 if (0 == strcmp(token, "$fail")) {
244 f.expires = squid_curtime + Config.negativeDnsTtl;
245 token = strtok(NULL, "\n");
246 assert(NULL != token);
247 f.error_message = xstrdup(token);
248 return &f;
249 }
250 if (0 != strcmp(token, "$name")) {
6a78c18e 251 debug(35, 1) ("fqdncacheParse: Got '%s', expecting '$name'\n", token);
bd34f258 252 return &f;
253 }
254 token = strtok(NULL, w_space);
255 if (NULL == token) {
6a78c18e 256 debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting TTL\n");
bd34f258 257 return &f;
258 }
add5d21f 259 f.flags.negcached = 0;
bd34f258 260 ttl = atoi(token);
261 if (ttl > 0)
262 f.expires = squid_curtime + ttl;
263 else
264 f.expires = squid_curtime + Config.positiveDnsTtl;
265 token = strtok(NULL, w_space);
266 if (NULL != token) {
267 f.names[0] = xstrdup(token);
268 f.name_count = 1;
f88bb09c 269 }
e84703ad 270 return &f;
f88bb09c 271}
59f34d62 272#else
59f34d62 273fqdncacheParse(rfc1035_rr * answers, int nr)
274{
275 static fqdncache_entry f;
276 int k;
59f34d62 277 int na = 0;
278 memset(&f, '\0', sizeof(f));
279 f.expires = squid_curtime;
add5d21f 280 f.flags.negcached = 1;
59f34d62 281 if (nr < 0) {
b18baa48 282 debug(35, 3) ("fqdncacheParse: Lookup failed (error %d)\n",
59f34d62 283 rfc1035_errno);
284 assert(rfc1035_error_message);
285 f.error_message = xstrdup(rfc1035_error_message);
286 return &f;
287 }
288 if (nr == 0) {
b18baa48 289 debug(35, 3) ("fqdncacheParse: No DNS records\n");
59f34d62 290 f.error_message = xstrdup("No DNS records");
291 return &f;
292 }
39d5df9b 293 debug(35, 3) ("fqdncacheParse: %d answers\n", nr);
59f34d62 294 assert(answers);
1810dde6 295 for (k = 0; k < nr; k++) {
59f34d62 296 if (answers[k].type != RFC1035_TYPE_PTR)
297 continue;
29b8d8d6 298 if (answers[k]._class != RFC1035_CLASS_IN)
59f34d62 299 continue;
300 na++;
add5d21f 301 f.flags.negcached = 0;
59f34d62 302 f.names[0] = xstrdup(answers[k].rdata);
303 f.name_count = 1;
304 f.expires = squid_curtime + answers[k].ttl;
305 return &f;
306 }
307 debug(35, 1) ("fqdncacheParse: No PTR record\n");
308 f.error_message = xstrdup("No PTR record");
309 return &f;
310}
311#endif
f88bb09c 312
429fdbec 313static void
59f34d62 314#if USE_DNSSERVERS
74addf6c 315fqdncacheHandleReply(void *data, char *reply)
59f34d62 316#else
317fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na)
318#endif
f88bb09c 319{
f88bb09c 320 int n;
e6ccf245 321 generic_cbdata *c = (generic_cbdata *)data;
322 fqdncache_entry *f = (fqdncache_entry *)c->data;
e84703ad 323 fqdncache_entry *x = NULL;
74addf6c 324 cbdataFree(c);
325 c = NULL;
c68e9c6b 326 n = ++FqdncacheStats.replies;
83704487 327 statHistCount(&statCounter.dns.svc_time,
74addf6c 328 tvSubMsec(f->request_time, current_time));
59f34d62 329#if USE_DNSSERVERS
c68e9c6b 330 x = fqdncacheParse(reply);
59f34d62 331#else
332 x = fqdncacheParse(answers, na);
333#endif
c68e9c6b 334 assert(x);
335 f->name_count = x->name_count;
336 for (n = 0; n < (int) f->name_count; n++)
337 f->names[n] = x->names[n];
338 f->error_message = x->error_message;
c68e9c6b 339 f->expires = x->expires;
add5d21f 340 f->flags = x->flags;
341 fqdncacheAddEntry(f);
342 fqdncacheCallback(f);
f88bb09c 343}
344
429fdbec 345void
348b2031 346fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerData)
f88bb09c 347{
348 fqdncache_entry *f = NULL;
f88bb09c 349 char *name = inet_ntoa(addr);
74addf6c 350 generic_cbdata *c;
698e6f16 351 assert(handler);
a3d5953d 352 debug(35, 4) ("fqdncache_nbgethostbyaddr: Name '%s'.\n", name);
f88bb09c 353 FqdncacheStats.requests++;
f88bb09c 354 if (name == NULL || name[0] == '\0') {
a3d5953d 355 debug(35, 4) ("fqdncache_nbgethostbyaddr: Invalid name!\n");
348b2031 356 handler(NULL, handlerData);
429fdbec 357 return;
f88bb09c 358 }
add5d21f 359 f = fqdncache_get(name);
360 if (NULL == f) {
361 /* miss */
362 (void) 0;
363 } else if (fqdncacheExpiredEntry(f)) {
364 /* hit, but expired -- bummer */
365 fqdncacheRelease(f);
366 f = NULL;
367 } else {
368 /* hit */
a3d5953d 369 debug(35, 4) ("fqdncache_nbgethostbyaddr: HIT for '%s'\n", name);
add5d21f 370 if (f->flags.negcached)
f88bb09c 371 FqdncacheStats.negative_hits++;
372 else
373 FqdncacheStats.hits++;
add5d21f 374 f->handler = handler;
fa80a8ef 375 f->handlerData = cbdataReference(handlerData);
add5d21f 376 fqdncacheCallback(f);
429fdbec 377 return;
f88bb09c 378 }
add5d21f 379
380 debug(35, 5) ("fqdncache_nbgethostbyaddr: MISS for '%s'\n", name);
381 FqdncacheStats.misses++;
382 f = fqdncacheCreateEntry(name);
383 f->handler = handler;
fa80a8ef 384 f->handlerData = cbdataReference(handlerData);
add5d21f 385 f->request_time = current_time;
72711e31 386 c = cbdataAlloc(generic_cbdata);
74addf6c 387 c->data = f;
59f34d62 388#if USE_DNSSERVERS
186477c1 389 dnsSubmit(hashKeyStr(&f->hash), fqdncacheHandleReply, c);
59f34d62 390#else
391 idnsPTRLookup(addr, fqdncacheHandleReply, c);
392#endif
f88bb09c 393}
394
f88bb09c 395/* initialize the fqdncache */
b8d8561b 396void
0673c0ba 397fqdncache_init(void)
f88bb09c 398{
aa9e2cab 399 int n;
19054954 400 if (fqdn_table)
401 return;
a3d5953d 402 debug(35, 3) ("Initializing FQDN Cache...\n");
f88bb09c 403 memset(&FqdncacheStats, '\0', sizeof(FqdncacheStats));
3eb55834 404 memset(&lru_list, '\0', sizeof(lru_list));
e55650e3 405 fqdncache_high = (long) (((float) Config.fqdncache.size *
f88bb09c 406 (float) FQDN_HIGH_WATER) / (float) 100);
e55650e3 407 fqdncache_low = (long) (((float) Config.fqdncache.size *
f88bb09c 408 (float) FQDN_LOW_WATER) / (float) 100);
aa9e2cab 409 n = hashPrime(fqdncache_high / 4);
6a78c18e 410 fqdn_table = hash_create((HASHCMP *) strcmp, n, hash4);
22f3fd98 411 cachemgrRegister("fqdncache",
412 "FQDN Cache Stats and Contents",
1da3b90b 413 fqdnStats, 0, 1);
add5d21f 414 memDataInit(MEM_FQDNCACHE_ENTRY, "fqdncache_entry",
415 sizeof(fqdncache_entry), 0);
f88bb09c 416}
417
0ee4272b 418const char *
b8d8561b 419fqdncache_gethostbyaddr(struct in_addr addr, int flags)
f88bb09c 420{
421 char *name = inet_ntoa(addr);
422 fqdncache_entry *f = NULL;
429fdbec 423 struct in_addr ip;
698e6f16 424 assert(name);
f88bb09c 425 FqdncacheStats.requests++;
add5d21f 426 f = fqdncache_get(name);
427 if (NULL == f) {
428 (void) 0;
429 } else if (fqdncacheExpiredEntry(f)) {
430 fqdncacheRelease(f);
431 f = NULL;
432 } else if (f->flags.negcached) {
433 FqdncacheStats.negative_hits++;
434 dns_error_message = f->error_message;
435 return NULL;
436 } else {
437 FqdncacheStats.hits++;
438 f->lastref = squid_curtime;
439 return f->names[0];
f88bb09c 440 }
f88bb09c 441 /* check if it's already a FQDN address in text form. */
429fdbec 442 if (!safe_inet_addr(name, &ip))
f88bb09c 443 return name;
429fdbec 444 FqdncacheStats.misses++;
f88bb09c 445 if (flags & FQDN_LOOKUP_IF_MISS)
348b2031 446 fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL);
f88bb09c 447 return NULL;
448}
449
450
451/* process objects list */
b8d8561b 452void
453fqdnStats(StoreEntry * sentry)
f88bb09c 454{
455 fqdncache_entry *f = NULL;
456 int k;
457 int ttl;
4bc76d59 458 if (fqdn_table == NULL)
f88bb09c 459 return;
15576b6a 460 storeAppendPrintf(sentry, "FQDN Cache Statistics:\n");
461 storeAppendPrintf(sentry, "FQDNcache Entries: %d\n",
59c4d35b 462 memInUse(MEM_FQDNCACHE_ENTRY));
15576b6a 463 storeAppendPrintf(sentry, "FQDNcache Requests: %d\n",
f88bb09c 464 FqdncacheStats.requests);
15576b6a 465 storeAppendPrintf(sentry, "FQDNcache Hits: %d\n",
f88bb09c 466 FqdncacheStats.hits);
15576b6a 467 storeAppendPrintf(sentry, "FQDNcache Negative Hits: %d\n",
f88bb09c 468 FqdncacheStats.negative_hits);
15576b6a 469 storeAppendPrintf(sentry, "FQDNcache Misses: %d\n",
f88bb09c 470 FqdncacheStats.misses);
15576b6a 471 storeAppendPrintf(sentry, "FQDN Cache Contents:\n\n");
0e70aa1e 472 storeAppendPrintf(sentry, "%-15.15s %3s %3s %3s %s\n",
473 "Address", "Flg", "TTL", "Cnt", "Hostnames");
0f6bebac 474 hash_first(fqdn_table);
475 while ((f = (fqdncache_entry *) hash_next(fqdn_table))) {
0e70aa1e 476 ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime));
477 storeAppendPrintf(sentry, "%-15.15s %c%c %3.3d % 3d",
186477c1 478 hashKeyStr(&f->hash),
add5d21f 479 f->flags.negcached ? 'N' : ' ',
0e70aa1e 480 f->flags.fromhosts ? 'H' : ' ',
f88bb09c 481 ttl,
482 (int) f->name_count);
483 for (k = 0; k < (int) f->name_count; k++)
484 storeAppendPrintf(sentry, " %s", f->names[k]);
22f3fd98 485 storeAppendPrintf(sentry, "\n");
f88bb09c 486 }
f88bb09c 487}
488
b8d8561b 489static void
79d39a72 490dummy_handler(const char *bufnotused, void *datanotused)
f88bb09c 491{
492 return;
493}
494
0ee4272b 495const char *
b8d8561b 496fqdnFromAddr(struct in_addr addr)
28ab0c0a 497{
0ee4272b 498 const char *n;
39de381a 499 static char buf[32];
17a0a4ee 500 if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0)))
28ab0c0a 501 return n;
f2052513 502 xstrncpy(buf, inet_ntoa(addr), 32);
39de381a 503 return buf;
28ab0c0a 504}
f201f309 505
429fdbec 506static void
507fqdncacheLockEntry(fqdncache_entry * f)
508{
4bc76d59 509 if (f->locks++ == 0) {
510 dlinkDelete(&f->lru, &lru_list);
511 dlinkAdd(f, &f->lru, &lru_list);
512 }
429fdbec 513}
514
515static void
516fqdncacheUnlockEntry(fqdncache_entry * f)
517{
ac06f720 518 assert(f->locks > 0);
429fdbec 519 f->locks--;
520 if (fqdncacheExpiredEntry(f))
add5d21f 521 fqdncacheRelease(f);
429fdbec 522}
523
ec878047 524static void
525fqdncacheFreeEntry(void *data)
526{
e6ccf245 527 fqdncache_entry *f = (fqdncache_entry *)data;
ec878047 528 int k;
529 for (k = 0; k < (int) f->name_count; k++)
530 safe_free(f->names[k]);
186477c1 531 safe_free(f->hash.key);
ec878047 532 safe_free(f->error_message);
db1cd23c 533 memFree(f, MEM_FQDNCACHE_ENTRY);
ec878047 534}
535
56e15c50 536void
537fqdncacheFreeMemory(void)
538{
ec878047 539 hashFreeItems(fqdn_table, fqdncacheFreeEntry);
56e15c50 540 hashFreeMemory(fqdn_table);
afe95a7e 541 fqdn_table = NULL;
56e15c50 542}
429fdbec 543
d20b1cd0 544/* Recalculate FQDN cache size upon reconfigure */
429fdbec 545void
546fqdncache_restart(void)
547{
e55650e3 548 fqdncache_high = (long) (((float) Config.fqdncache.size *
e144eae4 549 (float) FQDN_HIGH_WATER) / (float) 100);
e55650e3 550 fqdncache_low = (long) (((float) Config.fqdncache.size *
e144eae4 551 (float) FQDN_LOW_WATER) / (float) 100);
0e70aa1e 552 purge_entries_fromhosts();
553}
554
555/*
556 * adds a "static" entry from /etc/hosts. the worldist is to be
557 * managed by the caller, including pointed-to strings
558 */
559void
560fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames)
561{
562 fqdncache_entry *fce;
563 int j = 0;
564 if ((fce = fqdncache_get(addr))) {
565 if (1 == fce->flags.fromhosts) {
566 fqdncacheUnlockEntry(fce);
567 } else if (fce->locks > 0) {
568 debug(35, 1) ("fqdncacheAddEntryFromHosts: can't add static entry for locked address '%s'\n", addr);
569 return;
570 } else {
571 fqdncacheRelease(fce);
572 }
573 }
574 fce = fqdncacheCreateEntry(addr);
575 while (hostnames) {
576 fce->names[j] = xstrdup(hostnames->key);
577 j++;
578 hostnames = hostnames->next;
579 if (j >= FQDN_MAX_NAMES)
580 break;
581 }
582 fce->name_count = j;
583 fce->names[j] = NULL; /* it's safe */
584 fce->flags.fromhosts = 1;
585 fqdncacheAddEntry(fce);
586 fqdncacheLockEntry(fce);
429fdbec 587}
ce75f381 588
0e70aa1e 589
ce75f381 590#ifdef SQUID_SNMP
e7ef99a7 591/*
135171fe 592 * The function to return the fqdn statistics via SNMP
593 */
d60c11be 594
86115da5 595variable_list *
e7ef99a7 596snmp_netFqdnFn(variable_list * Var, snint * ErrP)
d60c11be 597{
736eb6ad 598 variable_list *Answer = NULL;
38650cc8 599 debug(49, 5) ("snmp_netFqdnFn: Processing request:\n");
e7ef99a7 600 snmpDebugOid(5, Var->name, Var->name_length);
86115da5 601 *ErrP = SNMP_ERR_NOERROR;
135171fe 602 switch (Var->name[LEN_SQ_NET + 1]) {
e7ef99a7 603 case FQDN_ENT:
736eb6ad 604 Answer = snmp_var_new_integer(Var->name, Var->name_length,
605 memInUse(MEM_FQDNCACHE_ENTRY),
606 SMI_GAUGE32);
135171fe 607 break;
e7ef99a7 608 case FQDN_REQ:
736eb6ad 609 Answer = snmp_var_new_integer(Var->name, Var->name_length,
610 FqdncacheStats.requests,
611 SMI_COUNTER32);
135171fe 612 break;
e7ef99a7 613 case FQDN_HITS:
736eb6ad 614 Answer = snmp_var_new_integer(Var->name, Var->name_length,
615 FqdncacheStats.hits,
616 SMI_COUNTER32);
135171fe 617 break;
e7ef99a7 618 case FQDN_PENDHIT:
add5d21f 619 /* this is now worthless */
736eb6ad 620 Answer = snmp_var_new_integer(Var->name, Var->name_length,
add5d21f 621 0,
736eb6ad 622 SMI_GAUGE32);
135171fe 623 break;
e7ef99a7 624 case FQDN_NEGHIT:
736eb6ad 625 Answer = snmp_var_new_integer(Var->name, Var->name_length,
626 FqdncacheStats.negative_hits,
627 SMI_COUNTER32);
135171fe 628 break;
e7ef99a7 629 case FQDN_MISS:
736eb6ad 630 Answer = snmp_var_new_integer(Var->name, Var->name_length,
631 FqdncacheStats.misses,
632 SMI_COUNTER32);
135171fe 633 break;
e7ef99a7 634 case FQDN_GHBN:
736eb6ad 635 Answer = snmp_var_new_integer(Var->name, Var->name_length,
998adf71 636 0, /* deprecated */
736eb6ad 637 SMI_COUNTER32);
135171fe 638 break;
ce75f381 639 default:
135171fe 640 *ErrP = SNMP_ERR_NOSUCHNAME;
736eb6ad 641 break;
86115da5 642 }
643 return Answer;
ce75f381 644}
e7ef99a7 645
135171fe 646#endif /*SQUID_SNMP */