3 * $Id: ipcache.cc,v 1.264 2007/10/13 00:02:28 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 #include "CacheManager.h"
40 #include "SquidTime.h"
44 typedef struct _ipcache_entry ipcache_entry
;
48 hash_link hash
; /* must be first */
56 struct timeval request_time
;
63 unsigned int negcached
:
66 unsigned int fromhosts
:
85 static dlink_list lru_list
;
87 static FREE ipcacheFreeEntry
;
89 static HLPCB ipcacheHandleReply
;
91 static IDNSCB ipcacheHandleReply
;
93 static IPH dummy_handler
;
94 static int ipcacheExpiredEntry(ipcache_entry
*);
95 static int ipcache_testname(void);
97 static int ipcacheParse(ipcache_entry
*, const char *buf
);
99 static int ipcacheParse(ipcache_entry
*, rfc1035_rr
*, int, const char *error
);
101 static ipcache_entry
*ipcache_get(const char *);
102 static void ipcacheLockEntry(ipcache_entry
*);
103 static void ipcacheStatPrint(ipcache_entry
*, StoreEntry
*);
104 static void ipcacheUnlockEntry(ipcache_entry
*);
105 static void ipcacheRelease(ipcache_entry
*);
107 static ipcache_addrs static_addrs
;
108 static hash_table
*ip_table
= NULL
;
110 static long ipcache_low
= 180;
111 static long ipcache_high
= 200;
113 #if LIBRESOLV_DNS_TTL_HACK
114 extern int _dns_ttl_
;
118 ipcache_testname(void)
121 debugs(14, 1, "Performing DNS Tests...");
123 if ((w
= Config
.dns_testname_list
) == NULL
)
126 for (; w
; w
= w
->next
) {
127 if (gethostbyname(w
->key
) != NULL
)
134 /* removes the given ipcache entry */
136 ipcacheRelease(ipcache_entry
* i
)
138 debugs(14, 3, "ipcacheRelease: Releasing entry for '" << (const char *) i
->hash
.key
<< "'");
140 hash_remove_link(ip_table
, (hash_link
*) i
);
141 dlinkDelete(&i
->lru
, &lru_list
);
145 static ipcache_entry
*
146 ipcache_get(const char *name
)
148 if (ip_table
!= NULL
)
149 return (ipcache_entry
*) hash_lookup(ip_table
, name
);
155 ipcacheExpiredEntry(ipcache_entry
* i
)
157 /* all static entries are locked, so this takes care of them too */
162 if (i
->addrs
.count
== 0)
163 if (0 == i
->flags
.negcached
)
166 if (i
->expires
> squid_curtime
)
173 ipcache_purgelru(void *voidnotused
)
176 dlink_node
*prev
= NULL
;
179 eventAdd("ipcache_purgelru", ipcache_purgelru
, NULL
, 10.0, 1);
181 for (m
= lru_list
.tail
; m
; m
= prev
) {
182 if (memInUse(MEM_IPCACHE_ENTRY
) < ipcache_low
)
187 i
= (ipcache_entry
*)m
->data
;
197 debugs(14, 9, "ipcache_purgelru: removed " << removed
<< " entries");
200 /* purges entries added from /etc/hosts (or whatever). */
202 purge_entries_fromhosts(void)
204 dlink_node
*m
= lru_list
.head
;
205 ipcache_entry
*i
= NULL
, *t
;
208 if (i
!= NULL
) { /* need to delay deletion */
209 ipcacheRelease(i
); /* we just override locks */
213 t
= (ipcache_entry
*)m
->data
;
215 if (t
->flags
.fromhosts
)
225 /* create blank ipcache_entry */
226 static ipcache_entry
*
227 ipcacheCreateEntry(const char *name
)
229 static ipcache_entry
*i
;
230 i
= (ipcache_entry
*)memAllocate(MEM_IPCACHE_ENTRY
);
231 i
->hash
.key
= xstrdup(name
);
232 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
237 ipcacheAddEntry(ipcache_entry
* i
)
239 hash_link
*e
= (hash_link
*)hash_lookup(ip_table
, i
->hash
.key
);
242 /* avoid colission */
243 ipcache_entry
*q
= (ipcache_entry
*) e
;
247 hash_join(ip_table
, &i
->hash
);
248 dlinkAdd(i
, &i
->lru
, &lru_list
);
249 i
->lastref
= squid_curtime
;
252 /* walks down the pending list, calling handlers */
254 ipcacheCallback(ipcache_entry
* i
)
256 IPH
*callback
= i
->handler
;
258 i
->lastref
= squid_curtime
;
265 callback
= i
->handler
;
269 if (cbdataReferenceValidDone(i
->handlerData
, &cbdata
)) {
270 dns_error_message
= i
->error_message
;
271 callback(i
->addrs
.count
? &i
->addrs
: NULL
, cbdata
);
274 ipcacheUnlockEntry(i
);
279 ipcacheParse(ipcache_entry
*i
, const char *inbuf
)
281 LOCAL_ARRAY(char, buf
, DNS_INBUF_SZ
);
286 const char *name
= (const char *)i
->hash
.key
;
287 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
288 i
->flags
.negcached
= 1;
289 safe_free(i
->addrs
.in_addrs
);
290 safe_free(i
->addrs
.bad_mask
);
291 safe_free(i
->error_message
);
295 debugs(14, 1, "ipcacheParse: Got <NULL> reply");
296 i
->error_message
= xstrdup("Internal Error");
300 xstrncpy(buf
, inbuf
, DNS_INBUF_SZ
);
301 debugs(14, 5, "ipcacheParse: parsing: {" << buf
<< "}");
302 token
= strtok(buf
, w_space
);
305 debugs(14, 1, "ipcacheParse: expecting result, got '" << inbuf
<< "'");
307 i
->error_message
= xstrdup("Internal Error");
311 if (0 == strcmp(token
, "$fail")) {
312 token
= strtok(NULL
, "\n");
313 assert(NULL
!= token
);
314 i
->error_message
= xstrdup(token
);
318 if (0 != strcmp(token
, "$addr")) {
319 debugs(14, 1, "ipcacheParse: expecting '$addr', got '" << inbuf
<< "' in response to '" << name
<< "'");
321 i
->error_message
= xstrdup("Internal Error");
325 token
= strtok(NULL
, w_space
);
328 debugs(14, 1, "ipcacheParse: expecting TTL, got '" << inbuf
<< "' in response to '" << name
<< "'");
330 i
->error_message
= xstrdup("Internal Error");
336 while (NULL
!= (token
= strtok(NULL
, w_space
))) {
346 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(ipcount
, sizeof(struct IN_ADDR
));
347 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(ipcount
, sizeof(unsigned char));
349 for (j
= 0, k
= 0; k
< ipcount
; k
++) {
350 if (safe_inet_addr(A
[k
], &i
->addrs
.in_addrs
[j
]))
353 debugs(14, 1, "ipcacheParse: Invalid IP address '" << A
[k
] << "' in response to '" << name
<< "'");
356 i
->addrs
.count
= (unsigned char) j
;
359 if (i
->addrs
.count
<= 0) {
360 debugs(14, 1, "ipcacheParse: No addresses in response to '" << name
<< "'");
364 if (ttl
== 0 || ttl
> Config
.positiveDnsTtl
)
365 ttl
= Config
.positiveDnsTtl
;
367 if (ttl
< Config
.negativeDnsTtl
)
368 ttl
= Config
.negativeDnsTtl
;
370 i
->expires
= squid_curtime
+ ttl
;
372 i
->flags
.negcached
= 0;
374 return i
->addrs
.count
;
379 ipcacheParse(ipcache_entry
*i
, rfc1035_rr
* answers
, int nr
, const char *error_message
)
385 const char *name
= (const char *)i
->hash
.key
;
386 i
->expires
= squid_curtime
+ Config
.negativeDnsTtl
;
387 i
->flags
.negcached
= 1;
388 safe_free(i
->addrs
.in_addrs
);
389 safe_free(i
->addrs
.bad_mask
);
390 safe_free(i
->error_message
);
394 debugs(14, 3, "ipcacheParse: Lookup failed '" << error_message
<< "' for '" << (const char *)i
->hash
.key
<< "'");
395 i
->error_message
= xstrdup(error_message
);
400 debugs(14, 3, "ipcacheParse: No DNS records in response to '" << name
<< "'");
401 i
->error_message
= xstrdup("No DNS records");
407 for (k
= 0; k
< nr
; k
++) {
408 if (answers
[k
].type
!= RFC1035_TYPE_A
)
411 if (answers
[k
]._class
!= RFC1035_CLASS_IN
)
414 if (answers
[k
].rdlength
!= 4) {
415 debugs(14, 1, "ipcacheParse: Invalid IP address in response to '" << name
<< "'");
423 debugs(14, 1, "ipcacheParse: No Address records in response to '" << name
<< "'");
424 i
->error_message
= xstrdup("No Address records");
428 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(na
, sizeof(struct IN_ADDR
));
429 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(na
, sizeof(unsigned char));
431 for (j
= 0, k
= 0; k
< nr
; k
++) {
432 if (answers
[k
]._class
!= RFC1035_CLASS_IN
)
435 if (answers
[k
].type
== RFC1035_TYPE_A
) {
436 if (answers
[k
].rdlength
!= 4)
439 xmemcpy(&i
->addrs
.in_addrs
[j
++], answers
[k
].rdata
, 4);
441 debugs(14, 3, "ipcacheParse: #" << j
- 1 << " " << inet_ntoa(i
->addrs
.in_addrs
[j
- 1]));
443 } else if (answers
[k
].type
!= RFC1035_TYPE_CNAME
)
446 if (ttl
== 0 || (int) answers
[k
].ttl
< ttl
)
447 ttl
= answers
[k
].ttl
;
454 i
->addrs
.count
= (unsigned char) na
;
456 i
->addrs
.count
= 255;
458 if (ttl
> Config
.positiveDnsTtl
)
459 ttl
= Config
.positiveDnsTtl
;
461 if (ttl
< Config
.negativeDnsTtl
)
462 ttl
= Config
.negativeDnsTtl
;
464 i
->expires
= squid_curtime
+ ttl
;
466 i
->flags
.negcached
= 0;
468 return i
->addrs
.count
;
475 ipcacheHandleReply(void *data
, char *reply
)
477 ipcacheHandleReply(void *data
, rfc1035_rr
* answers
, int na
, const char *error_message
)
481 static_cast<generic_cbdata
*>(data
)->unwrap(&i
);
482 IpcacheStats
.replies
++;
483 statHistCount(&statCounter
.dns
.svc_time
,
484 tvSubMsec(i
->request_time
, current_time
));
487 ipcacheParse(i
, reply
);
490 ipcacheParse(i
, answers
, na
, error_message
);
498 ipcache_nbgethostbyname(const char *name
, IPH
* handler
, void *handlerData
)
500 ipcache_entry
*i
= NULL
;
501 const ipcache_addrs
*addrs
= NULL
;
503 assert(handler
!= NULL
);
504 debugs(14, 4, "ipcache_nbgethostbyname: Name '" << name
<< "'.");
505 IpcacheStats
.requests
++;
507 if (name
== NULL
|| name
[0] == '\0') {
508 debugs(14, 4, "ipcache_nbgethostbyname: Invalid name!");
509 IpcacheStats
.invalid
++;
510 dns_error_message
= "Invalid hostname";
511 handler(NULL
, handlerData
);
515 if ((addrs
= ipcacheCheckNumeric(name
))) {
516 dns_error_message
= NULL
;
517 IpcacheStats
.numeric_hits
++;
518 handler(addrs
, handlerData
);
522 i
= ipcache_get(name
);
527 } else if (ipcacheExpiredEntry(i
)) {
528 /* hit, but expired -- bummer */
533 debugs(14, 4, "ipcache_nbgethostbyname: HIT for '" << name
<< "'");
535 if (i
->flags
.negcached
)
536 IpcacheStats
.negative_hits
++;
540 i
->handler
= handler
;
542 i
->handlerData
= cbdataReference(handlerData
);
549 debugs(14, 5, "ipcache_nbgethostbyname: MISS for '" << name
<< "'");
550 IpcacheStats
.misses
++;
551 i
= ipcacheCreateEntry(name
);
552 i
->handler
= handler
;
553 i
->handlerData
= cbdataReference(handlerData
);
554 i
->request_time
= current_time
;
555 c
= new generic_cbdata(i
);
558 dnsSubmit(hashKeyStr(&i
->hash
), ipcacheHandleReply
, c
);
561 idnsALookup(hashKeyStr(&i
->hash
), ipcacheHandleReply
, c
);
565 /* initialize the ipcache */
570 debugs(14, 3, "Initializing IP Cache...");
571 memset(&IpcacheStats
, '\0', sizeof(IpcacheStats
));
572 memset(&lru_list
, '\0', sizeof(lru_list
));
573 /* test naming lookup */
575 if (!opt_dns_tests
) {
576 debugs(14, 4, "ipcache_init: Skipping DNS name lookup tests.");
577 } else if (!ipcache_testname()) {
578 fatal("ipcache_init: DNS name lookup tests failed.");
580 debugs(14, 1, "Successful DNS name lookup tests...");
583 memset(&static_addrs
, '\0', sizeof(ipcache_addrs
));
585 static_addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(1, sizeof(struct IN_ADDR
));
586 static_addrs
.bad_mask
= (unsigned char *)xcalloc(1, sizeof(unsigned char));
587 ipcache_high
= (long) (((float) Config
.ipcache
.size
*
588 (float) Config
.ipcache
.high
) / (float) 100);
589 ipcache_low
= (long) (((float) Config
.ipcache
.size
*
590 (float) Config
.ipcache
.low
) / (float) 100);
591 n
= hashPrime(ipcache_high
/ 4);
592 ip_table
= hash_create((HASHCMP
*) strcmp
, n
, hash4
);
593 memDataInit(MEM_IPCACHE_ENTRY
, "ipcache_entry", sizeof(ipcache_entry
), 0);
597 ipcacheRegisterWithCacheManager(CacheManager
& manager
)
599 manager
.registerAction("ipcache",
600 "IP Cache Stats and Contents",
601 stat_ipcache_get
, 0, 1);
604 const ipcache_addrs
*
605 ipcache_gethostbyname(const char *name
, int flags
)
607 ipcache_entry
*i
= NULL
;
608 ipcache_addrs
*addrs
;
610 debugs(14, 3, "ipcache_gethostbyname: '" << name
<< "', flags=" << std::hex
<< flags
);
611 IpcacheStats
.requests
++;
612 i
= ipcache_get(name
);
616 } else if (ipcacheExpiredEntry(i
)) {
619 } else if (i
->flags
.negcached
) {
620 IpcacheStats
.negative_hits
++;
621 dns_error_message
= i
->error_message
;
625 i
->lastref
= squid_curtime
;
626 dns_error_message
= i
->error_message
;
630 dns_error_message
= NULL
;
632 if ((addrs
= ipcacheCheckNumeric(name
))) {
633 IpcacheStats
.numeric_hits
++;
637 IpcacheStats
.misses
++;
639 if (flags
& IP_LOOKUP_IF_MISS
)
640 ipcache_nbgethostbyname(name
, dummy_handler
, NULL
);
646 ipcacheStatPrint(ipcache_entry
* i
, StoreEntry
* sentry
)
649 storeAppendPrintf(sentry
, " %-32.32s %c%c %6d %6d %2d(%2d)",
650 hashKeyStr(&i
->hash
),
651 i
->flags
.fromhosts
? 'H' : ' ',
652 i
->flags
.negcached
? 'N' : ' ',
653 (int) (squid_curtime
- i
->lastref
),
654 (int) ((i
->flags
.fromhosts
? -1 : i
->expires
- squid_curtime
)),
655 (int) i
->addrs
.count
,
656 (int) i
->addrs
.badcount
);
658 for (k
= 0; k
< (int) i
->addrs
.count
; k
++) {
659 storeAppendPrintf(sentry
, " %15s-%3s", inet_ntoa(i
->addrs
.in_addrs
[k
]),
660 i
->addrs
.bad_mask
[k
] ? "BAD" : "OK ");
663 storeAppendPrintf(sentry
, "\n");
666 /* process objects list */
668 stat_ipcache_get(StoreEntry
* sentry
)
671 assert(ip_table
!= NULL
);
672 storeAppendPrintf(sentry
, "IP Cache Statistics:\n");
673 storeAppendPrintf(sentry
, "IPcache Entries: %d\n",
674 memInUse(MEM_IPCACHE_ENTRY
));
675 storeAppendPrintf(sentry
, "IPcache Requests: %d\n",
676 IpcacheStats
.requests
);
677 storeAppendPrintf(sentry
, "IPcache Hits: %d\n",
679 storeAppendPrintf(sentry
, "IPcache Negative Hits: %d\n",
680 IpcacheStats
.negative_hits
);
681 storeAppendPrintf(sentry
, "IPcache Numeric Hits: %d\n",
682 IpcacheStats
.numeric_hits
);
683 storeAppendPrintf(sentry
, "IPcache Misses: %d\n",
684 IpcacheStats
.misses
);
685 storeAppendPrintf(sentry
, "IPcache Invalid Request: %d\n",
686 IpcacheStats
.invalid
);
687 storeAppendPrintf(sentry
, "\n\n");
688 storeAppendPrintf(sentry
, "IP Cache Contents:\n\n");
689 storeAppendPrintf(sentry
, " %-29.29s %3s %6s %6s %1s\n",
696 for (m
= lru_list
.head
; m
; m
= m
->next
)
697 ipcacheStatPrint((ipcache_entry
*)m
->data
, sentry
);
701 dummy_handler(const ipcache_addrs
* addrsnotused
, void *datanotused
)
707 ipcacheInvalidate(const char *name
)
711 if ((i
= ipcache_get(name
)) == NULL
)
714 i
->expires
= squid_curtime
;
717 * NOTE, don't call ipcacheRelease here becuase we might be here due
718 * to a thread started from a callback.
723 ipcacheInvalidateNegative(const char *name
)
727 if ((i
= ipcache_get(name
)) == NULL
)
730 if (i
->flags
.negcached
)
731 i
->expires
= squid_curtime
;
734 * NOTE, don't call ipcacheRelease here becuase we might be here due
735 * to a thread started from a callback.
740 ipcacheCheckNumeric(const char *name
)
744 /* check if it's already a IP address in text form. */
746 if (!safe_inet_addr(name
, &ip
))
749 static_addrs
.count
= 1;
751 static_addrs
.cur
= 0;
753 static_addrs
.in_addrs
[0].s_addr
= ip
.s_addr
;
755 static_addrs
.bad_mask
[0] = FALSE
;
757 static_addrs
.badcount
= 0;
759 return &static_addrs
;
763 ipcacheLockEntry(ipcache_entry
* i
)
765 if (i
->locks
++ == 0) {
766 dlinkDelete(&i
->lru
, &lru_list
);
767 dlinkAdd(i
, &i
->lru
, &lru_list
);
772 ipcacheUnlockEntry(ipcache_entry
* i
)
774 assert(i
->locks
> 0);
777 if (ipcacheExpiredEntry(i
))
782 ipcacheCycleAddr(const char *name
, ipcache_addrs
* ia
)
789 if ((i
= ipcache_get(name
)) == NULL
)
792 if (i
->flags
.negcached
)
798 for (k
= 0; k
< ia
->count
; k
++) {
799 if (++ia
->cur
== ia
->count
)
802 if (!ia
->bad_mask
[ia
->cur
])
806 if (k
== ia
->count
) {
807 /* All bad, reset to All good */
808 debugs(14, 3, "ipcacheCycleAddr: Changing ALL " << name
<< " addrs from BAD to OK");
810 for (k
= 0; k
< ia
->count
; k
++)
818 debugs(14, 3, "ipcacheCycleAddr: " << name
<< " now at " << inet_ntoa(ia
->in_addrs
[ia
->cur
]));
822 * Marks the given address as BAD and calls ipcacheCycleAddr to
823 * advance the current pointer to the next OK address.
827 ipcacheMarkBadAddr(const char *name
, struct IN_ADDR addr
)
833 if ((i
= ipcache_get(name
)) == NULL
)
838 for (k
= 0; k
< (int) ia
->count
; k
++)
840 if (ia
->in_addrs
[k
].s_addr
== addr
.s_addr
)
844 if (k
== (int) ia
->count
) /* not found */
847 if (!ia
->bad_mask
[k
])
849 ia
->bad_mask
[k
] = TRUE
;
851 i
->expires
= XMIN(squid_curtime
+ XMAX((time_t)60, Config
.negativeDnsTtl
), i
->expires
);
852 debugs(14, 2, "ipcacheMarkBadAddr: " << name
<< " [" << inet_ntoa(addr
) << "]");
855 ipcacheCycleAddr(name
, ia
);
860 ipcacheMarkGoodAddr(const char *name
, struct IN_ADDR addr
)
866 if ((i
= ipcache_get(name
)) == NULL
)
871 for (k
= 0; k
< (int) ia
->count
; k
++)
873 if (ia
->in_addrs
[k
].s_addr
== addr
.s_addr
)
877 if (k
== (int) ia
->count
) /* not found */
880 if (!ia
->bad_mask
[k
]) /* already OK */
883 ia
->bad_mask
[k
] = FALSE
;
887 debugs(14, 2, "ipcacheMarkGoodAddr: " << name
<< " [" << inet_ntoa(addr
) << "]");
891 ipcacheFreeEntry(void *data
)
893 ipcache_entry
*i
= (ipcache_entry
*)data
;
894 safe_free(i
->addrs
.in_addrs
);
895 safe_free(i
->addrs
.bad_mask
);
896 safe_free(i
->hash
.key
);
897 safe_free(i
->error_message
);
898 memFree(i
, MEM_IPCACHE_ENTRY
);
902 ipcacheFreeMemory(void)
904 hashFreeItems(ip_table
, ipcacheFreeEntry
);
905 hashFreeMemory(ip_table
);
909 /* Recalculate IP cache size upon reconfigure */
911 ipcache_restart(void)
913 ipcache_high
= (long) (((float) Config
.ipcache
.size
*
914 (float) Config
.ipcache
.high
) / (float) 100);
915 ipcache_low
= (long) (((float) Config
.ipcache
.size
*
916 (float) Config
.ipcache
.low
) / (float) 100);
917 purge_entries_fromhosts();
921 * adds a "static" entry from /etc/hosts.
922 * returns 0 upon success, 1 if the ip address is invalid
925 ipcacheAddEntryFromHosts(const char *name
, const char *ipaddr
)
931 if (!safe_inet_addr(ipaddr
, &ip
)) {
932 if (strchr(ipaddr
, ':') && strspn(ipaddr
, "0123456789abcdefABCDEF:") == strlen(ipaddr
)) {
933 debugs(14, 3, "ipcacheAddEntryFromHosts: Skipping IPv6 address '" << ipaddr
<< "'");
935 debugs(14, 1, "ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr
<< "'");
941 if ((i
= ipcache_get(name
))) {
942 if (1 == i
->flags
.fromhosts
) {
943 ipcacheUnlockEntry(i
);
944 } else if (i
->locks
> 0) {
945 debugs(14, 1, "ipcacheAddEntryFromHosts: can't add static entry for locked name '" << name
<< "'");
952 i
= ipcacheCreateEntry(name
);
955 i
->addrs
.badcount
= 0;
957 i
->addrs
.in_addrs
= (struct IN_ADDR
*)xcalloc(1, sizeof(struct IN_ADDR
));
958 i
->addrs
.bad_mask
= (unsigned char *)xcalloc(1, sizeof(unsigned char));
959 i
->addrs
.in_addrs
[0].s_addr
= ip
.s_addr
;
960 i
->addrs
.bad_mask
[0] = FALSE
;
961 i
->flags
.fromhosts
= 1;
969 * The function to return the ip cache statistics to via SNMP
973 snmp_netIpFn(variable_list
* Var
, snint
* ErrP
)
975 variable_list
*Answer
= NULL
;
976 debugs(49, 5, "snmp_netIpFn: Processing request:");
977 snmpDebugOid(5, Var
->name
, Var
->name_length
);
978 *ErrP
= SNMP_ERR_NOERROR
;
980 switch (Var
->name
[LEN_SQ_NET
+ 1]) {
983 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
984 memInUse(MEM_IPCACHE_ENTRY
),
989 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
990 IpcacheStats
.requests
,
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
,
1008 IpcacheStats
.negative_hits
,
1013 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1014 IpcacheStats
.misses
,
1019 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1025 Answer
= snmp_var_new_integer(Var
->name
, Var
->name_length
,
1031 *ErrP
= SNMP_ERR_NOSUCHNAME
;
1032 snmp_var_free(Answer
);
1039 #endif /*SQUID_SNMP */