]>
Commit | Line | Data |
---|---|---|
f88bb09c | 1 | |
2 | /* | |
58cd5bbd | 3 | * $Id: fqdncache.cc,v 1.141 2000/10/17 08:06:03 adrian Exp $ |
f88bb09c | 4 | * |
7cf620a9 | 5 | * DEBUG: section 35 FQDN Cache |
f88bb09c | 6 | * AUTHOR: Harvest Derived |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 9 | * ---------------------------------------------------------- |
f88bb09c | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
efd900cb | 15 | * the Regents of the University of California. Please see the |
16 | * COPYRIGHT file for full details. Squid incorporates software | |
17 | * developed and/or copyrighted by other sources. Please see the | |
18 | * 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" | |
37 | ||
f88bb09c | 38 | #define FQDN_LOW_WATER 90 |
39 | #define FQDN_HIGH_WATER 95 | |
f88bb09c | 40 | |
add5d21f | 41 | typedef struct _fqdncache_entry fqdncache_entry; |
42 | ||
43 | struct _fqdncache_entry { | |
44 | /* first two items must be equivalent to hash_link */ | |
45 | char *name; | |
46 | fqdncache_entry *next; | |
47 | time_t lastref; | |
48 | time_t expires; | |
49 | unsigned char name_count; | |
50 | char *names[FQDN_MAX_NAMES + 1]; | |
51 | FQDNH *handler; | |
52 | void *handlerData; | |
53 | char *error_message; | |
54 | struct timeval request_time; | |
55 | dlink_node lru; | |
ac06f720 | 56 | unsigned short locks; |
add5d21f | 57 | struct { |
58 | unsigned int negcached:1; | |
59 | } flags; | |
60 | }; | |
61 | ||
f88bb09c | 62 | static struct { |
63 | int requests; | |
64 | int replies; | |
65 | int hits; | |
66 | int misses; | |
f88bb09c | 67 | int negative_hits; |
68 | int errors; | |
f88bb09c | 69 | int ghba_calls; /* # calls to blocking gethostbyaddr() */ |
70 | } FqdncacheStats; | |
71 | ||
4bc76d59 | 72 | static dlink_list lru_list; |
73 | ||
59f34d62 | 74 | #if USE_DNSSERVERS |
74addf6c | 75 | static HLPCB fqdncacheHandleReply; |
76 | static fqdncache_entry *fqdncacheParse(const char *buf); | |
59f34d62 | 77 | #else |
78 | static IDNSCB fqdncacheHandleReply; | |
79 | static fqdncache_entry *fqdncacheParse(rfc1035_rr *, int); | |
80 | #endif | |
add5d21f | 81 | static void fqdncacheRelease(fqdncache_entry *); |
82 | static fqdncache_entry *fqdncacheCreateEntry(const char *name); | |
83 | static void fqdncacheCallback(fqdncache_entry *); | |
f5b8bbc4 | 84 | static fqdncache_entry *fqdncache_get(const char *); |
348b2031 | 85 | static FQDNH dummy_handler; |
f5b8bbc4 | 86 | static int fqdncacheExpiredEntry(const fqdncache_entry *); |
f5b8bbc4 | 87 | static void fqdncacheLockEntry(fqdncache_entry * f); |
88 | static void fqdncacheUnlockEntry(fqdncache_entry * f); | |
ec878047 | 89 | static FREE fqdncacheFreeEntry; |
add5d21f | 90 | static void fqdncacheAddEntry(fqdncache_entry * f); |
f88bb09c | 91 | |
365e5b34 | 92 | static hash_table *fqdn_table = NULL; |
f88bb09c | 93 | |
24382924 | 94 | static long fqdncache_low = 180; |
95 | static long fqdncache_high = 200; | |
f88bb09c | 96 | |
f88bb09c | 97 | /* removes the given fqdncache entry */ |
b8d8561b | 98 | static void |
add5d21f | 99 | fqdncacheRelease(fqdncache_entry * f) |
f88bb09c | 100 | { |
f88bb09c | 101 | int k; |
3fda0827 | 102 | hash_remove_link(fqdn_table, (hash_link *) f); |
add5d21f | 103 | for (k = 0; k < (int) f->name_count; k++) |
104 | safe_free(f->names[k]); | |
105 | debug(35, 5) ("fqdncacheRelease: Released FQDN record for '%s'.\n", | |
106 | f->name); | |
4bc76d59 | 107 | dlinkDelete(&f->lru, &lru_list); |
429fdbec | 108 | safe_free(f->name); |
109 | safe_free(f->error_message); | |
db1cd23c | 110 | memFree(f, MEM_FQDNCACHE_ENTRY); |
f88bb09c | 111 | } |
112 | ||
113 | /* return match for given name */ | |
b8d8561b | 114 | static fqdncache_entry * |
0ee4272b | 115 | fqdncache_get(const char *name) |
f88bb09c | 116 | { |
117 | hash_link *e; | |
118 | static fqdncache_entry *f; | |
f88bb09c | 119 | f = NULL; |
120 | if (fqdn_table) { | |
121 | if ((e = hash_lookup(fqdn_table, name)) != NULL) | |
122 | f = (fqdncache_entry *) e; | |
123 | } | |
124 | return f; | |
125 | } | |
126 | ||
b8d8561b | 127 | static int |
fe4e214f | 128 | fqdncacheExpiredEntry(const fqdncache_entry * f) |
f88bb09c | 129 | { |
429fdbec | 130 | if (f->locks != 0) |
131 | return 0; | |
e84703ad | 132 | if (f->expires > squid_curtime) |
f88bb09c | 133 | return 0; |
134 | return 1; | |
135 | } | |
136 | ||
59c4d35b | 137 | void |
138 | fqdncache_purgelru(void *notused) | |
f88bb09c | 139 | { |
4bc76d59 | 140 | dlink_node *m; |
141 | dlink_node *prev = NULL; | |
142 | fqdncache_entry *f; | |
f88bb09c | 143 | int removed = 0; |
52040193 | 144 | eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 10.0, 1); |
4bc76d59 | 145 | for (m = lru_list.tail; m; m = prev) { |
59c4d35b | 146 | if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low) |
4bc76d59 | 147 | break; |
148 | prev = m->prev; | |
149 | f = m->data; | |
4bc76d59 | 150 | if (f->locks != 0) |
151 | continue; | |
add5d21f | 152 | fqdncacheRelease(f); |
f88bb09c | 153 | removed++; |
154 | } | |
ac750329 | 155 | debug(35, 9) ("fqdncache_purgelru: removed %d entries\n", removed); |
f88bb09c | 156 | } |
157 | ||
f88bb09c | 158 | /* create blank fqdncache_entry */ |
b8d8561b | 159 | static fqdncache_entry * |
add5d21f | 160 | fqdncacheCreateEntry(const char *name) |
f88bb09c | 161 | { |
4bc76d59 | 162 | static fqdncache_entry *f; |
59c4d35b | 163 | f = memAllocate(MEM_FQDNCACHE_ENTRY); |
4bc76d59 | 164 | f->name = xstrdup(name); |
165 | f->expires = squid_curtime + Config.negativeDnsTtl; | |
4bc76d59 | 166 | return f; |
f88bb09c | 167 | } |
168 | ||
b8d8561b | 169 | static void |
add5d21f | 170 | fqdncacheAddEntry(fqdncache_entry * f) |
f88bb09c | 171 | { |
add5d21f | 172 | hash_link *e = hash_lookup(fqdn_table, f->name); |
173 | if (NULL != e) { | |
174 | /* avoid colission */ | |
175 | fqdncache_entry *q = (fqdncache_entry *) e; | |
176 | fqdncacheRelease(q); | |
429fdbec | 177 | } |
add5d21f | 178 | hash_join(fqdn_table, (hash_link *) f); |
179 | dlinkAdd(f, &f->lru, &lru_list); | |
429fdbec | 180 | f->lastref = squid_curtime; |
f88bb09c | 181 | } |
182 | ||
183 | /* walks down the pending list, calling handlers */ | |
b8d8561b | 184 | static void |
add5d21f | 185 | fqdncacheCallback(fqdncache_entry * f) |
f88bb09c | 186 | { |
add5d21f | 187 | FQDNH *handler = f->handler; |
188 | void *handlerData = f->handlerData; | |
f88bb09c | 189 | f->lastref = squid_curtime; |
add5d21f | 190 | if (NULL == handler) |
191 | return; | |
5a2aa048 | 192 | fqdncacheLockEntry(f); |
add5d21f | 193 | f->handler = NULL; |
194 | f->handlerData = NULL; | |
195 | if (cbdataValid(handlerData)) { | |
196 | dns_error_message = f->error_message; | |
6b65d31c | 197 | handler(f->flags.negcached ? NULL : f->names[0], handlerData); |
f88bb09c | 198 | } |
add5d21f | 199 | cbdataUnlock(handlerData); |
429fdbec | 200 | fqdncacheUnlockEntry(f); |
f88bb09c | 201 | } |
202 | ||
b8d8561b | 203 | static fqdncache_entry * |
b18baa48 | 204 | #if USE_DNSSERVERS |
74addf6c | 205 | fqdncacheParse(const char *inbuf) |
f88bb09c | 206 | { |
bd34f258 | 207 | LOCAL_ARRAY(char, buf, DNS_INBUF_SZ); |
e84703ad | 208 | char *token; |
209 | static fqdncache_entry f; | |
bd34f258 | 210 | int ttl; |
bd34f258 | 211 | f.expires = squid_curtime; |
add5d21f | 212 | f.flags.negcached = 1; |
c68e9c6b | 213 | if (inbuf == NULL) { |
214 | debug(35, 1) ("fqdncacheParse: Got <NULL> reply\n"); | |
215 | return &f; | |
216 | } | |
c579f632 | 217 | xstrncpy(buf, inbuf, DNS_INBUF_SZ); |
218 | debug(35, 5) ("fqdncacheParse: parsing: {%s}\n", buf); | |
bd34f258 | 219 | token = strtok(buf, w_space); |
220 | if (NULL == token) { | |
6a78c18e | 221 | debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting '$name'\n"); |
bd34f258 | 222 | return &f; |
223 | } | |
224 | if (0 == strcmp(token, "$fail")) { | |
225 | f.expires = squid_curtime + Config.negativeDnsTtl; | |
226 | token = strtok(NULL, "\n"); | |
227 | assert(NULL != token); | |
228 | f.error_message = xstrdup(token); | |
229 | return &f; | |
230 | } | |
231 | if (0 != strcmp(token, "$name")) { | |
6a78c18e | 232 | debug(35, 1) ("fqdncacheParse: Got '%s', expecting '$name'\n", token); |
bd34f258 | 233 | return &f; |
234 | } | |
235 | token = strtok(NULL, w_space); | |
236 | if (NULL == token) { | |
6a78c18e | 237 | debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting TTL\n"); |
bd34f258 | 238 | return &f; |
239 | } | |
add5d21f | 240 | f.flags.negcached = 0; |
bd34f258 | 241 | ttl = atoi(token); |
242 | if (ttl > 0) | |
243 | f.expires = squid_curtime + ttl; | |
244 | else | |
245 | f.expires = squid_curtime + Config.positiveDnsTtl; | |
246 | token = strtok(NULL, w_space); | |
247 | if (NULL != token) { | |
248 | f.names[0] = xstrdup(token); | |
249 | f.name_count = 1; | |
f88bb09c | 250 | } |
e84703ad | 251 | return &f; |
f88bb09c | 252 | } |
59f34d62 | 253 | #else |
59f34d62 | 254 | fqdncacheParse(rfc1035_rr * answers, int nr) |
255 | { | |
256 | static fqdncache_entry f; | |
257 | int k; | |
258 | int j; | |
259 | int na = 0; | |
260 | memset(&f, '\0', sizeof(f)); | |
261 | f.expires = squid_curtime; | |
add5d21f | 262 | f.flags.negcached = 1; |
59f34d62 | 263 | if (nr < 0) { |
b18baa48 | 264 | debug(35, 3) ("fqdncacheParse: Lookup failed (error %d)\n", |
59f34d62 | 265 | rfc1035_errno); |
266 | assert(rfc1035_error_message); | |
267 | f.error_message = xstrdup(rfc1035_error_message); | |
268 | return &f; | |
269 | } | |
270 | if (nr == 0) { | |
b18baa48 | 271 | debug(35, 3) ("fqdncacheParse: No DNS records\n"); |
59f34d62 | 272 | f.error_message = xstrdup("No DNS records"); |
273 | return &f; | |
274 | } | |
39d5df9b | 275 | debug(35, 3) ("fqdncacheParse: %d answers\n", nr); |
59f34d62 | 276 | assert(answers); |
277 | for (j = 0, k = 0; k < nr; k++) { | |
278 | if (answers[k].type != RFC1035_TYPE_PTR) | |
279 | continue; | |
280 | if (answers[k].class != RFC1035_CLASS_IN) | |
281 | continue; | |
282 | na++; | |
add5d21f | 283 | f.flags.negcached = 0; |
59f34d62 | 284 | f.names[0] = xstrdup(answers[k].rdata); |
285 | f.name_count = 1; | |
286 | f.expires = squid_curtime + answers[k].ttl; | |
287 | return &f; | |
288 | } | |
289 | debug(35, 1) ("fqdncacheParse: No PTR record\n"); | |
290 | f.error_message = xstrdup("No PTR record"); | |
291 | return &f; | |
292 | } | |
293 | #endif | |
f88bb09c | 294 | |
429fdbec | 295 | static void |
59f34d62 | 296 | #if USE_DNSSERVERS |
74addf6c | 297 | fqdncacheHandleReply(void *data, char *reply) |
59f34d62 | 298 | #else |
299 | fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na) | |
300 | #endif | |
f88bb09c | 301 | { |
f88bb09c | 302 | int n; |
74addf6c | 303 | generic_cbdata *c = data; |
304 | fqdncache_entry *f = c->data; | |
e84703ad | 305 | fqdncache_entry *x = NULL; |
74addf6c | 306 | cbdataFree(c); |
307 | c = NULL; | |
c68e9c6b | 308 | n = ++FqdncacheStats.replies; |
83704487 | 309 | statHistCount(&statCounter.dns.svc_time, |
74addf6c | 310 | tvSubMsec(f->request_time, current_time)); |
59f34d62 | 311 | #if USE_DNSSERVERS |
c68e9c6b | 312 | x = fqdncacheParse(reply); |
59f34d62 | 313 | #else |
314 | x = fqdncacheParse(answers, na); | |
315 | #endif | |
c68e9c6b | 316 | assert(x); |
317 | f->name_count = x->name_count; | |
318 | for (n = 0; n < (int) f->name_count; n++) | |
319 | f->names[n] = x->names[n]; | |
320 | f->error_message = x->error_message; | |
c68e9c6b | 321 | f->expires = x->expires; |
add5d21f | 322 | f->flags = x->flags; |
323 | fqdncacheAddEntry(f); | |
324 | fqdncacheCallback(f); | |
f88bb09c | 325 | } |
326 | ||
429fdbec | 327 | void |
348b2031 | 328 | fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerData) |
f88bb09c | 329 | { |
330 | fqdncache_entry *f = NULL; | |
f88bb09c | 331 | char *name = inet_ntoa(addr); |
74addf6c | 332 | generic_cbdata *c; |
698e6f16 | 333 | assert(handler); |
a3d5953d | 334 | debug(35, 4) ("fqdncache_nbgethostbyaddr: Name '%s'.\n", name); |
f88bb09c | 335 | FqdncacheStats.requests++; |
f88bb09c | 336 | if (name == NULL || name[0] == '\0') { |
a3d5953d | 337 | debug(35, 4) ("fqdncache_nbgethostbyaddr: Invalid name!\n"); |
348b2031 | 338 | handler(NULL, handlerData); |
429fdbec | 339 | return; |
f88bb09c | 340 | } |
add5d21f | 341 | f = fqdncache_get(name); |
342 | if (NULL == f) { | |
343 | /* miss */ | |
344 | (void) 0; | |
345 | } else if (fqdncacheExpiredEntry(f)) { | |
346 | /* hit, but expired -- bummer */ | |
347 | fqdncacheRelease(f); | |
348 | f = NULL; | |
349 | } else { | |
350 | /* hit */ | |
a3d5953d | 351 | debug(35, 4) ("fqdncache_nbgethostbyaddr: HIT for '%s'\n", name); |
add5d21f | 352 | if (f->flags.negcached) |
f88bb09c | 353 | FqdncacheStats.negative_hits++; |
354 | else | |
355 | FqdncacheStats.hits++; | |
add5d21f | 356 | f->handler = handler; |
357 | f->handlerData = handlerData; | |
358 | cbdataLock(handlerData); | |
359 | fqdncacheCallback(f); | |
429fdbec | 360 | return; |
f88bb09c | 361 | } |
add5d21f | 362 | |
363 | debug(35, 5) ("fqdncache_nbgethostbyaddr: MISS for '%s'\n", name); | |
364 | FqdncacheStats.misses++; | |
365 | f = fqdncacheCreateEntry(name); | |
366 | f->handler = handler; | |
367 | f->handlerData = handlerData; | |
368 | cbdataLock(handlerData); | |
369 | f->request_time = current_time; | |
58cd5bbd | 370 | c = memAllocate(MEM_GEN_CBDATA); |
74addf6c | 371 | c->data = f; |
58cd5bbd | 372 | cbdataAdd(c, memFree, MEM_GEN_CBDATA); |
59f34d62 | 373 | #if USE_DNSSERVERS |
74addf6c | 374 | dnsSubmit(f->name, fqdncacheHandleReply, c); |
59f34d62 | 375 | #else |
376 | idnsPTRLookup(addr, fqdncacheHandleReply, c); | |
377 | #endif | |
f88bb09c | 378 | } |
379 | ||
f88bb09c | 380 | /* initialize the fqdncache */ |
b8d8561b | 381 | void |
0673c0ba | 382 | fqdncache_init(void) |
f88bb09c | 383 | { |
aa9e2cab | 384 | int n; |
19054954 | 385 | if (fqdn_table) |
386 | return; | |
a3d5953d | 387 | debug(35, 3) ("Initializing FQDN Cache...\n"); |
f88bb09c | 388 | memset(&FqdncacheStats, '\0', sizeof(FqdncacheStats)); |
3eb55834 | 389 | memset(&lru_list, '\0', sizeof(lru_list)); |
e55650e3 | 390 | fqdncache_high = (long) (((float) Config.fqdncache.size * |
f88bb09c | 391 | (float) FQDN_HIGH_WATER) / (float) 100); |
e55650e3 | 392 | fqdncache_low = (long) (((float) Config.fqdncache.size * |
f88bb09c | 393 | (float) FQDN_LOW_WATER) / (float) 100); |
aa9e2cab | 394 | n = hashPrime(fqdncache_high / 4); |
6a78c18e | 395 | fqdn_table = hash_create((HASHCMP *) strcmp, n, hash4); |
22f3fd98 | 396 | cachemgrRegister("fqdncache", |
397 | "FQDN Cache Stats and Contents", | |
1da3b90b | 398 | fqdnStats, 0, 1); |
add5d21f | 399 | memDataInit(MEM_FQDNCACHE_ENTRY, "fqdncache_entry", |
400 | sizeof(fqdncache_entry), 0); | |
f88bb09c | 401 | } |
402 | ||
0ee4272b | 403 | const char * |
b8d8561b | 404 | fqdncache_gethostbyaddr(struct in_addr addr, int flags) |
f88bb09c | 405 | { |
406 | char *name = inet_ntoa(addr); | |
407 | fqdncache_entry *f = NULL; | |
429fdbec | 408 | struct in_addr ip; |
698e6f16 | 409 | assert(name); |
f88bb09c | 410 | FqdncacheStats.requests++; |
add5d21f | 411 | f = fqdncache_get(name); |
412 | if (NULL == f) { | |
413 | (void) 0; | |
414 | } else if (fqdncacheExpiredEntry(f)) { | |
415 | fqdncacheRelease(f); | |
416 | f = NULL; | |
417 | } else if (f->flags.negcached) { | |
418 | FqdncacheStats.negative_hits++; | |
419 | dns_error_message = f->error_message; | |
420 | return NULL; | |
421 | } else { | |
422 | FqdncacheStats.hits++; | |
423 | f->lastref = squid_curtime; | |
424 | return f->names[0]; | |
f88bb09c | 425 | } |
f88bb09c | 426 | /* check if it's already a FQDN address in text form. */ |
429fdbec | 427 | if (!safe_inet_addr(name, &ip)) |
f88bb09c | 428 | return name; |
429fdbec | 429 | FqdncacheStats.misses++; |
f88bb09c | 430 | if (flags & FQDN_LOOKUP_IF_MISS) |
348b2031 | 431 | fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL); |
f88bb09c | 432 | return NULL; |
433 | } | |
434 | ||
435 | ||
436 | /* process objects list */ | |
b8d8561b | 437 | void |
438 | fqdnStats(StoreEntry * sentry) | |
f88bb09c | 439 | { |
440 | fqdncache_entry *f = NULL; | |
441 | int k; | |
442 | int ttl; | |
4bc76d59 | 443 | if (fqdn_table == NULL) |
f88bb09c | 444 | return; |
15576b6a | 445 | storeAppendPrintf(sentry, "FQDN Cache Statistics:\n"); |
446 | storeAppendPrintf(sentry, "FQDNcache Entries: %d\n", | |
59c4d35b | 447 | memInUse(MEM_FQDNCACHE_ENTRY)); |
15576b6a | 448 | storeAppendPrintf(sentry, "FQDNcache Requests: %d\n", |
f88bb09c | 449 | FqdncacheStats.requests); |
15576b6a | 450 | storeAppendPrintf(sentry, "FQDNcache Hits: %d\n", |
f88bb09c | 451 | FqdncacheStats.hits); |
15576b6a | 452 | storeAppendPrintf(sentry, "FQDNcache Negative Hits: %d\n", |
f88bb09c | 453 | FqdncacheStats.negative_hits); |
15576b6a | 454 | storeAppendPrintf(sentry, "FQDNcache Misses: %d\n", |
f88bb09c | 455 | FqdncacheStats.misses); |
15576b6a | 456 | storeAppendPrintf(sentry, "Blocking calls to gethostbyaddr(): %d\n", |
f88bb09c | 457 | FqdncacheStats.ghba_calls); |
15576b6a | 458 | storeAppendPrintf(sentry, "FQDN Cache Contents:\n\n"); |
f88bb09c | 459 | |
0f6bebac | 460 | hash_first(fqdn_table); |
461 | while ((f = (fqdncache_entry *) hash_next(fqdn_table))) { | |
add5d21f | 462 | ttl = (f->expires - squid_curtime); |
15576b6a | 463 | storeAppendPrintf(sentry, " %-32.32s %c %6d %d", |
f88bb09c | 464 | f->name, |
add5d21f | 465 | f->flags.negcached ? 'N' : ' ', |
f88bb09c | 466 | ttl, |
467 | (int) f->name_count); | |
468 | for (k = 0; k < (int) f->name_count; k++) | |
469 | storeAppendPrintf(sentry, " %s", f->names[k]); | |
22f3fd98 | 470 | storeAppendPrintf(sentry, "\n"); |
f88bb09c | 471 | } |
f88bb09c | 472 | } |
473 | ||
b8d8561b | 474 | static void |
79d39a72 | 475 | dummy_handler(const char *bufnotused, void *datanotused) |
f88bb09c | 476 | { |
477 | return; | |
478 | } | |
479 | ||
0ee4272b | 480 | const char * |
b8d8561b | 481 | fqdnFromAddr(struct in_addr addr) |
28ab0c0a | 482 | { |
0ee4272b | 483 | const char *n; |
39de381a | 484 | static char buf[32]; |
17a0a4ee | 485 | if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0))) |
28ab0c0a | 486 | return n; |
f2052513 | 487 | xstrncpy(buf, inet_ntoa(addr), 32); |
39de381a | 488 | return buf; |
28ab0c0a | 489 | } |
f201f309 | 490 | |
429fdbec | 491 | static void |
492 | fqdncacheLockEntry(fqdncache_entry * f) | |
493 | { | |
4bc76d59 | 494 | if (f->locks++ == 0) { |
495 | dlinkDelete(&f->lru, &lru_list); | |
496 | dlinkAdd(f, &f->lru, &lru_list); | |
497 | } | |
429fdbec | 498 | } |
499 | ||
500 | static void | |
501 | fqdncacheUnlockEntry(fqdncache_entry * f) | |
502 | { | |
ac06f720 | 503 | assert(f->locks > 0); |
429fdbec | 504 | f->locks--; |
505 | if (fqdncacheExpiredEntry(f)) | |
add5d21f | 506 | fqdncacheRelease(f); |
429fdbec | 507 | } |
508 | ||
ec878047 | 509 | static void |
510 | fqdncacheFreeEntry(void *data) | |
511 | { | |
512 | fqdncache_entry *f = data; | |
513 | int k; | |
514 | for (k = 0; k < (int) f->name_count; k++) | |
515 | safe_free(f->names[k]); | |
516 | safe_free(f->name); | |
517 | safe_free(f->error_message); | |
db1cd23c | 518 | memFree(f, MEM_FQDNCACHE_ENTRY); |
ec878047 | 519 | } |
520 | ||
56e15c50 | 521 | void |
522 | fqdncacheFreeMemory(void) | |
523 | { | |
ec878047 | 524 | hashFreeItems(fqdn_table, fqdncacheFreeEntry); |
56e15c50 | 525 | hashFreeMemory(fqdn_table); |
afe95a7e | 526 | fqdn_table = NULL; |
56e15c50 | 527 | } |
429fdbec | 528 | |
d20b1cd0 | 529 | /* Recalculate FQDN cache size upon reconfigure */ |
429fdbec | 530 | void |
531 | fqdncache_restart(void) | |
532 | { | |
e55650e3 | 533 | fqdncache_high = (long) (((float) Config.fqdncache.size * |
e144eae4 | 534 | (float) FQDN_HIGH_WATER) / (float) 100); |
e55650e3 | 535 | fqdncache_low = (long) (((float) Config.fqdncache.size * |
e144eae4 | 536 | (float) FQDN_LOW_WATER) / (float) 100); |
429fdbec | 537 | } |
ce75f381 | 538 | |
539 | #ifdef SQUID_SNMP | |
e7ef99a7 | 540 | /* |
135171fe | 541 | * The function to return the fqdn statistics via SNMP |
542 | */ | |
d60c11be | 543 | |
86115da5 | 544 | variable_list * |
e7ef99a7 | 545 | snmp_netFqdnFn(variable_list * Var, snint * ErrP) |
d60c11be | 546 | { |
736eb6ad | 547 | variable_list *Answer = NULL; |
d20b1cd0 | 548 | debug(49, 5) ("snmp_netFqdnFn: Processing request:\n", Var->name[LEN_SQ_NET + 1]); |
e7ef99a7 | 549 | snmpDebugOid(5, Var->name, Var->name_length); |
86115da5 | 550 | *ErrP = SNMP_ERR_NOERROR; |
135171fe | 551 | switch (Var->name[LEN_SQ_NET + 1]) { |
e7ef99a7 | 552 | case FQDN_ENT: |
736eb6ad | 553 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
554 | memInUse(MEM_FQDNCACHE_ENTRY), | |
555 | SMI_GAUGE32); | |
135171fe | 556 | break; |
e7ef99a7 | 557 | case FQDN_REQ: |
736eb6ad | 558 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
559 | FqdncacheStats.requests, | |
560 | SMI_COUNTER32); | |
135171fe | 561 | break; |
e7ef99a7 | 562 | case FQDN_HITS: |
736eb6ad | 563 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
564 | FqdncacheStats.hits, | |
565 | SMI_COUNTER32); | |
135171fe | 566 | break; |
e7ef99a7 | 567 | case FQDN_PENDHIT: |
add5d21f | 568 | /* this is now worthless */ |
736eb6ad | 569 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
add5d21f | 570 | 0, |
736eb6ad | 571 | SMI_GAUGE32); |
135171fe | 572 | break; |
e7ef99a7 | 573 | case FQDN_NEGHIT: |
736eb6ad | 574 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
575 | FqdncacheStats.negative_hits, | |
576 | SMI_COUNTER32); | |
135171fe | 577 | break; |
e7ef99a7 | 578 | case FQDN_MISS: |
736eb6ad | 579 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
580 | FqdncacheStats.misses, | |
581 | SMI_COUNTER32); | |
135171fe | 582 | break; |
e7ef99a7 | 583 | case FQDN_GHBN: |
736eb6ad | 584 | Answer = snmp_var_new_integer(Var->name, Var->name_length, |
585 | FqdncacheStats.ghba_calls, | |
586 | SMI_COUNTER32); | |
135171fe | 587 | break; |
ce75f381 | 588 | default: |
135171fe | 589 | *ErrP = SNMP_ERR_NOSUCHNAME; |
736eb6ad | 590 | break; |
86115da5 | 591 | } |
592 | return Answer; | |
ce75f381 | 593 | } |
e7ef99a7 | 594 | |
135171fe | 595 | #endif /*SQUID_SNMP */ |