fqdncache.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:18k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: fqdncache.c,v 1.126 1998/12/05 00:54:24 wessels Exp $
  3.  *
  4.  * DEBUG: section 35    FQDN Cache
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #define FQDN_LOW_WATER       90
  36. #define FQDN_HIGH_WATER      95
  37. static struct {
  38.     int requests;
  39.     int replies;
  40.     int hits;
  41.     int misses;
  42.     int pending_hits;
  43.     int negative_hits;
  44.     int errors;
  45.     int ghba_calls; /* # calls to blocking gethostbyaddr() */
  46. } FqdncacheStats;
  47. static dlink_list lru_list;
  48. static HLPCB fqdncacheHandleReply;
  49. static fqdncache_entry *fqdncacheParse(const char *buf);
  50. static void fqdncache_release(fqdncache_entry *);
  51. static fqdncache_entry *fqdncache_create(const char *name);
  52. static void fqdncache_call_pending(fqdncache_entry *);
  53. static void fqdncacheAddHostent(fqdncache_entry *, const struct hostent *);
  54. static fqdncache_entry *fqdncache_get(const char *);
  55. static FQDNH dummy_handler;
  56. static int fqdncacheExpiredEntry(const fqdncache_entry *);
  57. static void fqdncacheAddPending(fqdncache_entry *, FQDNH *, void *);
  58. static void fqdncacheChangeKey(fqdncache_entry * i);
  59. static void fqdncacheLockEntry(fqdncache_entry * f);
  60. static void fqdncacheUnlockEntry(fqdncache_entry * f);
  61. static FREE fqdncacheFreeEntry;
  62. static hash_table *fqdn_table = NULL;
  63. static char fqdncache_status_char[] =
  64. {
  65.     'C',
  66.     'N',
  67.     'P',
  68.     'D'
  69. };
  70. static long fqdncache_low = 180;
  71. static long fqdncache_high = 200;
  72. /* removes the given fqdncache entry */
  73. static void
  74. fqdncache_release(fqdncache_entry * f)
  75. {
  76.     int k;
  77.     assert(f->status != FQDN_PENDING);
  78.     assert(f->status != FQDN_DISPATCHED);
  79.     assert(f->pending_head == NULL);
  80.     hash_remove_link(fqdn_table, (hash_link *) f);
  81.     if (f->status == FQDN_CACHED) {
  82. for (k = 0; k < (int) f->name_count; k++)
  83.     safe_free(f->names[k]);
  84. debug(35, 5) ("fqdncache_release: Released FQDN record for '%s'.n",
  85.     f->name);
  86.     }
  87.     dlinkDelete(&f->lru, &lru_list);
  88.     safe_free(f->name);
  89.     safe_free(f->error_message);
  90.     memFree(f, MEM_FQDNCACHE_ENTRY);
  91. }
  92. /* return match for given name */
  93. static fqdncache_entry *
  94. fqdncache_get(const char *name)
  95. {
  96.     hash_link *e;
  97.     static fqdncache_entry *f;
  98.     f = NULL;
  99.     if (fqdn_table) {
  100. if ((e = hash_lookup(fqdn_table, name)) != NULL)
  101.     f = (fqdncache_entry *) e;
  102.     }
  103.     return f;
  104. }
  105. static int
  106. fqdncacheExpiredEntry(const fqdncache_entry * f)
  107. {
  108.     if (f->status == FQDN_PENDING)
  109. return 0;
  110.     if (f->status == FQDN_DISPATCHED)
  111. return 0;
  112.     if (f->locks != 0)
  113. return 0;
  114.     if (f->expires > squid_curtime)
  115. return 0;
  116.     return 1;
  117. }
  118. void
  119. fqdncache_purgelru(void *notused)
  120. {
  121.     dlink_node *m;
  122.     dlink_node *prev = NULL;
  123.     fqdncache_entry *f;
  124.     int removed = 0;
  125.     eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 10.0, 1);
  126.     for (m = lru_list.tail; m; m = prev) {
  127. if (memInUse(MEM_FQDNCACHE_ENTRY) < fqdncache_low)
  128.     break;
  129. prev = m->prev;
  130. f = m->data;
  131. if (f->status == FQDN_PENDING)
  132.     continue;
  133. if (f->status == FQDN_DISPATCHED)
  134.     continue;
  135. if (f->locks != 0)
  136.     continue;
  137. fqdncache_release(f);
  138. removed++;
  139.     }
  140.     debug(35, 9) ("fqdncache_purgelru: removed %d entriesn", removed);
  141. }
  142. /* create blank fqdncache_entry */
  143. static fqdncache_entry *
  144. fqdncache_create(const char *name)
  145. {
  146.     static fqdncache_entry *f;
  147.     f = memAllocate(MEM_FQDNCACHE_ENTRY);
  148.     f->name = xstrdup(name);
  149.     f->expires = squid_curtime + Config.negativeDnsTtl;
  150.     hash_join(fqdn_table, (hash_link *) f);
  151.     dlinkAdd(f, &f->lru, &lru_list);
  152.     return f;
  153. }
  154. static void
  155. fqdncacheAddHostent(fqdncache_entry * f, const struct hostent *hp)
  156. {
  157.     int k;
  158.     f->name_count = 0;
  159.     f->names[f->name_count++] = xstrdup((char *) hp->h_name);
  160.     for (k = 0; hp->h_aliases[k]; k++) {
  161. f->names[f->name_count++] = xstrdup(hp->h_aliases[k]);
  162. if (f->name_count == FQDN_MAX_NAMES)
  163.     break;
  164.     }
  165. }
  166. static fqdncache_entry *
  167. fqdncacheAddNew(const char *name, const struct hostent *hp, fqdncache_status_t status)
  168. {
  169.     fqdncache_entry *f;
  170.     assert(fqdncache_get(name) == NULL);
  171.     debug(35, 10) ("fqdncacheAddNew: Adding '%s', status=%cn",
  172. name,
  173. fqdncache_status_char[status]);
  174.     f = fqdncache_create(name);
  175.     if (hp)
  176. fqdncacheAddHostent(f, hp);
  177.     f->status = status;
  178.     f->lastref = squid_curtime;
  179.     return f;
  180. }
  181. /* walks down the pending list, calling handlers */
  182. static void
  183. fqdncache_call_pending(fqdncache_entry * f)
  184. {
  185.     fqdn_pending *p = NULL;
  186.     int nhandler = 0;
  187.     f->lastref = squid_curtime;
  188.     fqdncacheLockEntry(f);
  189.     while (f->pending_head != NULL) {
  190. p = f->pending_head;
  191. f->pending_head = p->next;
  192. if (p->handler) {
  193.     nhandler++;
  194.     dns_error_message = f->error_message;
  195.     p->handler((f->status == FQDN_CACHED) ? f->names[0] : NULL,
  196. p->handlerData);
  197. }
  198. memFree(p, MEM_FQDNCACHE_PENDING);
  199.     }
  200.     f->pending_head = NULL; /* nuke list */
  201.     debug(35, 10) ("fqdncache_call_pending: Called %d handlers.n", nhandler);
  202.     fqdncacheUnlockEntry(f);
  203. }
  204. static fqdncache_entry *
  205. fqdncacheParse(const char *inbuf)
  206. {
  207.     LOCAL_ARRAY(char, buf, DNS_INBUF_SZ);
  208.     char *token;
  209.     static fqdncache_entry f;
  210.     int ttl;
  211.     xstrncpy(buf, inbuf, DNS_INBUF_SZ);
  212.     debug(35, 5) ("fqdncacheParse: parsing: {%s}n", buf);
  213.     memset(&f, '', sizeof(f));
  214.     f.expires = squid_curtime;
  215.     f.status = FQDN_NEGATIVE_CACHED;
  216.     if (inbuf == NULL) {
  217. debug(35, 1) ("fqdncacheParse: Got <NULL> replyn");
  218. return &f;
  219.     }
  220.     token = strtok(buf, w_space);
  221.     if (NULL == token) {
  222. debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting '$name'n");
  223. return &f;
  224.     }
  225.     if (0 == strcmp(token, "$fail")) {
  226. f.expires = squid_curtime + Config.negativeDnsTtl;
  227. token = strtok(NULL, "n");
  228. assert(NULL != token);
  229. f.error_message = xstrdup(token);
  230. return &f;
  231.     }
  232.     if (0 != strcmp(token, "$name")) {
  233. debug(35, 1) ("fqdncacheParse: Got '%s', expecting '$name'n", token);
  234. return &f;
  235.     }
  236.     token = strtok(NULL, w_space);
  237.     if (NULL == token) {
  238. debug(35, 1) ("fqdncacheParse: Got <NULL>, expecting TTLn");
  239. return &f;
  240.     }
  241.     f.status = FQDN_CACHED;
  242.     ttl = atoi(token);
  243.     if (ttl > 0)
  244. f.expires = squid_curtime + ttl;
  245.     else
  246. f.expires = squid_curtime + Config.positiveDnsTtl;
  247.     token = strtok(NULL, w_space);
  248.     if (NULL != token) {
  249. f.names[0] = xstrdup(token);
  250. f.name_count = 1;
  251.     }
  252.     return &f;
  253. }
  254. static void
  255. fqdncacheHandleReply(void *data, char *reply)
  256. {
  257.     int n;
  258.     generic_cbdata *c = data;
  259.     fqdncache_entry *f = c->data;
  260.     fqdncache_entry *x = NULL;
  261.     assert(f->status == FQDN_DISPATCHED);
  262.     assert(f->locks);
  263.     cbdataFree(c);
  264.     c = NULL;
  265.     n = ++FqdncacheStats.replies;
  266.     statHistCount(&Counter.dns.svc_time,
  267. tvSubMsec(f->request_time, current_time));
  268.     x = fqdncacheParse(reply);
  269.     assert(x);
  270.     f->name_count = x->name_count;
  271.     for (n = 0; n < (int) f->name_count; n++)
  272. f->names[n] = x->names[n];
  273.     f->error_message = x->error_message;
  274.     f->status = x->status;
  275.     f->expires = x->expires;
  276.     fqdncache_call_pending(f);
  277.     fqdncacheUnlockEntry(f); /* unlock from FQDN_DISPATCHED */
  278. }
  279. static void
  280. fqdncacheAddPending(fqdncache_entry * f, FQDNH * handler, void *handlerData)
  281. {
  282.     fqdn_pending *pending = memAllocate(MEM_FQDNCACHE_PENDING);
  283.     fqdn_pending **I = NULL;
  284.     f->lastref = squid_curtime;
  285.     pending->handler = handler;
  286.     pending->handlerData = handlerData;
  287.     for (I = &(f->pending_head); *I; I = &((*I)->next));
  288.     *I = pending;
  289. }
  290. void
  291. fqdncache_nbgethostbyaddr(struct in_addr addr, FQDNH * handler, void *handlerData)
  292. {
  293.     fqdncache_entry *f = NULL;
  294.     char *name = inet_ntoa(addr);
  295.     generic_cbdata *c;
  296.     assert(handler);
  297.     debug(35, 4) ("fqdncache_nbgethostbyaddr: Name '%s'.n", name);
  298.     FqdncacheStats.requests++;
  299.     if (name == NULL || name[0] == '') {
  300. debug(35, 4) ("fqdncache_nbgethostbyaddr: Invalid name!n");
  301. handler(NULL, handlerData);
  302. return;
  303.     }
  304.     if ((f = fqdncache_get(name))) {
  305. if (fqdncacheExpiredEntry(f)) {
  306.     fqdncache_release(f);
  307.     f = NULL;
  308. }
  309.     }
  310.     if (f == NULL) {
  311. /* MISS: No entry, create the new one */
  312. debug(35, 5) ("fqdncache_nbgethostbyaddr: MISS for '%s'n", name);
  313. FqdncacheStats.misses++;
  314. f = fqdncacheAddNew(name, NULL, FQDN_PENDING);
  315. fqdncacheAddPending(f, handler, handlerData);
  316. f->request_time = current_time;
  317.     } else if (f->status == FQDN_CACHED || f->status == FQDN_NEGATIVE_CACHED) {
  318. /* HIT */
  319. debug(35, 4) ("fqdncache_nbgethostbyaddr: HIT for '%s'n", name);
  320. if (f->status == FQDN_NEGATIVE_CACHED)
  321.     FqdncacheStats.negative_hits++;
  322. else
  323.     FqdncacheStats.hits++;
  324. fqdncacheAddPending(f, handler, handlerData);
  325. fqdncache_call_pending(f);
  326. return;
  327.     } else if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED) {
  328. debug(35, 4) ("fqdncache_nbgethostbyaddr: PENDING for '%s'n", name);
  329. FqdncacheStats.pending_hits++;
  330. fqdncacheAddPending(f, handler, handlerData);
  331. if (squid_curtime - f->expires > 600) {
  332.     debug(35, 0) ("fqdncache_nbgethostbyname: '%s' PENDING for %d seconds, abortingn", name,
  333. (int) (squid_curtime + Config.negativeDnsTtl - f->expires));
  334.     fqdncacheChangeKey(f);
  335.     fqdncache_call_pending(f);
  336. }
  337. return;
  338.     } else {
  339. debug(35, 1) ("fqdncache_nbgethostbyaddr: BAD status %d",
  340.     (int) f->status);
  341. assert(0);
  342.     }
  343.     /* for HIT, PENDING, DISPATCHED we've returned.  For MISS we submit */
  344.     c = xcalloc(1, sizeof(*c));
  345.     c->data = f;
  346.     cbdataAdd(c, cbdataXfree, 0);
  347.     f->status = FQDN_DISPATCHED;
  348.     fqdncacheLockEntry(f); /* lock while FQDN_DISPATCHED */
  349.     dnsSubmit(f->name, fqdncacheHandleReply, c);
  350. }
  351. /* initialize the fqdncache */
  352. void
  353. fqdncache_init(void)
  354. {
  355.     int n;
  356.     if (fqdn_table)
  357. return;
  358.     debug(35, 3) ("Initializing FQDN Cache...n");
  359.     memset(&FqdncacheStats, '', sizeof(FqdncacheStats));
  360.     memset(&lru_list, '', sizeof(lru_list));
  361.     fqdncache_high = (long) (((float) Config.fqdncache.size *
  362.     (float) FQDN_HIGH_WATER) / (float) 100);
  363.     fqdncache_low = (long) (((float) Config.fqdncache.size *
  364.     (float) FQDN_LOW_WATER) / (float) 100);
  365.     n = hashPrime(fqdncache_high / 4);
  366.     fqdn_table = hash_create((HASHCMP *) strcmp, n, hash4);
  367.     cachemgrRegister("fqdncache",
  368. "FQDN Cache Stats and Contents",
  369. fqdnStats, 0, 1);
  370. }
  371. /* clean up the pending entries in dnsserver */
  372. /* return 1 if we found the host, 0 otherwise */
  373. int
  374. fqdncacheUnregister(struct in_addr addr, void *data)
  375. {
  376.     char *name = inet_ntoa(addr);
  377.     fqdncache_entry *f = NULL;
  378.     fqdn_pending *p = NULL;
  379.     int n = 0;
  380.     debug(35, 3) ("fqdncacheUnregister: name '%s'n", name);
  381.     if ((f = fqdncache_get(name)) == NULL)
  382. return 0;
  383.     if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED) {
  384. for (p = f->pending_head; p; p = p->next) {
  385.     if (p->handlerData != data)
  386. continue;
  387.     p->handler = NULL;
  388.     n++;
  389. }
  390.     }
  391.     if (n == 0)
  392. debug_trap("fqdncacheUnregister: callback data not found");
  393.     debug(35, 3) ("fqdncacheUnregister: unregistered %d handlersn", n);
  394.     return n;
  395. }
  396. const char *
  397. fqdncache_gethostbyaddr(struct in_addr addr, int flags)
  398. {
  399.     char *name = inet_ntoa(addr);
  400.     fqdncache_entry *f = NULL;
  401.     struct in_addr ip;
  402.     assert(name);
  403.     FqdncacheStats.requests++;
  404.     if ((f = fqdncache_get(name))) {
  405. if (fqdncacheExpiredEntry(f)) {
  406.     fqdncache_release(f);
  407.     f = NULL;
  408. }
  409.     }
  410.     if (f) {
  411. if (f->status == FQDN_NEGATIVE_CACHED) {
  412.     FqdncacheStats.negative_hits++;
  413.     dns_error_message = f->error_message;
  414.     return NULL;
  415. } else {
  416.     FqdncacheStats.hits++;
  417.     f->lastref = squid_curtime;
  418.     return f->names[0];
  419. }
  420.     }
  421.     /* check if it's already a FQDN address in text form. */
  422.     if (!safe_inet_addr(name, &ip))
  423. return name;
  424.     FqdncacheStats.misses++;
  425.     if (flags & FQDN_LOOKUP_IF_MISS)
  426. fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL);
  427.     return NULL;
  428. }
  429. /* process objects list */
  430. void
  431. fqdnStats(StoreEntry * sentry)
  432. {
  433.     fqdncache_entry *f = NULL;
  434.     int k;
  435.     int ttl;
  436.     if (fqdn_table == NULL)
  437. return;
  438.     storeAppendPrintf(sentry, "FQDN Cache Statistics:n");
  439.     storeAppendPrintf(sentry, "FQDNcache Entries: %dn",
  440. memInUse(MEM_FQDNCACHE_ENTRY));
  441.     storeAppendPrintf(sentry, "FQDNcache Requests: %dn",
  442. FqdncacheStats.requests);
  443.     storeAppendPrintf(sentry, "FQDNcache Hits: %dn",
  444. FqdncacheStats.hits);
  445.     storeAppendPrintf(sentry, "FQDNcache Pending Hits: %dn",
  446. FqdncacheStats.pending_hits);
  447.     storeAppendPrintf(sentry, "FQDNcache Negative Hits: %dn",
  448. FqdncacheStats.negative_hits);
  449.     storeAppendPrintf(sentry, "FQDNcache Misses: %dn",
  450. FqdncacheStats.misses);
  451.     storeAppendPrintf(sentry, "Blocking calls to gethostbyaddr(): %dn",
  452. FqdncacheStats.ghba_calls);
  453.     storeAppendPrintf(sentry, "FQDN Cache Contents:nn");
  454.     hash_first(fqdn_table);
  455.     while ((f = (fqdncache_entry *) hash_next(fqdn_table))) {
  456. if (f->status == FQDN_PENDING || f->status == FQDN_DISPATCHED)
  457.     ttl = 0;
  458. else
  459.     ttl = (f->expires - squid_curtime);
  460. storeAppendPrintf(sentry, " %-32.32s %c %6d %d",
  461.     f->name,
  462.     fqdncache_status_char[f->status],
  463.     ttl,
  464.     (int) f->name_count);
  465. for (k = 0; k < (int) f->name_count; k++)
  466.     storeAppendPrintf(sentry, " %s", f->names[k]);
  467. storeAppendPrintf(sentry, "n");
  468.     }
  469. }
  470. static void
  471. dummy_handler(const char *bufnotused, void *datanotused)
  472. {
  473.     return;
  474. }
  475. void
  476. fqdncacheReleaseInvalid(const char *name)
  477. {
  478.     fqdncache_entry *f;
  479.     if ((f = fqdncache_get(name)) == NULL)
  480. return;
  481.     if (f->status != FQDN_NEGATIVE_CACHED)
  482. return;
  483.     fqdncache_release(f);
  484. }
  485. const char *
  486. fqdnFromAddr(struct in_addr addr)
  487. {
  488.     const char *n;
  489.     static char buf[32];
  490.     if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0)))
  491. return n;
  492.     xstrncpy(buf, inet_ntoa(addr), 32);
  493.     return buf;
  494. }
  495. static void
  496. fqdncacheLockEntry(fqdncache_entry * f)
  497. {
  498.     if (f->locks++ == 0) {
  499. dlinkDelete(&f->lru, &lru_list);
  500. dlinkAdd(f, &f->lru, &lru_list);
  501.     }
  502. }
  503. static void
  504. fqdncacheUnlockEntry(fqdncache_entry * f)
  505. {
  506.     if (f->locks == 0) {
  507. debug_trap("fqdncacheUnlockEntry: Entry has no locks");
  508. return;
  509.     }
  510.     f->locks--;
  511.     if (fqdncacheExpiredEntry(f))
  512. fqdncache_release(f);
  513. }
  514. static void
  515. fqdncacheFreeEntry(void *data)
  516. {
  517.     fqdncache_entry *f = data;
  518.     fqdn_pending *p = NULL;
  519.     int k;
  520.     while ((p = f->pending_head)) {
  521. f->pending_head = p->next;
  522. memFree(p, MEM_FQDNCACHE_PENDING);
  523.     }
  524.     for (k = 0; k < (int) f->name_count; k++)
  525. safe_free(f->names[k]);
  526.     safe_free(f->name);
  527.     safe_free(f->error_message);
  528.     memFree(f, MEM_FQDNCACHE_ENTRY);
  529. }
  530. void
  531. fqdncacheFreeMemory(void)
  532. {
  533.     hashFreeItems(fqdn_table, fqdncacheFreeEntry);
  534.     hashFreeMemory(fqdn_table);
  535.     fqdn_table = NULL;
  536. }
  537. static void
  538. fqdncacheChangeKey(fqdncache_entry * f)
  539. {
  540.     static int index = 0;
  541.     LOCAL_ARRAY(char, new_key, 256);
  542.     hash_link *table_entry = hash_lookup(fqdn_table, f->name);
  543.     if (table_entry == NULL) {
  544. debug(35, 0) ("fqdncacheChangeKey: Could not find key '%s'n", f->name);
  545. return;
  546.     }
  547.     if (f != (fqdncache_entry *) table_entry) {
  548. debug_trap("fqdncacheChangeKey: f != table_entry!");
  549. return;
  550.     }
  551.     hash_remove_link(fqdn_table, table_entry);
  552.     snprintf(new_key, 256, "%d/", ++index);
  553.     strncat(new_key, f->name, 128);
  554.     debug(35, 1) ("fqdncacheChangeKey: from '%s' to '%s'n", f->name, new_key);
  555.     safe_free(f->name);
  556.     f->name = xstrdup(new_key);
  557.     hash_join(fqdn_table, (hash_link *) f);
  558. }
  559. /* call during reconfigure phase to clear out all the
  560.  * pending and dispatched reqeusts that got lost */
  561. void
  562. fqdncache_restart(void)
  563. {
  564.     fqdncache_entry *this;
  565.     assert(fqdn_table);
  566.     hash_first(fqdn_table);
  567.     while ((this = (fqdncache_entry *) hash_next(fqdn_table))) {
  568. if (this->status == FQDN_CACHED)
  569.     continue;
  570. if (this->status == FQDN_NEGATIVE_CACHED)
  571.     continue;
  572.     }
  573.     fqdncache_high = (long) (((float) Config.fqdncache.size *
  574.     (float) FQDN_HIGH_WATER) / (float) 100);
  575.     fqdncache_low = (long) (((float) Config.fqdncache.size *
  576.     (float) FQDN_LOW_WATER) / (float) 100);
  577. }
  578. #ifdef SQUID_SNMP
  579. /*
  580.  * The function to return the fqdn statistics via SNMP
  581.  */
  582. variable_list *
  583. snmp_netFqdnFn(variable_list * Var, snint * ErrP)
  584. {
  585.     variable_list *Answer;
  586.     debug(49, 5) ("snmp_netFqdnFn: Processing request:n", Var->name[LEN_SQ_NET +
  587.     1]);
  588.     snmpDebugOid(5, Var->name, Var->name_length);
  589.     Answer = snmp_var_new(Var->name, Var->name_length);
  590.     *ErrP = SNMP_ERR_NOERROR;
  591.     Answer->val_len = sizeof(snint);
  592.     Answer->val.integer = xmalloc(Answer->val_len);
  593.     Answer->type = SMI_COUNTER32;
  594.     switch (Var->name[LEN_SQ_NET + 1]) {
  595.     case FQDN_ENT:
  596. *(Answer->val.integer) = memInUse(MEM_FQDNCACHE_ENTRY);
  597. Answer->type = SMI_GAUGE32;
  598. break;
  599.     case FQDN_REQ:
  600. *(Answer->val.integer) = FqdncacheStats.requests;
  601. break;
  602.     case FQDN_HITS:
  603. *(Answer->val.integer) = FqdncacheStats.hits;
  604. break;
  605.     case FQDN_PENDHIT:
  606. *(Answer->val.integer) = FqdncacheStats.pending_hits;
  607. Answer->type = SMI_GAUGE32;
  608. break;
  609.     case FQDN_NEGHIT:
  610. *(Answer->val.integer) = FqdncacheStats.negative_hits;
  611. break;
  612.     case FQDN_MISS:
  613. *(Answer->val.integer) = FqdncacheStats.misses;
  614. break;
  615.     case FQDN_GHBN:
  616. *(Answer->val.integer) = FqdncacheStats.ghba_calls;
  617. break;
  618.     default:
  619. *ErrP = SNMP_ERR_NOSUCHNAME;
  620. snmp_var_free(Answer);
  621. return (NULL);
  622.     }
  623.     return Answer;
  624. }
  625. #endif /*SQUID_SNMP */