3 * $Id: ipcache.cc,v 1.251 2005/04/18 21:52:42 hno Exp $
5 * DEBUG: section 14 IP Cache
6 * AUTHOR: Harvest Derived
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
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.
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.
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.
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39 typedef struct _ipcache_entry ipcache_entry
;
43 hash_link hash
; /* must be first */
51 struct timeval request_time
;
58 unsigned int negcached
:
61 unsigned int fromhosts
:
79 static dlink_list lru_list
;
81 static FREE ipcacheFreeEntry
;
83 static HLPCB ipcacheHandleReply
;
85 static IDNSCB ipcacheHandleReply
;
87 static IPH dummy_handler
;
88 static int ipcacheExpiredEntry(ipcache_entry
*);
89 static int ipcache_testname(void);
91 static int ipcacheParse(ipcache_entry
*, const char *buf
);
93 static int ipcacheParse(ipcache_entry
*, rfc1035_rr
*, int, const char *error
);
95 static ipcache_entry
*ipcache_get(const char *);
96 static void ipcacheLockEntry(ipcache_entry
*);
97 static void ipcacheStatPrint(ipcache_entry
*, StoreEntry
*);
98 static void ipcacheUnlockEntry(ipcache_entry
*);
99 static void ipcacheRelease(ipcache_entry
*);
101 static ipcache_addrs static_addrs
;
102 static hash_table
*ip_table
= NULL
;
104 static long ipcache_low
= 180;
105 static long ipcache_high
= 200;
107 #if LIBRESOLV_DNS_TTL_HACK
108 extern int _dns_ttl_
;
112 ipcache_testname(void)
115 debug(14, 1) ("Performing DNS Tests...\n");
117 if ((w
= Config
.dns_testname_list
) == NULL
)
120 for (; w
; w
= w
->next
) {
121 if (gethostbyname(w
->key
) != NULL
)
128 /* removes the given ipcache entry */
130 ipcacheRelease(ipcache_entry
* i
)
132 debug(14, 3) ("ipcacheRelease: Releasing entry for '%s'\n", (const char *) i
->hash
.key
);
133 hash_remove_link(ip_table
, (hash_link
*) i
);
134 dlinkDelete(&i
->lru
, &lru_list
);
138 static ipcache_entry
*
139 ipcache_get(const char *name
)
141 if (ip_table
!= NULL
)
142 return (ipcache_entry
*) hash_lookup(ip_table
, name
);
148 ipcacheExpiredEntry(ipcache_entry
* i
)
150 /* all static entries are locked, so this takes care of them too */
155 if (i
->addrs
.count
== 0)
156 if (0 == i
->flags
.negcached
)
159 if (i
->expires
> squid_curtime
)
166 ipcache_purgelru(void *voidnotused
)
169 dlink_node
*prev
= NULL
;
172 eventAdd("ipcache_purgelru", ipcache_purgelru
, NULL
, 10.0, 1);
174 for (m
= lru_list
.tail
; m
; m
= prev
) {
175 if (memInUse(MEM_IPCACHE_ENTRY
) < ipcache_low
)
180 i
= (ipcache_entry
*)m
->data
;
190 debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed
);
193 /* purges entries added from /etc/hosts (or whatever). */
195 purge_entries_fromhosts(void)
197 dlink_node
*m
= lru_list
.head
;
198 ipcache_entry
*i
= NULL
, *t
;
201 if (i
!= NULL
) { /* need to delay deletion */
202 ipcacheRelease(i
); /* we just override locks */
206 t
= (ipcache_entry
*)m
->data
;
208 if (t
->flags
.fromhosts
)
218 /* create blank ipcache_entry */
219 static ipcache_entry
*
220 ipcacheCreateEntry(const char *name
)
222 static ipcache_entry
*i
;
223 i
= (ipcache_entry
*)memAllocate(MEM_IPCACHE_ENTRY
);
224 i
->hash
.key
= xstrdup(name
);
225 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
230 ipcacheAddEntry(ipcache_entry
* i
)
232 hash_link
*e
= (hash_link
*)hash_lookup(ip_table
, i
->hash
.key
);
235 /* avoid colission */
236 ipcache_entry
*q
= (ipcache_entry
*) e
;
240 hash_join(ip_table
, &i
->hash
);
241 dlinkAdd(i
, &i
->lru
, &lru_list
);
242 i
->lastref
= squid_curtime
;
245 /* walks down the pending list, calling handlers */
247 ipcacheCallback(ipcache_entry
* i
)
249 IPH
*callback
= i
->handler
;
251 i
->lastref
= squid_curtime
;
258 callback
= i
->handler
;
262 if (cbdataReferenceValidDone(i
->handlerData
, &cbdata
)) {
263 dns_error_message
= i
->error_message
;
264 callback(i
->flags
.negcached
? NULL
: &i
->addrs
, cbdata
);
267 ipcacheUnlockEntry(i
);
272 ipcacheParse(ipcache_entry
*i
, const char *inbuf
)
274 LOCAL_ARRAY(char, buf
, DNS_INBUF_SZ
);
279 const char *name
= (const char *)i
->hash
.key
;
280 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
281 i
->flags
.negcached
= 1;
282 safe_free(i
->addrs
.in_addrs
);
283 safe_free(i
->addrs
.bad_mask
);
284 safe_free(i
->error_message
);
288 debug(14, 1) ("ipcacheParse: Got <NULL> reply\n");
289 i
->error_message
= xstrdup("Internal Error");
293 xstrncpy(buf
, inbuf
, DNS_INBUF_SZ
);
294 debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf
);
295 token
= strtok(buf
, w_space
);
298 debug(14, 1) ("ipcacheParse: expecting result, got '%s'\n", inbuf
);
299 i
->error_message
= xstrdup("Internal Error");
303 if (0 == strcmp(token
, "$fail")) {
304 token
= strtok(NULL
, "\n");
305 assert(NULL
!= token
);
306 i
->error_message
= xstrdup(token
);
310 if (0 != strcmp(token
, "$addr")) {
311 debug(14, 1) ("ipcacheParse: expecting '$addr', got '%s' in response to '%s'\n", inbuf
, name
);
312 i
->error_message
= xstrdup("Internal Error");
316 token
= strtok(NULL
, w_space
);
319 debug(14, 1) ("ipcacheParse: expecting TTL, got '%s' in response to '%s'\n", inbuf
, name
);
320 i
->error_message
= xstrdup("Internal Error");
326 while (NULL
!= (token
= strtok(NULL
, w_space
))) {
336 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(ipcount
, sizeof(struct IN_ADDR
));
337 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(ipcount
, sizeof(unsigned char));
339 for (j
= 0, k
= 0; k
< ipcount
; k
++) {
340 if (safe_inet_addr(A
[k
], &i
->addrs
.in_addrs
[j
]))
343 debug(14, 1) ("ipcacheParse: Invalid IP address '%s' in response to '%s'\n", A
[k
], name
);
346 i
->addrs
.count
= (unsigned char) j
;
349 if (i
->addrs
.count
<= 0) {
350 debug(14, 1) ("ipcacheParse: No addresses in response to '%s'\n", name
);
354 if (ttl
== 0 || ttl
> Config
.positiveDnsTtl
)
355 ttl
= Config
.positiveDnsTtl
;
357 if (ttl
< Config
.negativeDnsTtl
)
358 ttl
= Config
.negativeDnsTtl
;
360 i
->expires
= squid_curtime
+ ttl
;
362 i
->flags
.negcached
= 0;
364 return i
->addrs
.count
;
369 ipcacheParse(ipcache_entry
*i
, rfc1035_rr
* answers
, int nr
, const char *error_message
)
375 const char *name
= (const char *)i
->hash
.key
;
376 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
377 i
->flags
.negcached
= 1;
378 safe_free(i
->addrs
.in_addrs
);
379 safe_free(i
->addrs
.bad_mask
);
380 safe_free(i
->error_message
);
384 debug(14, 3) ("ipcacheParse: Lookup failed '%s' for '%s'\n",
385 error_message
, (const char *)i
->hash
.key
);
386 i
->error_message
= xstrdup(error_message
);
391 debug(14, 3) ("ipcacheParse: No DNS records in response to '%s'\n", name
);
392 i
->error_message
= xstrdup("No DNS records");
398 for (k
= 0; k
< nr
; k
++) {
399 if (answers
[k
].type
!= RFC1035_TYPE_A
)
402 if (answers
[k
]._class
!= RFC1035_CLASS_IN
)
405 if (answers
[k
].rdlength
!= 4) {
406 debug(14, 1)("ipcacheParse: Invalid IP address in response to '%s'\n", name
);
414 debug(14, 1) ("ipcacheParse: No Address records in response to '%s'\n", name
);
415 i
->error_message
= xstrdup("No Address records");
419 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(na
, sizeof(struct IN_ADDR
));
420 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(na
, sizeof(unsigned char));
422 for (j
= 0, k
= 0; k
< nr
; k
++) {
423 if (answers
[k
].type
!= RFC1035_TYPE_A
)
426 if (answers
[k
]._class
!= RFC1035_CLASS_IN
)
429 if (answers
[k
].rdlength
!= 4)
432 if (ttl
== 0 || (int) answers
[k
].ttl
< ttl
)
433 ttl
= answers
[k
].ttl
;
435 xmemcpy(&i
->addrs
.in_addrs
[j
++], answers
[k
].rdata
, 4);
437 debug(14, 3) ("ipcacheParse: #%d %s\n",
439 inet_ntoa(i
->addrs
.in_addrs
[j
- 1]));
444 i
->addrs
.count
= (unsigned char) na
;
446 if (ttl
== 0 || ttl
> Config
.positiveDnsTtl
)
447 ttl
= Config
.positiveDnsTtl
;
449 if (ttl
< Config
.negativeDnsTtl
)
450 ttl
= Config
.negativeDnsTtl
;
452 i
->expires
= squid_curtime
+ ttl
;
454 i
->flags
.negcached
= 0;
456 return i
->addrs
.count
;
463 ipcacheHandleReply(void *data
, char *reply
)
465 ipcacheHandleReply(void *data
, rfc1035_rr
* answers
, int na
, const char *error_message
)
468 generic_cbdata
*c
= (generic_cbdata
*)data
;
469 ipcache_entry
*i
= (ipcache_entry
*)c
->data
;
472 IpcacheStats
.replies
++;
473 statHistCount(&statCounter
.dns
.svc_time
,
474 tvSubMsec(i
->request_time
, current_time
));
477 ipcacheParse(i
, reply
);
480 ipcacheParse(i
, answers
, na
, error_message
);
488 ipcache_nbgethostbyname(const char *name
, IPH
* handler
, void *handlerData
)
490 ipcache_entry
*i
= NULL
;
491 const ipcache_addrs
*addrs
= NULL
;
493 assert(handler
!= NULL
);
494 debug(14, 4) ("ipcache_nbgethostbyname: Name '%s'.\n", name
);
495 IpcacheStats
.requests
++;
497 if (name
== NULL
|| name
[0] == '\0') {
498 debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n");
499 dns_error_message
= "Invalid hostname";
500 handler(NULL
, handlerData
);
504 if ((addrs
= ipcacheCheckNumeric(name
))) {
505 dns_error_message
= NULL
;
506 handler(addrs
, handlerData
);
510 i
= ipcache_get(name
);
515 } else if (ipcacheExpiredEntry(i
)) {
516 /* hit, but expired -- bummer */
521 debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name
);
523 if (i
->flags
.negcached
)
524 IpcacheStats
.negative_hits
++;
528 i
->handler
= handler
;
530 i
->handlerData
= cbdataReference(handlerData
);
537 debug(14, 5) ("ipcache_nbgethostbyname: MISS for '%s'\n", name
);
538 IpcacheStats
.misses
++;
539 i
= ipcacheCreateEntry(name
);
540 i
->handler
= handler
;
541 i
->handlerData
= cbdataReference(handlerData
);
542 i
->request_time
= current_time
;
543 c
= cbdataAlloc(generic_cbdata
);
547 dnsSubmit(hashKeyStr(&i
->hash
), ipcacheHandleReply
, c
);
550 idnsALookup(hashKeyStr(&i
->hash
), ipcacheHandleReply
, c
);
554 /* initialize the ipcache */
559 debug(14, 3) ("Initializing IP Cache...\n");
560 memset(&IpcacheStats
, '\0', sizeof(IpcacheStats
));
561 memset(&lru_list
, '\0', sizeof(lru_list
));
562 /* test naming lookup */
564 if (!opt_dns_tests
) {
565 debug(14, 4) ("ipcache_init: Skipping DNS name lookup tests.\n");
566 } else if (!ipcache_testname()) {
567 fatal("ipcache_init: DNS name lookup tests failed.");
569 debug(14, 1) ("Successful DNS name lookup tests...\n");
572 memset(&static_addrs
, '\0', sizeof(ipcache_addrs
));
574 static_addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(1, sizeof(struct IN_ADDR
));
575 static_addrs
.bad_mask
= (unsigned char *)xcalloc(1, sizeof(unsigned char));
576 ipcache_high
= (long) (((float) Config
.ipcache
.size
*
577 (float) Config
.ipcache
.high
) / (float) 100);
578 ipcache_low
= (long) (((float) Config
.ipcache
.size
*
579 (float) Config
.ipcache
.low
) / (float) 100);
580 n
= hashPrime(ipcache_high
/ 4);
581 ip_table
= hash_create((HASHCMP
*) strcmp
, n
, hash4
);
582 cachemgrRegister("ipcache",
583 "IP Cache Stats and Contents",
584 stat_ipcache_get
, 0, 1);
585 memDataInit(MEM_IPCACHE_ENTRY
, "ipcache_entry", sizeof(ipcache_entry
), 0);
588 const ipcache_addrs
*
589 ipcache_gethostbyname(const char *name
, int flags
)
591 ipcache_entry
*i
= NULL
;
592 ipcache_addrs
*addrs
;
594 debug(14, 3) ("ipcache_gethostbyname: '%s', flags=%x\n", name
, flags
);
595 IpcacheStats
.requests
++;
596 i
= ipcache_get(name
);
600 } else if (ipcacheExpiredEntry(i
)) {
603 } else if (i
->flags
.negcached
) {
604 IpcacheStats
.negative_hits
++;
605 dns_error_message
= i
->error_message
;
609 i
->lastref
= squid_curtime
;
610 dns_error_message
= i
->error_message
;
614 dns_error_message
= NULL
;
616 if ((addrs
= ipcacheCheckNumeric(name
)))
619 IpcacheStats
.misses
++;
621 if (flags
& IP_LOOKUP_IF_MISS
)
622 ipcache_nbgethostbyname(name
, dummy_handler
, NULL
);
628 ipcacheStatPrint(ipcache_entry
* i
, StoreEntry
* sentry
)
631 storeAppendPrintf(sentry
, " %-32.32s %c%c %6d %6d %2d(%2d)",
632 hashKeyStr(&i
->hash
),
633 i
->flags
.fromhosts
? 'H' : ' ',
634 i
->flags
.negcached
? 'N' : ' ',
635 (int) (squid_curtime
- i
->lastref
),
636 (int) ((i
->flags
.fromhosts
? -1 : i
->expires
- squid_curtime
)),
637 (int) i
->addrs
.count
,
638 (int) i
->addrs
.badcount
);
640 for (k
= 0; k
< (int) i
->addrs
.count
; k
++) {
641 storeAppendPrintf(sentry
, " %15s-%3s", inet_ntoa(i
->addrs
.in_addrs
[k
]),
642 i
->addrs
.bad_mask
[k
] ? "BAD" : "OK ");
645 storeAppendPrintf(sentry
, "\n");
648 /* process objects list */
650 stat_ipcache_get(StoreEntry
* sentry
)
653 assert(ip_table
!= NULL
);
654 storeAppendPrintf(sentry
, "IP Cache Statistics:\n");
655 storeAppendPrintf(sentry
, "IPcache Entries: %d\n",
656 memInUse(MEM_IPCACHE_ENTRY
));
657 storeAppendPrintf(sentry
, "IPcache Requests: %d\n",
658 IpcacheStats
.requests
);
659 storeAppendPrintf(sentry
, "IPcache Hits: %d\n",
661 storeAppendPrintf(sentry
, "IPcache Negative Hits: %d\n",
662 IpcacheStats
.negative_hits
);
663 storeAppendPrintf(sentry
, "IPcache Misses: %d\n",
664 IpcacheStats
.misses
);
665 storeAppendPrintf(sentry
, "\n\n");
666 storeAppendPrintf(sentry
, "IP Cache Contents:\n\n");
667 storeAppendPrintf(sentry
, " %-29.29s %3s %6s %6s %1s\n",
674 for (m
= lru_list
.head
; m
; m
= m
->next
)
675 ipcacheStatPrint((ipcache_entry
*)m
->data
, sentry
);
679 dummy_handler(const ipcache_addrs
* addrsnotused
, void *datanotused
)
685 ipcacheInvalidate(const char *name
)
689 if ((i
= ipcache_get(name
)) == NULL
)
692 i
->expires
= squid_curtime
;
695 * NOTE, don't call ipcacheRelease here becuase we might be here due
696 * to a thread started from a callback.
701 ipcacheInvalidateNegative(const char *name
)
705 if ((i
= ipcache_get(name
)) == NULL
)
708 if (i
->flags
.negcached
)
709 i
->expires
= squid_curtime
;
712 * NOTE, don't call ipcacheRelease here becuase we might be here due
713 * to a thread started from a callback.
718 ipcacheCheckNumeric(const char *name
)
722 /* check if it's already a IP address in text form. */
724 if (!safe_inet_addr(name
, &ip
))
727 static_addrs
.count
= 1;
729 static_addrs
.cur
= 0;
731 static_addrs
.in_addrs
[0].s_addr
= ip
.s_addr
;
733 static_addrs
.bad_mask
[0] = FALSE
;
735 static_addrs
.badcount
= 0;
737 return &static_addrs
;
741 ipcacheLockEntry(ipcache_entry
* i
)
743 if (i
->locks
++ == 0) {
744 dlinkDelete(&i
->lru
, &lru_list
);
745 dlinkAdd(i
, &i
->lru
, &lru_list
);
750 ipcacheUnlockEntry(ipcache_entry
* i
)
752 assert(i
->locks
> 0);
755 if (ipcacheExpiredEntry(i
))
760 ipcacheCycleAddr(const char *name
, ipcache_addrs
* ia
)
767 if ((i
= ipcache_get(name
)) == NULL
)
770 if (i
->flags
.negcached
)
776 for (k
= 0; k
< ia
->count
; k
++) {
777 if (++ia
->cur
== ia
->count
)
780 if (!ia
->bad_mask
[ia
->cur
])
784 if (k
== ia
->count
) {
785 /* All bad, reset to All good */
786 debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n",
789 for (k
= 0; k
< ia
->count
; k
++)
797 debug(14, 3) ("ipcacheCycleAddr: %s now at %s\n", name
,
798 inet_ntoa(ia
->in_addrs
[ia
->cur
]));
802 * Marks the given address as BAD and calls ipcacheCycleAddr to
803 * advance the current pointer to the next OK address.
807 ipcacheMarkBadAddr(const char *name
, struct IN_ADDR addr
)
813 if ((i
= ipcache_get(name
)) == NULL
)
818 for (k
= 0; k
< (int) ia
->count
; k
++)
820 if (ia
->in_addrs
[k
].s_addr
== addr
.s_addr
)
824 if (k
== (int) ia
->count
) /* not found */
827 if (!ia
->bad_mask
[k
])
829 ia
->bad_mask
[k
] = TRUE
;
831 i
->expires
= XMIN(squid_curtime
+ XMAX((time_t)60, Config
.negativeDnsTtl
), i
->expires
);
832 debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name
, inet_ntoa(addr
));
835 ipcacheCycleAddr(name
, ia
);
840 ipcacheMarkGoodAddr(const char *name
, struct IN_ADDR addr
)
846 if ((i
= ipcache_get(name
)) == NULL
)
851 for (k
= 0; k
< (int) ia
->count
; k
++)
853 if (ia
->in_addrs
[k
].s_addr
== addr
.s_addr
)
857 if (k
== (int) ia
->count
) /* not found */
860 if (!ia
->bad_mask
[k
]) /* already OK */
863 ia
->bad_mask
[k
] = FALSE
;
867 debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name
, inet_ntoa(addr
));
871 ipcacheFreeEntry(void *data
)
873 ipcache_entry
*i
= (ipcache_entry
*)data
;
874 safe_free(i
->addrs
.in_addrs
);
875 safe_free(i
->addrs
.bad_mask
);
876 safe_free(i
->hash
.key
);
877 safe_free(i
->error_message
);
878 memFree(i
, MEM_IPCACHE_ENTRY
);
882 ipcacheFreeMemory(void)
884 hashFreeItems(ip_table
, ipcacheFreeEntry
);
885 hashFreeMemory(ip_table
);
889 /* Recalculate IP cache size upon reconfigure */
891 ipcache_restart(void)
893 ipcache_high
= (long) (((float) Config
.ipcache
.size
*
894 (float) Config
.ipcache
.high
) / (float) 100);
895 ipcache_low
= (long) (((float) Config
.ipcache
.size
*
896 (float) Config
.ipcache
.low
) / (float) 100);
897 purge_entries_fromhosts();
901 * adds a "static" entry from /etc/hosts.
902 * returns 0 upon success, 1 if the ip address is invalid
905 ipcacheAddEntryFromHosts(const char *name
, const char *ipaddr
)
911 if (!safe_inet_addr(ipaddr
, &ip
)) {
912 if (strchr(ipaddr
, ':') && strspn(ipaddr
, "0123456789abcdefABCDEF:") == strlen(ipaddr
)) {
913 debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr
);
915 debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n",
922 if ((i
= ipcache_get(name
))) {
923 if (1 == i
->flags
.fromhosts
) {
924 ipcacheUnlockEntry(i
);
925 } else if (i
->locks
> 0) {
926 debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry"
927 " for locked name '%s'\n", name
);
934 i
= ipcacheCreateEntry(name
);
937 i
->addrs
.badcount
= 0;
939 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(1, sizeof(struct IN_ADDR
));
940 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(1, sizeof(unsigned char));
941 i
->addrs
.in_addrs
[0].s_addr
= ip
.s_addr
;
942 i
->addrs
.bad_mask
[0] = FALSE
;
943 i
->flags
.fromhosts
= 1;
951 * The function to return the ip cache statistics to via SNMP
955 snmp_netIpFn(variable_list
* Var
, snint
* ErrP
)
957 variable_list
*Answer
= NULL
;
958 debug(49, 5) ("snmp_netIpFn: Processing request:\n");
959 snmpDebugOid(5, Var
->name
, Var
->name_length
);
960 *ErrP
= SNMP_ERR_NOERROR
;
962 switch (Var
->name
[LEN_SQ_NET
+ 1]) {
965 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
966 memInUse(MEM_IPCACHE_ENTRY
),
971 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
972 IpcacheStats
.requests
,
977 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
983 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
989 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
990 IpcacheStats
.negative_hits
,
995 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1001 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1007 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1013 *ErrP
= SNMP_ERR_NOSUCHNAME
;
1014 snmp_var_free(Answer
);
1021 #endif /*SQUID_SNMP */