--------------------- PatchSet 5307 Date: 2002/10/09 00:23:15 Author: rbcollins Branch: rbcollins_cxxtest Tag: (none) Log: and more Members: include/hash.h:1.4.44.3->1.4.44.4 include/profiling.h:1.2.4.1->1.2.4.2 include/radix.h:1.8->1.8.16.1 include/splay.h:1.6->1.6.20.1 include/util.h:1.11.20.6->1.11.20.7 src/Makefile.am:1.29.2.15->1.29.2.16 src/asn.c:1.18.2.1->1.18.2.2(DEAD) src/asn.cc:1.1->1.1.2.1 src/cache_diff.c:1.7->1.7.6.1(DEAD) src/cache_diff.cc:1.1->1.1.2.1 src/cache_manager.c:1.7.84.1->1.7.84.2(DEAD) src/cache_manager.cc:1.1->1.1.2.1 src/cachemgr.c:1.13->1.13.6.1(DEAD) src/cachemgr.cc:1.1->1.1.2.1 src/carp.c:1.8.18.1->1.8.18.2(DEAD) src/carp.cc:1.1->1.1.2.1 src/cbdata.c:1.16.2.2->1.16.2.3(DEAD) src/cbdata.cc:1.1->1.1.2.1 src/cf_gen.c:1.14->1.14.6.1(DEAD) src/cf_gen.cc:1.1->1.1.2.1 src/cf_gen_defines:1.5->1.5.40.1 src/clientStream.c:1.3->1.3.8.1(DEAD) src/clientStream.cc:1.1->1.1.2.1 src/clientStream.h:1.2.18.1->1.2.18.2 src/client_db.c:1.7.2.1->1.7.2.2(DEAD) src/client_db.cc:1.1->1.1.2.1 src/dnsserver.c:1.6->1.6.14.1(DEAD) src/dnsserver.cc:1.1->1.1.2.1 src/ipcache.c:1.19.6.1->1.19.6.2(DEAD) src/ipcache.cc:1.1->1.1.2.1 src/snmp_agent.c:1.9->1.9.44.1(DEAD) src/snmp_agent.cc:1.1->1.1.2.1 src/store_swapmeta.c:1.8.44.1->1.8.44.2(DEAD) src/store_swapmeta.cc:1.1->1.1.2.1 Index: squid/include/hash.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/hash.h,v retrieving revision 1.4.44.3 retrieving revision 1.4.44.4 diff -u -r1.4.44.3 -r1.4.44.4 --- squid/include/hash.h 6 Oct 2002 12:31:51 -0000 1.4.44.3 +++ squid/include/hash.h 9 Oct 2002 00:23:15 -0000 1.4.44.4 @@ -1,5 +1,5 @@ /* - * $Id: hash.h,v 1.4.44.3 2002/10/06 12:31:51 rbcollins Exp $ + * $Id: hash.h,v 1.4.44.4 2002/10/09 00:23:15 rbcollins Exp $ */ #ifndef SQUID_HASH_H @@ -39,7 +39,7 @@ SQUIDCEXTERN void hashFreeItems(hash_table *, HASHFREE *); SQUIDCEXTERN HASHHASH hash_string; SQUIDCEXTERN HASHHASH hash4; -extern const char *hashKeyStr(hash_link *); +SQUIDCEXTERN const char *hashKeyStr(hash_link *); /* * Here are some good prime number choices. It's important not to Index: squid/include/profiling.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/Attic/profiling.h,v retrieving revision 1.2.4.1 retrieving revision 1.2.4.2 diff -u -r1.2.4.1 -r1.2.4.2 --- squid/include/profiling.h 6 Oct 2002 06:07:43 -0000 1.2.4.1 +++ squid/include/profiling.h 9 Oct 2002 00:23:15 -0000 1.2.4.2 @@ -86,7 +86,7 @@ XPROF_LAST } xprof_type; -#define XP_NOBEST 9999999999 +#define XP_NOBEST (hrtime_t)-1 typedef struct _xprof_stats_node xprof_stats_node; typedef struct _xprof_stats_data xprof_stats_data; Index: squid/include/radix.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/radix.h,v retrieving revision 1.8 retrieving revision 1.8.16.1 diff -u -r1.8 -r1.8.16.1 --- squid/include/radix.h 21 Apr 2002 07:41:03 -0000 1.8 +++ squid/include/radix.h 9 Oct 2002 00:23:15 -0000 1.8.16.1 @@ -1,5 +1,5 @@ /* - * $Id: radix.h,v 1.8 2002/04/21 07:41:03 squidadm Exp $ + * $Id: radix.h,v 1.8.16.1 2002/10/09 00:23:15 rbcollins Exp $ */ #ifndef SQUID_RADIX_H @@ -80,7 +80,7 @@ * Annotations to tree concerning potential routes applying to subtrees. */ -extern struct squid_radix_mask { +SQUIDCEXTERN struct squid_radix_mask { short rm_b; /* bit offset; -1-index(netmask) */ char rm_unused; /* cf. rn_bmask */ unsigned char rm_flags; /* cf. rn_flags */ @@ -118,18 +118,18 @@ }; -extern void squid_rn_init (void); -extern int squid_rn_inithead(void **, int); -extern int squid_rn_refines(void *, void *); -extern int squid_rn_walktree(struct squid_radix_node_head *, int (*)(struct squid_radix_node *, void *), void *); -extern struct squid_radix_node *squid_rn_addmask(void *, int, int); -extern struct squid_radix_node *squid_rn_addroute(void *, void *, struct squid_radix_node_head *, struct squid_radix_node[2]); -extern struct squid_radix_node *squid_rn_delete(void *, void *, struct squid_radix_node_head *); -extern struct squid_radix_node *squid_rn_insert(void *, struct squid_radix_node_head *, int *, struct squid_radix_node[2]); -extern struct squid_radix_node *squid_rn_match(void *, struct squid_radix_node_head *); -extern struct squid_radix_node *squid_rn_newpair(void *, int, struct squid_radix_node[2]); -extern struct squid_radix_node *squid_rn_search(void *, struct squid_radix_node *); -extern struct squid_radix_node *squid_rn_search_m(void *, struct squid_radix_node *, void *); -extern struct squid_radix_node *squid_rn_lookup(void *, void *, struct squid_radix_node_head *); +SQUIDCEXTERN void squid_rn_init (void); +SQUIDCEXTERN int squid_rn_inithead(void **, int); +SQUIDCEXTERN int squid_rn_refines(void *, void *); +SQUIDCEXTERN int squid_rn_walktree(struct squid_radix_node_head *, int (*)(struct squid_radix_node *, void *), void *); +SQUIDCEXTERN struct squid_radix_node *squid_rn_addmask(void *, int, int); +SQUIDCEXTERN struct squid_radix_node *squid_rn_addroute(void *, void *, struct squid_radix_node_head *, struct squid_radix_node[2]); +SQUIDCEXTERN struct squid_radix_node *squid_rn_delete(void *, void *, struct squid_radix_node_head *); +SQUIDCEXTERN struct squid_radix_node *squid_rn_insert(void *, struct squid_radix_node_head *, int *, struct squid_radix_node[2]); +SQUIDCEXTERN struct squid_radix_node *squid_rn_match(void *, struct squid_radix_node_head *); +SQUIDCEXTERN struct squid_radix_node *squid_rn_newpair(void *, int, struct squid_radix_node[2]); +SQUIDCEXTERN struct squid_radix_node *squid_rn_search(void *, struct squid_radix_node *); +SQUIDCEXTERN struct squid_radix_node *squid_rn_search_m(void *, struct squid_radix_node *, void *); +SQUIDCEXTERN struct squid_radix_node *squid_rn_lookup(void *, void *, struct squid_radix_node_head *); #endif /* SQUID_RADIX_H */ Index: squid/include/splay.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/splay.h,v retrieving revision 1.6 retrieving revision 1.6.20.1 diff -u -r1.6 -r1.6.20.1 --- squid/include/splay.h 6 Apr 2002 11:34:49 -0000 1.6 +++ squid/include/splay.h 9 Oct 2002 00:23:15 -0000 1.6.20.1 @@ -1,5 +1,5 @@ /* - * $Id: splay.h,v 1.6 2002/04/06 11:34:49 squidadm Exp $ + * $Id: splay.h,v 1.6.20.1 2002/10/09 00:23:15 rbcollins Exp $ */ #ifndef SQUID_SPLAY_H @@ -15,12 +15,12 @@ typedef void SPLAYWALKEE(void *nodedata, void *state); typedef void SPLAYFREE(void *); -extern int splayLastResult; +SQUIDCEXTERN int splayLastResult; -extern splayNode *splay_insert(void *, splayNode *, SPLAYCMP *); -extern splayNode *splay_splay(const void *, splayNode *, SPLAYCMP *); -extern splayNode *splay_delete(const void *, splayNode *, SPLAYCMP *); -extern void splay_destroy(splayNode *, SPLAYFREE *); -extern void splay_walk(splayNode *, SPLAYWALKEE *, void *); +SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, SPLAYCMP *); +SQUIDCEXTERN splayNode *splay_splay(const void *, splayNode *, SPLAYCMP *); +SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, SPLAYCMP *); +SQUIDCEXTERN void splay_destroy(splayNode *, SPLAYFREE *); +SQUIDCEXTERN void splay_walk(splayNode *, SPLAYWALKEE *, void *); #endif /* SQUID_SPLAY_H */ Index: squid/include/util.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/util.h,v retrieving revision 1.11.20.6 retrieving revision 1.11.20.7 diff -u -r1.11.20.6 -r1.11.20.7 --- squid/include/util.h 8 Oct 2002 11:11:34 -0000 1.11.20.6 +++ squid/include/util.h 9 Oct 2002 00:23:15 -0000 1.11.20.7 @@ -1,5 +1,5 @@ /* - * $Id: util.h,v 1.11.20.6 2002/10/08 11:11:34 rbcollins Exp $ + * $Id: util.h,v 1.11.20.7 2002/10/09 00:23:15 rbcollins Exp $ * * AUTHOR: Harvest Derived * @@ -61,7 +61,7 @@ #define _etext etext #endif -extern const char *getfullhostname(void); +SQUIDCEXTERN const char *getfullhostname(void); SQUIDCEXTERN const char *mkhttpdlogtime(const time_t *); SQUIDCEXTERN const char *mkrfc1123(time_t); SQUIDCEXTERN char *uudecode(const char *); Index: squid/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v retrieving revision 1.29.2.15 retrieving revision 1.29.2.16 diff -u -r1.29.2.15 -r1.29.2.16 --- squid/src/Makefile.am 8 Oct 2002 14:57:57 -0000 1.29.2.15 +++ squid/src/Makefile.am 9 Oct 2002 00:23:15 -0000 1.29.2.16 @@ -15,7 +15,7 @@ endif if USE_SNMP -SNMPSOURCE = snmp_core.c snmp_agent.c +SNMPSOURCE = snmp_core.c snmp_agent.cc else SNMPSOURCE = endif @@ -95,21 +95,21 @@ $(UNLINKD) \ cachemgr$(CGIEXT) -cf_gen_SOURCES = cf_gen.c defines.h +cf_gen_SOURCES = cf_gen.cc defines.h nodist_cf_gen_HEADER = cf_gen_defines.h cf_gen.$(OBJEXT): cf_gen_defines.h squidclient_SOURCES = client.cc -cachemgr__CGIEXT__SOURCES = cachemgr.c +cachemgr__CGIEXT__SOURCES = cachemgr.cc EXTRA_squid_SOURCES = \ delay_pools.c \ dns.c \ - dnsserver.c \ + dnsserver.cc \ dns_internal.c \ htcp.cc \ leakfinder.c \ snmp_core.c \ - snmp_agent.c \ + snmp_agent.cc \ unlinkd.cc \ ssl_support.c \ ssl_support.h \ @@ -118,19 +118,19 @@ squid_SOURCES = \ access_log.cc \ acl.cc \ - asn.c \ + asn.cc \ authenticate.cc \ cache_cf.cc \ CacheDigest.cc \ - cache_manager.c \ - carp.c \ - cbdata.c \ - client_db.c \ + cache_manager.cc \ + carp.cc \ + cbdata.cc \ + client_db.cc \ client_side.c \ client_side_reply.cc \ client_side_request.c \ client_side_request.h \ - clientStream.c \ + clientStream.cc \ clientStream.h \ comm.c \ comm_select.c \ @@ -172,7 +172,7 @@ ident.cc \ internal.c \ ipc.c \ - ipcache.c \ + ipcache.cc \ IPInterception.cc \ IPInterception.h \ $(LEAKFINDERSOURCE) \ @@ -213,7 +213,7 @@ store_log.c \ store_rebuild.c \ store_swapin.c \ - store_swapmeta.c \ + store_swapmeta.cc \ store_swapout.c \ structs.h \ tools.c \ @@ -259,6 +259,8 @@ pinger.c \ debug.c +dnsserver_SOURCES = dnsserver.cc + nodist_pinger_SOURCES = \ globals.c --- squid/src/asn.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,475 +0,0 @@ - -/* - * $Id: asn.c,v 1.18.2.1 2002/10/04 07:07:19 rbcollins Exp $ - * - * DEBUG: section 53 AS Number handling - * AUTHOR: Duane Wessels, Kostas Anagnostakis - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "radix.h" -#include "StoreClient.h" -#include "Store.h" - -#define WHOIS_PORT 43 -#define AS_REQBUF_SZ 4096 - -/* BEGIN of definitions for radix tree entries */ - -/* int in memory with length */ -typedef u_char m_int[1 + sizeof(unsigned int)]; -#define store_m_int(i, m) \ - (i = htonl(i), m[0] = sizeof(m_int), xmemcpy(m+1, &i, sizeof(unsigned int))) -#define get_m_int(i, m) \ - (xmemcpy(&i, m+1, sizeof(unsigned int)), ntohl(i)) - -/* END of definitions for radix tree entries */ - -/* Head for ip to asn radix tree */ -struct squid_radix_node_head *AS_tree_head; - -/* - * Structure for as number information. it could be simply - * an intlist but it's coded as a structure for future - * enhancements (e.g. expires) - */ -struct _as_info { - intlist *as_number; - time_t expires; /* NOTUSED */ -}; - -struct _ASState { - StoreEntry *entry; - store_client *sc; - request_t *request; - int as_number; - off_t offset; - int reqofs; - char reqbuf[AS_REQBUF_SZ]; -}; - -typedef struct _ASState ASState; -typedef struct _as_info as_info; - -/* entry into the radix tree */ -struct _rtentry { - struct squid_radix_node e_nodes[2]; - as_info *e_info; - m_int e_addr; - m_int e_mask; -}; - -typedef struct _rtentry rtentry; - -static int asnAddNet(char *, int); -static void asnCacheStart(int as); -static STCB asHandleReply; -static int destroyRadixNode(struct squid_radix_node *rn, void *w); -static int printRadixNode(struct squid_radix_node *rn, void *w); -static void asnAclInitialize(acl * acls); -static void asStateFree(void *data); -static void destroyRadixNodeInfo(as_info *); -static OBJH asnStats; - -/* PUBLIC */ - -int -asnMatchIp(void *data, struct in_addr addr) -{ - unsigned long lh; - struct squid_radix_node *rn; - as_info *e; - m_int m_addr; - intlist *a = NULL; - intlist *b = NULL; - lh = ntohl(addr.s_addr); - debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); - - if (AS_tree_head == NULL) - return 0; - if (addr.s_addr == no_addr.s_addr) - return 0; - if (addr.s_addr == any_addr.s_addr) - return 0; - store_m_int(lh, m_addr); - rn = squid_rn_match(m_addr, AS_tree_head); - if (rn == NULL) { - debug(53, 3) ("asnMatchIp: Address not in as db.\n"); - return 0; - } - debug(53, 3) ("asnMatchIp: Found in db!\n"); - e = ((rtentry *) rn)->e_info; - assert(e); - for (a = (intlist *) data; a; a = a->next) - for (b = e->as_number; b; b = b->next) - if (a->i == b->i) { - debug(53, 5) ("asnMatchIp: Found a match!\n"); - return 1; - } - debug(53, 5) ("asnMatchIp: AS not in as db.\n"); - return 0; -} - -static void -asnAclInitialize(acl * acls) -{ - acl *a; - intlist *i; - debug(53, 3) ("asnAclInitialize\n"); - for (a = acls; a; a = a->next) { - if (a->type != ACL_DST_ASN && a->type != ACL_SRC_ASN) - continue; - for (i = a->data; i; i = i->next) - asnCacheStart(i->i); - } -} - -/* initialize the radix tree structure */ - -extern int squid_max_keylen; /* yuck.. this is in lib/radix.c */ - -CBDATA_TYPE(ASState); -void -asnInit(void) -{ - static int inited = 0; - squid_max_keylen = 40; - CBDATA_INIT_TYPE(ASState); - if (0 == inited++) - squid_rn_init(); - squid_rn_inithead((void **) &AS_tree_head, 8); - asnAclInitialize(Config.aclList); - cachemgrRegister("asndb", "AS Number Database", asnStats, 0, 1); -} - -void -asnFreeMemory(void) -{ - squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head); - destroyRadixNode((struct squid_radix_node *) 0, (void *) AS_tree_head); -} - -static void -asnStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "Address \tAS Numbers\n"); - squid_rn_walktree(AS_tree_head, printRadixNode, sentry); -} - -/* PRIVATE */ - - -static void -asnCacheStart(int as) -{ - LOCAL_ARRAY(char, asres, 4096); - StoreEntry *e; - request_t *req; - ASState *asState; - StoreIOBuffer readBuffer = EMPTYIOBUFFER; - asState = cbdataAlloc(ASState); - debug(53, 3) ("asnCacheStart: AS %d\n", as); - snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as); - asState->as_number = as; - req = urlParse(METHOD_GET, asres); - assert(NULL != req); - asState->request = requestLink(req); - if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { - e = storeCreateEntry(asres, asres, null_request_flags, METHOD_GET); - asState->sc = storeClientListAdd(e, asState); - fwdStart(-1, e, asState->request); - } else { - storeLockObject(e); - asState->sc = storeClientListAdd(e, asState); - } - asState->entry = e; - asState->offset = 0; - asState->reqofs = 0; - readBuffer.offset = asState->offset; - readBuffer.length = AS_REQBUF_SZ; - readBuffer.data = asState->reqbuf; - storeClientCopy(asState->sc, - e, - readBuffer, - asHandleReply, - asState); -} - -static void -asHandleReply(void *data, StoreIOBuffer result) -{ - ASState *asState = data; - StoreEntry *e = asState->entry; - char *s; - char *t; - char *buf = asState->reqbuf; - int leftoversz = -1; - - debug(53, 3) ("asHandleReply: Called with size=%u\n", result.length); - debug(53, 3) ("asHandleReply: buffer='%s'\n", buf); - - /* First figure out whether we should abort the request */ - if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { - asStateFree(asState); - return; - } - if (result.length == 0 && e->mem_obj->inmem_hi > 0) { - asStateFree(asState); - return; - } else if (result.flags.error) { - debug(53, 1) ("asHandleReply: Called with Error set and size=%u\n", result.length); - asStateFree(asState); - return; - } else if (HTTP_OK != e->mem_obj->reply->sline.status) { - debug(53, 1) ("WARNING: AS %d whois request failed\n", - asState->as_number); - asStateFree(asState); - return; - } - /* - * Next, attempt to parse our request - * Remembering that the actual buffer size is retsize + reqofs! - */ - s = buf; - while (s - buf < (result.length + asState->reqofs) && *s != '\0') { - while (*s && xisspace(*s)) - s++; - for (t = s; *t; t++) { - if (xisspace(*t)) - break; - } - if (*t == '\0') { - /* oof, word should continue on next block */ - break; - } - *t = '\0'; - debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s, asState->as_number); - asnAddNet(s, asState->as_number); - s = t + 1; - } - - /* - * Next, grab the end of the 'valid data' in the buffer, and figure - * out how much data is left in our buffer, which we need to keep - * around for the next request - */ - leftoversz = (asState->reqofs + result.length) - (s - buf); - assert(leftoversz >= 0); - - /* - * Next, copy the left over data, from s to s + leftoversz to the - * beginning of the buffer - */ - xmemmove(buf, s, leftoversz); - - /* - * Next, update our offset and reqofs, and kick off a copy if required - */ - asState->offset += result.length; - asState->reqofs = leftoversz; - debug(53, 3) ("asState->offset = %ld\n", (long int) asState->offset); - if (e->store_status == STORE_PENDING) { - StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e)); - tempBuffer.offset = asState->offset; - tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; - tempBuffer.data = asState->reqbuf + asState->reqofs; - storeClientCopy(asState->sc, - e, - tempBuffer, - asHandleReply, - asState); - } else if (asState->offset < e->mem_obj->inmem_hi) { - StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - debug(53, 3) ("asHandleReply: asState->offset < e->mem_obj->inmem_hi %s\n", storeUrl(e)); - tempBuffer.offset = asState->offset; - tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; - tempBuffer.data = asState->reqbuf + asState->reqofs; - storeClientCopy(asState->sc, - e, - tempBuffer, - asHandleReply, - asState); - } else { - debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); - asStateFree(asState); - } -} - -static void -asStateFree(void *data) -{ - ASState *asState = data; - debug(53, 3) ("asnStateFree: %s\n", storeUrl(asState->entry)); - storeUnregister(asState->sc, asState->entry, asState); - storeUnlockObject(asState->entry); - requestUnlink(asState->request); - cbdataFree(asState); -} - - -/* add a network (addr, mask) to the radix tree, with matching AS - * number */ - -static int -asnAddNet(char *as_string, int as_number) -{ - rtentry *e = xmalloc(sizeof(rtentry)); - struct squid_radix_node *rn; - char dbg1[32], dbg2[32]; - intlist **Tail = NULL; - intlist *q = NULL; - as_info *asinfo = NULL; - struct in_addr in_a, in_m; - long mask, addr; - char *t; - int bitl; - - t = strchr(as_string, '/'); - if (t == NULL) { - debug(53, 3) ("asnAddNet: failed, invalid response from whois server.\n"); - return 0; - } - *t = '\0'; - addr = inet_addr(as_string); - bitl = atoi(t + 1); - if (bitl < 0) - bitl = 0; - if (bitl > 32) - bitl = 32; - mask = bitl ? 0xfffffffful << (32 - bitl) : 0; - - in_a.s_addr = addr; - in_m.s_addr = mask; - xstrncpy(dbg1, inet_ntoa(in_a), 32); - xstrncpy(dbg2, inet_ntoa(in_m), 32); - addr = ntohl(addr); - /*mask = ntohl(mask); */ - debug(53, 3) ("asnAddNet: called for %s/%s\n", dbg1, dbg2); - memset(e, '\0', sizeof(rtentry)); - store_m_int(addr, e->e_addr); - store_m_int(mask, e->e_mask); - rn = squid_rn_lookup(e->e_addr, e->e_mask, AS_tree_head); - if (rn != NULL) { - asinfo = ((rtentry *) rn)->e_info; - if (intlistFind(asinfo->as_number, as_number)) { - debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %d\n", - dbg1, bitl, as_number); - } else { - debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!\n"); - for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next); - q = xcalloc(1, sizeof(intlist)); - q->i = as_number; - *(Tail) = q; - e->e_info = asinfo; - } - } else { - q = xcalloc(1, sizeof(intlist)); - q->i = as_number; - asinfo = xmalloc(sizeof(asinfo)); - asinfo->as_number = q; - rn = squid_rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes); - rn = squid_rn_match(e->e_addr, AS_tree_head); - assert(rn != NULL); - e->e_info = asinfo; - } - if (rn == 0) { - xfree(e); - debug(53, 3) ("asnAddNet: Could not add entry.\n"); - return 0; - } - e->e_info = asinfo; - return 1; -} - -static int -destroyRadixNode(struct squid_radix_node *rn, void *w) -{ - struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w; - - if (rn && !(rn->rn_flags & RNF_ROOT)) { - rtentry *e = (rtentry *) rn; - rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh); - if (rn == 0) - debug(53, 3) ("destroyRadixNode: internal screwup\n"); - destroyRadixNodeInfo(e->e_info); - xfree(rn); - } - return 1; -} - -static void -destroyRadixNodeInfo(as_info * e_info) -{ - intlist *prev = NULL; - intlist *data = e_info->as_number; - while (data) { - prev = data; - data = data->next; - xfree(prev); - } - xfree(data); -} - -static int -mask_len(u_long mask) -{ - int len = 32; - if (mask == 0) - return 0; - while ((mask & 1) == 0) { - len--; - mask >>= 1; - } - return len; -} - -static int -printRadixNode(struct squid_radix_node *rn, void *w) -{ - StoreEntry *sentry = w; - rtentry *e = (rtentry *) rn; - intlist *q; - as_info *asinfo; - struct in_addr addr; - struct in_addr mask; - assert(e); - assert(e->e_info); - (void) get_m_int(addr.s_addr, e->e_addr); - (void) get_m_int(mask.s_addr, e->e_mask); - storeAppendPrintf(sentry, "%15s/%d\t", - inet_ntoa(addr), mask_len(ntohl(mask.s_addr))); - asinfo = e->e_info; - assert(asinfo->as_number); - for (q = asinfo->as_number; q; q = q->next) - storeAppendPrintf(sentry, " %d", q->i); - storeAppendPrintf(sentry, "\n"); - return 0; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/asn.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,474 @@ + +/* + * $Id: asn.cc,v 1.1.2.1 2002/10/09 00:23:15 rbcollins Exp $ + * + * DEBUG: section 53 AS Number handling + * AUTHOR: Duane Wessels, Kostas Anagnostakis + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "radix.h" +#include "StoreClient.h" +#include "Store.h" + +#define WHOIS_PORT 43 +#define AS_REQBUF_SZ 4096 + +/* BEGIN of definitions for radix tree entries */ + +/* int in memory with length */ +typedef u_char m_int[1 + sizeof(unsigned int)]; +#define store_m_int(i, m) \ + (i = htonl(i), m[0] = sizeof(m_int), xmemcpy(m+1, &i, sizeof(unsigned int))) +#define get_m_int(i, m) \ + (xmemcpy(&i, m+1, sizeof(unsigned int)), ntohl(i)) + +/* END of definitions for radix tree entries */ + +/* Head for ip to asn radix tree */ +struct squid_radix_node_head *AS_tree_head; + +/* + * Structure for as number information. it could be simply + * an intlist but it's coded as a structure for future + * enhancements (e.g. expires) + */ +struct _as_info { + intlist *as_number; + time_t expires; /* NOTUSED */ +}; + +struct _ASState { + StoreEntry *entry; + store_client *sc; + request_t *request; + int as_number; + off_t offset; + int reqofs; + char reqbuf[AS_REQBUF_SZ]; +}; + +typedef struct _ASState ASState; +typedef struct _as_info as_info; + +/* entry into the radix tree */ +struct _rtentry { + struct squid_radix_node e_nodes[2]; + as_info *e_info; + m_int e_addr; + m_int e_mask; +}; + +typedef struct _rtentry rtentry; + +static int asnAddNet(char *, int); +static void asnCacheStart(int as); +static STCB asHandleReply; +static int destroyRadixNode(struct squid_radix_node *rn, void *w); +static int printRadixNode(struct squid_radix_node *rn, StoreEntry *); +static void asnAclInitialize(acl * acls); +static void asStateFree(void *data); +static void destroyRadixNodeInfo(as_info *); +static OBJH asnStats; + +/* PUBLIC */ + +int +asnMatchIp(void *data, struct in_addr addr) +{ + unsigned long lh; + struct squid_radix_node *rn; + as_info *e; + m_int m_addr; + intlist *a = NULL; + intlist *b = NULL; + lh = ntohl(addr.s_addr); + debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); + + if (AS_tree_head == NULL) + return 0; + if (addr.s_addr == no_addr.s_addr) + return 0; + if (addr.s_addr == any_addr.s_addr) + return 0; + store_m_int(lh, m_addr); + rn = squid_rn_match(m_addr, AS_tree_head); + if (rn == NULL) { + debug(53, 3) ("asnMatchIp: Address not in as db.\n"); + return 0; + } + debug(53, 3) ("asnMatchIp: Found in db!\n"); + e = ((rtentry *) rn)->e_info; + assert(e); + for (a = (intlist *) data; a; a = a->next) + for (b = e->as_number; b; b = b->next) + if (a->i == b->i) { + debug(53, 5) ("asnMatchIp: Found a match!\n"); + return 1; + } + debug(53, 5) ("asnMatchIp: AS not in as db.\n"); + return 0; +} + +static void +asnAclInitialize(acl * acls) +{ + acl *a; + intlist *i; + debug(53, 3) ("asnAclInitialize\n"); + for (a = acls; a; a = a->next) { + if (a->type != ACL_DST_ASN && a->type != ACL_SRC_ASN) + continue; + for (i = (intlist *)a->data; i; i = i->next) + asnCacheStart(i->i); + } +} + +/* initialize the radix tree structure */ + +extern int squid_max_keylen; /* yuck.. this is in lib/radix.c */ + +CBDATA_TYPE(ASState); +void +asnInit(void) +{ + static int inited = 0; + squid_max_keylen = 40; + CBDATA_INIT_TYPE(ASState); + if (0 == inited++) + squid_rn_init(); + squid_rn_inithead((void **) &AS_tree_head, 8); + asnAclInitialize(Config.aclList); + cachemgrRegister("asndb", "AS Number Database", asnStats, 0, 1); +} + +void +asnFreeMemory(void) +{ + squid_rn_walktree(AS_tree_head, destroyRadixNode, AS_tree_head); + destroyRadixNode((struct squid_radix_node *) 0, (void *) AS_tree_head); +} + +static void +asnStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "Address \tAS Numbers\n"); + squid_rn_walktree(AS_tree_head, printRadixNode, sentry); +} + +/* PRIVATE */ + + +static void +asnCacheStart(int as) +{ + LOCAL_ARRAY(char, asres, 4096); + StoreEntry *e; + request_t *req; + ASState *asState; + StoreIOBuffer readBuffer = EMPTYIOBUFFER; + asState = cbdataAlloc(ASState); + debug(53, 3) ("asnCacheStart: AS %d\n", as); + snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as); + asState->as_number = as; + req = urlParse(METHOD_GET, asres); + assert(NULL != req); + asState->request = requestLink(req); + if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { + e = storeCreateEntry(asres, asres, null_request_flags, METHOD_GET); + asState->sc = storeClientListAdd(e, asState); + fwdStart(-1, e, asState->request); + } else { + storeLockObject(e); + asState->sc = storeClientListAdd(e, asState); + } + asState->entry = e; + asState->offset = 0; + asState->reqofs = 0; + readBuffer.offset = asState->offset; + readBuffer.length = AS_REQBUF_SZ; + readBuffer.data = asState->reqbuf; + storeClientCopy(asState->sc, + e, + readBuffer, + asHandleReply, + asState); +} + +static void +asHandleReply(void *data, StoreIOBuffer result) +{ + ASState *asState = (ASState *)data; + StoreEntry *e = asState->entry; + char *s; + char *t; + char *buf = asState->reqbuf; + int leftoversz = -1; + + debug(53, 3) ("asHandleReply: Called with size=%u\n", result.length); + debug(53, 3) ("asHandleReply: buffer='%s'\n", buf); + + /* First figure out whether we should abort the request */ + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { + asStateFree(asState); + return; + } + if (result.length == 0 && e->mem_obj->inmem_hi > 0) { + asStateFree(asState); + return; + } else if (result.flags.error) { + debug(53, 1) ("asHandleReply: Called with Error set and size=%u\n", result.length); + asStateFree(asState); + return; + } else if (HTTP_OK != e->mem_obj->reply->sline.status) { + debug(53, 1) ("WARNING: AS %d whois request failed\n", + asState->as_number); + asStateFree(asState); + return; + } + /* + * Next, attempt to parse our request + * Remembering that the actual buffer size is retsize + reqofs! + */ + s = buf; + while (s - buf < (off_t)(result.length + asState->reqofs) && *s != '\0') { + while (*s && xisspace(*s)) + s++; + for (t = s; *t; t++) { + if (xisspace(*t)) + break; + } + if (*t == '\0') { + /* oof, word should continue on next block */ + break; + } + *t = '\0'; + debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s, asState->as_number); + asnAddNet(s, asState->as_number); + s = t + 1; + } + + /* + * Next, grab the end of the 'valid data' in the buffer, and figure + * out how much data is left in our buffer, which we need to keep + * around for the next request + */ + leftoversz = (asState->reqofs + result.length) - (s - buf); + assert(leftoversz >= 0); + + /* + * Next, copy the left over data, from s to s + leftoversz to the + * beginning of the buffer + */ + xmemmove(buf, s, leftoversz); + + /* + * Next, update our offset and reqofs, and kick off a copy if required + */ + asState->offset += result.length; + asState->reqofs = leftoversz; + debug(53, 3) ("asState->offset = %ld\n", (long int) asState->offset); + if (e->store_status == STORE_PENDING) { + StoreIOBuffer tempBuffer = EMPTYIOBUFFER; + debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e)); + tempBuffer.offset = asState->offset; + tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; + tempBuffer.data = asState->reqbuf + asState->reqofs; + storeClientCopy(asState->sc, + e, + tempBuffer, + asHandleReply, + asState); + } else if (asState->offset < e->mem_obj->inmem_hi) { + StoreIOBuffer tempBuffer = EMPTYIOBUFFER; + debug(53, 3) ("asHandleReply: asState->offset < e->mem_obj->inmem_hi %s\n", storeUrl(e)); + tempBuffer.offset = asState->offset; + tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; + tempBuffer.data = asState->reqbuf + asState->reqofs; + storeClientCopy(asState->sc, + e, + tempBuffer, + asHandleReply, + asState); + } else { + debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); + asStateFree(asState); + } +} + +static void +asStateFree(void *data) +{ + ASState *asState = (ASState *)data; + debug(53, 3) ("asnStateFree: %s\n", storeUrl(asState->entry)); + storeUnregister(asState->sc, asState->entry, asState); + storeUnlockObject(asState->entry); + requestUnlink(asState->request); + cbdataFree(asState); +} + + +/* add a network (addr, mask) to the radix tree, with matching AS + * number */ + +static int +asnAddNet(char *as_string, int as_number) +{ + rtentry *e = (rtentry *)xmalloc(sizeof(rtentry)); + struct squid_radix_node *rn; + char dbg1[32], dbg2[32]; + intlist **Tail = NULL; + intlist *q = NULL; + as_info *asinfo = NULL; + struct in_addr in_a, in_m; + long mask, addr; + char *t; + int bitl; + + t = strchr(as_string, '/'); + if (t == NULL) { + debug(53, 3) ("asnAddNet: failed, invalid response from whois server.\n"); + return 0; + } + *t = '\0'; + addr = inet_addr(as_string); + bitl = atoi(t + 1); + if (bitl < 0) + bitl = 0; + if (bitl > 32) + bitl = 32; + mask = bitl ? 0xfffffffful << (32 - bitl) : 0; + + in_a.s_addr = addr; + in_m.s_addr = mask; + xstrncpy(dbg1, inet_ntoa(in_a), 32); + xstrncpy(dbg2, inet_ntoa(in_m), 32); + addr = ntohl(addr); + /*mask = ntohl(mask); */ + debug(53, 3) ("asnAddNet: called for %s/%s\n", dbg1, dbg2); + memset(e, '\0', sizeof(rtentry)); + store_m_int(addr, e->e_addr); + store_m_int(mask, e->e_mask); + rn = squid_rn_lookup(e->e_addr, e->e_mask, AS_tree_head); + if (rn != NULL) { + asinfo = ((rtentry *) rn)->e_info; + if (intlistFind(asinfo->as_number, as_number)) { + debug(53, 3) ("asnAddNet: Ignoring repeated network '%s/%d' for AS %d\n", + dbg1, bitl, as_number); + } else { + debug(53, 3) ("asnAddNet: Warning: Found a network with multiple AS numbers!\n"); + for (Tail = &asinfo->as_number; *Tail; Tail = &(*Tail)->next); + q = (intlist *)xcalloc(1, sizeof(intlist)); + q->i = as_number; + *(Tail) = q; + e->e_info = asinfo; + } + } else { + q = (intlist *)xcalloc(1, sizeof(intlist)); + q->i = as_number; + asinfo = (as_info *)xmalloc(sizeof(asinfo)); + asinfo->as_number = q; + rn = squid_rn_addroute(e->e_addr, e->e_mask, AS_tree_head, e->e_nodes); + rn = squid_rn_match(e->e_addr, AS_tree_head); + assert(rn != NULL); + e->e_info = asinfo; + } + if (rn == 0) { + xfree(e); + debug(53, 3) ("asnAddNet: Could not add entry.\n"); + return 0; + } + e->e_info = asinfo; + return 1; +} + +static int +destroyRadixNode(struct squid_radix_node *rn, void *w) +{ + struct squid_radix_node_head *rnh = (struct squid_radix_node_head *) w; + + if (rn && !(rn->rn_flags & RNF_ROOT)) { + rtentry *e = (rtentry *) rn; + rn = squid_rn_delete(rn->rn_key, rn->rn_mask, rnh); + if (rn == 0) + debug(53, 3) ("destroyRadixNode: internal screwup\n"); + destroyRadixNodeInfo(e->e_info); + xfree(rn); + } + return 1; +} + +static void +destroyRadixNodeInfo(as_info * e_info) +{ + intlist *prev = NULL; + intlist *data = e_info->as_number; + while (data) { + prev = data; + data = data->next; + xfree(prev); + } + xfree(data); +} + +static int +mask_len(u_long mask) +{ + int len = 32; + if (mask == 0) + return 0; + while ((mask & 1) == 0) { + len--; + mask >>= 1; + } + return len; +} + +static int +printRadixNode(struct squid_radix_node *rn, StoreEntry *sentry) +{ + rtentry *e = (rtentry *) rn; + intlist *q; + as_info *asinfo; + struct in_addr addr; + struct in_addr mask; + assert(e); + assert(e->e_info); + (void) get_m_int(addr.s_addr, e->e_addr); + (void) get_m_int(mask.s_addr, e->e_mask); + storeAppendPrintf(sentry, "%15s/%d\t", + inet_ntoa(addr), mask_len(ntohl(mask.s_addr))); + asinfo = e->e_info; + assert(asinfo->as_number); + for (q = asinfo->as_number; q; q = q->next) + storeAppendPrintf(sentry, " %d", q->i); + storeAppendPrintf(sentry, "\n"); + return 0; +} --- squid/src/cache_diff.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,292 +0,0 @@ - -/* - * $Id: cache_diff.c,v 1.7 2002/09/01 16:30:41 squidadm Exp $ - * - * AUTHOR: Alex Rousskov - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/* - * Computes the difference between the contents of two caches - * using swap logs - * Reports the percentage of common files and other stats - */ - -#include "squid.h" - -typedef struct { - const char *name; - hash_table *hash; - int count; /* #currently cached entries */ - int scanned_count; /* #scanned entries */ - int bad_add_count; /* #duplicate adds */ - int bad_del_count; /* #dels with no prior add */ -} CacheIndex; - - -typedef struct _CacheEntry { - const cache_key *key; - struct _CacheEntry *next; - /* storeSwapLogData s; */ - unsigned char key_arr[MD5_DIGEST_CHARS]; -} CacheEntry; - - -/* copied from url.c */ -const char *RequestMethodStr[] = -{ - "NONE", - "GET", - "POST", - "PUT", - "HEAD", - "CONNECT", - "TRACE", - "PURGE" -}; - - -static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file); - - -static CacheEntry * -cacheEntryCreate(const storeSwapLogData * s) -{ - CacheEntry *e = xcalloc(1, sizeof(CacheEntry)); - assert(s); - /* e->s = *s; */ - xmemcpy(e->key_arr, s->key, MD5_DIGEST_CHARS); - e->key = &e->key_arr[0]; - return e; -} - -static void -cacheEntryDestroy(CacheEntry * e) -{ - assert(e); - xfree(e); -} - -static CacheIndex * -cacheIndexCreate(const char *name) -{ - CacheIndex *idx; - if (!name || !strlen(name)) - return NULL; - - idx = xcalloc(1, sizeof(CacheIndex)); - idx->name = name; - idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash); - - return idx; -} - -static void -cacheIndexDestroy(CacheIndex * idx) -{ - hash_link *hashr = NULL; - if (idx) { - /* destroy hash list contents */ - hash_first(idx->hash); - while (hashr = hash_next(idx->hash)) { - hash_remove_link(idx->hash, hashr); - cacheEntryDestroy((CacheEntry *) hashr); - } - /* destroy the hash table itself */ - hashFreeMemory(idx->hash); - xfree(idx); - } -} - -static int -cacheIndexAddLog(CacheIndex * idx, const char *fname) -{ - FILE *file; - int scanned_count = 0; - assert(idx); - assert(fname && strlen(fname)); - - file = fopen(fname, "r"); - if (!file) { - fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); - return 0; - } -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(fileno(file), O_BINARY); -#endif - scanned_count = cacheIndexScan(idx, fname, file); - - fclose(file); - return scanned_count; -} - -static void -cacheIndexInitReport(CacheIndex * idx) -{ - assert(idx); - fprintf(stderr, "%s: bad swap_add: %d\n", - idx->name, idx->bad_add_count); - fprintf(stderr, "%s: bad swap_del: %d\n", - idx->name, idx->bad_del_count); - fprintf(stderr, "%s: scanned lines: %d\n", - idx->name, idx->scanned_count); -} - -static int -cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file) -{ - int count = 0; - storeSwapLogData s; - fprintf(stderr, "%s scanning\n", fname); - while (fread(&s, sizeof(s), 1, file) == 1) { - count++; - idx->scanned_count++; - /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX) - * continue; */ - if (s.op == SWAP_LOG_ADD) { - CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); - if (olde) { - idx->bad_add_count++; - } else { - CacheEntry *e = cacheEntryCreate(&s); - hash_join(idx->hash, &e->hash); - idx->count++; - } - } else if (s.op == SWAP_LOG_DEL) { - CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); - if (!olde) - idx->bad_del_count++; - else { - assert(idx->count); - hash_remove_link(idx->hash, (hash_link *) olde); - cacheEntryDestroy(olde); - idx->count--; - } - } else { - fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); - exit(-3); - } - } - fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n", - fname, count, (int) (count * sizeof(CacheEntry))); - return count; -} - -static void -cacheIndexCmpReport(CacheIndex * idx, int shared_count) -{ - assert(idx && shared_count <= idx->count); - - printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n", - idx->name, - idx->count, - idx->count - shared_count, - shared_count, - xpercent(idx->count - shared_count, idx->count), - xpercent(shared_count, idx->count)); -} - -static void -cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2) -{ - int shared_count = 0; - int hashed_count = 0; - hash_link *hashr = NULL; - CacheIndex *small_idx = idx1; - CacheIndex *large_idx = idx2; - assert(idx1 && idx2); - - /* check our guess */ - if (idx1->count > idx2->count) { - small_idx = idx2; - large_idx = idx1; - } - /* find shared_count */ - hash_first(small_idx->hash); - for (hashr = hash_next(small_idx->hash)) { - hashed_count++; - if (hash_lookup(large_idx->hash, hashr->key)) - shared_count++; - } - assert(hashed_count == small_idx->count); - - cacheIndexCmpReport(idx1, shared_count); - cacheIndexCmpReport(idx2, shared_count); -} - - -static int -usage(const char *prg_name) -{ - fprintf(stderr, "usage: %s : ... : ...\n", - prg_name); - return -1; -} - -int -main(int argc, char *argv[]) -{ - CacheIndex *CacheIdx[2]; - CacheIndex *idx = NULL; - int idxCount = 0; - int i; - - if (argc < 5) - return usage(argv[0]); - - for (i = 1; i < argc; ++i) { - const int len = strlen(argv[i]); - if (!len) - return usage(argv[0]); - if (argv[i][len - 1] == ':') { - idxCount++; - if (len < 2 || idxCount > 2) - return usage(argv[0]); - idx = cacheIndexCreate(argv[i]); - CacheIdx[idxCount - 1] = idx; - } else { - if (!idx) - return usage(argv[0]); - cacheIndexAddLog(idx, argv[i]); - } - } - - if (idxCount != 2) - return usage(argv[0]); - - cacheIndexInitReport(CacheIdx[0]); - cacheIndexInitReport(CacheIdx[1]); - - cacheIndexCmp(CacheIdx[0], CacheIdx[1]); - - cacheIndexDestroy(CacheIdx[0]); - cacheIndexDestroy(CacheIdx[1]); - - return 1; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/cache_diff.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,292 @@ + +/* + * $Id: cache_diff.cc,v 1.1.2.1 2002/10/09 00:23:15 rbcollins Exp $ + * + * AUTHOR: Alex Rousskov + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * Computes the difference between the contents of two caches + * using swap logs + * Reports the percentage of common files and other stats + */ + +#include "squid.h" + +typedef struct { + const char *name; + hash_table *hash; + int count; /* #currently cached entries */ + int scanned_count; /* #scanned entries */ + int bad_add_count; /* #duplicate adds */ + int bad_del_count; /* #dels with no prior add */ +} CacheIndex; + + +typedef struct _CacheEntry { + const cache_key *key; + struct _CacheEntry *next; + /* storeSwapLogData s; */ + unsigned char key_arr[MD5_DIGEST_CHARS]; +} CacheEntry; + + +/* copied from url.c */ +const char *RequestMethodStr[] = +{ + "NONE", + "GET", + "POST", + "PUT", + "HEAD", + "CONNECT", + "TRACE", + "PURGE" +}; + + +static int cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file); + + +static CacheEntry * +cacheEntryCreate(const storeSwapLogData * s) +{ + CacheEntry *e = xcalloc(1, sizeof(CacheEntry)); + assert(s); + /* e->s = *s; */ + xmemcpy(e->key_arr, s->key, MD5_DIGEST_CHARS); + e->key = &e->key_arr[0]; + return e; +} + +static void +cacheEntryDestroy(CacheEntry * e) +{ + assert(e); + xfree(e); +} + +static CacheIndex * +cacheIndexCreate(const char *name) +{ + CacheIndex *idx; + if (!name || !strlen(name)) + return NULL; + + idx = xcalloc(1, sizeof(CacheIndex)); + idx->name = name; + idx->hash = hash_create(storeKeyHashCmp, 2e6, storeKeyHashHash); + + return idx; +} + +static void +cacheIndexDestroy(CacheIndex * idx) +{ + hash_link *hashr = NULL; + if (idx) { + /* destroy hash list contents */ + hash_first(idx->hash); + while (hashr = hash_next(idx->hash)) { + hash_remove_link(idx->hash, hashr); + cacheEntryDestroy((CacheEntry *) hashr); + } + /* destroy the hash table itself */ + hashFreeMemory(idx->hash); + xfree(idx); + } +} + +static int +cacheIndexAddLog(CacheIndex * idx, const char *fname) +{ + FILE *file; + int scanned_count = 0; + assert(idx); + assert(fname && strlen(fname)); + + file = fopen(fname, "r"); + if (!file) { + fprintf(stderr, "cannot open %s: %s\n", fname, strerror(errno)); + return 0; + } +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(fileno(file), O_BINARY); +#endif + scanned_count = cacheIndexScan(idx, fname, file); + + fclose(file); + return scanned_count; +} + +static void +cacheIndexInitReport(CacheIndex * idx) +{ + assert(idx); + fprintf(stderr, "%s: bad swap_add: %d\n", + idx->name, idx->bad_add_count); + fprintf(stderr, "%s: bad swap_del: %d\n", + idx->name, idx->bad_del_count); + fprintf(stderr, "%s: scanned lines: %d\n", + idx->name, idx->scanned_count); +} + +static int +cacheIndexScan(CacheIndex * idx, const char *fname, FILE * file) +{ + int count = 0; + storeSwapLogData s; + fprintf(stderr, "%s scanning\n", fname); + while (fread(&s, sizeof(s), 1, file) == 1) { + count++; + idx->scanned_count++; + /* if (s.op <= SWAP_LOG_NOP || s.op >= SWAP_LOG_MAX) + * continue; */ + if (s.op == SWAP_LOG_ADD) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + if (olde) { + idx->bad_add_count++; + } else { + CacheEntry *e = cacheEntryCreate(&s); + hash_join(idx->hash, &e->hash); + idx->count++; + } + } else if (s.op == SWAP_LOG_DEL) { + CacheEntry *olde = (CacheEntry *) hash_lookup(idx->hash, s.key); + if (!olde) + idx->bad_del_count++; + else { + assert(idx->count); + hash_remove_link(idx->hash, (hash_link *) olde); + cacheEntryDestroy(olde); + idx->count--; + } + } else { + fprintf(stderr, "%s:%d: unknown swap log action\n", fname, count); + exit(-3); + } + } + fprintf(stderr, "%s:%d: scanned (size: %d bytes)\n", + fname, count, (int) (count * sizeof(CacheEntry))); + return count; +} + +static void +cacheIndexCmpReport(CacheIndex * idx, int shared_count) +{ + assert(idx && shared_count <= idx->count); + + printf("%s:\t %7d = %7d + %7d (%7.2f%% + %7.2f%%)\n", + idx->name, + idx->count, + idx->count - shared_count, + shared_count, + xpercent(idx->count - shared_count, idx->count), + xpercent(shared_count, idx->count)); +} + +static void +cacheIndexCmp(CacheIndex * idx1, CacheIndex * idx2) +{ + int shared_count = 0; + int hashed_count = 0; + hash_link *hashr = NULL; + CacheIndex *small_idx = idx1; + CacheIndex *large_idx = idx2; + assert(idx1 && idx2); + + /* check our guess */ + if (idx1->count > idx2->count) { + small_idx = idx2; + large_idx = idx1; + } + /* find shared_count */ + hash_first(small_idx->hash); + for (hashr = hash_next(small_idx->hash)) { + hashed_count++; + if (hash_lookup(large_idx->hash, hashr->key)) + shared_count++; + } + assert(hashed_count == small_idx->count); + + cacheIndexCmpReport(idx1, shared_count); + cacheIndexCmpReport(idx2, shared_count); +} + + +static int +usage(const char *prg_name) +{ + fprintf(stderr, "usage: %s : ... : ...\n", + prg_name); + return -1; +} + +int +main(int argc, char *argv[]) +{ + CacheIndex *CacheIdx[2]; + CacheIndex *idx = NULL; + int idxCount = 0; + int i; + + if (argc < 5) + return usage(argv[0]); + + for (i = 1; i < argc; ++i) { + const int len = strlen(argv[i]); + if (!len) + return usage(argv[0]); + if (argv[i][len - 1] == ':') { + idxCount++; + if (len < 2 || idxCount > 2) + return usage(argv[0]); + idx = cacheIndexCreate(argv[i]); + CacheIdx[idxCount - 1] = idx; + } else { + if (!idx) + return usage(argv[0]); + cacheIndexAddLog(idx, argv[i]); + } + } + + if (idxCount != 2) + return usage(argv[0]); + + cacheIndexInitReport(CacheIdx[0]); + cacheIndexInitReport(CacheIdx[1]); + + cacheIndexCmp(CacheIdx[0], CacheIdx[1]); + + cacheIndexDestroy(CacheIdx[0]); + cacheIndexDestroy(CacheIdx[1]); + + return 1; +} --- squid/src/cache_manager.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,350 +0,0 @@ - -/* - * $Id: cache_manager.c,v 1.7.84.1 2002/10/04 07:07:20 rbcollins Exp $ - * - * DEBUG: section 16 Cache Manager Objects - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -#define MGR_PASSWD_SZ 128 - -typedef struct { - StoreEntry *entry; - char *action; - char *user_name; - char *passwd; -} cachemgrStateData; - -typedef struct _action_table { - char *action; - char *desc; - OBJH *handler; - struct { - unsigned int pw_req:1; - unsigned int atomic:1; - } flags; - struct _action_table *next; -} action_table; - -static action_table *cachemgrFindAction(const char *action); -static cachemgrStateData *cachemgrParseUrl(const char *url); -static void cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request); -static int cachemgrCheckPassword(cachemgrStateData *); -static void cachemgrStateFree(cachemgrStateData * mgr); -static char *cachemgrPasswdGet(cachemgr_passwd *, const char *); -static const char *cachemgrActionProtection(const action_table * at); -static OBJH cachemgrShutdown; -static OBJH cachemgrMenu; -static OBJH cachemgrOfflineToggle; - -action_table *ActionTable = NULL; - -void -cachemgrRegister(const char *action, const char *desc, OBJH * handler, int pw_req_flag, int atomic) -{ - action_table *a; - action_table **A; - if (cachemgrFindAction(action) != NULL) { - debug(16, 3) ("cachemgrRegister: Duplicate '%s'\n", action); - return; - } - a = xcalloc(1, sizeof(action_table)); - a->action = xstrdup(action); - a->desc = xstrdup(desc); - a->handler = handler; - a->flags.pw_req = pw_req_flag; - a->flags.atomic = atomic; - for (A = &ActionTable; *A; A = &(*A)->next); - *A = a; - debug(16, 3) ("cachemgrRegister: registered %s\n", action); -} - -static action_table * -cachemgrFindAction(const char *action) -{ - action_table *a; - for (a = ActionTable; a != NULL; a = a->next) { - if (0 == strcmp(a->action, action)) - return a; - } - return NULL; -} - -static cachemgrStateData * -cachemgrParseUrl(const char *url) -{ - int t; - LOCAL_ARRAY(char, host, MAX_URL); - LOCAL_ARRAY(char, request, MAX_URL); - LOCAL_ARRAY(char, password, MAX_URL); - action_table *a; - cachemgrStateData *mgr = NULL; - const char *prot; - t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password); - if (t < 2) { - xstrncpy(request, "menu", MAX_URL); -#ifdef _SQUID_OS2_ - /* - * emx's sscanf insists of returning 2 because it sets request - * to null - */ - } else if (request[0] == '\0') { - xstrncpy(request, "menu", MAX_URL); -#endif - } else if ((a = cachemgrFindAction(request)) == NULL) { - debug(16, 1) ("cachemgrParseUrl: action '%s' not found\n", request); - return NULL; - } else { - prot = cachemgrActionProtection(a); - if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { - debug(16, 1) ("cachemgrParseUrl: action '%s' is %s\n", request, prot); - return NULL; - } - } - /* set absent entries to NULL so we can test if they are present later */ - mgr = xcalloc(1, sizeof(cachemgrStateData)); - mgr->user_name = NULL; - mgr->passwd = t == 3 ? xstrdup(password) : NULL; - mgr->action = xstrdup(request); - return mgr; -} - -static void -cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request) -{ - const char *basic_cookie; /* base 64 _decoded_ user:passwd pair */ - const char *passwd_del; - assert(mgr && request); - basic_cookie = httpHeaderGetAuth(&request->header, HDR_AUTHORIZATION, "Basic"); - if (!basic_cookie) - return; - if (!(passwd_del = strchr(basic_cookie, ':'))) { - debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie format '%s'\n", basic_cookie); - return; - } - /* found user:password pair, reset old values */ - safe_free(mgr->user_name); - safe_free(mgr->passwd); - mgr->user_name = xstrdup(basic_cookie); - mgr->user_name[passwd_del - basic_cookie] = '\0'; - mgr->passwd = xstrdup(passwd_del + 1); - /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */ - debug(16, 9) ("cachemgrParseHeaders: got user: '%s' passwd: '%s'\n", mgr->user_name, mgr->passwd); -} - -/* - * return 0 if mgr->password is good - */ -static int -cachemgrCheckPassword(cachemgrStateData * mgr) -{ - char *pwd = cachemgrPasswdGet(Config.passwd_list, mgr->action); - action_table *a = cachemgrFindAction(mgr->action); - assert(a != NULL); - if (pwd == NULL) - return a->flags.pw_req; - if (strcmp(pwd, "disable") == 0) - return 1; - if (strcmp(pwd, "none") == 0) - return 0; - if (!mgr->passwd) - return 1; - return strcmp(pwd, mgr->passwd); -} - -static void -cachemgrStateFree(cachemgrStateData * mgr) -{ - safe_free(mgr->action); - safe_free(mgr->user_name); - safe_free(mgr->passwd); - storeUnlockObject(mgr->entry); - xfree(mgr); -} - -void -cachemgrStart(int fd, request_t * request, StoreEntry * entry) -{ - cachemgrStateData *mgr = NULL; - ErrorState *err = NULL; - action_table *a; - debug(16, 3) ("objectcacheStart: '%s'\n", storeUrl(entry)); - if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) { - err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND); - err->url = xstrdup(storeUrl(entry)); - errorAppendEntry(entry, err); - entry->expires = squid_curtime; - return; - } - mgr->entry = entry; - storeLockObject(entry); - entry->expires = squid_curtime; - debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", - fd_table[fd].ipaddr, mgr->action); - /* get additional info from request headers */ - cachemgrParseHeaders(mgr, request); - /* Check password */ - if (cachemgrCheckPassword(mgr) != 0) { - /* build error message */ - ErrorState *err; - HttpReply *rep; - err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED); - /* warn if user specified incorrect password */ - if (mgr->passwd) - debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); - else - debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); - err->request = requestLink(request); - rep = errorBuildReply(err); - errorStateFree(err); - /* - * add Authenticate header, use 'action' as a realm because - * password depends on action - */ - httpHeaderPutAuth(&rep->header, "Basic", mgr->action); - /* move info to the mem_obj->reply */ - httpReplyAbsorb(entry->mem_obj->reply, rep); - /* store the reply */ - httpReplySwapOut(entry->mem_obj->reply, entry); - entry->expires = squid_curtime; - storeComplete(entry); - cachemgrStateFree(mgr); - return; - } - debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n", - mgr->user_name ? mgr->user_name : "", - fd_table[fd].ipaddr, mgr->action); - /* retrieve object requested */ - a = cachemgrFindAction(mgr->action); - assert(a != NULL); - if (a->flags.atomic) - storeBuffer(entry); - { - http_version_t version; - HttpReply *rep = entry->mem_obj->reply; - /* prove there are no previous reply headers around */ - assert(0 == rep->sline.status); - httpBuildVersion(&version, 1, 0); - httpReplySetHeaders(rep, - version, - HTTP_OK, - NULL, - "text/plain", - -1, /* C-Len */ - squid_curtime, /* LMT */ - squid_curtime); - httpReplySwapOut(rep, entry); - } - a->handler(entry); - if (a->flags.atomic) { - storeBufferFlush(entry); - storeComplete(entry); - } - cachemgrStateFree(mgr); -} - -static void -cachemgrShutdown(StoreEntry * entryunused) -{ - debug(16, 0) ("Shutdown by command.\n"); - shut_down(0); -} - -static void -cachemgrOfflineToggle(StoreEntry * sentry) -{ - Config.onoff.offline = !Config.onoff.offline; - debug(16, 0) ("offline_mode now %s.\n", - Config.onoff.offline ? "ON" : "OFF"); - storeAppendPrintf(sentry, "offline_mode is now %s\n", - Config.onoff.offline ? "ON" : "OFF"); -} - -static const char * -cachemgrActionProtection(const action_table * at) -{ - char *pwd; - assert(at); - pwd = cachemgrPasswdGet(Config.passwd_list, at->action); - if (!pwd) - return at->flags.pw_req ? "hidden" : "public"; - if (!strcmp(pwd, "disable")) - return "disabled"; - if (strcmp(pwd, "none") == 0) - return "public"; - return "protected"; -} - -static void -cachemgrMenu(StoreEntry * sentry) -{ - action_table *a; - for (a = ActionTable; a != NULL; a = a->next) { - storeAppendPrintf(sentry, " %-22s\t%s\t%s\n", - a->action, a->desc, cachemgrActionProtection(a)); - } -} - -static char * -cachemgrPasswdGet(cachemgr_passwd * a, const char *action) -{ - wordlist *w; - while (a != NULL) { - for (w = a->actions; w != NULL; w = w->next) { - if (0 == strcmp(w->key, action)) - return a->passwd; - if (0 == strcmp(w->key, "all")) - return a->passwd; - } - a = a->next; - } - return NULL; -} - -void -cachemgrInit(void) -{ - cachemgrRegister("menu", - "This Cachemanager Menu", - cachemgrMenu, 0, 1); - cachemgrRegister("shutdown", - "Shut Down the Squid Process", - cachemgrShutdown, 1, 1); - cachemgrRegister("offline_toggle", - "Toggle offline_mode setting", - cachemgrOfflineToggle, 1, 1); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/cache_manager.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,350 @@ + +/* + * $Id: cache_manager.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 16 Cache Manager Objects + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + +#define MGR_PASSWD_SZ 128 + +typedef struct { + StoreEntry *entry; + char *action; + char *user_name; + char *passwd; +} cachemgrStateData; + +typedef struct _action_table { + char *action; + char *desc; + OBJH *handler; + struct { + unsigned int pw_req:1; + unsigned int atomic:1; + } flags; + struct _action_table *next; +} action_table; + +static action_table *cachemgrFindAction(const char *action); +static cachemgrStateData *cachemgrParseUrl(const char *url); +static void cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request); +static int cachemgrCheckPassword(cachemgrStateData *); +static void cachemgrStateFree(cachemgrStateData * mgr); +static char *cachemgrPasswdGet(cachemgr_passwd *, const char *); +static const char *cachemgrActionProtection(const action_table * at); +static OBJH cachemgrShutdown; +static OBJH cachemgrMenu; +static OBJH cachemgrOfflineToggle; + +action_table *ActionTable = NULL; + +void +cachemgrRegister(const char *action, const char *desc, OBJH * handler, int pw_req_flag, int atomic) +{ + action_table *a; + action_table **A; + if (cachemgrFindAction(action) != NULL) { + debug(16, 3) ("cachemgrRegister: Duplicate '%s'\n", action); + return; + } + a = (action_table *)xcalloc(1, sizeof(action_table)); + a->action = xstrdup(action); + a->desc = xstrdup(desc); + a->handler = handler; + a->flags.pw_req = pw_req_flag; + a->flags.atomic = atomic; + for (A = &ActionTable; *A; A = &(*A)->next); + *A = a; + debug(16, 3) ("cachemgrRegister: registered %s\n", action); +} + +static action_table * +cachemgrFindAction(const char *action) +{ + action_table *a; + for (a = ActionTable; a != NULL; a = a->next) { + if (0 == strcmp(a->action, action)) + return a; + } + return NULL; +} + +static cachemgrStateData * +cachemgrParseUrl(const char *url) +{ + int t; + LOCAL_ARRAY(char, host, MAX_URL); + LOCAL_ARRAY(char, request, MAX_URL); + LOCAL_ARRAY(char, password, MAX_URL); + action_table *a; + cachemgrStateData *mgr = NULL; + const char *prot; + t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password); + if (t < 2) { + xstrncpy(request, "menu", MAX_URL); +#ifdef _SQUID_OS2_ + /* + * emx's sscanf insists of returning 2 because it sets request + * to null + */ + } else if (request[0] == '\0') { + xstrncpy(request, "menu", MAX_URL); +#endif + } else if ((a = cachemgrFindAction(request)) == NULL) { + debug(16, 1) ("cachemgrParseUrl: action '%s' not found\n", request); + return NULL; + } else { + prot = cachemgrActionProtection(a); + if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { + debug(16, 1) ("cachemgrParseUrl: action '%s' is %s\n", request, prot); + return NULL; + } + } + /* set absent entries to NULL so we can test if they are present later */ + mgr = (cachemgrStateData *)xcalloc(1, sizeof(cachemgrStateData)); + mgr->user_name = NULL; + mgr->passwd = t == 3 ? xstrdup(password) : NULL; + mgr->action = xstrdup(request); + return mgr; +} + +static void +cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request) +{ + const char *basic_cookie; /* base 64 _decoded_ user:passwd pair */ + const char *passwd_del; + assert(mgr && request); + basic_cookie = httpHeaderGetAuth(&request->header, HDR_AUTHORIZATION, "Basic"); + if (!basic_cookie) + return; + if (!(passwd_del = strchr(basic_cookie, ':'))) { + debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie format '%s'\n", basic_cookie); + return; + } + /* found user:password pair, reset old values */ + safe_free(mgr->user_name); + safe_free(mgr->passwd); + mgr->user_name = xstrdup(basic_cookie); + mgr->user_name[passwd_del - basic_cookie] = '\0'; + mgr->passwd = xstrdup(passwd_del + 1); + /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */ + debug(16, 9) ("cachemgrParseHeaders: got user: '%s' passwd: '%s'\n", mgr->user_name, mgr->passwd); +} + +/* + * return 0 if mgr->password is good + */ +static int +cachemgrCheckPassword(cachemgrStateData * mgr) +{ + char *pwd = cachemgrPasswdGet(Config.passwd_list, mgr->action); + action_table *a = cachemgrFindAction(mgr->action); + assert(a != NULL); + if (pwd == NULL) + return a->flags.pw_req; + if (strcmp(pwd, "disable") == 0) + return 1; + if (strcmp(pwd, "none") == 0) + return 0; + if (!mgr->passwd) + return 1; + return strcmp(pwd, mgr->passwd); +} + +static void +cachemgrStateFree(cachemgrStateData * mgr) +{ + safe_free(mgr->action); + safe_free(mgr->user_name); + safe_free(mgr->passwd); + storeUnlockObject(mgr->entry); + xfree(mgr); +} + +void +cachemgrStart(int fd, request_t * request, StoreEntry * entry) +{ + cachemgrStateData *mgr = NULL; + ErrorState *err = NULL; + action_table *a; + debug(16, 3) ("objectcacheStart: '%s'\n", storeUrl(entry)); + if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) { + err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND); + err->url = xstrdup(storeUrl(entry)); + errorAppendEntry(entry, err); + entry->expires = squid_curtime; + return; + } + mgr->entry = entry; + storeLockObject(entry); + entry->expires = squid_curtime; + debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", + fd_table[fd].ipaddr, mgr->action); + /* get additional info from request headers */ + cachemgrParseHeaders(mgr, request); + /* Check password */ + if (cachemgrCheckPassword(mgr) != 0) { + /* build error message */ + ErrorState *err; + HttpReply *rep; + err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED); + /* warn if user specified incorrect password */ + if (mgr->passwd) + debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); + else + debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); + err->request = requestLink(request); + rep = errorBuildReply(err); + errorStateFree(err); + /* + * add Authenticate header, use 'action' as a realm because + * password depends on action + */ + httpHeaderPutAuth(&rep->header, "Basic", mgr->action); + /* move info to the mem_obj->reply */ + httpReplyAbsorb(entry->mem_obj->reply, rep); + /* store the reply */ + httpReplySwapOut(entry->mem_obj->reply, entry); + entry->expires = squid_curtime; + storeComplete(entry); + cachemgrStateFree(mgr); + return; + } + debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n", + mgr->user_name ? mgr->user_name : "", + fd_table[fd].ipaddr, mgr->action); + /* retrieve object requested */ + a = cachemgrFindAction(mgr->action); + assert(a != NULL); + if (a->flags.atomic) + storeBuffer(entry); + { + http_version_t version; + HttpReply *rep = entry->mem_obj->reply; + /* prove there are no previous reply headers around */ + assert(0 == rep->sline.status); + httpBuildVersion(&version, 1, 0); + httpReplySetHeaders(rep, + version, + HTTP_OK, + NULL, + "text/plain", + -1, /* C-Len */ + squid_curtime, /* LMT */ + squid_curtime); + httpReplySwapOut(rep, entry); + } + a->handler(entry); + if (a->flags.atomic) { + storeBufferFlush(entry); + storeComplete(entry); + } + cachemgrStateFree(mgr); +} + +static void +cachemgrShutdown(StoreEntry * entryunused) +{ + debug(16, 0) ("Shutdown by command.\n"); + shut_down(0); +} + +static void +cachemgrOfflineToggle(StoreEntry * sentry) +{ + Config.onoff.offline = !Config.onoff.offline; + debug(16, 0) ("offline_mode now %s.\n", + Config.onoff.offline ? "ON" : "OFF"); + storeAppendPrintf(sentry, "offline_mode is now %s\n", + Config.onoff.offline ? "ON" : "OFF"); +} + +static const char * +cachemgrActionProtection(const action_table * at) +{ + char *pwd; + assert(at); + pwd = cachemgrPasswdGet(Config.passwd_list, at->action); + if (!pwd) + return at->flags.pw_req ? "hidden" : "public"; + if (!strcmp(pwd, "disable")) + return "disabled"; + if (strcmp(pwd, "none") == 0) + return "public"; + return "protected"; +} + +static void +cachemgrMenu(StoreEntry * sentry) +{ + action_table *a; + for (a = ActionTable; a != NULL; a = a->next) { + storeAppendPrintf(sentry, " %-22s\t%s\t%s\n", + a->action, a->desc, cachemgrActionProtection(a)); + } +} + +static char * +cachemgrPasswdGet(cachemgr_passwd * a, const char *action) +{ + wordlist *w; + while (a != NULL) { + for (w = a->actions; w != NULL; w = w->next) { + if (0 == strcmp(w->key, action)) + return a->passwd; + if (0 == strcmp(w->key, "all")) + return a->passwd; + } + a = a->next; + } + return NULL; +} + +void +cachemgrInit(void) +{ + cachemgrRegister("menu", + "This Cachemanager Menu", + cachemgrMenu, 0, 1); + cachemgrRegister("shutdown", + "Shut Down the Squid Process", + cachemgrShutdown, 1, 1); + cachemgrRegister("offline_toggle", + "Toggle offline_mode setting", + cachemgrOfflineToggle, 1, 1); +} --- squid/src/cachemgr.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,753 +0,0 @@ - -/* - * $Id: cachemgr.c,v 1.13 2002/09/01 16:30:41 squidadm Exp $ - * - * DEBUG: section 0 CGI Cache Manager - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "config.h" - -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_STDIO_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_CTYPE_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_FCNTL_H -#include -#endif -#if HAVE_GRP_H -#include -#endif -#if HAVE_GNUMALLOC_H -#include -#elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) -#include -#endif -#if HAVE_MEMORY_H -#include -#endif -#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */ -#define _SQUID_NETDB_H_ -#include -#endif -#if HAVE_PWD_H -#include -#endif -#if HAVE_SIGNAL_H -#include -#endif -#if HAVE_TIME_H -#include -#endif -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_TIME_H -#include -#endif -#if HAVE_SYS_RESOURCE_H -#include /* needs sys/time.h above it */ -#endif -#if HAVE_SYS_SOCKET_H -#include -#endif -#if HAVE_NETINET_IN_H -#include -#endif -#if HAVE_ARPA_INET_H -#include -#endif -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_UN_H -#include -#endif -#if HAVE_SYS_WAIT_H -#include -#endif -#if HAVE_LIBC_H -#include -#endif -#if HAVE_STRING_H -#include -#endif -#if HAVE_STRINGS_H -#include -#endif -#if HAVE_BSTRING_H -#include -#endif -#if HAVE_CRYPT_H -#include -#endif -#if HAVE_SYS_SELECT_H -#include -#endif - -#include - -#include "util.h" -#include "snprintf.h" - -typedef struct { - char *hostname; - int port; - char *action; - char *user_name; - char *passwd; - char *pub_auth; -} cachemgr_request; - -/* - * Debugging macros (info goes to error_log on your web server) - * Note: do not run cache manager with non zero debugging level - * if you do not debug, it may write a lot of [sensitive] - * information to your error log. - */ - -/* debugging level 0 (disabled) - 3 (max) */ -#define DEBUG_LEVEL 0 -#define debug(level) if ((level) <= DEBUG_LEVEL && DEBUG_LEVEL > 0) - -/* - * Static variables and constants - */ -static const time_t passwd_ttl = 60 * 60 * 3; /* in sec */ -static const char *script_name = "/cgi-bin/cachemgr.cgi"; -static const char *progname = NULL; -static time_t now; -static struct in_addr no_addr; - -/* - * Function prototypes - */ -#define safe_free(str) { if (str) { xfree(str); (str) = NULL; } } -static const char *safe_str(const char *str); -static const char *xstrtok(char **str, char del); -static void print_trailer(void); -static void auth_html(const char *host, int port, const char *user_name); -static void error_html(const char *msg); -static char *menu_url(cachemgr_request * req, const char *action); -static int parse_status_line(const char *sline, const char **statusStr); -static cachemgr_request *read_request(void); -static char *read_get_request(void); -static char *read_post_request(void); - -static void make_pub_auth(cachemgr_request * req); -static void decode_pub_auth(cachemgr_request * req); -static void reset_auth(cachemgr_request * req); -static const char *make_auth_header(const cachemgr_request * req); - - -static const char * -safe_str(const char *str) -{ - return str ? str : ""; -} - -/* relaxed number format */ -static int -is_number(const char *str) -{ - return strspn(str, "\t -+01234567890./\n") == strlen(str); -} - -static const char * -xstrtok(char **str, char del) -{ - if (*str) { - char *p = strchr(*str, del); - char *tok = *str; - int len; - if (p) { - *str = p + 1; - *p = '\0'; - } else - *str = NULL; - /* trim */ - len = strlen(tok); - while (len && xisspace(tok[len - 1])) - tok[--len] = '\0'; - while (xisspace(*tok)) - tok++; - return tok; - } else - return ""; -} - -static void -print_trailer(void) -{ - printf("
\n"); - printf("
\n"); - printf("Generated %s, by %s/%s@%s\n", - mkrfc1123(now), progname, VERSION, getfullhostname()); - printf("
\n"); -} - -static void -auth_html(const char *host, int port, const char *user_name) -{ - if (!user_name) - user_name = ""; - if (!host || !strlen(host)) - host = "localhost"; - printf("Content-Type: text/html\r\n\r\n"); - printf("\n"); - printf("Cache Manager Interface\n"); - printf("\n"); - printf("

Cache Manager Interface

\n"); - printf("

This is a WWW interface to the instrumentation interface\n"); - printf("for the Squid object cache.

\n"); - printf("
\n"); - printf("
\n", script_name); - printf("\n"); - printf("\n", host); - printf("\n", port); - printf("\n", user_name); - printf("\n"); - printf("
Cache Host:
Cache Port:
Manager name:
Password:

\n"); - printf("\n"); - printf("
\n"); - print_trailer(); -} - -static void -error_html(const char *msg) -{ - printf("Content-Type: text/html\r\n\r\n"); - printf("\n"); - printf("Cache Manager Error\n"); - printf("\n"); - printf("

Cache Manager Error

\n"); - printf("

\n%s

\n", msg); - print_trailer(); -} - -/* returns http status extracted from status line or -1 on parsing failure */ -static int -parse_status_line(const char *sline, const char **statusStr) -{ - const char *sp = strchr(sline, ' '); - if (statusStr) - *statusStr = NULL; - if (strncasecmp(sline, "HTTP/", 5) || !sp) - return -1; - while (xisspace(*++sp)); - if (!xisdigit(*sp)) - return -1; - if (statusStr) - *statusStr = sp; - return atoi(sp); -} - -static char * -menu_url(cachemgr_request * req, const char *action) -{ - static char url[1024]; - snprintf(url, sizeof(url), "%s?host=%s&port=%d&user_name=%s&operation=%s&auth=%s", - script_name, - req->hostname, - req->port, - safe_str(req->user_name), - action, - safe_str(req->pub_auth)); - return url; -} - -static const char * -munge_menu_line(const char *buf, cachemgr_request * req) -{ - char *x; - const char *a; - const char *d; - const char *p; - char *a_url; - char *buf_copy; - static char html[2 * 1024]; - if (strlen(buf) < 1) - return buf; - if (*buf != ' ') - return buf; - buf_copy = x = xstrdup(buf); - a = xstrtok(&x, '\t'); - d = xstrtok(&x, '\t'); - p = xstrtok(&x, '\t'); - a_url = xstrdup(menu_url(req, a)); - /* no reason to give a url for a disabled action */ - if (!strcmp(p, "disabled")) - snprintf(html, sizeof(html), "
  • %s (disabled).\n", d, a_url); - else - /* disable a hidden action (requires a password, but password is not in squid.conf) */ - if (!strcmp(p, "hidden")) - snprintf(html, sizeof(html), "
  • %s (hidden).\n", d, a_url); - else - /* disable link if authentication is required and we have no password */ - if (!strcmp(p, "protected") && !req->passwd) - snprintf(html, sizeof(html), "
  • %s (requires authentication).\n", - d, menu_url(req, "authenticate"), a_url); - else - /* highlight protected but probably available entries */ - if (!strcmp(p, "protected")) - snprintf(html, sizeof(html), "
  • %s\n", - a_url, d); - /* public entry or unknown type of protection */ - else - snprintf(html, sizeof(html), "
  • %s\n", a_url, d); - xfree(a_url); - xfree(buf_copy); - return html; -} - -static const char * -munge_other_line(const char *buf, cachemgr_request * req) -{ - static const char *ttags[] = - {"td", "th"}; - static char html[4096]; - static int table_line_num = 0; - static int next_is_header = 0; - int is_header = 0; - const char *ttag; - char *buf_copy; - char *x, *p; - int l = 0; - /* does it look like a table? */ - if (!strchr(buf, '\t') || *buf == '\t') { - /* nope, just text */ - snprintf(html, sizeof(html), "%s%s", - table_line_num ? "\n
    " : "", buf);
    -	table_line_num = 0;
    -	return html;
    -    }
    -    /* start html table */
    -    if (!table_line_num) {
    -	l += snprintf(html + l, sizeof(html) - l, "
    \n"); - next_is_header = 0; - } - /* remove '\n' */ - is_header = (!table_line_num || next_is_header) && !strchr(buf, ':') && !is_number(buf); - ttag = ttags[is_header]; - /* record starts */ - l += snprintf(html + l, sizeof(html) - l, ""); - /* substitute '\t' */ - buf_copy = x = xstrdup(buf); - if ((p = strchr(x, '\n'))) - *p = '\0'; - while (x && strlen(x)) { - int column_span = 1; - const char *cell = xstrtok(&x, '\t'); - while (x && *x == '\t') { - column_span++; - x++; - } - l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s", - ttag, column_span, - is_header ? "center" : is_number(cell) ? "right" : "left", - cell, ttag); - } - xfree(buf_copy); - /* record ends */ - l += snprintf(html + l, sizeof(html) - l, "\n"); - next_is_header = is_header && strstr(buf, "\t\t"); - table_line_num++; - return html; -} - -static int -read_reply(int s, cachemgr_request * req) -{ - char buf[4 * 1024]; - FILE *fp = fdopen(s, "r"); - /* interpretation states */ - enum { - isStatusLine, isHeaders, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError - } istate = isStatusLine; - int parse_menu = 0; - const char *action = req->action; - const char *statusStr = NULL; - int status = -1; - if (0 == strlen(req->action)) - parse_menu = 1; - else if (0 == strcasecmp(req->action, "menu")) - parse_menu = 1; - if (fp == NULL) { - perror("fdopen"); - return 1; - } - if (parse_menu) - action = "menu"; - /* read reply interpreting one line at a time depending on state */ - while (istate < isEof) { - if (!fgets(buf, sizeof(buf), fp)) - istate = istate == isForward ? isForwardEof : isEof; - switch (istate) { - case isStatusLine: - /* get HTTP status */ - /* uncomment the following if you want to debug headers */ - /* fputs("\r\n\r\n", stdout); */ - status = parse_status_line(buf, &statusStr); - istate = status == 200 ? isHeaders : isForward; - /* if cache asks for authentication, we have to reset our info */ - if (status == 401 || status == 407) { - reset_auth(req); - status = 403; /* Forbiden, see comments in case isForward: */ - } - /* this is a way to pass HTTP status to the Web server */ - if (statusStr) - printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */ - break; - case isHeaders: - /* forward header field */ - if (!strcmp(buf, "\r\n")) { /* end of headers */ - fputs("Content-Type: text/html\r\n", stdout); /* add our type */ - istate = isBodyStart; - } - if (strncasecmp(buf, "Content-Type:", 13)) /* filter out their type */ - fputs(buf, stdout); - break; - case isBodyStart: - printf("\n"); - printf("CacheMgr@%s: %s\n", - req->hostname, action); - printf("\n"); - printf("\n"); - if (parse_menu) { - printf("

    Cache Manager menu for %s:

    ", - menu_url(req, "authenticate"), req->hostname); - printf("
      \n"); - } else { - printf("

      %s\n


      \n", - menu_url(req, "menu"), "Cache Manager menu"); - printf("
      \n");
      -	    }
      -	    istate = isBody;
      -	    /* yes, fall through, we do not want to loose the first line */
      -	case isBody:
      -	    /* interpret [and reformat] cache response */
      -	    if (parse_menu)
      -		fputs(munge_menu_line(buf, req), stdout);
      -	    else
      -		fputs(munge_other_line(buf, req), stdout);
      -	    break;
      -	case isForward:
      -	    /* forward: no modifications allowed */
      -	    /*
      -	     * Note: we currently do not know any way to get browser.reply to
      -	     * 401 to .cgi because web server filters out all auth info. Thus we
      -	     * disable authentication headers for now.
      -	     */
      -	    if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));	/* skip */
      -	    else
      -		fputs(buf, stdout);
      -	    break;
      -	case isEof:
      -	    /* print trailers */
      -	    if (parse_menu)
      -		printf("
    \n"); - else - printf("
    \n"); - print_trailer(); - istate = isSuccess; - break; - case isForwardEof: - /* indicate that we finished processing an "error" sequence */ - istate = isError; - break; - default: - printf("%s: internal bug: invalid state reached: %d", script_name, istate); - istate = isError; - } - } - close(s); - return 0; -} - -static int -process_request(cachemgr_request * req) -{ - const struct hostent *hp; - static struct sockaddr_in S; - int s; - int l; - static char buf[2 * 1024]; - if (req == NULL) { - auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, ""); - return 1; - } - if (req->hostname == NULL) { - req->hostname = xstrdup(CACHEMGR_HOSTNAME); - } - if (req->port == 0) { - req->port = CACHE_HTTP_PORT; - } - if (req->action == NULL) { - req->action = xstrdup(""); - } - if (!strcmp(req->action, "authenticate")) { - auth_html(req->hostname, req->port, req->user_name); - return 0; - } - if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - snprintf(buf, 1024, "socket: %s\n", xstrerror()); - error_html(buf); - return 1; - } - memset(&S, '\0', sizeof(struct sockaddr_in)); - S.sin_family = AF_INET; - if ((hp = gethostbyname(req->hostname)) != NULL) { - assert(hp->h_length <= sizeof(S.sin_addr.s_addr)); - xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); - } else if (safe_inet_addr(req->hostname, &S.sin_addr)) - (void) 0; - else { - snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); - error_html(buf); - return 1; - } - S.sin_port = htons(req->port); - if (connect(s, (struct sockaddr *) &S, sizeof(struct sockaddr_in)) < 0) { - snprintf(buf, 1024, "connect: %s\n", xstrerror()); - error_html(buf); - return 1; - } - l = snprintf(buf, sizeof(buf), - "GET cache_object://%s/%s HTTP/1.0\r\n" - "Accept: */*\r\n" - "%s" /* Authentication info or nothing */ - "\r\n", - req->hostname, - req->action, - make_auth_header(req)); - write(s, buf, l); - debug(1) fprintf(stderr, "wrote request: '%s'\n", buf); - return read_reply(s, req); -} - -int -main(int argc, char *argv[]) -{ - char *s; - cachemgr_request *req; - safe_inet_addr("255.255.255.255", &no_addr); - now = time(NULL); - if ((s = strrchr(argv[0], '/'))) - progname = xstrdup(s + 1); - else - progname = xstrdup(argv[0]); - if ((s = getenv("SCRIPT_NAME")) != NULL) - script_name = xstrdup(s); - req = read_request(); - return process_request(req); -} - -static char * -read_post_request(void) -{ - char *s; - char *buf; - int len; - if ((s = getenv("REQUEST_METHOD")) == NULL) - return NULL; - if (0 != strcasecmp(s, "POST")) - return NULL; - if ((s = getenv("CONTENT_LENGTH")) == NULL) - return NULL; - if ((len = atoi(s)) <= 0) - return NULL; - buf = xmalloc(len + 1); - fread(buf, len, 1, stdin); - buf[len] = '\0'; - return buf; -} - -static char * -read_get_request(void) -{ - char *s; - if ((s = getenv("QUERY_STRING")) == NULL) - return NULL; - return xstrdup(s); -} - -static cachemgr_request * -read_request(void) -{ - char *buf; - cachemgr_request *req; - char *s; - char *t; - char *q; - if ((buf = read_post_request()) != NULL) - (void) 0; - else if ((buf = read_get_request()) != NULL) - (void) 0; - else - return NULL; - if (strlen(buf) == 0) - return NULL; - req = xcalloc(1, sizeof(cachemgr_request)); - for (s = strtok(buf, "&"); s != NULL; s = strtok(NULL, "&")) { - t = xstrdup(s); - if ((q = strchr(t, '=')) == NULL) - continue; - *q++ = '\0'; - if (0 == strcasecmp(t, "host") && strlen(q)) - req->hostname = xstrdup(q); - else if (0 == strcasecmp(t, "port") && strlen(q)) - req->port = atoi(q); - else if (0 == strcasecmp(t, "user_name") && strlen(q)) - req->user_name = xstrdup(q); - else if (0 == strcasecmp(t, "passwd") && strlen(q)) - req->passwd = xstrdup(q); - else if (0 == strcasecmp(t, "auth") && strlen(q)) - req->pub_auth = xstrdup(q), decode_pub_auth(req); - else if (0 == strcasecmp(t, "operation")) - req->action = xstrdup(q); - } - make_pub_auth(req); - debug(1) fprintf(stderr, "cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s'\n", - safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action)); - return req; -} - - -/* Routines to support authentication */ - -/* - * Encodes auth info into a "public" form. - * Currently no powerful encryption is used. - */ -static void -make_pub_auth(cachemgr_request * req) -{ - static char buf[1024]; - safe_free(req->pub_auth); - debug(3) fprintf(stderr, "cmgr: encoding for pub...\n"); - if (!req->passwd || !strlen(req->passwd)) - return; - /* host | time | user | passwd */ - snprintf(buf, sizeof(buf), "%s|%d|%s|%s", - req->hostname, - (int) now, - req->user_name ? req->user_name : "", - req->passwd); - debug(3) fprintf(stderr, "cmgr: pre-encoded for pub: %s\n", buf); - debug(3) fprintf(stderr, "cmgr: encoded: '%s'\n", base64_encode(buf)); - req->pub_auth = xstrdup(base64_encode(buf)); -} - -static void -decode_pub_auth(cachemgr_request * req) -{ - char *buf; - const char *host_name; - const char *time_str; - const char *user_name; - const char *passwd; - - debug(2) fprintf(stderr, "cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); - safe_free(req->passwd); - if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname))) - return; - buf = xstrdup(base64_decode(req->pub_auth)); - debug(3) fprintf(stderr, "cmgr: length ok\n"); - /* parse ( a lot of memory leaks, but that is cachemgr style :) */ - if ((host_name = strtok(buf, "|")) == NULL) - return; - debug(3) fprintf(stderr, "cmgr: decoded host: '%s'\n", host_name); - if ((time_str = strtok(NULL, "|")) == NULL) - return; - debug(3) fprintf(stderr, "cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); - if ((user_name = strtok(NULL, "|")) == NULL) - return; - debug(3) fprintf(stderr, "cmgr: decoded uname: '%s'\n", user_name); - if ((passwd = strtok(NULL, "|")) == NULL) - return; - debug(2) fprintf(stderr, "cmgr: decoded passwd: '%s'\n", passwd); - /* verify freshness and validity */ - if (atoi(time_str) + passwd_ttl < now) - return; - if (strcasecmp(host_name, req->hostname)) - return; - debug(1) fprintf(stderr, "cmgr: verified auth. info.\n"); - /* ok, accept */ - xfree(req->user_name); - req->user_name = xstrdup(user_name); - req->passwd = xstrdup(passwd); - xfree(buf); -} - -static void -reset_auth(cachemgr_request * req) -{ - safe_free(req->passwd); - safe_free(req->pub_auth); -} - -static const char * -make_auth_header(const cachemgr_request * req) -{ - static char buf[1024]; - off_t l = 0; - const char *str64; - if (!req->passwd) - return ""; - - snprintf(buf, sizeof(buf), "%s:%s", - req->user_name ? req->user_name : "", - req->passwd); - - str64 = base64_encode(buf); - l += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); - assert(l < sizeof(buf)); - l += snprintf(&buf[l], sizeof(buf) - l, - "Proxy-Authorization: Basic %s\r\n", str64); - return buf; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/cachemgr.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,753 @@ + +/* + * $Id: cachemgr.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 0 CGI Cache Manager + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" + +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_GRP_H +#include +#endif +#if HAVE_GNUMALLOC_H +#include +#elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) +#include +#endif +#if HAVE_MEMORY_H +#include +#endif +#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */ +#define _SQUID_NETDB_H_ +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include /* needs sys/time.h above it */ +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_UN_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif +#if HAVE_LIBC_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_STRINGS_H +#include +#endif +#if HAVE_BSTRING_H +#include +#endif +#if HAVE_CRYPT_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif + +#include + +#include "util.h" +#include "snprintf.h" + +typedef struct { + char *hostname; + int port; + char *action; + char *user_name; + char *passwd; + char *pub_auth; +} cachemgr_request; + +/* + * Debugging macros (info goes to error_log on your web server) + * Note: do not run cache manager with non zero debugging level + * if you do not debug, it may write a lot of [sensitive] + * information to your error log. + */ + +/* debugging level 0 (disabled) - 3 (max) */ +#define DEBUG_LEVEL 0 +#define debug(level) if ((level) <= DEBUG_LEVEL && DEBUG_LEVEL > 0) + +/* + * Static variables and constants + */ +static const time_t passwd_ttl = 60 * 60 * 3; /* in sec */ +static const char *script_name = "/cgi-bin/cachemgr.cgi"; +static const char *progname = NULL; +static time_t now; +static struct in_addr no_addr; + +/* + * Function prototypes + */ +#define safe_free(str) { if (str) { xfree(str); (str) = NULL; } } +static const char *safe_str(const char *str); +static const char *xstrtok(char **str, char del); +static void print_trailer(void); +static void auth_html(const char *host, int port, const char *user_name); +static void error_html(const char *msg); +static char *menu_url(cachemgr_request * req, const char *action); +static int parse_status_line(const char *sline, const char **statusStr); +static cachemgr_request *read_request(void); +static char *read_get_request(void); +static char *read_post_request(void); + +static void make_pub_auth(cachemgr_request * req); +static void decode_pub_auth(cachemgr_request * req); +static void reset_auth(cachemgr_request * req); +static const char *make_auth_header(const cachemgr_request * req); + + +static const char * +safe_str(const char *str) +{ + return str ? str : ""; +} + +/* relaxed number format */ +static int +is_number(const char *str) +{ + return strspn(str, "\t -+01234567890./\n") == strlen(str); +} + +static const char * +xstrtok(char **str, char del) +{ + if (*str) { + char *p = strchr(*str, del); + char *tok = *str; + int len; + if (p) { + *str = p + 1; + *p = '\0'; + } else + *str = NULL; + /* trim */ + len = strlen(tok); + while (len && xisspace(tok[len - 1])) + tok[--len] = '\0'; + while (xisspace(*tok)) + tok++; + return tok; + } else + return ""; +} + +static void +print_trailer(void) +{ + printf("
    \n"); + printf("
    \n"); + printf("Generated %s, by %s/%s@%s\n", + mkrfc1123(now), progname, VERSION, getfullhostname()); + printf("
    \n"); +} + +static void +auth_html(const char *host, int port, const char *user_name) +{ + if (!user_name) + user_name = ""; + if (!host || !strlen(host)) + host = "localhost"; + printf("Content-Type: text/html\r\n\r\n"); + printf("\n"); + printf("Cache Manager Interface\n"); + printf("\n"); + printf("

    Cache Manager Interface

    \n"); + printf("

    This is a WWW interface to the instrumentation interface\n"); + printf("for the Squid object cache.

    \n"); + printf("
    \n"); + printf("
    \n", script_name); + printf("\n"); + printf("\n", host); + printf("\n", port); + printf("\n", user_name); + printf("\n"); + printf("
    Cache Host:
    Cache Port:
    Manager name:
    Password:

    \n"); + printf("\n"); + printf("
    \n"); + print_trailer(); +} + +static void +error_html(const char *msg) +{ + printf("Content-Type: text/html\r\n\r\n"); + printf("\n"); + printf("Cache Manager Error\n"); + printf("\n"); + printf("

    Cache Manager Error

    \n"); + printf("

    \n%s

    \n", msg); + print_trailer(); +} + +/* returns http status extracted from status line or -1 on parsing failure */ +static int +parse_status_line(const char *sline, const char **statusStr) +{ + const char *sp = strchr(sline, ' '); + if (statusStr) + *statusStr = NULL; + if (strncasecmp(sline, "HTTP/", 5) || !sp) + return -1; + while (xisspace(*++sp)); + if (!xisdigit(*sp)) + return -1; + if (statusStr) + *statusStr = sp; + return atoi(sp); +} + +static char * +menu_url(cachemgr_request * req, const char *action) +{ + static char url[1024]; + snprintf(url, sizeof(url), "%s?host=%s&port=%d&user_name=%s&operation=%s&auth=%s", + script_name, + req->hostname, + req->port, + safe_str(req->user_name), + action, + safe_str(req->pub_auth)); + return url; +} + +static const char * +munge_menu_line(const char *buf, cachemgr_request * req) +{ + char *x; + const char *a; + const char *d; + const char *p; + char *a_url; + char *buf_copy; + static char html[2 * 1024]; + if (strlen(buf) < 1) + return buf; + if (*buf != ' ') + return buf; + buf_copy = x = xstrdup(buf); + a = xstrtok(&x, '\t'); + d = xstrtok(&x, '\t'); + p = xstrtok(&x, '\t'); + a_url = xstrdup(menu_url(req, a)); + /* no reason to give a url for a disabled action */ + if (!strcmp(p, "disabled")) + snprintf(html, sizeof(html), "
  • %s (disabled).\n", d, a_url); + else + /* disable a hidden action (requires a password, but password is not in squid.conf) */ + if (!strcmp(p, "hidden")) + snprintf(html, sizeof(html), "
  • %s (hidden).\n", d, a_url); + else + /* disable link if authentication is required and we have no password */ + if (!strcmp(p, "protected") && !req->passwd) + snprintf(html, sizeof(html), "
  • %s (requires authentication).\n", + d, menu_url(req, "authenticate"), a_url); + else + /* highlight protected but probably available entries */ + if (!strcmp(p, "protected")) + snprintf(html, sizeof(html), "
  • %s\n", + a_url, d); + /* public entry or unknown type of protection */ + else + snprintf(html, sizeof(html), "
  • %s\n", a_url, d); + xfree(a_url); + xfree(buf_copy); + return html; +} + +static const char * +munge_other_line(const char *buf, cachemgr_request * req) +{ + static const char *ttags[] = + {"td", "th"}; + static char html[4096]; + static int table_line_num = 0; + static int next_is_header = 0; + int is_header = 0; + const char *ttag; + char *buf_copy; + char *x, *p; + int l = 0; + /* does it look like a table? */ + if (!strchr(buf, '\t') || *buf == '\t') { + /* nope, just text */ + snprintf(html, sizeof(html), "%s%s", + table_line_num ? "\n
    " : "", buf);
    +	table_line_num = 0;
    +	return html;
    +    }
    +    /* start html table */
    +    if (!table_line_num) {
    +	l += snprintf(html + l, sizeof(html) - l, "
    \n"); + next_is_header = 0; + } + /* remove '\n' */ + is_header = (!table_line_num || next_is_header) && !strchr(buf, ':') && !is_number(buf); + ttag = ttags[is_header]; + /* record starts */ + l += snprintf(html + l, sizeof(html) - l, ""); + /* substitute '\t' */ + buf_copy = x = xstrdup(buf); + if ((p = strchr(x, '\n'))) + *p = '\0'; + while (x && strlen(x)) { + int column_span = 1; + const char *cell = xstrtok(&x, '\t'); + while (x && *x == '\t') { + column_span++; + x++; + } + l += snprintf(html + l, sizeof(html) - l, "<%s colspan=\"%d\" align=\"%s\">%s", + ttag, column_span, + is_header ? "center" : is_number(cell) ? "right" : "left", + cell, ttag); + } + xfree(buf_copy); + /* record ends */ + l += snprintf(html + l, sizeof(html) - l, "\n"); + next_is_header = is_header && strstr(buf, "\t\t"); + table_line_num++; + return html; +} + +static int +read_reply(int s, cachemgr_request * req) +{ + char buf[4 * 1024]; + FILE *fp = fdopen(s, "r"); + /* interpretation states */ + enum { + isStatusLine, isHeaders, isBodyStart, isBody, isForward, isEof, isForwardEof, isSuccess, isError + } istate = isStatusLine; + int parse_menu = 0; + const char *action = req->action; + const char *statusStr = NULL; + int status = -1; + if (0 == strlen(req->action)) + parse_menu = 1; + else if (0 == strcasecmp(req->action, "menu")) + parse_menu = 1; + if (fp == NULL) { + perror("fdopen"); + return 1; + } + if (parse_menu) + action = "menu"; + /* read reply interpreting one line at a time depending on state */ + while (istate < isEof) { + if (!fgets(buf, sizeof(buf), fp)) + istate = istate == isForward ? isForwardEof : isEof; + switch (istate) { + case isStatusLine: + /* get HTTP status */ + /* uncomment the following if you want to debug headers */ + /* fputs("\r\n\r\n", stdout); */ + status = parse_status_line(buf, &statusStr); + istate = status == 200 ? isHeaders : isForward; + /* if cache asks for authentication, we have to reset our info */ + if (status == 401 || status == 407) { + reset_auth(req); + status = 403; /* Forbiden, see comments in case isForward: */ + } + /* this is a way to pass HTTP status to the Web server */ + if (statusStr) + printf("Status: %d %s", status, statusStr); /* statusStr has '\n' */ + break; + case isHeaders: + /* forward header field */ + if (!strcmp(buf, "\r\n")) { /* end of headers */ + fputs("Content-Type: text/html\r\n", stdout); /* add our type */ + istate = isBodyStart; + } + if (strncasecmp(buf, "Content-Type:", 13)) /* filter out their type */ + fputs(buf, stdout); + break; + case isBodyStart: + printf("\n"); + printf("CacheMgr@%s: %s\n", + req->hostname, action); + printf("\n"); + printf("\n"); + if (parse_menu) { + printf("

    Cache Manager menu for %s:

    ", + menu_url(req, "authenticate"), req->hostname); + printf("
      \n"); + } else { + printf("

      %s\n


      \n", + menu_url(req, "menu"), "Cache Manager menu"); + printf("
      \n");
      +	    }
      +	    istate = isBody;
      +	    /* yes, fall through, we do not want to loose the first line */
      +	case isBody:
      +	    /* interpret [and reformat] cache response */
      +	    if (parse_menu)
      +		fputs(munge_menu_line(buf, req), stdout);
      +	    else
      +		fputs(munge_other_line(buf, req), stdout);
      +	    break;
      +	case isForward:
      +	    /* forward: no modifications allowed */
      +	    /*
      +	     * Note: we currently do not know any way to get browser.reply to
      +	     * 401 to .cgi because web server filters out all auth info. Thus we
      +	     * disable authentication headers for now.
      +	     */
      +	    if (!strncasecmp(buf, "WWW-Authenticate:", 17) || !strncasecmp(buf, "Proxy-Authenticate:", 19));	/* skip */
      +	    else
      +		fputs(buf, stdout);
      +	    break;
      +	case isEof:
      +	    /* print trailers */
      +	    if (parse_menu)
      +		printf("
    \n"); + else + printf("
    \n"); + print_trailer(); + istate = isSuccess; + break; + case isForwardEof: + /* indicate that we finished processing an "error" sequence */ + istate = isError; + break; + default: + printf("%s: internal bug: invalid state reached: %d", script_name, istate); + istate = isError; + } + } + close(s); + return 0; +} + +static int +process_request(cachemgr_request * req) +{ + const struct hostent *hp; + static struct sockaddr_in S; + int s; + int l; + static char buf[2 * 1024]; + if (req == NULL) { + auth_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT, ""); + return 1; + } + if (req->hostname == NULL) { + req->hostname = xstrdup(CACHEMGR_HOSTNAME); + } + if (req->port == 0) { + req->port = CACHE_HTTP_PORT; + } + if (req->action == NULL) { + req->action = xstrdup(""); + } + if (!strcmp(req->action, "authenticate")) { + auth_html(req->hostname, req->port, req->user_name); + return 0; + } + if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + snprintf(buf, 1024, "socket: %s\n", xstrerror()); + error_html(buf); + return 1; + } + memset(&S, '\0', sizeof(struct sockaddr_in)); + S.sin_family = AF_INET; + if ((hp = gethostbyname(req->hostname)) != NULL) { + assert(hp->h_length >= 0 && (size_t)hp->h_length <= sizeof(S.sin_addr.s_addr)); + xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); + } else if (safe_inet_addr(req->hostname, &S.sin_addr)) + (void) 0; + else { + snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); + error_html(buf); + return 1; + } + S.sin_port = htons(req->port); + if (connect(s, (struct sockaddr *) &S, sizeof(struct sockaddr_in)) < 0) { + snprintf(buf, 1024, "connect: %s\n", xstrerror()); + error_html(buf); + return 1; + } + l = snprintf(buf, sizeof(buf), + "GET cache_object://%s/%s HTTP/1.0\r\n" + "Accept: */*\r\n" + "%s" /* Authentication info or nothing */ + "\r\n", + req->hostname, + req->action, + make_auth_header(req)); + write(s, buf, l); + debug(1) fprintf(stderr, "wrote request: '%s'\n", buf); + return read_reply(s, req); +} + +int +main(int argc, char *argv[]) +{ + char *s; + cachemgr_request *req; + safe_inet_addr("255.255.255.255", &no_addr); + now = time(NULL); + if ((s = strrchr(argv[0], '/'))) + progname = xstrdup(s + 1); + else + progname = xstrdup(argv[0]); + if ((s = getenv("SCRIPT_NAME")) != NULL) + script_name = xstrdup(s); + req = read_request(); + return process_request(req); +} + +static char * +read_post_request(void) +{ + char *s; + char *buf; + int len; + if ((s = getenv("REQUEST_METHOD")) == NULL) + return NULL; + if (0 != strcasecmp(s, "POST")) + return NULL; + if ((s = getenv("CONTENT_LENGTH")) == NULL) + return NULL; + if ((len = atoi(s)) <= 0) + return NULL; + buf = (char *)xmalloc(len + 1); + fread(buf, len, 1, stdin); + buf[len] = '\0'; + return buf; +} + +static char * +read_get_request(void) +{ + char *s; + if ((s = getenv("QUERY_STRING")) == NULL) + return NULL; + return xstrdup(s); +} + +static cachemgr_request * +read_request(void) +{ + char *buf; + cachemgr_request *req; + char *s; + char *t; + char *q; + if ((buf = read_post_request()) != NULL) + (void) 0; + else if ((buf = read_get_request()) != NULL) + (void) 0; + else + return NULL; + if (strlen(buf) == 0) + return NULL; + req = (cachemgr_request *)xcalloc(1, sizeof(cachemgr_request)); + for (s = strtok(buf, "&"); s != NULL; s = strtok(NULL, "&")) { + t = xstrdup(s); + if ((q = strchr(t, '=')) == NULL) + continue; + *q++ = '\0'; + if (0 == strcasecmp(t, "host") && strlen(q)) + req->hostname = xstrdup(q); + else if (0 == strcasecmp(t, "port") && strlen(q)) + req->port = atoi(q); + else if (0 == strcasecmp(t, "user_name") && strlen(q)) + req->user_name = xstrdup(q); + else if (0 == strcasecmp(t, "passwd") && strlen(q)) + req->passwd = xstrdup(q); + else if (0 == strcasecmp(t, "auth") && strlen(q)) + req->pub_auth = xstrdup(q), decode_pub_auth(req); + else if (0 == strcasecmp(t, "operation")) + req->action = xstrdup(q); + } + make_pub_auth(req); + debug(1) fprintf(stderr, "cmgr: got req: host: '%s' port: %d uname: '%s' passwd: '%s' auth: '%s' oper: '%s'\n", + safe_str(req->hostname), req->port, safe_str(req->user_name), safe_str(req->passwd), safe_str(req->pub_auth), safe_str(req->action)); + return req; +} + + +/* Routines to support authentication */ + +/* + * Encodes auth info into a "public" form. + * Currently no powerful encryption is used. + */ +static void +make_pub_auth(cachemgr_request * req) +{ + static char buf[1024]; + safe_free(req->pub_auth); + debug(3) fprintf(stderr, "cmgr: encoding for pub...\n"); + if (!req->passwd || !strlen(req->passwd)) + return; + /* host | time | user | passwd */ + snprintf(buf, sizeof(buf), "%s|%d|%s|%s", + req->hostname, + (int) now, + req->user_name ? req->user_name : "", + req->passwd); + debug(3) fprintf(stderr, "cmgr: pre-encoded for pub: %s\n", buf); + debug(3) fprintf(stderr, "cmgr: encoded: '%s'\n", base64_encode(buf)); + req->pub_auth = xstrdup(base64_encode(buf)); +} + +static void +decode_pub_auth(cachemgr_request * req) +{ + char *buf; + const char *host_name; + const char *time_str; + const char *user_name; + const char *passwd; + + debug(2) fprintf(stderr, "cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); + safe_free(req->passwd); + if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname))) + return; + buf = xstrdup(base64_decode(req->pub_auth)); + debug(3) fprintf(stderr, "cmgr: length ok\n"); + /* parse ( a lot of memory leaks, but that is cachemgr style :) */ + if ((host_name = strtok(buf, "|")) == NULL) + return; + debug(3) fprintf(stderr, "cmgr: decoded host: '%s'\n", host_name); + if ((time_str = strtok(NULL, "|")) == NULL) + return; + debug(3) fprintf(stderr, "cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); + if ((user_name = strtok(NULL, "|")) == NULL) + return; + debug(3) fprintf(stderr, "cmgr: decoded uname: '%s'\n", user_name); + if ((passwd = strtok(NULL, "|")) == NULL) + return; + debug(2) fprintf(stderr, "cmgr: decoded passwd: '%s'\n", passwd); + /* verify freshness and validity */ + if (atoi(time_str) + passwd_ttl < now) + return; + if (strcasecmp(host_name, req->hostname)) + return; + debug(1) fprintf(stderr, "cmgr: verified auth. info.\n"); + /* ok, accept */ + xfree(req->user_name); + req->user_name = xstrdup(user_name); + req->passwd = xstrdup(passwd); + xfree(buf); +} + +static void +reset_auth(cachemgr_request * req) +{ + safe_free(req->passwd); + safe_free(req->pub_auth); +} + +static const char * +make_auth_header(const cachemgr_request * req) +{ + static char buf[1024]; + size_t stringLength = 0; + const char *str64; + if (!req->passwd) + return ""; + + snprintf(buf, sizeof(buf), "%s:%s", + req->user_name ? req->user_name : "", + req->passwd); + + str64 = base64_encode(buf); + stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); + assert(stringLength < sizeof(buf)); + stringLength += snprintf(&buf[stringLength], sizeof(buf) - stringLength, + "Proxy-Authorization: Basic %s\r\n", str64); + return buf; +} --- squid/src/carp.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,193 +0,0 @@ - -/* - * $Id: carp.c,v 1.8.18.1 2002/10/04 07:07:20 rbcollins Exp $ - * - * DEBUG: section 39 Cache Array Routing Protocol - * AUTHOR: Henrik Nordstrom - * BASED ON: carp.c by Eric Stern and draft-vinod-carp-v1-03.txt - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -#if USE_CARP - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) - -static int n_carp_peers = 0; -static peer **carp_peers = NULL; -static OBJH carpCachemgr; - -static int -peerSortWeight(const void *a, const void *b) -{ - const peer *const *p1 = a, *const *p2 = b; - return (*p1)->weight - (*p2)->weight; -} - -void -carpInit(void) -{ - int W = 0; - int K; - int k; - double P_last, X_last, Xn; - peer *p; - peer **P; - char *t; - /* Clean up */ - for (k = 0; k < n_carp_peers; k++) { - cbdataReferenceDone(carp_peers[k]); - } - safe_free(carp_peers); - n_carp_peers = 0; - /* find out which peers we have */ - for (p = Config.peers; p; p = p->next) { - if (!p->options.carp) - continue; - assert(p->type == PEER_PARENT); - if (p->weight == 0) - continue; - n_carp_peers++; - W += p->weight; - } - if (n_carp_peers == 0) - return; - carp_peers = xcalloc(n_carp_peers, sizeof(*carp_peers)); - /* Build a list of the found peers and calculate hashes and load factors */ - for (P = carp_peers, p = Config.peers; p; p = p->next) { - if (!p->options.carp) - continue; - if (p->weight == 0) - continue; - /* calculate this peers hash */ - p->carp.hash = 0; - for (t = p->host; *t != 0; t++) - p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + (unsigned int) *t; - p->carp.hash += p->carp.hash * 0x62531965; - p->carp.hash = ROTATE_LEFT(p->carp.hash, 21); - /* and load factor */ - p->carp.load_factor = ((double) p->weight) / (double) W; - if (floor(p->carp.load_factor * 1000.0) == 0.0) - p->carp.load_factor = 0.0; - /* add it to our list of peers */ - *P++ = cbdataReference(p); - } - /* Sort our list on weight */ - qsort(carp_peers, n_carp_peers, sizeof(*carp_peers), peerSortWeight); - /* Calculate the load factor multipliers X_k - * - * X_1 = pow ((K*p_1), (1/K)) - * X_k = ([K-k+1] * [P_k - P_{k-1}])/(X_1 * X_2 * ... * X_{k-1}) - * X_k += pow ((X_{k-1}, {K-k+1}) - * X_k = pow (X_k, {1/(K-k+1)}) - * simplified to have X_1 part of the loop - */ - K = n_carp_peers; - P_last = 0.0; /* Empty P_0 */ - Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */ - X_last = 0.0; /* Empty X_0, nullifies the first pow statement */ - for (k = 1; k <= K; k++) { - double Kk1 = (double) (K - k + 1); - p = carp_peers[k - 1]; - p->carp.load_multiplier = (Kk1 * (p->carp.load_factor - P_last)) / Xn; - p->carp.load_multiplier += pow(X_last, Kk1); - p->carp.load_multiplier = pow(p->carp.load_multiplier, 1.0 / Kk1); - Xn *= p->carp.load_multiplier; - X_last = p->carp.load_multiplier; - P_last = p->carp.load_factor; - } - cachemgrRegister("carp", "CARP information", carpCachemgr, 0, 1); -} - -peer * -carpSelectParent(request_t * request) -{ - int k; - const char *c; - peer *p = NULL; - peer *tp; - unsigned int user_hash = 0; - unsigned int combined_hash; - double score; - double high_score = 0; - const char *key = NULL; - - if (n_carp_peers == 0) - return NULL; - - key = urlCanonical(request); - - /* calculate hash key */ - debug(39, 2) ("carpSelectParent: Calculating hash for %s\n", key); - for (c = key; *c != 0; c++) - user_hash += ROTATE_LEFT(user_hash, 19) + *c; - /* select peer */ - for (k = 0; k < n_carp_peers; k++) { - tp = carp_peers[k]; - combined_hash = (user_hash ^ tp->carp.hash); - combined_hash += combined_hash * 0x62531965; - combined_hash = ROTATE_LEFT(combined_hash, 21); - score = combined_hash * tp->carp.load_multiplier; - debug(39, 3) ("carpSelectParent: %s combined_hash %u score %.0f\n", - tp->host, combined_hash, score); - if ((score > high_score) && peerHTTPOkay(tp, request)) { - p = tp; - high_score = score; - } - } - if (p) - debug(39, 2) ("carpSelectParent: selected %s\n", p->host); - return p; -} - -static void -carpCachemgr(StoreEntry * sentry) -{ - peer *p; - int sumfetches = 0; - storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n", - "Hostname", - "Hash", - "Multiplier", - "Factor", - "Actual"); - for (p = Config.peers; p; p = p->next) - sumfetches += p->stats.fetches; - for (p = Config.peers; p; p = p->next) { - storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n", - p->host, p->carp.hash, - p->carp.load_multiplier, - p->carp.load_factor, - sumfetches ? (double) p->stats.fetches / sumfetches : -1.0); - } -} - -#endif --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/carp.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,193 @@ + +/* + * $Id: carp.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 39 Cache Array Routing Protocol + * AUTHOR: Henrik Nordstrom + * BASED ON: carp.c by Eric Stern and draft-vinod-carp-v1-03.txt + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + +#if USE_CARP + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +static int n_carp_peers = 0; +static peer **carp_peers = NULL; +static OBJH carpCachemgr; + +static int +peerSortWeight(const void *a, const void *b) +{ + const peer *const *p1 = a, *const *p2 = b; + return (*p1)->weight - (*p2)->weight; +} + +void +carpInit(void) +{ + int W = 0; + int K; + int k; + double P_last, X_last, Xn; + peer *p; + peer **P; + char *t; + /* Clean up */ + for (k = 0; k < n_carp_peers; k++) { + cbdataReferenceDone(carp_peers[k]); + } + safe_free(carp_peers); + n_carp_peers = 0; + /* find out which peers we have */ + for (p = Config.peers; p; p = p->next) { + if (!p->options.carp) + continue; + assert(p->type == PEER_PARENT); + if (p->weight == 0) + continue; + n_carp_peers++; + W += p->weight; + } + if (n_carp_peers == 0) + return; + carp_peers = xcalloc(n_carp_peers, sizeof(*carp_peers)); + /* Build a list of the found peers and calculate hashes and load factors */ + for (P = carp_peers, p = Config.peers; p; p = p->next) { + if (!p->options.carp) + continue; + if (p->weight == 0) + continue; + /* calculate this peers hash */ + p->carp.hash = 0; + for (t = p->host; *t != 0; t++) + p->carp.hash += ROTATE_LEFT(p->carp.hash, 19) + (unsigned int) *t; + p->carp.hash += p->carp.hash * 0x62531965; + p->carp.hash = ROTATE_LEFT(p->carp.hash, 21); + /* and load factor */ + p->carp.load_factor = ((double) p->weight) / (double) W; + if (floor(p->carp.load_factor * 1000.0) == 0.0) + p->carp.load_factor = 0.0; + /* add it to our list of peers */ + *P++ = cbdataReference(p); + } + /* Sort our list on weight */ + qsort(carp_peers, n_carp_peers, sizeof(*carp_peers), peerSortWeight); + /* Calculate the load factor multipliers X_k + * + * X_1 = pow ((K*p_1), (1/K)) + * X_k = ([K-k+1] * [P_k - P_{k-1}])/(X_1 * X_2 * ... * X_{k-1}) + * X_k += pow ((X_{k-1}, {K-k+1}) + * X_k = pow (X_k, {1/(K-k+1)}) + * simplified to have X_1 part of the loop + */ + K = n_carp_peers; + P_last = 0.0; /* Empty P_0 */ + Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */ + X_last = 0.0; /* Empty X_0, nullifies the first pow statement */ + for (k = 1; k <= K; k++) { + double Kk1 = (double) (K - k + 1); + p = carp_peers[k - 1]; + p->carp.load_multiplier = (Kk1 * (p->carp.load_factor - P_last)) / Xn; + p->carp.load_multiplier += pow(X_last, Kk1); + p->carp.load_multiplier = pow(p->carp.load_multiplier, 1.0 / Kk1); + Xn *= p->carp.load_multiplier; + X_last = p->carp.load_multiplier; + P_last = p->carp.load_factor; + } + cachemgrRegister("carp", "CARP information", carpCachemgr, 0, 1); +} + +peer * +carpSelectParent(request_t * request) +{ + int k; + const char *c; + peer *p = NULL; + peer *tp; + unsigned int user_hash = 0; + unsigned int combined_hash; + double score; + double high_score = 0; + const char *key = NULL; + + if (n_carp_peers == 0) + return NULL; + + key = urlCanonical(request); + + /* calculate hash key */ + debug(39, 2) ("carpSelectParent: Calculating hash for %s\n", key); + for (c = key; *c != 0; c++) + user_hash += ROTATE_LEFT(user_hash, 19) + *c; + /* select peer */ + for (k = 0; k < n_carp_peers; k++) { + tp = carp_peers[k]; + combined_hash = (user_hash ^ tp->carp.hash); + combined_hash += combined_hash * 0x62531965; + combined_hash = ROTATE_LEFT(combined_hash, 21); + score = combined_hash * tp->carp.load_multiplier; + debug(39, 3) ("carpSelectParent: %s combined_hash %u score %.0f\n", + tp->host, combined_hash, score); + if ((score > high_score) && peerHTTPOkay(tp, request)) { + p = tp; + high_score = score; + } + } + if (p) + debug(39, 2) ("carpSelectParent: selected %s\n", p->host); + return p; +} + +static void +carpCachemgr(StoreEntry * sentry) +{ + peer *p; + int sumfetches = 0; + storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n", + "Hostname", + "Hash", + "Multiplier", + "Factor", + "Actual"); + for (p = Config.peers; p; p = p->next) + sumfetches += p->stats.fetches; + for (p = Config.peers; p; p = p->next) { + storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n", + p->host, p->carp.hash, + p->carp.load_multiplier, + p->carp.load_factor, + sumfetches ? (double) p->stats.fetches / sumfetches : -1.0); + } +} + +#endif --- squid/src/cbdata.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,323 +0,0 @@ - -/* - * $Id: cbdata.c,v 1.16.2.2 2002/10/04 22:35:17 rbcollins Exp $ - * - * DEBUG: section 45 Callback Data Registry - * ORIGINAL AUTHOR: Duane Wessels - * Modified by Moez Mahfoudh (08/12/2000) - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/* - * These routines manage a set of registered callback data pointers. - * One of the easiest ways to make Squid coredump is to issue a - * callback to for some data structure which has previously been - * freed. With these routines, we register (add) callback data - * pointers, lock them just before registering the callback function, - * validate them before issuing the callback, and then free them - * when finished. - */ - -#include "squid.h" -#include "Store.h" - -static int cbdataCount = 0; -#if CBDATA_DEBUG -dlink_list cbdataEntries; -#endif - -typedef struct _cbdata { - int valid; - int locks; - int type; -#if CBDATA_DEBUG - dlink_node link; - const char *file; - int line; -#endif - long y; /* cookie used while debugging */ - union { - void *pointer; - double double_float; - int integer; - } data; -} cbdata; - -static OBJH cbdataDump; - -struct { - MemPool *pool; - FREE *free_func; -} *cbdata_index = NULL; -int cbdata_types = 0; - -#define OFFSET_OF(type, member) ((int)(char *)&((type *)0L)->member) -#define CBDATA_COOKIE 0xDEADBEEF -#define CBDATA_CHECK(c) assert(c->y == ((long)c ^ CBDATA_COOKIE)) - -static void -cbdataInternalInitType(cbdata_type type, const char *name, int size, FREE * free_func) -{ - char *label; - if (type >= cbdata_types) { - cbdata_index = xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index)); - memset(&cbdata_index[cbdata_types], 0, - (type + 1 - cbdata_types) * sizeof(*cbdata_index)); - cbdata_types = type + 1; - } - if (cbdata_index[type].pool) - return; - label = xmalloc(strlen(name) + 20); - snprintf(label, strlen(name) + 20, "cbdata %s (%d)", name, (int) type); - assert(OFFSET_OF(cbdata, data) == (sizeof(cbdata) - sizeof(((cbdata *) NULL)->data))); - cbdata_index[type].pool = memPoolCreate(label, size + OFFSET_OF(cbdata, data)); - cbdata_index[type].free_func = free_func; -} - -cbdata_type -cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_func) -{ - if (type) - return type; - type = cbdata_types; - cbdataInternalInitType(type, name, size, free_func); - return type; -} - -void -cbdataInit(void) -{ - debug(45, 3) ("cbdataInit\n"); - cachemgrRegister("cbdata", - "Callback Data Registry Contents", - cbdataDump, 0, 1); -#define CREATE_CBDATA(type) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), NULL) -#define CREATE_CBDATA_FREE(type, free_func) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), free_func) - /* XXX - * most of these should be moved out to their respective module. - */ - CREATE_CBDATA(acl_access); - CREATE_CBDATA(aclCheck_t); - CREATE_CBDATA(clientHttpRequest); - CREATE_CBDATA(ConnStateData); - CREATE_CBDATA(ErrorState); - CREATE_CBDATA(FwdState); - CREATE_CBDATA(generic_cbdata); - CREATE_CBDATA(helper); - CREATE_CBDATA(helper_server); - CREATE_CBDATA(statefulhelper); - CREATE_CBDATA(helper_stateful_server); - CREATE_CBDATA_FREE(peer, peerDestroy); - CREATE_CBDATA(ps_state); - CREATE_CBDATA(RemovalPolicy); - CREATE_CBDATA(RemovalPolicyWalker); - CREATE_CBDATA(RemovalPurgeWalker); -} - -void * -#if CBDATA_DEBUG -cbdataInternalAllocDbg(cbdata_type type, const char *file, int line) -#else -cbdataInternalAlloc(cbdata_type type) -#endif -{ - cbdata *p; - assert(type > 0 && type < cbdata_types); - p = memPoolAlloc(cbdata_index[type].pool); - p->type = type; - p->valid = 1; - p->locks = 0; -#if CBDATA_DEBUG - p->file = file; - p->line = line; -#endif - p->y = (long) p ^ CBDATA_COOKIE; - cbdataCount++; - -#if CBDATA_DEBUG - dlinkAdd(p, &p->link, &cbdataEntries); -#endif - return (void *) &p->data; -} - -void * -#if CBDATA_DEBUG -cbdataInternalFreeDbg(void *p, const char *file, int line) -#else -cbdataInternalFree(void *p) -#endif -{ - cbdata *c; - FREE *free_func; -#if CBDATA_DEBUG - debug(45, 3) ("cbdataFree: %p %s:%d\n", p, file, line); -#else - debug(45, 3) ("cbdataFree: %p\n", p); -#endif - c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); - CBDATA_CHECK(c); - c->valid = 0; - if (c->locks) { - debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n", - p, c->locks); - return NULL; - } - cbdataCount--; - debug(45, 3) ("cbdataFree: Freeing %p\n", p); -#if CBDATA_DEBUG - dlinkDelete(&c->link, &cbdataEntries); -#endif - free_func = cbdata_index[c->type].free_func; - if (free_func) - free_func((void *) p); - memPoolFree(cbdata_index[c->type].pool, c); - return NULL; -} - -void -#if CBDATA_DEBUG -cbdataInternalLockDbg(const void *p, const char *file, int line) -#else -cbdataInternalLock(const void *p) -#endif -{ - cbdata *c; - if (p == NULL) - return; - c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); -#if CBDATA_DEBUG - debug(45, 3) ("cbdataLock: %p=%d %s:%d\n", p, c ? c->locks + 1 : -1, file, line); -#else - debug(45, 3) ("cbdataLock: %p=%d\n", p, c ? c->locks + 1 : -1); -#endif - CBDATA_CHECK(c); - c->locks++; -} - -void -#if CBDATA_DEBUG -cbdataInternalUnlockDbg(const void *p, const char *file, int line) -#else -cbdataInternalUnlock(const void *p) -#endif -{ - cbdata *c; - FREE *free_func; - if (p == NULL) - return; - c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); -#if CBDATA_DEBUG - debug(45, 3) ("cbdataUnlock: %p=%d %s:%d\n", p, c ? c->locks - 1 : -1, file, line); -#else - debug(45, 3) ("cbdataUnlock: %p=%d\n", p, c ? c->locks - 1 : -1); -#endif - CBDATA_CHECK(c); - assert(c != NULL); - assert(c->locks > 0); - c->locks--; - if (c->valid || c->locks) - return; - cbdataCount--; - debug(45, 3) ("cbdataUnlock: Freeing %p\n", p); -#if CBDATA_DEBUG - dlinkDelete(&c->link, &cbdataEntries); -#endif - free_func = cbdata_index[c->type].free_func; - if (free_func) - free_func((void *) p); - memPoolFree(cbdata_index[c->type].pool, c); -} - -int -cbdataReferenceValid(const void *p) -{ - cbdata *c; - if (p == NULL) - return 1; /* A NULL pointer cannot become invalid */ - debug(45, 3) ("cbdataReferenceValid: %p\n", p); - c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); - CBDATA_CHECK(c); - assert(c->locks > 0); - return c->valid; -} - -int -#if CBDATA_DEBUG -cbdataInternalReferenceDoneValidDbg(void **pp, void **tp, const char *file, int line) -#else -cbdataInternalReferenceDoneValid(void **pp, void **tp) -#endif -{ - void *p = (void *) *pp; - int valid = cbdataReferenceValid(p); - *pp = NULL; -#if CBDATA_DEBUG - cbdataInternalUnlockDbg(p, file, line); -#else - cbdataInternalUnlock(p); -#endif - if (valid) { - *tp = p; - return 1; - } else { - *tp = NULL; - return 0; - } -} - - -static void -cbdataDump(StoreEntry * sentry) -{ -#if CBDATA_DEBUG - dlink_node *n; - cbdata *p; - int i; -#endif - storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount); -#if CBDATA_DEBUG - storeAppendPrintf(sentry, "Pointer\tType\tLocks\tAllocated by\n"); - for (n = cbdataEntries.head; n; n = n->next) { - p = n->data; - storeAppendPrintf(sentry, "%c%p\t%d\t%d\t%20s:%-5d\n", p->valid ? ' ' : '!', &p->data, p->type, p->locks, p->file, p->line); - } - storeAppendPrintf(sentry, "\n"); - storeAppendPrintf(sentry, "types\tsize\tallocated\ttotal\n"); - for (i = 1; i < cbdata_types; i++) { - MemPool *pool = cbdata_index[i].pool; - if (pool) { - int obj_size = pool->obj_size - OFFSET_OF(cbdata, data); - storeAppendPrintf(sentry, "%s\t%d\t%d\t%d\n", pool->label + 7, obj_size, pool->meter.inuse.level, obj_size * pool->meter.inuse.level); - } - } -#else - storeAppendPrintf(sentry, "detailed allocation information only available when compiled with CBDATA_DEBUG\n"); -#endif - storeAppendPrintf(sentry, "\nsee also \"Memory utilization\" for detailed per type statistics\n"); -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/cbdata.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,323 @@ + +/* + * $Id: cbdata.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 45 Callback Data Registry + * ORIGINAL AUTHOR: Duane Wessels + * Modified by Moez Mahfoudh (08/12/2000) + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * These routines manage a set of registered callback data pointers. + * One of the easiest ways to make Squid coredump is to issue a + * callback to for some data structure which has previously been + * freed. With these routines, we register (add) callback data + * pointers, lock them just before registering the callback function, + * validate them before issuing the callback, and then free them + * when finished. + */ + +#include "squid.h" +#include "Store.h" + +static int cbdataCount = 0; +#if CBDATA_DEBUG +dlink_list cbdataEntries; +#endif + +typedef struct _cbdata { + int valid; + int locks; + int type; +#if CBDATA_DEBUG + dlink_node link; + const char *file; + int line; +#endif + long y; /* cookie used while debugging */ + union { + void *pointer; + double double_float; + int integer; + } data; +} cbdata; + +static OBJH cbdataDump; + +struct CBDataIndex { + MemPool *pool; + FREE *free_func; +} *cbdata_index = NULL; +int cbdata_types = 0; + +#define OFFSET_OF(type, member) ((int)(char *)&((type *)0L)->member) +#define CBDATA_COOKIE (long)0xDEADBEEF +#define CBDATA_CHECK(c) assert(c->y == ((long)c ^ CBDATA_COOKIE)) + +static void +cbdataInternalInitType(cbdata_type type, const char *name, int size, FREE * free_func) +{ + char *label; + if (type >= cbdata_types) { + cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index)); + memset(&cbdata_index[cbdata_types], 0, + (type + 1 - cbdata_types) * sizeof(*cbdata_index)); + cbdata_types = type + 1; + } + if (cbdata_index[type].pool) + return; + label = (char *)xmalloc(strlen(name) + 20); + snprintf(label, strlen(name) + 20, "cbdata %s (%d)", name, (int) type); + assert(OFFSET_OF(cbdata, data) == (sizeof(cbdata) - sizeof(((cbdata *) NULL)->data))); + cbdata_index[type].pool = memPoolCreate(label, size + OFFSET_OF(cbdata, data)); + cbdata_index[type].free_func = free_func; +} + +cbdata_type +cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_func) +{ + if (type) + return type; + type = (cbdata_type)cbdata_types; + cbdataInternalInitType(type, name, size, free_func); + return type; +} + +void +cbdataInit(void) +{ + debug(45, 3) ("cbdataInit\n"); + cachemgrRegister("cbdata", + "Callback Data Registry Contents", + cbdataDump, 0, 1); +#define CREATE_CBDATA(type) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), NULL) +#define CREATE_CBDATA_FREE(type, free_func) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), free_func) + /* XXX + * most of these should be moved out to their respective module. + */ + CREATE_CBDATA(acl_access); + CREATE_CBDATA(aclCheck_t); + CREATE_CBDATA(clientHttpRequest); + CREATE_CBDATA(ConnStateData); + CREATE_CBDATA(ErrorState); + CREATE_CBDATA(FwdState); + CREATE_CBDATA(generic_cbdata); + CREATE_CBDATA(helper); + CREATE_CBDATA(helper_server); + CREATE_CBDATA(statefulhelper); + CREATE_CBDATA(helper_stateful_server); + CREATE_CBDATA_FREE(peer, peerDestroy); + CREATE_CBDATA(ps_state); + CREATE_CBDATA(RemovalPolicy); + CREATE_CBDATA(RemovalPolicyWalker); + CREATE_CBDATA(RemovalPurgeWalker); +} + +void * +#if CBDATA_DEBUG +cbdataInternalAllocDbg(cbdata_type type, const char *file, int line) +#else +cbdataInternalAlloc(cbdata_type type) +#endif +{ + cbdata *p; + assert(type > 0 && type < cbdata_types); + p = (cbdata *)memPoolAlloc(cbdata_index[type].pool); + p->type = type; + p->valid = 1; + p->locks = 0; +#if CBDATA_DEBUG + p->file = file; + p->line = line; +#endif + p->y = (long) p ^ CBDATA_COOKIE; + cbdataCount++; + +#if CBDATA_DEBUG + dlinkAdd(p, &p->link, &cbdataEntries); +#endif + return (void *) &p->data; +} + +void * +#if CBDATA_DEBUG +cbdataInternalFreeDbg(void *p, const char *file, int line) +#else +cbdataInternalFree(void *p) +#endif +{ + cbdata *c; + FREE *free_func; +#if CBDATA_DEBUG + debug(45, 3) ("cbdataFree: %p %s:%d\n", p, file, line); +#else + debug(45, 3) ("cbdataFree: %p\n", p); +#endif + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); + CBDATA_CHECK(c); + c->valid = 0; + if (c->locks) { + debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n", + p, c->locks); + return NULL; + } + cbdataCount--; + debug(45, 3) ("cbdataFree: Freeing %p\n", p); +#if CBDATA_DEBUG + dlinkDelete(&c->link, &cbdataEntries); +#endif + free_func = cbdata_index[c->type].free_func; + if (free_func) + free_func((void *) p); + memPoolFree(cbdata_index[c->type].pool, c); + return NULL; +} + +void +#if CBDATA_DEBUG +cbdataInternalLockDbg(const void *p, const char *file, int line) +#else +cbdataInternalLock(const void *p) +#endif +{ + cbdata *c; + if (p == NULL) + return; + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); +#if CBDATA_DEBUG + debug(45, 3) ("cbdataLock: %p=%d %s:%d\n", p, c ? c->locks + 1 : -1, file, line); +#else + debug(45, 3) ("cbdataLock: %p=%d\n", p, c ? c->locks + 1 : -1); +#endif + CBDATA_CHECK(c); + c->locks++; +} + +void +#if CBDATA_DEBUG +cbdataInternalUnlockDbg(const void *p, const char *file, int line) +#else +cbdataInternalUnlock(const void *p) +#endif +{ + cbdata *c; + FREE *free_func; + if (p == NULL) + return; + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); +#if CBDATA_DEBUG + debug(45, 3) ("cbdataUnlock: %p=%d %s:%d\n", p, c ? c->locks - 1 : -1, file, line); +#else + debug(45, 3) ("cbdataUnlock: %p=%d\n", p, c ? c->locks - 1 : -1); +#endif + CBDATA_CHECK(c); + assert(c != NULL); + assert(c->locks > 0); + c->locks--; + if (c->valid || c->locks) + return; + cbdataCount--; + debug(45, 3) ("cbdataUnlock: Freeing %p\n", p); +#if CBDATA_DEBUG + dlinkDelete(&c->link, &cbdataEntries); +#endif + free_func = cbdata_index[c->type].free_func; + if (free_func) + free_func((void *) p); + memPoolFree(cbdata_index[c->type].pool, c); +} + +int +cbdataReferenceValid(const void *p) +{ + cbdata *c; + if (p == NULL) + return 1; /* A NULL pointer cannot become invalid */ + debug(45, 3) ("cbdataReferenceValid: %p\n", p); + c = (cbdata *) (((char *) p) - OFFSET_OF(cbdata, data)); + CBDATA_CHECK(c); + assert(c->locks > 0); + return c->valid; +} + +int +#if CBDATA_DEBUG +cbdataInternalReferenceDoneValidDbg(void **pp, void **tp, const char *file, int line) +#else +cbdataInternalReferenceDoneValid(void **pp, void **tp) +#endif +{ + void *p = (void *) *pp; + int valid = cbdataReferenceValid(p); + *pp = NULL; +#if CBDATA_DEBUG + cbdataInternalUnlockDbg(p, file, line); +#else + cbdataInternalUnlock(p); +#endif + if (valid) { + *tp = p; + return 1; + } else { + *tp = NULL; + return 0; + } +} + + +static void +cbdataDump(StoreEntry * sentry) +{ +#if CBDATA_DEBUG + dlink_node *n; + cbdata *p; + int i; +#endif + storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount); +#if CBDATA_DEBUG + storeAppendPrintf(sentry, "Pointer\tType\tLocks\tAllocated by\n"); + for (n = cbdataEntries.head; n; n = n->next) { + p = n->data; + storeAppendPrintf(sentry, "%c%p\t%d\t%d\t%20s:%-5d\n", p->valid ? ' ' : '!', &p->data, p->type, p->locks, p->file, p->line); + } + storeAppendPrintf(sentry, "\n"); + storeAppendPrintf(sentry, "types\tsize\tallocated\ttotal\n"); + for (i = 1; i < cbdata_types; i++) { + MemPool *pool = cbdata_index[i].pool; + if (pool) { + int obj_size = pool->obj_size - OFFSET_OF(cbdata, data); + storeAppendPrintf(sentry, "%s\t%d\t%d\t%d\n", pool->label + 7, obj_size, pool->meter.inuse.level, obj_size * pool->meter.inuse.level); + } + } +#else + storeAppendPrintf(sentry, "detailed allocation information only available when compiled with CBDATA_DEBUG\n"); +#endif + storeAppendPrintf(sentry, "\nsee also \"Memory utilization\" for detailed per type statistics\n"); +} --- squid/src/cf_gen.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,669 +0,0 @@ - -/* - * $Id: cf_gen.c,v 1.14 2002/09/01 16:30:42 squidadm Exp $ - * - * DEBUG: none Generate squid.conf.default and cf_parser.h - * AUTHOR: Max Okumoto - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/***************************************************************************** - * Abstract: This program parses the input file and generates code and - * files used to configure the variables in squid. - * (ie it creates the squid.conf.default file from the cf.data file) - * - * The output files are as follows: - * cf_parser.h - this file contains, default_all() which - * initializes variables with the default - * values, parse_line() that parses line from - * squid.conf.default, dump_config that dumps the - * current the values of the variables. - * squid.conf.default - default configuration file given to the server - * administrator. - *****************************************************************************/ - -#include "config.h" -#include "cf_gen_defines.h" - -#if HAVE_STDIO_H -#include -#endif -#if HAVE_STRING_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_CTYPE_H -#include -#endif -#if HAVE_ASSERT_H -#include -#endif -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) -#include -#endif -#if HAVE_FCNTL_H -#include -#endif - -#include "util.h" - -#define MAX_LINE 1024 /* longest configuration line */ -#define _PATH_PARSER "cf_parser.h" -#define _PATH_SQUID_CONF "squid.conf.default" - -enum State { - sSTART, - s1, - sDOC, - sNOCOMMENT, - sEXIT -}; - -typedef struct Line { - char *data; - struct Line *next; -} Line; - -typedef struct EntryAlias { - struct EntryAlias *next; - char *name; -} EntryAlias; - -typedef struct Entry { - char *name; - EntryAlias *alias; - char *type; - char *loc; - char *default_value; - Line *default_if_none; - char *comment; - char *ifdef; - Line *doc; - Line *nocomment; - int array_flag; - struct Entry *next; -} Entry; - - -static const char WS[] = " \t"; -static int gen_default(Entry *, FILE *); -static void gen_parse(Entry *, FILE *); -static void gen_dump(Entry *, FILE *); -static void gen_free(Entry *, FILE *); -static void gen_conf(Entry *, FILE *); -static void gen_default_if_none(Entry *, FILE *); - -static void -lineAdd(Line ** L, const char *str) -{ - while (*L) - L = &(*L)->next; - *L = xcalloc(1, sizeof(Line)); - (*L)->data = xstrdup(str); -} - -int -main(int argc, char *argv[]) -{ - FILE *fp; - char *input_filename = argv[1]; - const char *output_filename = _PATH_PARSER; - const char *conf_filename = _PATH_SQUID_CONF; - int linenum = 0; - Entry *entries = NULL; - Entry *curr = NULL; - enum State state; - int rc = 0; - char *ptr = NULL; -#ifdef _SQUID_OS2_ - const char *rmode = "rt"; -#else - const char *rmode = "r"; -#endif - - /*-------------------------------------------------------------------* - * Parse input file - *-------------------------------------------------------------------*/ - - /* Open input file */ - if ((fp = fopen(input_filename, rmode)) == NULL) { - perror(input_filename); - exit(1); - } -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(fileno(fp), O_TEXT); -#endif - state = sSTART; - while (feof(fp) == 0 && state != sEXIT) { - char buff[MAX_LINE]; - char *t; - if (NULL == fgets(buff, MAX_LINE, fp)) - break; - linenum++; - if ((t = strchr(buff, '\n'))) - *t = '\0'; - switch (state) { - case sSTART: - if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { - /* ignore empty and comment lines */ - (void) 0; - } else if (!strncmp(buff, "NAME:", 5)) { - char *name, *aliasname; - if ((name = strtok(buff + 5, WS)) == NULL) { - printf("Error in input file\n"); - exit(1); - } - curr = calloc(1, sizeof(Entry)); - curr->name = xstrdup(name); - while ((aliasname = strtok(NULL, WS)) != NULL) { - EntryAlias *alias = calloc(1, sizeof(EntryAlias)); - alias->next = curr->alias; - alias->name = xstrdup(aliasname); - curr->alias = alias; - } - state = s1; - } else if (!strcmp(buff, "EOF")) { - state = sEXIT; - } else if (!strcmp(buff, "COMMENT_START")) { - curr = calloc(1, sizeof(Entry)); - curr->name = xstrdup("comment"); - curr->loc = xstrdup("none"); - state = sDOC; - } else { - printf("Error on line %d\n", linenum); - printf("--> %s\n", buff); - exit(1); - } - break; - - case s1: - if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { - /* ignore empty and comment lines */ - (void) 0; - } else if (!strncmp(buff, "COMMENT:", 8)) { - ptr = buff + 8; - while (xisspace(*ptr)) - ptr++; - curr->comment = xstrdup(ptr); - } else if (!strncmp(buff, "DEFAULT:", 8)) { - ptr = buff + 8; - while (xisspace(*ptr)) - ptr++; - curr->default_value = xstrdup(ptr); - } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { - ptr = buff + 16; - while (xisspace(*ptr)) - ptr++; - lineAdd(&curr->default_if_none, ptr); - } else if (!strncmp(buff, "LOC:", 4)) { - if ((ptr = strtok(buff + 4, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - curr->loc = xstrdup(ptr); - } else if (!strncmp(buff, "TYPE:", 5)) { - if ((ptr = strtok(buff + 5, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - /* hack to support arrays, rather than pointers */ - if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) { - curr->array_flag = 1; - *(ptr + strlen(ptr) - 2) = '\0'; - } - curr->type = xstrdup(ptr); - } else if (!strncmp(buff, "IFDEF:", 6)) { - if ((ptr = strtok(buff + 6, WS)) == NULL) { - printf("Error on line %d\n", linenum); - exit(1); - } - curr->ifdef = xstrdup(ptr); - } else if (!strcmp(buff, "DOC_START")) { - state = sDOC; - } else if (!strcmp(buff, "DOC_NONE")) { - /* add to list of entries */ - curr->next = entries; - entries = curr; - state = sSTART; - } else { - printf("Error on line %d\n", linenum); - exit(1); - } - break; - - case sDOC: - if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { - Line *head = NULL; - Line *line = curr->doc; - /* reverse order of doc lines */ - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - curr->doc = head; - /* add to list of entries */ - curr->next = entries; - entries = curr; - state = sSTART; - } else if (!strcmp(buff, "NOCOMMENT_START")) { - state = sNOCOMMENT; - } else { - Line *line = calloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->doc; - curr->doc = line; - } - break; - - case sNOCOMMENT: - if (!strcmp(buff, "NOCOMMENT_END")) { - Line *head = NULL; - Line *line = curr->nocomment; - /* reverse order of lines */ - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - curr->nocomment = head; - state = sDOC; - } else { - Line *line = calloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->nocomment; - curr->nocomment = line; - } - break; - - case sEXIT: - assert(0); /* should never get here */ - break; - } - } - if (state != sEXIT) { - printf("Error unexpected EOF\n"); - exit(1); - } else { - /* reverse order of entries */ - Entry *head = NULL; - - while (entries != NULL) { - Entry *tmp; - - tmp = entries->next; - entries->next = head; - head = entries; - entries = tmp; - } - entries = head; - } - fclose(fp); - - /*-------------------------------------------------------------------* - * Generate default_all() - * Generate parse_line() - * Generate dump_config() - * Generate free_all() - * Generate example squid.conf.default file - *-------------------------------------------------------------------*/ - - /* Open output x.c file */ - if ((fp = fopen(output_filename, "w")) == NULL) { - perror(output_filename); - exit(1); - } -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(fileno(fp), O_TEXT); -#endif - fprintf(fp, - "/*\n" - " * Generated automatically from %s by %s\n" - " *\n" - " * Abstract: This file contains routines used to configure the\n" - " * variables in the squid server.\n" - " */\n" - "\n", - input_filename, argv[0] - ); - rc = gen_default(entries, fp); - gen_default_if_none(entries, fp); - gen_parse(entries, fp); - gen_dump(entries, fp); - gen_free(entries, fp); - fclose(fp); - - /* Open output x.conf file */ - if ((fp = fopen(conf_filename, "w")) == NULL) { - perror(conf_filename); - exit(1); - } -#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) - setmode(fileno(fp), O_TEXT); -#endif - gen_conf(entries, fp); - fclose(fp); - - return (rc); -} - -static int -gen_default(Entry * head, FILE * fp) -{ - Entry *entry; - int rc = 0; - fprintf(fp, - "static void\n" - "default_line(const char *s)\n" - "{\n" - "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" - "\txstrncpy(tmp_line, s, BUFSIZ);\n" - "\txstrncpy(config_input_line, s, BUFSIZ);\n" - "\tconfig_lineno++;\n" - "\tparse_line(tmp_line);\n" - "}\n" - ); - fprintf(fp, - "static void\n" - "default_all(void)\n" - "{\n" - "\tcfg_filename = \"Default Configuration\";\n" - "\tconfig_lineno = 0;\n" - ); - for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->name); - assert(entry != entry->next); - - if (!strcmp(entry->name, "comment")) - continue; - if (entry->loc == NULL) { - fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); - rc |= 1; - continue; - } - if (entry->default_value == NULL) { - fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); - rc |= 1; - continue; - } - assert(entry->default_value); - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - if (strcmp(entry->default_value, "none") == 0) { - fprintf(fp, "\t/* No default for %s */\n", entry->name); - } else { - fprintf(fp, "\tdefault_line(\"%s %s\");\n", - entry->name, - entry->default_value); - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); - } - fprintf(fp, "\tcfg_filename = NULL;\n"); - fprintf(fp, "}\n\n"); - return rc; -} - -static void -gen_default_if_none(Entry * head, FILE * fp) -{ - Entry *entry; - Line *line; - fprintf(fp, - "static void\n" - "defaults_if_none(void)\n" - "{\n" - ); - for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->name); - assert(entry->loc); - if (entry->default_if_none == NULL) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - if (entry->default_if_none) { - fprintf(fp, - "\tif (check_null_%s(%s)) {\n", - entry->type, - entry->loc); - for (line = entry->default_if_none; line; line = line->next) - fprintf(fp, - "\t\tdefault_line(\"%s %s\");\n", - entry->name, - line->data); - fprintf(fp, "\t}\n"); - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); - } - fprintf(fp, "}\n\n"); -} - -static void -gen_parse(Entry * head, FILE * fp) -{ - Entry *entry; - char *name; - EntryAlias *alias; - - fprintf(fp, - "static int\n" - "parse_line(char *buff)\n" - "{\n" - "\tint\tresult = 1;\n" - "\tchar\t*token;\n" - "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n" - "\tif ((token = strtok(buff, w_space)) == NULL)\n" - "\t\t(void) 0;\t/* ignore empty lines */\n" - ); - - for (entry = head; entry != NULL; entry = entry->next) { - if (strcmp(entry->name, "comment") == 0) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - name = entry->name; - alias = entry->alias; - next_alias: - fprintf(fp, "\telse if (!strcmp(token, \"%s\"))\n", name); - assert(entry->loc); - if (strcmp(entry->loc, "none") == 0) { - fprintf(fp, - "\t\tparse_%s();\n", - entry->type - ); - } else { - fprintf(fp, - "\t\tparse_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : "" - ); - } - if (alias) { - name = alias->name; - alias = alias->next; - goto next_alias; - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); - } - - fprintf(fp, - "\telse\n" - "\t\tresult = 0; /* failure */\n" - "\treturn(result);\n" - "}\n\n" - ); -} - -static void -gen_dump(Entry * head, FILE * fp) -{ - Entry *entry; - fprintf(fp, - "static void\n" - "dump_config(StoreEntry *entry)\n" - "{\n" - ); - for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->loc); - if (strcmp(entry->loc, "none") == 0) - continue; - if (strcmp(entry->name, "comment") == 0) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", - entry->type, - entry->name, - entry->loc); - if (entry->ifdef) - fprintf(fp, "#endif\n"); - } - fprintf(fp, "}\n\n"); -} - -static void -gen_free(Entry * head, FILE * fp) -{ - Entry *entry; - fprintf(fp, - "static void\n" - "free_all(void)\n" - "{\n" - ); - for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->loc); - if (strcmp(entry->loc, "none") == 0) - continue; - if (strcmp(entry->name, "comment") == 0) - continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - fprintf(fp, "\tfree_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : ""); - if (entry->ifdef) - fprintf(fp, "#endif\n"); - } - fprintf(fp, "}\n\n"); -} - -static int -defined(char *name) -{ - int i = 0; - if (!name) - return 1; - for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); - } - return defines[i].defined; -} - -static const char * -available_if(char *name) -{ - int i = 0; - assert(name); - for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); - } - return defines[i].enable; -} - -static void -gen_conf(Entry * head, FILE * fp) -{ - Entry *entry; - char buf[8192]; - Line *def = NULL; - - for (entry = head; entry != NULL; entry = entry->next) { - Line *line; - int blank = 1; - - if (!strcmp(entry->name, "comment")) - (void) 0; - else - fprintf(fp, "# TAG: %s", entry->name); - if (entry->comment) - fprintf(fp, "\t%s", entry->comment); - fprintf(fp, "\n"); - if (!defined(entry->ifdef)) { - fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n"); - fprintf(fp, "# %s option\n#\n", available_if(entry->ifdef)); - } - for (line = entry->doc; line != NULL; line = line->next) { - fprintf(fp, "#%s\n", line->data); - } - if (entry->default_value && strcmp(entry->default_value, "none") != 0) { - sprintf(buf, "%s %s", entry->name, entry->default_value); - lineAdd(&def, buf); - } - if (entry->default_if_none) { - for (line = entry->default_if_none; line; line = line->next) { - sprintf(buf, "%s %s", entry->name, line->data); - lineAdd(&def, buf); - } - } - if (entry->nocomment) - blank = 0; - if (!def && entry->doc && !entry->nocomment && - strcmp(entry->name, "comment") != 0) - lineAdd(&def, "none"); - if (def && (entry->doc || entry->nocomment)) { - if (blank) - fprintf(fp, "#\n"); - fprintf(fp, "#Default:\n"); - while (def != NULL) { - line = def; - def = line->next; - fprintf(fp, "# %s\n", line->data); - xfree(line->data); - xfree(line); - } - blank = 1; - } - if (entry->nocomment && blank) - fprintf(fp, "#\n"); - for (line = entry->nocomment; line != NULL; line = line->next) { - fprintf(fp, "%s\n", line->data); - } - if (entry->doc != NULL) { - fprintf(fp, "\n"); - } - } -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/cf_gen.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,669 @@ + +/* + * $Id: cf_gen.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: none Generate squid.conf.default and cf_parser.h + * AUTHOR: Max Okumoto + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/***************************************************************************** + * Abstract: This program parses the input file and generates code and + * files used to configure the variables in squid. + * (ie it creates the squid.conf.default file from the cf.data file) + * + * The output files are as follows: + * cf_parser.h - this file contains, default_all() which + * initializes variables with the default + * values, parse_line() that parses line from + * squid.conf.default, dump_config that dumps the + * current the values of the variables. + * squid.conf.default - default configuration file given to the server + * administrator. + *****************************************************************************/ + +#include "config.h" +#include "cf_gen_defines.h" + +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_ASSERT_H +#include +#endif +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + +#include "util.h" + +#define MAX_LINE 1024 /* longest configuration line */ +#define _PATH_PARSER "cf_parser.h" +#define _PATH_SQUID_CONF "squid.conf.default" + +enum State { + sSTART, + s1, + sDOC, + sNOCOMMENT, + sEXIT +}; + +typedef struct Line { + char *data; + struct Line *next; +} Line; + +typedef struct EntryAlias { + struct EntryAlias *next; + char *name; +} EntryAlias; + +typedef struct Entry { + char *name; + EntryAlias *alias; + char *type; + char *loc; + char *default_value; + Line *default_if_none; + char *comment; + char *ifdef; + Line *doc; + Line *nocomment; + int array_flag; + struct Entry *next; +} Entry; + + +static const char WS[] = " \t"; +static int gen_default(Entry *, FILE *); +static void gen_parse(Entry *, FILE *); +static void gen_dump(Entry *, FILE *); +static void gen_free(Entry *, FILE *); +static void gen_conf(Entry *, FILE *); +static void gen_default_if_none(Entry *, FILE *); + +static void +lineAdd(Line ** L, const char *str) +{ + while (*L) + L = &(*L)->next; + *L = (Line *)xcalloc(1, sizeof(Line)); + (*L)->data = xstrdup(str); +} + +int +main(int argc, char *argv[]) +{ + FILE *fp; + char *input_filename = argv[1]; + const char *output_filename = _PATH_PARSER; + const char *conf_filename = _PATH_SQUID_CONF; + int linenum = 0; + Entry *entries = NULL; + Entry *curr = NULL; + enum State state; + int rc = 0; + char *ptr = NULL; +#ifdef _SQUID_OS2_ + const char *rmode = "rt"; +#else + const char *rmode = "r"; +#endif + + /*-------------------------------------------------------------------* + * Parse input file + *-------------------------------------------------------------------*/ + + /* Open input file */ + if ((fp = fopen(input_filename, rmode)) == NULL) { + perror(input_filename); + exit(1); + } +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(fileno(fp), O_TEXT); +#endif + state = sSTART; + while (feof(fp) == 0 && state != sEXIT) { + char buff[MAX_LINE]; + char *t; + if (NULL == fgets(buff, MAX_LINE, fp)) + break; + linenum++; + if ((t = strchr(buff, '\n'))) + *t = '\0'; + switch (state) { + case sSTART: + if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { + /* ignore empty and comment lines */ + (void) 0; + } else if (!strncmp(buff, "NAME:", 5)) { + char *name, *aliasname; + if ((name = strtok(buff + 5, WS)) == NULL) { + printf("Error in input file\n"); + exit(1); + } + curr = (Entry *)calloc(1, sizeof(Entry)); + curr->name = xstrdup(name); + while ((aliasname = strtok(NULL, WS)) != NULL) { + EntryAlias *alias = (EntryAlias *)calloc(1, sizeof(EntryAlias)); + alias->next = curr->alias; + alias->name = xstrdup(aliasname); + curr->alias = alias; + } + state = s1; + } else if (!strcmp(buff, "EOF")) { + state = sEXIT; + } else if (!strcmp(buff, "COMMENT_START")) { + curr = (Entry *)calloc(1, sizeof(Entry)); + curr->name = xstrdup("comment"); + curr->loc = xstrdup("none"); + state = sDOC; + } else { + printf("Error on line %d\n", linenum); + printf("--> %s\n", buff); + exit(1); + } + break; + + case s1: + if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { + /* ignore empty and comment lines */ + (void) 0; + } else if (!strncmp(buff, "COMMENT:", 8)) { + ptr = buff + 8; + while (xisspace(*ptr)) + ptr++; + curr->comment = xstrdup(ptr); + } else if (!strncmp(buff, "DEFAULT:", 8)) { + ptr = buff + 8; + while (xisspace(*ptr)) + ptr++; + curr->default_value = xstrdup(ptr); + } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { + ptr = buff + 16; + while (xisspace(*ptr)) + ptr++; + lineAdd(&curr->default_if_none, ptr); + } else if (!strncmp(buff, "LOC:", 4)) { + if ((ptr = strtok(buff + 4, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + curr->loc = xstrdup(ptr); + } else if (!strncmp(buff, "TYPE:", 5)) { + if ((ptr = strtok(buff + 5, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + /* hack to support arrays, rather than pointers */ + if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) { + curr->array_flag = 1; + *(ptr + strlen(ptr) - 2) = '\0'; + } + curr->type = xstrdup(ptr); + } else if (!strncmp(buff, "IFDEF:", 6)) { + if ((ptr = strtok(buff + 6, WS)) == NULL) { + printf("Error on line %d\n", linenum); + exit(1); + } + curr->ifdef = xstrdup(ptr); + } else if (!strcmp(buff, "DOC_START")) { + state = sDOC; + } else if (!strcmp(buff, "DOC_NONE")) { + /* add to list of entries */ + curr->next = entries; + entries = curr; + state = sSTART; + } else { + printf("Error on line %d\n", linenum); + exit(1); + } + break; + + case sDOC: + if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { + Line *head = NULL; + Line *line = curr->doc; + /* reverse order of doc lines */ + while (line != NULL) { + Line *tmp; + tmp = line->next; + line->next = head; + head = line; + line = tmp; + } + curr->doc = head; + /* add to list of entries */ + curr->next = entries; + entries = curr; + state = sSTART; + } else if (!strcmp(buff, "NOCOMMENT_START")) { + state = sNOCOMMENT; + } else { + Line *line = (Line *)calloc(1, sizeof(Line)); + line->data = xstrdup(buff); + line->next = curr->doc; + curr->doc = line; + } + break; + + case sNOCOMMENT: + if (!strcmp(buff, "NOCOMMENT_END")) { + Line *head = NULL; + Line *line = curr->nocomment; + /* reverse order of lines */ + while (line != NULL) { + Line *tmp; + tmp = line->next; + line->next = head; + head = line; + line = tmp; + } + curr->nocomment = head; + state = sDOC; + } else { + Line *line = (Line *)calloc(1, sizeof(Line)); + line->data = xstrdup(buff); + line->next = curr->nocomment; + curr->nocomment = line; + } + break; + + case sEXIT: + assert(0); /* should never get here */ + break; + } + } + if (state != sEXIT) { + printf("Error unexpected EOF\n"); + exit(1); + } else { + /* reverse order of entries */ + Entry *head = NULL; + + while (entries != NULL) { + Entry *tmp; + + tmp = entries->next; + entries->next = head; + head = entries; + entries = tmp; + } + entries = head; + } + fclose(fp); + + /*-------------------------------------------------------------------* + * Generate default_all() + * Generate parse_line() + * Generate dump_config() + * Generate free_all() + * Generate example squid.conf.default file + *-------------------------------------------------------------------*/ + + /* Open output x.c file */ + if ((fp = fopen(output_filename, "w")) == NULL) { + perror(output_filename); + exit(1); + } +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(fileno(fp), O_TEXT); +#endif + fprintf(fp, + "/*\n" + " * Generated automatically from %s by %s\n" + " *\n" + " * Abstract: This file contains routines used to configure the\n" + " * variables in the squid server.\n" + " */\n" + "\n", + input_filename, argv[0] + ); + rc = gen_default(entries, fp); + gen_default_if_none(entries, fp); + gen_parse(entries, fp); + gen_dump(entries, fp); + gen_free(entries, fp); + fclose(fp); + + /* Open output x.conf file */ + if ((fp = fopen(conf_filename, "w")) == NULL) { + perror(conf_filename); + exit(1); + } +#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_) + setmode(fileno(fp), O_TEXT); +#endif + gen_conf(entries, fp); + fclose(fp); + + return (rc); +} + +static int +gen_default(Entry * head, FILE * fp) +{ + Entry *entry; + int rc = 0; + fprintf(fp, + "static void\n" + "default_line(const char *s)\n" + "{\n" + "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" + "\txstrncpy(tmp_line, s, BUFSIZ);\n" + "\txstrncpy(config_input_line, s, BUFSIZ);\n" + "\tconfig_lineno++;\n" + "\tparse_line(tmp_line);\n" + "}\n" + ); + fprintf(fp, + "static void\n" + "default_all(void)\n" + "{\n" + "\tcfg_filename = \"Default Configuration\";\n" + "\tconfig_lineno = 0;\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { + assert(entry->name); + assert(entry != entry->next); + + if (!strcmp(entry->name, "comment")) + continue; + if (entry->loc == NULL) { + fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); + rc |= 1; + continue; + } + if (entry->default_value == NULL) { + fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); + rc |= 1; + continue; + } + assert(entry->default_value); + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + if (strcmp(entry->default_value, "none") == 0) { + fprintf(fp, "\t/* No default for %s */\n", entry->name); + } else { + fprintf(fp, "\tdefault_line(\"%s %s\");\n", + entry->name, + entry->default_value); + } + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } + fprintf(fp, "\tcfg_filename = NULL;\n"); + fprintf(fp, "}\n\n"); + return rc; +} + +static void +gen_default_if_none(Entry * head, FILE * fp) +{ + Entry *entry; + Line *line; + fprintf(fp, + "static void\n" + "defaults_if_none(void)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { + assert(entry->name); + assert(entry->loc); + if (entry->default_if_none == NULL) + continue; + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + if (entry->default_if_none) { + fprintf(fp, + "\tif (check_null_%s(%s)) {\n", + entry->type, + entry->loc); + for (line = entry->default_if_none; line; line = line->next) + fprintf(fp, + "\t\tdefault_line(\"%s %s\");\n", + entry->name, + line->data); + fprintf(fp, "\t}\n"); + } + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } + fprintf(fp, "}\n\n"); +} + +static void +gen_parse(Entry * head, FILE * fp) +{ + Entry *entry; + char *name; + EntryAlias *alias; + + fprintf(fp, + "static int\n" + "parse_line(char *buff)\n" + "{\n" + "\tint\tresult = 1;\n" + "\tchar\t*token;\n" + "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n" + "\tif ((token = strtok(buff, w_space)) == NULL)\n" + "\t\t(void) 0;\t/* ignore empty lines */\n" + ); + + for (entry = head; entry != NULL; entry = entry->next) { + if (strcmp(entry->name, "comment") == 0) + continue; + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + name = entry->name; + alias = entry->alias; + next_alias: + fprintf(fp, "\telse if (!strcmp(token, \"%s\"))\n", name); + assert(entry->loc); + if (strcmp(entry->loc, "none") == 0) { + fprintf(fp, + "\t\tparse_%s();\n", + entry->type + ); + } else { + fprintf(fp, + "\t\tparse_%s(&%s%s);\n", + entry->type, entry->loc, + entry->array_flag ? "[0]" : "" + ); + } + if (alias) { + name = alias->name; + alias = alias->next; + goto next_alias; + } + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } + + fprintf(fp, + "\telse\n" + "\t\tresult = 0; /* failure */\n" + "\treturn(result);\n" + "}\n\n" + ); +} + +static void +gen_dump(Entry * head, FILE * fp) +{ + Entry *entry; + fprintf(fp, + "static void\n" + "dump_config(StoreEntry *entry)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { + assert(entry->loc); + if (strcmp(entry->loc, "none") == 0) + continue; + if (strcmp(entry->name, "comment") == 0) + continue; + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", + entry->type, + entry->name, + entry->loc); + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } + fprintf(fp, "}\n\n"); +} + +static void +gen_free(Entry * head, FILE * fp) +{ + Entry *entry; + fprintf(fp, + "static void\n" + "free_all(void)\n" + "{\n" + ); + for (entry = head; entry != NULL; entry = entry->next) { + assert(entry->loc); + if (strcmp(entry->loc, "none") == 0) + continue; + if (strcmp(entry->name, "comment") == 0) + continue; + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + fprintf(fp, "\tfree_%s(&%s%s);\n", + entry->type, entry->loc, + entry->array_flag ? "[0]" : ""); + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } + fprintf(fp, "}\n\n"); +} + +static int +defined(char *name) +{ + int i = 0; + if (!name) + return 1; + for (i = 0; strcmp(defines[i].name, name) != 0; i++) { + assert(defines[i].name); + } + return defines[i].defined; +} + +static const char * +available_if(char *name) +{ + int i = 0; + assert(name); + for (i = 0; strcmp(defines[i].name, name) != 0; i++) { + assert(defines[i].name); + } + return defines[i].enable; +} + +static void +gen_conf(Entry * head, FILE * fp) +{ + Entry *entry; + char buf[8192]; + Line *def = NULL; + + for (entry = head; entry != NULL; entry = entry->next) { + Line *line; + int blank = 1; + + if (!strcmp(entry->name, "comment")) + (void) 0; + else + fprintf(fp, "# TAG: %s", entry->name); + if (entry->comment) + fprintf(fp, "\t%s", entry->comment); + fprintf(fp, "\n"); + if (!defined(entry->ifdef)) { + fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n"); + fprintf(fp, "# %s option\n#\n", available_if(entry->ifdef)); + } + for (line = entry->doc; line != NULL; line = line->next) { + fprintf(fp, "#%s\n", line->data); + } + if (entry->default_value && strcmp(entry->default_value, "none") != 0) { + sprintf(buf, "%s %s", entry->name, entry->default_value); + lineAdd(&def, buf); + } + if (entry->default_if_none) { + for (line = entry->default_if_none; line; line = line->next) { + sprintf(buf, "%s %s", entry->name, line->data); + lineAdd(&def, buf); + } + } + if (entry->nocomment) + blank = 0; + if (!def && entry->doc && !entry->nocomment && + strcmp(entry->name, "comment") != 0) + lineAdd(&def, "none"); + if (def && (entry->doc || entry->nocomment)) { + if (blank) + fprintf(fp, "#\n"); + fprintf(fp, "#Default:\n"); + while (def != NULL) { + line = def; + def = line->next; + fprintf(fp, "# %s\n", line->data); + xfree(line->data); + xfree(line); + } + blank = 1; + } + if (entry->nocomment && blank) + fprintf(fp, "#\n"); + for (line = entry->nocomment; line != NULL; line = line->next) { + fprintf(fp, "%s\n", line->data); + } + if (entry->doc != NULL) { + fprintf(fp, "\n"); + } + } +} Index: squid/src/cf_gen_defines =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf_gen_defines,v retrieving revision 1.5 retrieving revision 1.5.40.1 diff -u -r1.5 -r1.5.40.1 --- squid/src/cf_gen_defines 3 Dec 2001 08:03:21 -0000 1.5 +++ squid/src/cf_gen_defines 9 Oct 2002 00:23:16 -0000 1.5.40.1 @@ -33,5 +33,5 @@ print "}," } END { - print "{(void *)0L, 0}};" + print "{(char const *)0L, (char const *)0L, 0}};" } --- squid/src/clientStream.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,275 +0,0 @@ - -/* - * $Id: clientStream.c,v 1.3 2002/09/24 10:59:14 rbcollins Exp $ - * - * DEBUG: section 87 Client-side Stream routines. - * AUTHOR: Robert Collins - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -/* - * A client Stream is a uni directional pipe, with the usual non-blocking - * asynchronous approach present elsewhere in squid. - * - * Each pipe node has a data push function, and a data request function. - * This limits flexability - the data flow is no longer assembled at each - * step. - * - * An alternative approach is to pass each node in the pipe the call- - * back to use on each IO call. This allows the callbacks to be changed - * very easily by a participating node, but requires more maintenance - * in each node (store the call back to the msot recent IO request in - * the nodes context.) Such an approach also prevents dynamically - * changing the pipeline from outside without an additional interface - * method to extract the callback and context from the next node. - * - * One important characteristic of the stream is that the readfunc - * on the terminating node, and the callback on the first node - * will be NULL, and never used. - */ - -#include "squid.h" -#include "clientStream.h" - -CBDATA_TYPE(clientStreamNode); - -/* - * TODO: rather than each node undeleting the next, have a clientStreamDelete - * that walks the list - */ - -/* - * clientStream quick notes: - * - * Each node including the HEAD of the clientStream has a cbdataReference - * held by the stream. Freeing the stream then removes that reference - * and cbdataFrees every node. - * Any node with other References, and all nodes downstream will only - * free when those references are released. - * Stream nodes MAY hold references to the data member of the node. - * - * Specifically - on creation no reference is made. - * If you pass a data variable to a node, give it an initial reference. - * If the data member is non-null on FREE, cbdataFree WILL be called. - * This you must never call cbdataFree on your own context without - * explicitly setting the stream node data member to NULL and - * cbdataReferenceDone'ing it. - * - * No data member may hold a reference to it's stream node. - * The stream guarantees that DETACH will be called before - * freeing the node, alowing data members to cleanup. - * - * If a node's data holds a reference to something that needs to - * free the stream a circular reference list will occur. - * This results no data being freed until that reference is removed. - * One way to accomplish this is to explicitly remove the - * data from your own node before freeing the stream. - * - * (i.e. - * mycontext = this->data; - * cbdataReferenceDone (mycontext); - * clientStreamFreeLinst (this->head); - * cbdataFree (mycontext); - * return; - */ - -/* Local functions */ -static FREE clientStreamFree; - -clientStreamNode * -clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status, - void *data) -{ - clientStreamNode *temp; - CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree); - temp = cbdataAlloc(clientStreamNode); - temp->readfunc = readfunc; - temp->callback = callback; - temp->detach = detach; - temp->status = status; - temp->data = data; - return temp; -} - -/* - * Initialise a client Stream. - * list is the stream - * func is the read function for the head - * callback is the callback for the tail - * tailbuf and taillen are the initial buffer and length for the tail. - */ -void -clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus, - void *readdata, CSCB * callback, CSD * cdetach, void *callbackdata, - StoreIOBuffer tailBuffer) -{ - clientStreamNode *temp = clientStreamNew(func, NULL, rdetach, readstatus, - readdata); - dlinkAdd(temp, &temp->node, list); - cbdataReference(temp); - temp->head = list; - clientStreamInsertHead(list, NULL, callback, cdetach, NULL, callbackdata); - temp = list->tail->data; - temp->readBuffer = tailBuffer; -} - -/* - * Doesn't actually insert at head. Instead it inserts one *after* - * head. This is because HEAD is a special node, as is tail - * This function is not suitable for inserting the real HEAD. - * TODO: should we always initalise the buffers and length, to - * allow safe insertion of elements in the downstream cycle? - */ -void -clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback, - CSD * detach, CSS * status, void *data) -{ - clientStreamNode *temp; - - /* test preconditions */ - assert(list != NULL); - assert(list->head); - temp = clientStreamNew(func, callback, detach, status, data); - temp->head = list; - debug(87, 3) - ("clientStreamInsertHead: Inserted node %p with data %p after head\n", - temp, data); - dlinkAddAfter(temp, &temp->node, list->head, list); - cbdataReference(temp); -} - -/* - * Callback the next node the in chain with it's requested data - */ -void -clientStreamCallback(clientStreamNode * this, clientHttpRequest * http, - HttpReply * rep, StoreIOBuffer replyBuffer) -{ - clientStreamNode *next; - assert(this && http && this->node.next); - next = this->node.next->data; - - debug(87, - 3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n", - next->callback, next->data, this); - next->callback(next, http, rep, replyBuffer); -} - -/* - * Call the previous node in the chain to read some data - */ -void -clientStreamRead(clientStreamNode * this, clientHttpRequest * http, - StoreIOBuffer readBuffer) -{ - /* place the parameters on the 'stack' */ - clientStreamNode *prev; - assert(this && http && this->node.prev); - prev = this->node.prev->data; - - debug(87, 3) ("clientStreamRead: Calling %p with cbdata %p from node %p\n", - prev->readfunc, prev->data, this); - this->readBuffer = readBuffer; - prev->readfunc(prev, http); -} - -/* - * Detach from the stream - only allowed for terminal members - */ -void -clientStreamDetach(clientStreamNode * this, clientHttpRequest * http) -{ - clientStreamNode *prev = NULL; - clientStreamNode *temp = this; - - if (this->node.prev) { - prev = this->node.prev->data; - } - assert(this->node.next == NULL); - debug(87, 3) ("clientStreamDetach: Detaching node %p\n", this); - /* And clean up this node */ - /* ESI TODO: push refcount class through to head */ - cbdataReferenceDone(temp); - cbdataFree(this); - /* and tell the prev that the detach has occured */ - /* - * We do it in this order so that the detaching node is always - * at the end of the list - */ - if (prev) { - debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n", - prev->detach, prev->data); - prev->detach(prev, http); - } -} - -/* - * Abort the stream - detach every node in the pipeline. - */ -void -clientStreamAbort(clientStreamNode * this, clientHttpRequest * http) -{ - dlink_list *list; - - assert(this != NULL); - assert(http != NULL); - list = this->head; - debug(87, 3) ("clientStreamAbort: Aborting stream with tail %p\n", - list->tail); - if (list->tail) { - clientStreamDetach(list->tail->data, http); - } -} - -/* - * Call the upstream node to find it's status - */ -clientStream_status_t -clientStreamStatus(clientStreamNode * this, clientHttpRequest * http) -{ - clientStreamNode *prev; - assert(this && http && this->node.prev); - prev = this->node.prev->data; - return prev->status(prev, http); -} - -/* Local function bodies */ -void -clientStreamFree(void *foo) -{ - clientStreamNode *this = foo; - - debug(87, 3) ("Freeing clientStreamNode %p\n", this); - if (this->data) { - cbdataFree(this->data); - } - if (this->node.next || this->node.prev) { - dlinkDelete(&this->node, this->head); - } -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/clientStream.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,290 @@ + +/* + * $Id: clientStream.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 87 Client-side Stream routines. + * AUTHOR: Robert Collins + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with thisObject program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * A client Stream is a uni directional pipe, with the usual non-blocking + * asynchronous approach present elsewhere in squid. + * + * Each pipe node has a data push function, and a data request function. + * This limits flexability - the data flow is no longer assembled at each + * step. + * + * An alternative approach is to pass each node in the pipe the call- + * back to use on each IO call. This allows the callbacks to be changed + * very easily by a participating node, but requires more maintenance + * in each node (store the call back to the msot recent IO request in + * the nodes context.) Such an approach also prevents dynamically + * changing the pipeline from outside without an additional interface + * method to extract the callback and context from the next node. + * + * One important characteristic of the stream is that the readfunc + * on the terminating node, and the callback on the first node + * will be NULL, and never used. + */ + +#include "squid.h" +#include "clientStream.h" + +CBDATA_TYPE(clientStreamNode); + +/* + * TODO: rather than each node undeleting the next, have a clientStreamDelete + * that walks the list + */ + +/* + * clientStream quick notes: + * + * Each node including the HEAD of the clientStream has a cbdataReference + * held by the stream. Freeing the stream then removes that reference + * and cbdataFrees every node. + * Any node with other References, and all nodes downstream will only + * free when those references are released. + * Stream nodes MAY hold references to the data member of the node. + * + * Specifically - on creation no reference is made. + * If you pass a data variable to a node, give it an initial reference. + * If the data member is non-null on FREE, cbdataFree WILL be called. + * This you must never call cbdataFree on your own context without + * explicitly setting the stream node data member to NULL and + * cbdataReferenceDone'ing it. + * + * No data member may hold a reference to it's stream node. + * The stream guarantees that DETACH will be called before + * freeing the node, alowing data members to cleanup. + * + * If a node's data holds a reference to something that needs to + * free the stream a circular reference list will occur. + * This results no data being freed until that reference is removed. + * One way to accomplish thisObject is to explicitly remove the + * data from your own node before freeing the stream. + * + * (i.e. + * mycontext = thisObject->data; + * cbdataReferenceDone (mycontext); + * clientStreamFreeLinst (thisObject->head); + * cbdataFree (mycontext); + * return; + */ + +/* Local functions */ +static FREE clientStreamFree; + +clientStreamNode * +clientStreamNew(CSR * readfunc, CSCB * callback, CSD * detach, CSS * status, + void *data) +{ + clientStreamNode *temp; + CBDATA_INIT_TYPE_FREECB(clientStreamNode, clientStreamFree); + temp = cbdataAlloc(clientStreamNode); + temp->readfunc = readfunc; + temp->callback = callback; + temp->detach = detach; + temp->status = status; + temp->data = data; + return temp; +} + +/* + * Initialise a client Stream. + * list is the stream + * func is the read function for the head + * callback is the callback for the tail + * tailbuf and taillen are the initial buffer and length for the tail. + */ +void +clientStreamInit(dlink_list * list, CSR * func, CSD * rdetach, CSS * readstatus, + void *readdata, CSCB * callback, CSD * cdetach, void *callbackdata, + StoreIOBuffer tailBuffer) +{ + clientStreamNode *temp = clientStreamNew(func, NULL, rdetach, readstatus, + readdata); + dlinkAdd(temp, &temp->node, list); + cbdataReference(temp); + temp->head = list; + clientStreamInsertHead(list, NULL, callback, cdetach, NULL, callbackdata); + temp = (clientStreamNode *)list->tail->data; + temp->readBuffer = tailBuffer; +} + +/* + * Doesn't actually insert at head. Instead it inserts one *after* + * head. This is because HEAD is a special node, as is tail + * This function is not suitable for inserting the real HEAD. + * TODO: should we always initalise the buffers and length, to + * allow safe insertion of elements in the downstream cycle? + */ +void +clientStreamInsertHead(dlink_list * list, CSR * func, CSCB * callback, + CSD * detach, CSS * status, void *data) +{ + clientStreamNode *temp; + + /* test preconditions */ + assert(list != NULL); + assert(list->head); + temp = clientStreamNew(func, callback, detach, status, data); + temp->head = list; + debug(87, 3) + ("clientStreamInsertHead: Inserted node %p with data %p after head\n", + temp, data); + dlinkAddAfter(temp, &temp->node, list->head, list); + cbdataReference(temp); +} + +/* + * Callback the next node the in chain with it's requested data + */ +void +clientStreamCallback(clientStreamNode * thisObject, clientHttpRequest * http, + HttpReply * rep, StoreIOBuffer replyBuffer) +{ + clientStreamNode *next; + assert(thisObject && http && thisObject->node.next); + next = thisObject->next(); + + debug(87, + 3) ("clientStreamCallback: Calling %p with cbdata %p from node %p\n", + next->callback, next->data, thisObject); + next->callback(next, http, rep, replyBuffer); +} + +/* + * Call the previous node in the chain to read some data + */ +void +clientStreamRead(clientStreamNode * thisObject, clientHttpRequest * http, + StoreIOBuffer readBuffer) +{ + /* place the parameters on the 'stack' */ + clientStreamNode *prev; + assert(thisObject && http && thisObject->prev()); + prev = thisObject->prev(); + + debug(87, 3) ("clientStreamRead: Calling %p with cbdata %p from node %p\n", + prev->readfunc, prev->data, thisObject); + thisObject->readBuffer = readBuffer; + prev->readfunc(prev, http); +} + +/* + * Detach from the stream - only allowed for terminal members + */ +void +clientStreamDetach(clientStreamNode * thisObject, clientHttpRequest * http) +{ + clientStreamNode *prev = thisObject->prev(); + clientStreamNode *temp = thisObject; + + assert(thisObject->node.next == NULL); + debug(87, 3) ("clientStreamDetach: Detaching node %p\n", thisObject); + /* And clean up thisObject node */ + /* ESI TODO: push refcount class through to head */ + cbdataReferenceDone(temp); + cbdataFree(thisObject); + /* and tell the prev that the detach has occured */ + /* + * We do it in thisObject order so that the detaching node is always + * at the end of the list + */ + if (prev) { + debug(87, 3) ("clientStreamDetach: Calling %p with cbdata %p\n", + prev->detach, prev->data); + prev->detach(prev, http); + } +} + +/* + * Abort the stream - detach every node in the pipeline. + */ +void +clientStreamAbort(clientStreamNode * thisObject, clientHttpRequest * http) +{ + dlink_list *list; + + assert(thisObject != NULL); + assert(http != NULL); + list = thisObject->head; + debug(87, 3) ("clientStreamAbort: Aborting stream with tail %p\n", + list->tail); + if (list->tail) { + clientStreamDetach((clientStreamNode *)list->tail->data, http); + } +} + +/* + * Call the upstream node to find it's status + */ +clientStream_status_t +clientStreamStatus(clientStreamNode * thisObject, clientHttpRequest * http) +{ + clientStreamNode *prev; + assert(thisObject && http && thisObject->node.prev); + prev = (clientStreamNode *)thisObject->node.prev->data; + return prev->status(prev, http); +} + +/* Local function bodies */ +void +clientStreamFree(void *foo) +{ + clientStreamNode *thisObject = (clientStreamNode *)foo; + + debug(87, 3) ("Freeing clientStreamNode %p\n", thisObject); + if (thisObject->data) { + cbdataFree(thisObject->data); + } + if (thisObject->node.next || thisObject->node.prev) { + dlinkDelete(&thisObject->node, thisObject->head); + } +} + +_clientStreamNode * +_clientStreamNode::prev() const +{ + if (node.prev) + return (_clientStreamNode *)node.prev->data; + else + return NULL; +} + +_clientStreamNode * +_clientStreamNode::next() const +{ + if (node.next) + return (_clientStreamNode *)node.next->data; + else + return NULL; +} Index: squid/src/clientStream.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/clientStream.h,v retrieving revision 1.2.18.1 retrieving revision 1.2.18.2 diff -u -r1.2.18.1 -r1.2.18.2 --- squid/src/clientStream.h 4 Oct 2002 11:09:07 -0000 1.2.18.1 +++ squid/src/clientStream.h 9 Oct 2002 00:23:16 -0000 1.2.18.2 @@ -1,6 +1,6 @@ /* - * $Id: clientStream.h,v 1.2.18.1 2002/10/04 11:09:07 rbcollins Exp $ + * $Id: clientStream.h,v 1.2.18.2 2002/10/09 00:23:16 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -47,6 +47,11 @@ struct _clientStreamNode { +#ifdef __cplusplus +public: + _clientStreamNode *prev() const; + _clientStreamNode *next() const; +#endif dlink_node node; dlink_list *head; /* sucks I know, but hey, the interface is limited */ CSR *readfunc; --- squid/src/client_db.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,337 +0,0 @@ - -/* - * $Id: client_db.c,v 1.7.2.1 2002/10/04 07:07:21 rbcollins Exp $ - * - * DEBUG: section 0 Client Database - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - - -static hash_table *client_table = NULL; -static ClientInfo *clientdbAdd(struct in_addr addr); -static FREE clientdbFreeItem; - -static ClientInfo * -clientdbAdd(struct in_addr addr) -{ - ClientInfo *c; - c = memAllocate(MEM_CLIENT_INFO); - c->hash.key = xstrdup(inet_ntoa(addr)); - c->addr = addr; - hash_join(client_table, &c->hash); - statCounter.client_http.clients++; - return c; -} - -void -clientdbInit(void) -{ - if (client_table) - return; - client_table = hash_create((HASHCMP *) strcmp, 467, hash_string); - cachemgrRegister("client_list", - "Cache Client List", - clientdbDump, - 0, 1); -} - -void -clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size) -{ - char *key; - ClientInfo *c; - if (!Config.onoff.client_db) - return; - key = inet_ntoa(addr); - c = (ClientInfo *) hash_lookup(client_table, key); - if (c == NULL) - c = clientdbAdd(addr); - if (c == NULL) - debug_trap("clientdbUpdate: Failed to add entry"); - if (p == PROTO_HTTP) { - c->Http.n_requests++; - c->Http.result_hist[ltype]++; - kb_incr(&c->Http.kbytes_out, size); - if (logTypeIsATcpHit(ltype)) - kb_incr(&c->Http.hit_kbytes_out, size); - } else if (p == PROTO_ICP) { - c->Icp.n_requests++; - c->Icp.result_hist[ltype]++; - kb_incr(&c->Icp.kbytes_out, size); - if (LOG_UDP_HIT == ltype) - kb_incr(&c->Icp.hit_kbytes_out, size); - } -} - -/* - * clientdbEstablished() - * This function tracks the number of currently established connections - * for a client IP address. When a connection is accepted, call this - * with delta = 1. When the connection is closed, call with delta = - * -1. To get the current value, simply call with delta = 0. - */ -int -clientdbEstablished(struct in_addr addr, int delta) -{ - char *key; - ClientInfo *c; - if (!Config.onoff.client_db) - return 0; - key = inet_ntoa(addr); - c = (ClientInfo *) hash_lookup(client_table, key); - if (c == NULL) - c = clientdbAdd(addr); - if (c == NULL) - debug_trap("clientdbUpdate: Failed to add entry"); - c->n_established += delta; - return c->n_established; -} - -#define CUTOFF_SECONDS 3600 -int -clientdbCutoffDenied(struct in_addr addr) -{ - char *key; - int NR; - int ND; - double p; - ClientInfo *c; - if (!Config.onoff.client_db) - return 0; - key = inet_ntoa(addr); - c = (ClientInfo *) hash_lookup(client_table, key); - if (c == NULL) - return 0; - /* - * If we are in a cutoff window, we don't send a reply - */ - if (squid_curtime - c->cutoff.time < CUTOFF_SECONDS) - return 1; - /* - * Calculate the percent of DENIED replies since the last - * cutoff time. - */ - NR = c->Icp.n_requests - c->cutoff.n_req; - if (NR < 150) - NR = 150; - ND = c->Icp.result_hist[LOG_UDP_DENIED] - c->cutoff.n_denied; - p = 100.0 * ND / NR; - if (p < 95.0) - return 0; - debug(1, 0) ("WARNING: Probable misconfigured neighbor at %s\n", key); - debug(1, 0) ("WARNING: %d of the last %d ICP replies are DENIED\n", ND, NR); - debug(1, 0) ("WARNING: No replies will be sent for the next %d seconds\n", - CUTOFF_SECONDS); - c->cutoff.time = squid_curtime; - c->cutoff.n_req = c->Icp.n_requests; - c->cutoff.n_denied = c->Icp.result_hist[LOG_UDP_DENIED]; - return 1; -} - - -void -clientdbDump(StoreEntry * sentry) -{ - ClientInfo *c; - log_type l; - int icp_total = 0; - int icp_hits = 0; - int http_total = 0; - int http_hits = 0; - storeAppendPrintf(sentry, "Cache Clients:\n"); - hash_first(client_table); - while ((c = (ClientInfo *) hash_next(client_table))) { - storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash)); - storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr)); - storeAppendPrintf(sentry, "Currently established connections: %d\n", - c->n_established); - storeAppendPrintf(sentry, " ICP Requests %d\n", - c->Icp.n_requests); - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) { - if (c->Icp.result_hist[l] == 0) - continue; - icp_total += c->Icp.result_hist[l]; - if (LOG_UDP_HIT == l) - icp_hits += c->Icp.result_hist[l]; - storeAppendPrintf(sentry, - " %-20.20s %7d %3d%%\n", - log_tags[l], - c->Icp.result_hist[l], - percent(c->Icp.result_hist[l], c->Icp.n_requests)); - } - storeAppendPrintf(sentry, " HTTP Requests %d\n", - c->Http.n_requests); - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) { - if (c->Http.result_hist[l] == 0) - continue; - http_total += c->Http.result_hist[l]; - if (logTypeIsATcpHit(l)) - http_hits += c->Http.result_hist[l]; - storeAppendPrintf(sentry, - " %-20.20s %7d %3d%%\n", - log_tags[l], - c->Http.result_hist[l], - percent(c->Http.result_hist[l], c->Http.n_requests)); - } - storeAppendPrintf(sentry, "\n"); - } - storeAppendPrintf(sentry, "TOTALS\n"); - storeAppendPrintf(sentry, "ICP : %d Queries, %d Hits (%3d%%)\n", - icp_total, icp_hits, percent(icp_hits, icp_total)); - storeAppendPrintf(sentry, "HTTP: %d Requests, %d Hits (%3d%%)\n", - http_total, http_hits, percent(http_hits, http_total)); -} - -static void -clientdbFreeItem(void *data) -{ - ClientInfo *c = data; - safe_free(c->hash.key); - memFree(c, MEM_CLIENT_INFO); -} - -void -clientdbFreeMemory(void) -{ - hashFreeItems(client_table, clientdbFreeItem); - hashFreeMemory(client_table); - client_table = NULL; -} - -#if SQUID_SNMP -struct in_addr * -client_entry(struct in_addr *current) -{ - ClientInfo *c = NULL; - char *key; - if (current) { - key = inet_ntoa(*current); - hash_first(client_table); - while ((c = (ClientInfo *) hash_next(client_table))) { - if (!strcmp(key, hashKeyStr(&c->hash))) - break; - } - c = (ClientInfo *) hash_next(client_table); - } else { - hash_first(client_table); - c = (ClientInfo *) hash_next(client_table); - } - hash_last(client_table); - if (c) - return (&c->addr); - else - return (NULL); - -} - -variable_list * -snmp_meshCtblFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - static char key[15]; - ClientInfo *c = NULL; - int aggr = 0; - log_type l; - *ErrP = SNMP_ERR_NOERROR; - debug(49, 6) ("snmp_meshCtblFn: Current : \n"); - snmpDebugOid(6, Var->name, Var->name_length); - snprintf(key, sizeof(key), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4], - Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]); - debug(49, 5) ("snmp_meshCtblFn: [%s] requested!\n", key); - c = (ClientInfo *) hash_lookup(client_table, key); - if (c == NULL) { - debug(49, 5) ("snmp_meshCtblFn: not found.\n"); - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; - } - switch (Var->name[LEN_SQ_NET + 2]) { - case MESH_CTBL_ADDR: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->addr.s_addr, - SMI_IPADDRESS); - break; - case MESH_CTBL_HTBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.kbytes_out.kb, - SMI_COUNTER32); - break; - case MESH_CTBL_HTREQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.n_requests, - SMI_COUNTER32); - break; - case MESH_CTBL_HTHITS: - aggr = 0; - for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) { - if (logTypeIsATcpHit(l)) - aggr += c->Http.result_hist[l]; - } - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) aggr, - SMI_COUNTER32); - break; - case MESH_CTBL_HTHITBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Http.hit_kbytes_out.kb, - SMI_COUNTER32); - break; - case MESH_CTBL_ICPBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.kbytes_out.kb, - SMI_COUNTER32); - break; - case MESH_CTBL_ICPREQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.n_requests, - SMI_COUNTER32); - break; - case MESH_CTBL_ICPHITS: - aggr = c->Icp.result_hist[LOG_UDP_HIT]; - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) aggr, - SMI_COUNTER32); - break; - case MESH_CTBL_ICPHITBYTES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->Icp.hit_kbytes_out.kb, - SMI_COUNTER32); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - debug(49, 5) ("snmp_meshCtblFn: illegal column.\n"); - break; - } - return Answer; -} - -#endif /*SQUID_SNMP */ --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/client_db.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,343 @@ + +/* + * $Id: client_db.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 0 Client Database + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + + +static hash_table *client_table = NULL; +static ClientInfo *clientdbAdd(struct in_addr addr); +static FREE clientdbFreeItem; + +static ClientInfo * +clientdbAdd(struct in_addr addr) +{ + ClientInfo *c; + c = (ClientInfo *)memAllocate(MEM_CLIENT_INFO); + c->hash.key = xstrdup(inet_ntoa(addr)); + c->addr = addr; + hash_join(client_table, &c->hash); + statCounter.client_http.clients++; + return c; +} + +void +clientdbInit(void) +{ + if (client_table) + return; + client_table = hash_create((HASHCMP *) strcmp, 467, hash_string); + cachemgrRegister("client_list", + "Cache Client List", + clientdbDump, + 0, 1); +} + +void +clientdbUpdate(struct in_addr addr, log_type ltype, protocol_t p, size_t size) +{ + char *key; + ClientInfo *c; + if (!Config.onoff.client_db) + return; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) + c = clientdbAdd(addr); + if (c == NULL) + debug_trap("clientdbUpdate: Failed to add entry"); + if (p == PROTO_HTTP) { + c->Http.n_requests++; + c->Http.result_hist[ltype]++; + kb_incr(&c->Http.kbytes_out, size); + if (logTypeIsATcpHit(ltype)) + kb_incr(&c->Http.hit_kbytes_out, size); + } else if (p == PROTO_ICP) { + c->Icp.n_requests++; + c->Icp.result_hist[ltype]++; + kb_incr(&c->Icp.kbytes_out, size); + if (LOG_UDP_HIT == ltype) + kb_incr(&c->Icp.hit_kbytes_out, size); + } +} + +/* + * clientdbEstablished() + * This function tracks the number of currently established connections + * for a client IP address. When a connection is accepted, call this + * with delta = 1. When the connection is closed, call with delta = + * -1. To get the current value, simply call with delta = 0. + */ +int +clientdbEstablished(struct in_addr addr, int delta) +{ + char *key; + ClientInfo *c; + if (!Config.onoff.client_db) + return 0; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) + c = clientdbAdd(addr); + if (c == NULL) + debug_trap("clientdbUpdate: Failed to add entry"); + c->n_established += delta; + return c->n_established; +} + +#define CUTOFF_SECONDS 3600 +int +clientdbCutoffDenied(struct in_addr addr) +{ + char *key; + int NR; + int ND; + double p; + ClientInfo *c; + if (!Config.onoff.client_db) + return 0; + key = inet_ntoa(addr); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) + return 0; + /* + * If we are in a cutoff window, we don't send a reply + */ + if (squid_curtime - c->cutoff.time < CUTOFF_SECONDS) + return 1; + /* + * Calculate the percent of DENIED replies since the last + * cutoff time. + */ + NR = c->Icp.n_requests - c->cutoff.n_req; + if (NR < 150) + NR = 150; + ND = c->Icp.result_hist[LOG_UDP_DENIED] - c->cutoff.n_denied; + p = 100.0 * ND / NR; + if (p < 95.0) + return 0; + debug(1, 0) ("WARNING: Probable misconfigured neighbor at %s\n", key); + debug(1, 0) ("WARNING: %d of the last %d ICP replies are DENIED\n", ND, NR); + debug(1, 0) ("WARNING: No replies will be sent for the next %d seconds\n", + CUTOFF_SECONDS); + c->cutoff.time = squid_curtime; + c->cutoff.n_req = c->Icp.n_requests; + c->cutoff.n_denied = c->Icp.result_hist[LOG_UDP_DENIED]; + return 1; +} + +log_type &operator++ (log_type &aLogType) +{ + aLogType = (log_type)(++(int)aLogType); + return aLogType; +} + + +void +clientdbDump(StoreEntry * sentry) +{ + ClientInfo *c; + log_type l; + int icp_total = 0; + int icp_hits = 0; + int http_total = 0; + int http_hits = 0; + storeAppendPrintf(sentry, "Cache Clients:\n"); + hash_first(client_table); + while ((c = (ClientInfo *) hash_next(client_table))) { + storeAppendPrintf(sentry, "Address: %s\n", hashKeyStr(&c->hash)); + storeAppendPrintf(sentry, "Name: %s\n", fqdnFromAddr(c->addr)); + storeAppendPrintf(sentry, "Currently established connections: %d\n", + c->n_established); + storeAppendPrintf(sentry, " ICP Requests %d\n", + c->Icp.n_requests); + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { + if (c->Icp.result_hist[l] == 0) + continue; + icp_total += c->Icp.result_hist[l]; + if (LOG_UDP_HIT == l) + icp_hits += c->Icp.result_hist[l]; + storeAppendPrintf(sentry, + " %-20.20s %7d %3d%%\n", + log_tags[l], + c->Icp.result_hist[l], + percent(c->Icp.result_hist[l], c->Icp.n_requests)); + } + storeAppendPrintf(sentry, " HTTP Requests %d\n", + c->Http.n_requests); + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; ++l) { + if (c->Http.result_hist[l] == 0) + continue; + http_total += c->Http.result_hist[l]; + if (logTypeIsATcpHit(l)) + http_hits += c->Http.result_hist[l]; + storeAppendPrintf(sentry, + " %-20.20s %7d %3d%%\n", + log_tags[l], + c->Http.result_hist[l], + percent(c->Http.result_hist[l], c->Http.n_requests)); + } + storeAppendPrintf(sentry, "\n"); + } + storeAppendPrintf(sentry, "TOTALS\n"); + storeAppendPrintf(sentry, "ICP : %d Queries, %d Hits (%3d%%)\n", + icp_total, icp_hits, percent(icp_hits, icp_total)); + storeAppendPrintf(sentry, "HTTP: %d Requests, %d Hits (%3d%%)\n", + http_total, http_hits, percent(http_hits, http_total)); +} + +static void +clientdbFreeItem(void *data) +{ + ClientInfo *c = (ClientInfo *)data; + safe_free(c->hash.key); + memFree(c, MEM_CLIENT_INFO); +} + +void +clientdbFreeMemory(void) +{ + hashFreeItems(client_table, clientdbFreeItem); + hashFreeMemory(client_table); + client_table = NULL; +} + +#if SQUID_SNMP +struct in_addr * +client_entry(struct in_addr *current) +{ + ClientInfo *c = NULL; + char *key; + if (current) { + key = inet_ntoa(*current); + hash_first(client_table); + while ((c = (ClientInfo *) hash_next(client_table))) { + if (!strcmp(key, hashKeyStr(&c->hash))) + break; + } + c = (ClientInfo *) hash_next(client_table); + } else { + hash_first(client_table); + c = (ClientInfo *) hash_next(client_table); + } + hash_last(client_table); + if (c) + return (&c->addr); + else + return (NULL); + +} + +variable_list * +snmp_meshCtblFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + static char key[15]; + ClientInfo *c = NULL; + int aggr = 0; + log_type l; + *ErrP = SNMP_ERR_NOERROR; + debug(49, 6) ("snmp_meshCtblFn: Current : \n"); + snmpDebugOid(6, Var->name, Var->name_length); + snprintf(key, sizeof(key), "%d.%d.%d.%d", Var->name[LEN_SQ_NET + 3], Var->name[LEN_SQ_NET + 4], + Var->name[LEN_SQ_NET + 5], Var->name[LEN_SQ_NET + 6]); + debug(49, 5) ("snmp_meshCtblFn: [%s] requested!\n", key); + c = (ClientInfo *) hash_lookup(client_table, key); + if (c == NULL) { + debug(49, 5) ("snmp_meshCtblFn: not found.\n"); + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; + } + switch (Var->name[LEN_SQ_NET + 2]) { + case MESH_CTBL_ADDR: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->addr.s_addr, + SMI_IPADDRESS); + break; + case MESH_CTBL_HTBYTES: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_HTREQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.n_requests, + SMI_COUNTER32); + break; + case MESH_CTBL_HTHITS: + aggr = 0; + for (l = LOG_TAG_NONE; l < LOG_TYPE_MAX; l++) { + if (logTypeIsATcpHit(l)) + aggr += c->Http.result_hist[l]; + } + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) aggr, + SMI_COUNTER32); + break; + case MESH_CTBL_HTHITBYTES: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Http.hit_kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPBYTES: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.kbytes_out.kb, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPREQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.n_requests, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPHITS: + aggr = c->Icp.result_hist[LOG_UDP_HIT]; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) aggr, + SMI_COUNTER32); + break; + case MESH_CTBL_ICPHITBYTES: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) c->Icp.hit_kbytes_out.kb, + SMI_COUNTER32); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + debug(49, 5) ("snmp_meshCtblFn: illegal column.\n"); + break; + } + return Answer; +} + +#endif /*SQUID_SNMP */ --- squid/src/dnsserver.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,354 +0,0 @@ - -/* - * $Id: dnsserver.c,v 1.6 2002/07/01 16:06:40 squidadm Exp $ - * - * DEBUG: section 0 DNS Resolver - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "config.h" - -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_STDIO_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_CTYPE_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_FCNTL_H -#include -#endif -#if HAVE_GRP_H -#include -#endif -#if HAVE_GNUMALLOC_H -#include -#elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) -#include -#endif -#if HAVE_MEMORY_H -#include -#endif -#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */ -#define _SQUID_NETDB_H_ -#include -#endif -#if HAVE_PWD_H -#include -#endif -#if HAVE_SIGNAL_H -#include -#endif -#if HAVE_TIME_H -#include -#endif -#if HAVE_SYS_PARAM_H -#include -#endif -#if HAVE_SYS_TIME_H -#include -#endif -#if HAVE_SYS_RESOURCE_H -#include /* needs sys/time.h above it */ -#endif -#if HAVE_SYS_SOCKET_H -#include -#endif -#if HAVE_NETINET_IN_H -#include -#endif -#if HAVE_ARPA_INET_H -#include -#endif -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_UN_H -#include -#endif -#if HAVE_SYS_WAIT_H -#include -#endif -#if HAVE_LIBC_H -#include -#endif -#ifdef HAVE_SYS_SYSCALL_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STRINGS_H -#include -#endif -#if HAVE_BSTRING_H -#include -#endif -#ifdef HAVE_CRYPT_H -#include -#endif -#if HAVE_SYS_SELECT_H -#include -#endif -#if HAVE_GETOPT_H -#include -#endif - -#if HAVE_ARPA_NAMESER_H -#include -#endif -#if HAVE_RESOLV_H -#include -#endif - -#include "util.h" -#include "snprintf.h" - -#if !defined(_SQUID_AIX_) -extern int h_errno; -#endif - -#if LIBRESOLV_DNS_TTL_HACK -extern int _dns_ttl_; /* this is a really *dirty* hack - bne */ -#endif - -#ifdef _SQUID_NEXT_ -/* This is a really bloody hack. frank@langen.bull.de - * Workaround bug in gethostbyname which sets h_errno wrong - * WARNING: This hack queries only the resolver and not NetInfo or YP - */ -struct hostent *_res_gethostbyname(char *name); -#define gethostbyname _res_gethostbyname -#endif /* _SQUID_NEXT_ */ - -static struct in_addr no_addr; - -#ifdef _SQUID_OS2_ -struct state _res = -{0}; /* it's not in any of the libraries */ -#endif - -/* error messages from gethostbyname() */ -static char * -my_h_msgs(int x) -{ - if (x == HOST_NOT_FOUND) - return "Host not found (authoritative)"; - else if (x == TRY_AGAIN) - return "Host not found (non-authoritative)"; - else if (x == NO_RECOVERY) - return "Non recoverable errors"; - else if (x == NO_DATA || x == NO_ADDRESS) - return "Valid name, no data record of requested type"; - else - return "Unknown DNS problem"; -} - -#define REQ_SZ 512 - -static void -lookup(const char *buf) -{ - const struct hostent *result = NULL; - int reverse = 0; - int ttl = 0; - int retry = 0; - int i; - struct in_addr addr; - if (0 == strcmp(buf, "$shutdown")) - exit(0); - if (0 == strcmp(buf, "$hello")) { - printf("$alive\n"); - return; - } - /* check if it's already an IP address in text form. */ - for (;;) { - if (safe_inet_addr(buf, &addr)) { - reverse = 1; - result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET); - } else { - result = gethostbyname(buf); - } - if (NULL != result) - break; - if (h_errno != TRY_AGAIN) - break; - if (++retry == 3) - break; - sleep(1); - } - if (NULL == result) { - if (h_errno == TRY_AGAIN) { - printf("$fail Name Server for domain '%s' is unavailable.\n", buf); - } else { - printf("$fail DNS Domain '%s' is invalid: %s.\n", - buf, my_h_msgs(h_errno)); - } - return; - } -#if LIBRESOLV_DNS_TTL_HACK - /* DNS TTL handling - bne@CareNet.hu - * for first try it's a dirty hack, by hacking getanswer - * to place the ttl in a global variable */ - if (_dns_ttl_ > -1) - ttl = _dns_ttl_; -#endif - if (reverse) { - printf("$name %d %s\n", ttl, result->h_name); - return; - } - printf("$addr %d", ttl); - for (i = 0; NULL != result->h_addr_list[i]; i++) { - if (32 == i) - break; - xmemcpy(&addr, result->h_addr_list[i], sizeof(addr)); - printf(" %s", inet_ntoa(addr)); - } - printf("\n"); -} - -static void -usage(void) -{ - fprintf(stderr, "usage: dnsserver -Dhv -s nameserver\n" - "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" - "\t-h Help\n" - "\t-v Version\n" - "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" - "\t must be an IP address, -s option may be repeated\n"); -} - -int -main(int argc, char *argv[]) -{ - char request[512]; - char *t = NULL; - int c; - int opt_s = 0; - extern char *optarg; - - safe_inet_addr("255.255.255.255", &no_addr); - -#if HAVE_RES_INIT - res_init(); -#ifdef RES_DEFAULT - _res.options = RES_DEFAULT; -#endif -#ifdef RES_DEFNAMES - _res.options &= ~RES_DEFNAMES; -#endif -#ifdef RES_DNSRCH - _res.options &= ~RES_DNSRCH; -#endif -#endif - - while ((c = getopt(argc, argv, "Dhs:v")) != -1) { - switch (c) { - case 'D': -#ifdef RES_DEFNAMES - _res.options |= RES_DEFNAMES; -#endif -#ifdef RES_DNSRCH - _res.options |= RES_DNSRCH; -#endif - break; - case 's': -#if HAVE_RES_INIT - if (opt_s == 0) { - _res.nscount = 0; - /* - * Setting RES_INIT here causes coredumps when -s is - * used with -D option. It looks to me like setting - * RES_INIT is wrong. The resolver code sets RES_INIT - * after calling res_init(). When we change the _res - * structure and set RES_INIT, some internal resolver - * structures get confused. -DW 2.1.p1 - */ -#if SEEMS_WRONG - _res.options |= RES_INIT; -#endif - opt_s = 1; - } else if (_res.nscount == MAXNS) { - fprintf(stderr, "Too many -s options, only %d are allowed\n", - MAXNS); - break; - } -#if HAVE_RES_NSADDR_LIST - _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; - safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr); -#elif HAVE_RES_NS_LIST - _res.ns_list[_res.nscount] = _res.ns_list[0]; - safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr); -#else /* Unknown NS list format */ - fprintf(stderr, "-s is not supported on this resolver\n"); -#endif -#else /* !HAVE_RES_INIT */ - fprintf(stderr, "-s is not supported on this resolver\n"); -#endif /* HAVE_RES_INIT */ - break; - case 'v': - printf("dnsserver version %s\n", VERSION); - exit(0); - break; - case 'h': - default: - usage(); - exit(1); - break; - } - } - - for (;;) { - memset(request, '\0', REQ_SZ); - if (fgets(request, REQ_SZ, stdin) == NULL) - exit(1); - t = strrchr(request, '\n'); - if (t == NULL) /* Ignore if no newline */ - continue; - *t = '\0'; /* strip NL */ - if ((t = strrchr(request, '\r')) != NULL) - *t = '\0'; /* strip CR */ - lookup(request); - fflush(stdout); - } - /* NOTREACHED */ - return 0; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/dnsserver.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,354 @@ + +/* + * $Id: dnsserver.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 0 DNS Resolver + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "config.h" + +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_STDIO_H +#include +#endif +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_GRP_H +#include +#endif +#if HAVE_GNUMALLOC_H +#include +#elif HAVE_MALLOC_H && !defined(_SQUID_FREEBSD_) && !defined(_SQUID_NEXT_) +#include +#endif +#if HAVE_MEMORY_H +#include +#endif +#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_) /* protect NEXTSTEP */ +#define _SQUID_NETDB_H_ +#include +#endif +#if HAVE_PWD_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_TIME_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include /* needs sys/time.h above it */ +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_UN_H +#include +#endif +#if HAVE_SYS_WAIT_H +#include +#endif +#if HAVE_LIBC_H +#include +#endif +#ifdef HAVE_SYS_SYSCALL_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#if HAVE_BSTRING_H +#include +#endif +#ifdef HAVE_CRYPT_H +#include +#endif +#if HAVE_SYS_SELECT_H +#include +#endif +#if HAVE_GETOPT_H +#include +#endif + +#if HAVE_ARPA_NAMESER_H +#include +#endif +#if HAVE_RESOLV_H +#include +#endif + +#include "util.h" +#include "snprintf.h" + +#if !defined(_SQUID_AIX_) +extern int h_errno; +#endif + +#if LIBRESOLV_DNS_TTL_HACK +extern int _dns_ttl_; /* this is a really *dirty* hack - bne */ +#endif + +#ifdef _SQUID_NEXT_ +/* This is a really bloody hack. frank@langen.bull.de + * Workaround bug in gethostbyname which sets h_errno wrong + * WARNING: This hack queries only the resolver and not NetInfo or YP + */ +struct hostent *_res_gethostbyname(char *name); +#define gethostbyname _res_gethostbyname +#endif /* _SQUID_NEXT_ */ + +static struct in_addr no_addr; + +#ifdef _SQUID_OS2_ +struct state _res = +{0}; /* it's not in any of the libraries */ +#endif + +/* error messages from gethostbyname() */ +static char * +my_h_msgs(int x) +{ + if (x == HOST_NOT_FOUND) + return "Host not found (authoritative)"; + else if (x == TRY_AGAIN) + return "Host not found (non-authoritative)"; + else if (x == NO_RECOVERY) + return "Non recoverable errors"; + else if (x == NO_DATA || x == NO_ADDRESS) + return "Valid name, no data record of requested type"; + else + return "Unknown DNS problem"; +} + +#define REQ_SZ 512 + +static void +lookup(const char *buf) +{ + const struct hostent *result = NULL; + int reverse = 0; + int ttl = 0; + int retry = 0; + int i; + struct in_addr addr; + if (0 == strcmp(buf, "$shutdown")) + exit(0); + if (0 == strcmp(buf, "$hello")) { + printf("$alive\n"); + return; + } + /* check if it's already an IP address in text form. */ + for (;;) { + if (safe_inet_addr(buf, &addr)) { + reverse = 1; + result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET); + } else { + result = gethostbyname(buf); + } + if (NULL != result) + break; + if (h_errno != TRY_AGAIN) + break; + if (++retry == 3) + break; + sleep(1); + } + if (NULL == result) { + if (h_errno == TRY_AGAIN) { + printf("$fail Name Server for domain '%s' is unavailable.\n", buf); + } else { + printf("$fail DNS Domain '%s' is invalid: %s.\n", + buf, my_h_msgs(h_errno)); + } + return; + } +#if LIBRESOLV_DNS_TTL_HACK + /* DNS TTL handling - bne@CareNet.hu + * for first try it's a dirty hack, by hacking getanswer + * to place the ttl in a global variable */ + if (_dns_ttl_ > -1) + ttl = _dns_ttl_; +#endif + if (reverse) { + printf("$name %d %s\n", ttl, result->h_name); + return; + } + printf("$addr %d", ttl); + for (i = 0; NULL != result->h_addr_list[i]; i++) { + if (32 == i) + break; + xmemcpy(&addr, result->h_addr_list[i], sizeof(addr)); + printf(" %s", inet_ntoa(addr)); + } + printf("\n"); +} + +static void +usage(void) +{ + fprintf(stderr, "usage: dnsserver -Dhv -s nameserver\n" + "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" + "\t-h Help\n" + "\t-v Version\n" + "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" + "\t must be an IP address, -s option may be repeated\n"); +} + +int +main(int argc, char *argv[]) +{ + char request[512]; + char *t = NULL; + int c; + int opt_s = 0; + extern char *optarg; + + safe_inet_addr("255.255.255.255", &no_addr); + +#if HAVE_RES_INIT + res_init(); +#ifdef RES_DEFAULT + _res.options = RES_DEFAULT; +#endif +#ifdef RES_DEFNAMES + _res.options &= ~RES_DEFNAMES; +#endif +#ifdef RES_DNSRCH + _res.options &= ~RES_DNSRCH; +#endif +#endif + + while ((c = getopt(argc, argv, "Dhs:v")) != -1) { + switch (c) { + case 'D': +#ifdef RES_DEFNAMES + _res.options |= RES_DEFNAMES; +#endif +#ifdef RES_DNSRCH + _res.options |= RES_DNSRCH; +#endif + break; + case 's': +#if HAVE_RES_INIT + if (opt_s == 0) { + _res.nscount = 0; + /* + * Setting RES_INIT here causes coredumps when -s is + * used with -D option. It looks to me like setting + * RES_INIT is wrong. The resolver code sets RES_INIT + * after calling res_init(). When we change the _res + * structure and set RES_INIT, some internal resolver + * structures get confused. -DW 2.1.p1 + */ +#if SEEMS_WRONG + _res.options |= RES_INIT; +#endif + opt_s = 1; + } else if (_res.nscount == MAXNS) { + fprintf(stderr, "Too many -s options, only %d are allowed\n", + MAXNS); + break; + } +#if HAVE_RES_NSADDR_LIST + _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; + safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr); +#elif HAVE_RES_NS_LIST + _res.ns_list[_res.nscount] = _res.ns_list[0]; + safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr); +#else /* Unknown NS list format */ + fprintf(stderr, "-s is not supported on this resolver\n"); +#endif +#else /* !HAVE_RES_INIT */ + fprintf(stderr, "-s is not supported on this resolver\n"); +#endif /* HAVE_RES_INIT */ + break; + case 'v': + printf("dnsserver version %s\n", VERSION); + exit(0); + break; + case 'h': + default: + usage(); + exit(1); + break; + } + } + + for (;;) { + memset(request, '\0', REQ_SZ); + if (fgets(request, REQ_SZ, stdin) == NULL) + exit(1); + t = strrchr(request, '\n'); + if (t == NULL) /* Ignore if no newline */ + continue; + *t = '\0'; /* strip NL */ + if ((t = strrchr(request, '\r')) != NULL) + *t = '\0'; /* strip CR */ + lookup(request); + fflush(stdout); + } + /* NOTREACHED */ + return 0; +} --- squid/src/ipcache.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,823 +0,0 @@ - -/* - * $Id: ipcache.c,v 1.19.6.1 2002/10/04 07:07:26 rbcollins Exp $ - * - * DEBUG: section 14 IP Cache - * AUTHOR: Harvest Derived - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -typedef struct _ipcache_entry ipcache_entry; - -struct _ipcache_entry { - hash_link hash; /* must be first */ - time_t lastref; - time_t expires; - ipcache_addrs addrs; - IPH *handler; - void *handlerData; - char *error_message; - struct timeval request_time; - dlink_node lru; - unsigned short locks; - struct { - unsigned int negcached:1; - unsigned int fromhosts:1; - } flags; -}; - -static struct { - int requests; - int replies; - int hits; - int misses; - int negative_hits; - int errors; - int ghbn_calls; /* # calls to blocking gethostbyname() */ - int release_locked; -} IpcacheStats; - -static dlink_list lru_list; - -static FREE ipcacheFreeEntry; -#if USE_DNSSERVERS -static HLPCB ipcacheHandleReply; -#else -static IDNSCB ipcacheHandleReply; -#endif -static IPH dummy_handler; -static int ipcacheExpiredEntry(ipcache_entry *); -static int ipcache_testname(void); -#if USE_DNSSERVERS -static ipcache_entry *ipcacheParse(const char *buf); -#else -static ipcache_entry *ipcacheParse(rfc1035_rr *, int); -#endif -static ipcache_entry *ipcache_get(const char *); -static void ipcacheLockEntry(ipcache_entry *); -static void ipcacheStatPrint(ipcache_entry *, StoreEntry *); -static void ipcacheUnlockEntry(ipcache_entry *); -static void ipcacheRelease(ipcache_entry *); - -static ipcache_addrs static_addrs; -static hash_table *ip_table = NULL; - -static long ipcache_low = 180; -static long ipcache_high = 200; - -#if LIBRESOLV_DNS_TTL_HACK -extern int _dns_ttl_; -#endif - -static int -ipcache_testname(void) -{ - wordlist *w = NULL; - debug(14, 1) ("Performing DNS Tests...\n"); - if ((w = Config.dns_testname_list) == NULL) - return 1; - for (; w; w = w->next) { - IpcacheStats.ghbn_calls++; - if (gethostbyname(w->key) != NULL) - return 1; - } - return 0; -} - -/* removes the given ipcache entry */ -static void -ipcacheRelease(ipcache_entry * i) -{ - hash_remove_link(ip_table, (hash_link *) i); - dlinkDelete(&i->lru, &lru_list); - ipcacheFreeEntry(i); -} - -static ipcache_entry * -ipcache_get(const char *name) -{ - if (ip_table != NULL) - return (ipcache_entry *) hash_lookup(ip_table, name); - else - return NULL; -} - -static int -ipcacheExpiredEntry(ipcache_entry * i) -{ - /* all static entries are locked, so this takes care of them too */ - if (i->locks != 0) - return 0; - if (i->addrs.count == 0) - if (0 == i->flags.negcached) - return 1; - if (i->expires > squid_curtime) - return 0; - return 1; -} - -void -ipcache_purgelru(void *voidnotused) -{ - dlink_node *m; - dlink_node *prev = NULL; - ipcache_entry *i; - int removed = 0; - eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1); - for (m = lru_list.tail; m; m = prev) { - if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low) - break; - prev = m->prev; - i = m->data; - if (i->locks != 0) - continue; - ipcacheRelease(i); - removed++; - } - debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed); -} - -/* purges entries added from /etc/hosts (or whatever). */ -static void -purge_entries_fromhosts(void) -{ - dlink_node *m = lru_list.head; - ipcache_entry *i = NULL, *t; - while (m) { - if (i != NULL) { /* need to delay deletion */ - ipcacheRelease(i); /* we just override locks */ - i = NULL; - } - t = m->data; - if (t->flags.fromhosts) - i = t; - m = m->next; - } - if (i != NULL) - ipcacheRelease(i); -} - -/* create blank ipcache_entry */ -static ipcache_entry * -ipcacheCreateEntry(const char *name) -{ - static ipcache_entry *i; - i = memAllocate(MEM_IPCACHE_ENTRY); - i->hash.key = xstrdup(name); - i->expires = squid_curtime + Config.negativeDnsTtl; - return i; -} - -static void -ipcacheAddEntry(ipcache_entry * i) -{ - hash_link *e = hash_lookup(ip_table, i->hash.key); - if (NULL != e) { - /* avoid colission */ - ipcache_entry *q = (ipcache_entry *) e; - ipcacheRelease(q); - } - hash_join(ip_table, &i->hash); - dlinkAdd(i, &i->lru, &lru_list); - i->lastref = squid_curtime; -} - -/* walks down the pending list, calling handlers */ -static void -ipcacheCallback(ipcache_entry * i) -{ - IPH *callback = i->handler; - void *cbdata; - i->lastref = squid_curtime; - if (!i->handler) - return; - ipcacheLockEntry(i); - callback = i->handler; - i->handler = NULL; - if (cbdataReferenceValidDone(i->handlerData, &cbdata)) { - dns_error_message = i->error_message; - callback(i->flags.negcached ? NULL : &i->addrs, cbdata); - } - ipcacheUnlockEntry(i); -} - -static ipcache_entry * -#if USE_DNSSERVERS -ipcacheParse(const char *inbuf) -{ - LOCAL_ARRAY(char, buf, DNS_INBUF_SZ); - char *token; - static ipcache_entry i; - int j; - int k; - int ipcount = 0; - int ttl; - char A[32][16]; - memset(&i, '\0', sizeof(i)); - i.expires = squid_curtime; - i.flags.negcached = 1; - if (inbuf == NULL) { - debug(14, 1) ("ipcacheParse: Got reply\n"); - i.error_message = xstrdup("Internal Squid Error"); - return &i; - } - xstrncpy(buf, inbuf, DNS_INBUF_SZ); - debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf); - token = strtok(buf, w_space); - if (NULL == token) { - debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n"); - return &i; - } - if (0 == strcmp(token, "$fail")) { - i.expires = squid_curtime + Config.negativeDnsTtl; - token = strtok(NULL, "\n"); - assert(NULL != token); - i.error_message = xstrdup(token); - return &i; - } - if (0 != strcmp(token, "$addr")) { - debug(14, 1) ("ipcacheParse: Got '%s', expecting '$addr'\n", token); - return &i; - } - token = strtok(NULL, w_space); - if (NULL == token) { - debug(14, 1) ("ipcacheParse: Got , expecting TTL\n"); - return &i; - } - i.flags.negcached = 0; - ttl = atoi(token); - if (ttl > 0) - i.expires = squid_curtime + ttl; - else - i.expires = squid_curtime + Config.positiveDnsTtl; - while (NULL != (token = strtok(NULL, w_space))) { - xstrncpy(A[ipcount], token, 16); - if (++ipcount == 32) - break; - } - if (0 == ipcount) { - i.addrs.in_addrs = NULL; - i.addrs.bad_mask = NULL; - } else { - i.addrs.in_addrs = xcalloc(ipcount, sizeof(struct in_addr)); - i.addrs.bad_mask = xcalloc(ipcount, sizeof(unsigned char)); - } - for (j = 0, k = 0; k < ipcount; k++) { - if (safe_inet_addr(A[k], &i.addrs.in_addrs[j])) - j++; - else - debug(14, 1) ("ipcacheParse: Invalid IP address '%s'\n", A[k]); - } - i.addrs.count = (unsigned char) j; - return &i; -} -#else -ipcacheParse(rfc1035_rr * answers, int nr) -{ - static ipcache_entry i; - int k; - int j; - int na = 0; - memset(&i, '\0', sizeof(i)); - i.expires = squid_curtime + Config.negativeDnsTtl; - i.flags.negcached = 1; - if (nr < 0) { - debug(14, 3) ("ipcacheParse: Lookup failed (error %d)\n", - rfc1035_errno); - assert(rfc1035_error_message); - i.error_message = xstrdup(rfc1035_error_message); - return &i; - } - if (nr == 0) { - debug(14, 3) ("ipcacheParse: No DNS records\n"); - i.error_message = xstrdup("No DNS records"); - return &i; - } - assert(answers); - for (j = 0, k = 0; k < nr; k++) { - if (answers[k].type != RFC1035_TYPE_A) - continue; - if (answers[k]._class != RFC1035_CLASS_IN) - continue; - na++; - } - if (na == 0) { - debug(14, 1) ("ipcacheParse: No Address records\n"); - i.error_message = xstrdup("No Address records"); - return &i; - } - i.flags.negcached = 0; - i.addrs.in_addrs = xcalloc(na, sizeof(struct in_addr)); - i.addrs.bad_mask = xcalloc(na, sizeof(unsigned char)); - i.addrs.count = (unsigned char) na; - for (j = 0, k = 0; k < nr; k++) { - if (answers[k].type != RFC1035_TYPE_A) - continue; - if (answers[k]._class != RFC1035_CLASS_IN) - continue; - if (j == 0) - i.expires = squid_curtime + answers[k].ttl; - assert(answers[k].rdlength == 4); - xmemcpy(&i.addrs.in_addrs[j++], answers[k].rdata, 4); - debug(14, 3) ("ipcacheParse: #%d %s\n", - j - 1, - inet_ntoa(i.addrs.in_addrs[j - 1])); - } - assert(j == na); - return &i; -} -#endif - -static void -#if USE_DNSSERVERS -ipcacheHandleReply(void *data, char *reply) -#else -ipcacheHandleReply(void *data, rfc1035_rr * answers, int na) -#endif -{ - generic_cbdata *c = data; - ipcache_entry *i = c->data; - ipcache_entry *x = NULL; - cbdataFree(c); - c = NULL; - IpcacheStats.replies++; - statHistCount(&statCounter.dns.svc_time, - tvSubMsec(i->request_time, current_time)); -#if USE_DNSSERVERS - x = ipcacheParse(reply); -#else - x = ipcacheParse(answers, na); -#endif - assert(x); - i->addrs = x->addrs; - i->error_message = x->error_message; - i->expires = x->expires; - i->flags = x->flags; - ipcacheAddEntry(i); - ipcacheCallback(i); -} - -void -ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData) -{ - ipcache_entry *i = NULL; - const ipcache_addrs *addrs = NULL; - generic_cbdata *c; - assert(handler != NULL); - debug(14, 4) ("ipcache_nbgethostbyname: Name '%s'.\n", name); - IpcacheStats.requests++; - if (name == NULL || name[0] == '\0') { - debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n"); - handler(NULL, handlerData); - return; - } - if ((addrs = ipcacheCheckNumeric(name))) { - handler(addrs, handlerData); - return; - } - i = ipcache_get(name); - if (NULL == i) { - /* miss */ - (void) 0; - } else if (ipcacheExpiredEntry(i)) { - /* hit, but expired -- bummer */ - ipcacheRelease(i); - i = NULL; - } else { - /* hit */ - debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name); - if (i->flags.negcached) - IpcacheStats.negative_hits++; - else - IpcacheStats.hits++; - i->handler = handler; - i->handlerData = cbdataReference(handlerData); - ipcacheCallback(i); - return; - } - debug(14, 5) ("ipcache_nbgethostbyname: MISS for '%s'\n", name); - IpcacheStats.misses++; - i = ipcacheCreateEntry(name); - i->handler = handler; - i->handlerData = cbdataReference(handlerData); - i->request_time = current_time; - c = cbdataAlloc(generic_cbdata); - c->data = i; -#if USE_DNSSERVERS - dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c); -#else - idnsALookup(hashKeyStr(&i->hash), ipcacheHandleReply, c); -#endif -} - -/* initialize the ipcache */ -void -ipcache_init(void) -{ - int n; - debug(14, 3) ("Initializing IP Cache...\n"); - memset(&IpcacheStats, '\0', sizeof(IpcacheStats)); - memset(&lru_list, '\0', sizeof(lru_list)); - /* test naming lookup */ - if (!opt_dns_tests) { - debug(14, 4) ("ipcache_init: Skipping DNS name lookup tests.\n"); - } else if (!ipcache_testname()) { - fatal("ipcache_init: DNS name lookup tests failed."); - } else { - debug(14, 1) ("Successful DNS name lookup tests...\n"); - } - memset(&static_addrs, '\0', sizeof(ipcache_addrs)); - static_addrs.in_addrs = xcalloc(1, sizeof(struct in_addr)); - static_addrs.bad_mask = xcalloc(1, sizeof(unsigned char)); - ipcache_high = (long) (((float) Config.ipcache.size * - (float) Config.ipcache.high) / (float) 100); - ipcache_low = (long) (((float) Config.ipcache.size * - (float) Config.ipcache.low) / (float) 100); - n = hashPrime(ipcache_high / 4); - ip_table = hash_create((HASHCMP *) strcmp, n, hash4); - cachemgrRegister("ipcache", - "IP Cache Stats and Contents", - stat_ipcache_get, 0, 1); - memDataInit(MEM_IPCACHE_ENTRY, "ipcache_entry", sizeof(ipcache_entry), 0); -} - -const ipcache_addrs * -ipcache_gethostbyname(const char *name, int flags) -{ - ipcache_entry *i = NULL; - ipcache_addrs *addrs; - assert(name); - debug(14, 3) ("ipcache_gethostbyname: '%s', flags=%x\n", name, flags); - IpcacheStats.requests++; - i = ipcache_get(name); - if (NULL == i) { - (void) 0; - } else if (ipcacheExpiredEntry(i)) { - ipcacheRelease(i); - i = NULL; - } else if (i->flags.negcached) { - IpcacheStats.negative_hits++; - dns_error_message = i->error_message; - return NULL; - } else { - IpcacheStats.hits++; - i->lastref = squid_curtime; - return &i->addrs; - } - if ((addrs = ipcacheCheckNumeric(name))) - return addrs; - IpcacheStats.misses++; - if (flags & IP_LOOKUP_IF_MISS) - ipcache_nbgethostbyname(name, dummy_handler, NULL); - return NULL; -} - -static void -ipcacheStatPrint(ipcache_entry * i, StoreEntry * sentry) -{ - int k; - storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)", - hashKeyStr(&i->hash), - i->flags.fromhosts ? 'H' : ' ', - i->flags.negcached ? 'N' : ' ', - (int) (squid_curtime - i->lastref), - (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)), - (int) i->addrs.count, - (int) i->addrs.badcount); - for (k = 0; k < (int) i->addrs.count; k++) { - storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]), - i->addrs.bad_mask[k] ? "BAD" : "OK "); - } - storeAppendPrintf(sentry, "\n"); -} - -/* process objects list */ -void -stat_ipcache_get(StoreEntry * sentry) -{ - dlink_node *m; - assert(ip_table != NULL); - storeAppendPrintf(sentry, "IP Cache Statistics:\n"); - storeAppendPrintf(sentry, "IPcache Entries: %d\n", - memInUse(MEM_IPCACHE_ENTRY)); - storeAppendPrintf(sentry, "IPcache Requests: %d\n", - IpcacheStats.requests); - storeAppendPrintf(sentry, "IPcache Hits: %d\n", - IpcacheStats.hits); - storeAppendPrintf(sentry, "IPcache Negative Hits: %d\n", - IpcacheStats.negative_hits); - storeAppendPrintf(sentry, "IPcache Misses: %d\n", - IpcacheStats.misses); - storeAppendPrintf(sentry, "Blocking calls to gethostbyname(): %d\n", - IpcacheStats.ghbn_calls); - storeAppendPrintf(sentry, "Attempts to release locked entries: %d\n", - IpcacheStats.release_locked); - storeAppendPrintf(sentry, "\n\n"); - storeAppendPrintf(sentry, "IP Cache Contents:\n\n"); - storeAppendPrintf(sentry, " %-29.29s %3s %6s %6s %1s\n", - "Hostname", - "Flg", - "lstref", - "TTL", - "N"); - for (m = lru_list.head; m; m = m->next) - ipcacheStatPrint(m->data, sentry); -} - -static void -dummy_handler(const ipcache_addrs * addrsnotused, void *datanotused) -{ - return; -} - -void -ipcacheInvalidate(const char *name) -{ - ipcache_entry *i; - if ((i = ipcache_get(name)) == NULL) - return; - i->expires = squid_curtime; - /* - * NOTE, don't call ipcacheRelease here becuase we might be here due - * to a thread started from a callback. - */ -} - -ipcache_addrs * -ipcacheCheckNumeric(const char *name) -{ - struct in_addr ip; - /* check if it's already a IP address in text form. */ - if (!safe_inet_addr(name, &ip)) - return NULL; - static_addrs.count = 1; - static_addrs.cur = 0; - static_addrs.in_addrs[0].s_addr = ip.s_addr; - static_addrs.bad_mask[0] = FALSE; - static_addrs.badcount = 0; - return &static_addrs; -} - -static void -ipcacheLockEntry(ipcache_entry * i) -{ - if (i->locks++ == 0) { - dlinkDelete(&i->lru, &lru_list); - dlinkAdd(i, &i->lru, &lru_list); - } -} - -static void -ipcacheUnlockEntry(ipcache_entry * i) -{ - assert(i->locks > 0); - i->locks--; - if (ipcacheExpiredEntry(i)) - ipcacheRelease(i); -} - -void -ipcacheCycleAddr(const char *name, ipcache_addrs * ia) -{ - ipcache_entry *i; - unsigned char k; - assert(name || ia); - if (NULL == ia) { - if ((i = ipcache_get(name)) == NULL) - return; - if (i->flags.negcached) - return; - ia = &i->addrs; - } - for (k = 0; k < ia->count; k++) { - if (++ia->cur == ia->count) - ia->cur = 0; - if (!ia->bad_mask[ia->cur]) - break; - } - if (k == ia->count) { - /* All bad, reset to All good */ - debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n", - name); - for (k = 0; k < ia->count; k++) - ia->bad_mask[k] = 0; - ia->badcount = 0; - ia->cur = 0; - } - debug(14, 3) ("ipcacheCycleAddr: %s now at %s\n", name, - inet_ntoa(ia->in_addrs[ia->cur])); -} - -/* - * Marks the given address as BAD and calls ipcacheCycleAddr to - * advance the current pointer to the next OK address. - */ -void -ipcacheMarkBadAddr(const char *name, struct in_addr addr) -{ - ipcache_entry *i; - ipcache_addrs *ia; - int k; - if ((i = ipcache_get(name)) == NULL) - return; - ia = &i->addrs; - for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) - break; - } - if (k == (int) ia->count) /* not found */ - return; - if (!ia->bad_mask[k]) { - ia->bad_mask[k] = TRUE; - ia->badcount++; - debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, inet_ntoa(addr)); - } - ipcacheCycleAddr(name, ia); -} - -void -ipcacheMarkGoodAddr(const char *name, struct in_addr addr) -{ - ipcache_entry *i; - ipcache_addrs *ia; - int k; - if ((i = ipcache_get(name)) == NULL) - return; - ia = &i->addrs; - for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) - break; - } - if (k == (int) ia->count) /* not found */ - return; - if (!ia->bad_mask[k]) /* already OK */ - return; - ia->bad_mask[k] = FALSE; - ia->badcount--; - debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name, inet_ntoa(addr)); -} - -static void -ipcacheFreeEntry(void *data) -{ - ipcache_entry *i = data; - safe_free(i->addrs.in_addrs); - safe_free(i->addrs.bad_mask); - safe_free(i->hash.key); - safe_free(i->error_message); - memFree(i, MEM_IPCACHE_ENTRY); -} - -void -ipcacheFreeMemory(void) -{ - hashFreeItems(ip_table, ipcacheFreeEntry); - hashFreeMemory(ip_table); - ip_table = NULL; -} - -/* Recalculate IP cache size upon reconfigure */ -void -ipcache_restart(void) -{ - ipcache_high = (long) (((float) Config.ipcache.size * - (float) Config.ipcache.high) / (float) 100); - ipcache_low = (long) (((float) Config.ipcache.size * - (float) Config.ipcache.low) / (float) 100); - purge_entries_fromhosts(); -} - -/* - * adds a "static" entry from /etc/hosts. - * returns 0 upon success, 1 if the ip address is invalid - */ -int -ipcacheAddEntryFromHosts(const char *name, const char *ipaddr) -{ - ipcache_entry *i; - struct in_addr ip; - if (!safe_inet_addr(ipaddr, &ip)) { - if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) { - debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr); - } else { - debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n", - ipaddr); - } - return 1; - } - if ((i = ipcache_get(name))) { - if (1 == i->flags.fromhosts) { - ipcacheUnlockEntry(i); - } else if (i->locks > 0) { - debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry" - " for locked name '%s'\n", name); - return 1; - } else { - ipcacheRelease(i); - } - } - i = ipcacheCreateEntry(name); - i->addrs.count = 1; - i->addrs.cur = 0; - i->addrs.badcount = 0; - i->addrs.in_addrs = xcalloc(1, sizeof(struct in_addr)); - i->addrs.bad_mask = xcalloc(1, sizeof(unsigned char)); - i->addrs.in_addrs[0].s_addr = ip.s_addr; - i->addrs.bad_mask[0] = FALSE; - i->flags.fromhosts = 1; - ipcacheAddEntry(i); - ipcacheLockEntry(i); - return 0; -} - -#ifdef SQUID_SNMP -/* - * The function to return the ip cache statistics to via SNMP - */ - -variable_list * -snmp_netIpFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - debug(49, 5) ("snmp_netIpFn: Processing request:\n"); - snmpDebugOid(5, Var->name, Var->name_length); - *ErrP = SNMP_ERR_NOERROR; - switch (Var->name[LEN_SQ_NET + 1]) { - case IP_ENT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - memInUse(MEM_IPCACHE_ENTRY), - SMI_GAUGE32); - break; - case IP_REQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.requests, - SMI_COUNTER32); - break; - case IP_HITS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.hits, - SMI_COUNTER32); - break; - case IP_PENDHIT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - 0, - SMI_GAUGE32); - break; - case IP_NEGHIT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.negative_hits, - SMI_COUNTER32); - break; - case IP_MISS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.misses, - SMI_COUNTER32); - break; - case IP_GHBN: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.ghbn_calls, - SMI_COUNTER32); - break; - case IP_LOC: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IpcacheStats.release_locked, - SMI_COUNTER32); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - snmp_var_free(Answer); - return (NULL); - } - return Answer; -} - -#endif /*SQUID_SNMP */ --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/ipcache.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,823 @@ + +/* + * $Id: ipcache.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 14 IP Cache + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + +typedef struct _ipcache_entry ipcache_entry; + +struct _ipcache_entry { + hash_link hash; /* must be first */ + time_t lastref; + time_t expires; + ipcache_addrs addrs; + IPH *handler; + void *handlerData; + char *error_message; + struct timeval request_time; + dlink_node lru; + unsigned short locks; + struct { + unsigned int negcached:1; + unsigned int fromhosts:1; + } flags; +}; + +static struct { + int requests; + int replies; + int hits; + int misses; + int negative_hits; + int errors; + int ghbn_calls; /* # calls to blocking gethostbyname() */ + int release_locked; +} IpcacheStats; + +static dlink_list lru_list; + +static FREE ipcacheFreeEntry; +#if USE_DNSSERVERS +static HLPCB ipcacheHandleReply; +#else +static IDNSCB ipcacheHandleReply; +#endif +static IPH dummy_handler; +static int ipcacheExpiredEntry(ipcache_entry *); +static int ipcache_testname(void); +#if USE_DNSSERVERS +static ipcache_entry *ipcacheParse(const char *buf); +#else +static ipcache_entry *ipcacheParse(rfc1035_rr *, int); +#endif +static ipcache_entry *ipcache_get(const char *); +static void ipcacheLockEntry(ipcache_entry *); +static void ipcacheStatPrint(ipcache_entry *, StoreEntry *); +static void ipcacheUnlockEntry(ipcache_entry *); +static void ipcacheRelease(ipcache_entry *); + +static ipcache_addrs static_addrs; +static hash_table *ip_table = NULL; + +static long ipcache_low = 180; +static long ipcache_high = 200; + +#if LIBRESOLV_DNS_TTL_HACK +extern int _dns_ttl_; +#endif + +static int +ipcache_testname(void) +{ + wordlist *w = NULL; + debug(14, 1) ("Performing DNS Tests...\n"); + if ((w = Config.dns_testname_list) == NULL) + return 1; + for (; w; w = w->next) { + IpcacheStats.ghbn_calls++; + if (gethostbyname(w->key) != NULL) + return 1; + } + return 0; +} + +/* removes the given ipcache entry */ +static void +ipcacheRelease(ipcache_entry * i) +{ + hash_remove_link(ip_table, (hash_link *) i); + dlinkDelete(&i->lru, &lru_list); + ipcacheFreeEntry(i); +} + +static ipcache_entry * +ipcache_get(const char *name) +{ + if (ip_table != NULL) + return (ipcache_entry *) hash_lookup(ip_table, name); + else + return NULL; +} + +static int +ipcacheExpiredEntry(ipcache_entry * i) +{ + /* all static entries are locked, so this takes care of them too */ + if (i->locks != 0) + return 0; + if (i->addrs.count == 0) + if (0 == i->flags.negcached) + return 1; + if (i->expires > squid_curtime) + return 0; + return 1; +} + +void +ipcache_purgelru(void *voidnotused) +{ + dlink_node *m; + dlink_node *prev = NULL; + ipcache_entry *i; + int removed = 0; + eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1); + for (m = lru_list.tail; m; m = prev) { + if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low) + break; + prev = m->prev; + i = (ipcache_entry *)m->data; + if (i->locks != 0) + continue; + ipcacheRelease(i); + removed++; + } + debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed); +} + +/* purges entries added from /etc/hosts (or whatever). */ +static void +purge_entries_fromhosts(void) +{ + dlink_node *m = lru_list.head; + ipcache_entry *i = NULL, *t; + while (m) { + if (i != NULL) { /* need to delay deletion */ + ipcacheRelease(i); /* we just override locks */ + i = NULL; + } + t = (ipcache_entry*)m->data; + if (t->flags.fromhosts) + i = t; + m = m->next; + } + if (i != NULL) + ipcacheRelease(i); +} + +/* create blank ipcache_entry */ +static ipcache_entry * +ipcacheCreateEntry(const char *name) +{ + static ipcache_entry *i; + i = (ipcache_entry *)memAllocate(MEM_IPCACHE_ENTRY); + i->hash.key = xstrdup(name); + i->expires = squid_curtime + Config.negativeDnsTtl; + return i; +} + +static void +ipcacheAddEntry(ipcache_entry * i) +{ + hash_link *e = (hash_link *)hash_lookup(ip_table, i->hash.key); + if (NULL != e) { + /* avoid colission */ + ipcache_entry *q = (ipcache_entry *) e; + ipcacheRelease(q); + } + hash_join(ip_table, &i->hash); + dlinkAdd(i, &i->lru, &lru_list); + i->lastref = squid_curtime; +} + +/* walks down the pending list, calling handlers */ +static void +ipcacheCallback(ipcache_entry * i) +{ + IPH *callback = i->handler; + void *cbdata; + i->lastref = squid_curtime; + if (!i->handler) + return; + ipcacheLockEntry(i); + callback = i->handler; + i->handler = NULL; + if (cbdataReferenceValidDone(i->handlerData, &cbdata)) { + dns_error_message = i->error_message; + callback(i->flags.negcached ? NULL : &i->addrs, cbdata); + } + ipcacheUnlockEntry(i); +} + +static ipcache_entry * +#if USE_DNSSERVERS +ipcacheParse(const char *inbuf) +{ + LOCAL_ARRAY(char, buf, DNS_INBUF_SZ); + char *token; + static ipcache_entry i; + int j; + int k; + int ipcount = 0; + int ttl; + char A[32][16]; + memset(&i, '\0', sizeof(i)); + i.expires = squid_curtime; + i.flags.negcached = 1; + if (inbuf == NULL) { + debug(14, 1) ("ipcacheParse: Got reply\n"); + i.error_message = xstrdup("Internal Squid Error"); + return &i; + } + xstrncpy(buf, inbuf, DNS_INBUF_SZ); + debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf); + token = strtok(buf, w_space); + if (NULL == token) { + debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n"); + return &i; + } + if (0 == strcmp(token, "$fail")) { + i.expires = squid_curtime + Config.negativeDnsTtl; + token = strtok(NULL, "\n"); + assert(NULL != token); + i.error_message = xstrdup(token); + return &i; + } + if (0 != strcmp(token, "$addr")) { + debug(14, 1) ("ipcacheParse: Got '%s', expecting '$addr'\n", token); + return &i; + } + token = strtok(NULL, w_space); + if (NULL == token) { + debug(14, 1) ("ipcacheParse: Got , expecting TTL\n"); + return &i; + } + i.flags.negcached = 0; + ttl = atoi(token); + if (ttl > 0) + i.expires = squid_curtime + ttl; + else + i.expires = squid_curtime + Config.positiveDnsTtl; + while (NULL != (token = strtok(NULL, w_space))) { + xstrncpy(A[ipcount], token, 16); + if (++ipcount == 32) + break; + } + if (0 == ipcount) { + i.addrs.in_addrs = NULL; + i.addrs.bad_mask = NULL; + } else { + i.addrs.in_addrs = xcalloc(ipcount, sizeof(struct in_addr)); + i.addrs.bad_mask = xcalloc(ipcount, sizeof(unsigned char)); + } + for (j = 0, k = 0; k < ipcount; k++) { + if (safe_inet_addr(A[k], &i.addrs.in_addrs[j])) + j++; + else + debug(14, 1) ("ipcacheParse: Invalid IP address '%s'\n", A[k]); + } + i.addrs.count = (unsigned char) j; + return &i; +} +#else +ipcacheParse(rfc1035_rr * answers, int nr) +{ + static ipcache_entry i; + int k; + int j; + int na = 0; + memset(&i, '\0', sizeof(i)); + i.expires = squid_curtime + Config.negativeDnsTtl; + i.flags.negcached = 1; + if (nr < 0) { + debug(14, 3) ("ipcacheParse: Lookup failed (error %d)\n", + rfc1035_errno); + assert(rfc1035_error_message); + i.error_message = xstrdup(rfc1035_error_message); + return &i; + } + if (nr == 0) { + debug(14, 3) ("ipcacheParse: No DNS records\n"); + i.error_message = xstrdup("No DNS records"); + return &i; + } + assert(answers); + for (j = 0, k = 0; k < nr; k++) { + if (answers[k].type != RFC1035_TYPE_A) + continue; + if (answers[k]._class != RFC1035_CLASS_IN) + continue; + na++; + } + if (na == 0) { + debug(14, 1) ("ipcacheParse: No Address records\n"); + i.error_message = xstrdup("No Address records"); + return &i; + } + i.flags.negcached = 0; + i.addrs.in_addrs = (struct in_addr *)xcalloc(na, sizeof(struct in_addr)); + i.addrs.bad_mask = (unsigned char *)xcalloc(na, sizeof(unsigned char)); + i.addrs.count = (unsigned char) na; + for (j = 0, k = 0; k < nr; k++) { + if (answers[k].type != RFC1035_TYPE_A) + continue; + if (answers[k]._class != RFC1035_CLASS_IN) + continue; + if (j == 0) + i.expires = squid_curtime + answers[k].ttl; + assert(answers[k].rdlength == 4); + xmemcpy(&i.addrs.in_addrs[j++], answers[k].rdata, 4); + debug(14, 3) ("ipcacheParse: #%d %s\n", + j - 1, + inet_ntoa(i.addrs.in_addrs[j - 1])); + } + assert(j == na); + return &i; +} +#endif + +static void +#if USE_DNSSERVERS +ipcacheHandleReply(void *data, char *reply) +#else +ipcacheHandleReply(void *data, rfc1035_rr * answers, int na) +#endif +{ + generic_cbdata *c = (generic_cbdata *)data; + ipcache_entry *i = (ipcache_entry *)c->data; + ipcache_entry *x = NULL; + cbdataFree(c); + c = NULL; + IpcacheStats.replies++; + statHistCount(&statCounter.dns.svc_time, + tvSubMsec(i->request_time, current_time)); +#if USE_DNSSERVERS + x = ipcacheParse(reply); +#else + x = ipcacheParse(answers, na); +#endif + assert(x); + i->addrs = x->addrs; + i->error_message = x->error_message; + i->expires = x->expires; + i->flags = x->flags; + ipcacheAddEntry(i); + ipcacheCallback(i); +} + +void +ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData) +{ + ipcache_entry *i = NULL; + const ipcache_addrs *addrs = NULL; + generic_cbdata *c; + assert(handler != NULL); + debug(14, 4) ("ipcache_nbgethostbyname: Name '%s'.\n", name); + IpcacheStats.requests++; + if (name == NULL || name[0] == '\0') { + debug(14, 4) ("ipcache_nbgethostbyname: Invalid name!\n"); + handler(NULL, handlerData); + return; + } + if ((addrs = ipcacheCheckNumeric(name))) { + handler(addrs, handlerData); + return; + } + i = ipcache_get(name); + if (NULL == i) { + /* miss */ + (void) 0; + } else if (ipcacheExpiredEntry(i)) { + /* hit, but expired -- bummer */ + ipcacheRelease(i); + i = NULL; + } else { + /* hit */ + debug(14, 4) ("ipcache_nbgethostbyname: HIT for '%s'\n", name); + if (i->flags.negcached) + IpcacheStats.negative_hits++; + else + IpcacheStats.hits++; + i->handler = handler; + i->handlerData = cbdataReference(handlerData); + ipcacheCallback(i); + return; + } + debug(14, 5) ("ipcache_nbgethostbyname: MISS for '%s'\n", name); + IpcacheStats.misses++; + i = ipcacheCreateEntry(name); + i->handler = handler; + i->handlerData = cbdataReference(handlerData); + i->request_time = current_time; + c = cbdataAlloc(generic_cbdata); + c->data = i; +#if USE_DNSSERVERS + dnsSubmit(hashKeyStr(&i->hash), ipcacheHandleReply, c); +#else + idnsALookup(hashKeyStr(&i->hash), ipcacheHandleReply, c); +#endif +} + +/* initialize the ipcache */ +void +ipcache_init(void) +{ + int n; + debug(14, 3) ("Initializing IP Cache...\n"); + memset(&IpcacheStats, '\0', sizeof(IpcacheStats)); + memset(&lru_list, '\0', sizeof(lru_list)); + /* test naming lookup */ + if (!opt_dns_tests) { + debug(14, 4) ("ipcache_init: Skipping DNS name lookup tests.\n"); + } else if (!ipcache_testname()) { + fatal("ipcache_init: DNS name lookup tests failed."); + } else { + debug(14, 1) ("Successful DNS name lookup tests...\n"); + } + memset(&static_addrs, '\0', sizeof(ipcache_addrs)); + static_addrs.in_addrs = (struct in_addr *)xcalloc(1, sizeof(struct in_addr)); + static_addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char)); + ipcache_high = (long) (((float) Config.ipcache.size * + (float) Config.ipcache.high) / (float) 100); + ipcache_low = (long) (((float) Config.ipcache.size * + (float) Config.ipcache.low) / (float) 100); + n = hashPrime(ipcache_high / 4); + ip_table = hash_create((HASHCMP *) strcmp, n, hash4); + cachemgrRegister("ipcache", + "IP Cache Stats and Contents", + stat_ipcache_get, 0, 1); + memDataInit(MEM_IPCACHE_ENTRY, "ipcache_entry", sizeof(ipcache_entry), 0); +} + +const ipcache_addrs * +ipcache_gethostbyname(const char *name, int flags) +{ + ipcache_entry *i = NULL; + ipcache_addrs *addrs; + assert(name); + debug(14, 3) ("ipcache_gethostbyname: '%s', flags=%x\n", name, flags); + IpcacheStats.requests++; + i = ipcache_get(name); + if (NULL == i) { + (void) 0; + } else if (ipcacheExpiredEntry(i)) { + ipcacheRelease(i); + i = NULL; + } else if (i->flags.negcached) { + IpcacheStats.negative_hits++; + dns_error_message = i->error_message; + return NULL; + } else { + IpcacheStats.hits++; + i->lastref = squid_curtime; + return &i->addrs; + } + if ((addrs = ipcacheCheckNumeric(name))) + return addrs; + IpcacheStats.misses++; + if (flags & IP_LOOKUP_IF_MISS) + ipcache_nbgethostbyname(name, dummy_handler, NULL); + return NULL; +} + +static void +ipcacheStatPrint(ipcache_entry * i, StoreEntry * sentry) +{ + int k; + storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)", + hashKeyStr(&i->hash), + i->flags.fromhosts ? 'H' : ' ', + i->flags.negcached ? 'N' : ' ', + (int) (squid_curtime - i->lastref), + (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)), + (int) i->addrs.count, + (int) i->addrs.badcount); + for (k = 0; k < (int) i->addrs.count; k++) { + storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]), + i->addrs.bad_mask[k] ? "BAD" : "OK "); + } + storeAppendPrintf(sentry, "\n"); +} + +/* process objects list */ +void +stat_ipcache_get(StoreEntry * sentry) +{ + dlink_node *m; + assert(ip_table != NULL); + storeAppendPrintf(sentry, "IP Cache Statistics:\n"); + storeAppendPrintf(sentry, "IPcache Entries: %d\n", + memInUse(MEM_IPCACHE_ENTRY)); + storeAppendPrintf(sentry, "IPcache Requests: %d\n", + IpcacheStats.requests); + storeAppendPrintf(sentry, "IPcache Hits: %d\n", + IpcacheStats.hits); + storeAppendPrintf(sentry, "IPcache Negative Hits: %d\n", + IpcacheStats.negative_hits); + storeAppendPrintf(sentry, "IPcache Misses: %d\n", + IpcacheStats.misses); + storeAppendPrintf(sentry, "Blocking calls to gethostbyname(): %d\n", + IpcacheStats.ghbn_calls); + storeAppendPrintf(sentry, "Attempts to release locked entries: %d\n", + IpcacheStats.release_locked); + storeAppendPrintf(sentry, "\n\n"); + storeAppendPrintf(sentry, "IP Cache Contents:\n\n"); + storeAppendPrintf(sentry, " %-29.29s %3s %6s %6s %1s\n", + "Hostname", + "Flg", + "lstref", + "TTL", + "N"); + for (m = lru_list.head; m; m = m->next) + ipcacheStatPrint((ipcache_entry *)m->data, sentry); +} + +static void +dummy_handler(const ipcache_addrs * addrsnotused, void *datanotused) +{ + return; +} + +void +ipcacheInvalidate(const char *name) +{ + ipcache_entry *i; + if ((i = ipcache_get(name)) == NULL) + return; + i->expires = squid_curtime; + /* + * NOTE, don't call ipcacheRelease here becuase we might be here due + * to a thread started from a callback. + */ +} + +ipcache_addrs * +ipcacheCheckNumeric(const char *name) +{ + struct in_addr ip; + /* check if it's already a IP address in text form. */ + if (!safe_inet_addr(name, &ip)) + return NULL; + static_addrs.count = 1; + static_addrs.cur = 0; + static_addrs.in_addrs[0].s_addr = ip.s_addr; + static_addrs.bad_mask[0] = FALSE; + static_addrs.badcount = 0; + return &static_addrs; +} + +static void +ipcacheLockEntry(ipcache_entry * i) +{ + if (i->locks++ == 0) { + dlinkDelete(&i->lru, &lru_list); + dlinkAdd(i, &i->lru, &lru_list); + } +} + +static void +ipcacheUnlockEntry(ipcache_entry * i) +{ + assert(i->locks > 0); + i->locks--; + if (ipcacheExpiredEntry(i)) + ipcacheRelease(i); +} + +void +ipcacheCycleAddr(const char *name, ipcache_addrs * ia) +{ + ipcache_entry *i; + unsigned char k; + assert(name || ia); + if (NULL == ia) { + if ((i = ipcache_get(name)) == NULL) + return; + if (i->flags.negcached) + return; + ia = &i->addrs; + } + for (k = 0; k < ia->count; k++) { + if (++ia->cur == ia->count) + ia->cur = 0; + if (!ia->bad_mask[ia->cur]) + break; + } + if (k == ia->count) { + /* All bad, reset to All good */ + debug(14, 3) ("ipcacheCycleAddr: Changing ALL %s addrs from BAD to OK\n", + name); + for (k = 0; k < ia->count; k++) + ia->bad_mask[k] = 0; + ia->badcount = 0; + ia->cur = 0; + } + debug(14, 3) ("ipcacheCycleAddr: %s now at %s\n", name, + inet_ntoa(ia->in_addrs[ia->cur])); +} + +/* + * Marks the given address as BAD and calls ipcacheCycleAddr to + * advance the current pointer to the next OK address. + */ +void +ipcacheMarkBadAddr(const char *name, struct in_addr addr) +{ + ipcache_entry *i; + ipcache_addrs *ia; + int k; + if ((i = ipcache_get(name)) == NULL) + return; + ia = &i->addrs; + for (k = 0; k < (int) ia->count; k++) { + if (ia->in_addrs[k].s_addr == addr.s_addr) + break; + } + if (k == (int) ia->count) /* not found */ + return; + if (!ia->bad_mask[k]) { + ia->bad_mask[k] = TRUE; + ia->badcount++; + debug(14, 2) ("ipcacheMarkBadAddr: %s [%s]\n", name, inet_ntoa(addr)); + } + ipcacheCycleAddr(name, ia); +} + +void +ipcacheMarkGoodAddr(const char *name, struct in_addr addr) +{ + ipcache_entry *i; + ipcache_addrs *ia; + int k; + if ((i = ipcache_get(name)) == NULL) + return; + ia = &i->addrs; + for (k = 0; k < (int) ia->count; k++) { + if (ia->in_addrs[k].s_addr == addr.s_addr) + break; + } + if (k == (int) ia->count) /* not found */ + return; + if (!ia->bad_mask[k]) /* already OK */ + return; + ia->bad_mask[k] = FALSE; + ia->badcount--; + debug(14, 2) ("ipcacheMarkGoodAddr: %s [%s]\n", name, inet_ntoa(addr)); +} + +static void +ipcacheFreeEntry(void *data) +{ + ipcache_entry *i = (ipcache_entry *)data; + safe_free(i->addrs.in_addrs); + safe_free(i->addrs.bad_mask); + safe_free(i->hash.key); + safe_free(i->error_message); + memFree(i, MEM_IPCACHE_ENTRY); +} + +void +ipcacheFreeMemory(void) +{ + hashFreeItems(ip_table, ipcacheFreeEntry); + hashFreeMemory(ip_table); + ip_table = NULL; +} + +/* Recalculate IP cache size upon reconfigure */ +void +ipcache_restart(void) +{ + ipcache_high = (long) (((float) Config.ipcache.size * + (float) Config.ipcache.high) / (float) 100); + ipcache_low = (long) (((float) Config.ipcache.size * + (float) Config.ipcache.low) / (float) 100); + purge_entries_fromhosts(); +} + +/* + * adds a "static" entry from /etc/hosts. + * returns 0 upon success, 1 if the ip address is invalid + */ +int +ipcacheAddEntryFromHosts(const char *name, const char *ipaddr) +{ + ipcache_entry *i; + struct in_addr ip; + if (!safe_inet_addr(ipaddr, &ip)) { + if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) { + debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr); + } else { + debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n", + ipaddr); + } + return 1; + } + if ((i = ipcache_get(name))) { + if (1 == i->flags.fromhosts) { + ipcacheUnlockEntry(i); + } else if (i->locks > 0) { + debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry" + " for locked name '%s'\n", name); + return 1; + } else { + ipcacheRelease(i); + } + } + i = ipcacheCreateEntry(name); + i->addrs.count = 1; + i->addrs.cur = 0; + i->addrs.badcount = 0; + i->addrs.in_addrs = (struct in_addr *)xcalloc(1, sizeof(struct in_addr)); + i->addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char)); + i->addrs.in_addrs[0].s_addr = ip.s_addr; + i->addrs.bad_mask[0] = FALSE; + i->flags.fromhosts = 1; + ipcacheAddEntry(i); + ipcacheLockEntry(i); + return 0; +} + +#ifdef SQUID_SNMP +/* + * The function to return the ip cache statistics to via SNMP + */ + +variable_list * +snmp_netIpFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + debug(49, 5) ("snmp_netIpFn: Processing request:\n"); + snmpDebugOid(5, Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_NET + 1]) { + case IP_ENT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + memInUse(MEM_IPCACHE_ENTRY), + SMI_GAUGE32); + break; + case IP_REQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.requests, + SMI_COUNTER32); + break; + case IP_HITS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.hits, + SMI_COUNTER32); + break; + case IP_PENDHIT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + 0, + SMI_GAUGE32); + break; + case IP_NEGHIT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.negative_hits, + SMI_COUNTER32); + break; + case IP_MISS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.misses, + SMI_COUNTER32); + break; + case IP_GHBN: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.ghbn_calls, + SMI_COUNTER32); + break; + case IP_LOC: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IpcacheStats.release_locked, + SMI_COUNTER32); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return (NULL); + } + return Answer; +} + +#endif /*SQUID_SNMP */ --- squid/src/snmp_agent.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,462 +0,0 @@ - -/* - * $Id: snmp_agent.c,v 1.9 2001/10/24 09:42:13 squidadm Exp $ - * - * DEBUG: section 49 SNMP Interface - * AUTHOR: Kostas Anagnostakis - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - - -#include "squid.h" -#include "cache_snmp.h" - -/************************************************************************ - - SQUID MIB Implementation - - ************************************************************************/ - -variable_list * -snmp_sysFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - debug(49, 5) ("snmp_sysFn: Processing request:\n"); - snmpDebugOid(5, Var->name, Var->name_length); - *ErrP = SNMP_ERR_NOERROR; - switch (Var->name[LEN_SQ_SYS]) { - case SYSVMSIZ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - store_mem_size >> 10, - ASN_INTEGER); - break; - case SYSSTOR: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - store_swap_size, - ASN_INTEGER); - break; - case SYS_UPTIME: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - tvSubDsec(squid_start, current_time) * 100, - SMI_TIMETICKS); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - return Answer; -} - -variable_list * -snmp_confFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - const char *cp = NULL; - debug(49, 5) ("snmp_confFn: Processing request with magic %d!\n", Var->name[8]); - *ErrP = SNMP_ERR_NOERROR; - switch (Var->name[LEN_SQ_CONF]) { - case CONF_ADMIN: - Answer = snmp_var_new(Var->name, Var->name_length); - Answer->type = ASN_OCTET_STR; - Answer->val_len = strlen(Config.adminEmail); - Answer->val.string = (u_char *) xstrdup(Config.adminEmail); - break; - case CONF_VERSION: - Answer = snmp_var_new(Var->name, Var->name_length); - Answer->type = ASN_OCTET_STR; - Answer->val_len = strlen(appname); - Answer->val.string = (u_char *) xstrdup(appname); - break; - case CONF_VERSION_ID: - Answer = snmp_var_new(Var->name, Var->name_length); - Answer->type = ASN_OCTET_STR; - Answer->val_len = strlen(VERSION); - Answer->val.string = (u_char *) xstrdup(VERSION); - break; - case CONF_STORAGE: - switch (Var->name[LEN_SQ_CONF + 1]) { - case CONF_ST_MMAXSZ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) Config.memMaxSize >> 20, - ASN_INTEGER); - break; - case CONF_ST_SWMAXSZ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) Config.Swap.maxSize >> 10, - ASN_INTEGER); - break; - case CONF_ST_SWHIWM: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) Config.Swap.highWaterMark, - ASN_INTEGER); - break; - case CONF_ST_SWLOWM: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) Config.Swap.lowWaterMark, - ASN_INTEGER); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - break; - case CONF_LOG_FAC: - Answer = snmp_var_new(Var->name, Var->name_length); - if (!(cp = Config.debugOptions)) - cp = "None"; - Answer->type = ASN_OCTET_STR; - Answer->val_len = strlen(cp); - Answer->val.string = (u_char *) xstrdup(cp); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - return Answer; -} - -variable_list * -snmp_meshPtblFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - struct in_addr *laddr; - char *cp = NULL; - peer *p = NULL; - int cnt = 0; - debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var->name[LEN_SQ_MESH + 3]); - *ErrP = SNMP_ERR_NOERROR; - laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]); - for (p = Config.peers; p != NULL; p = p->next, cnt++) - if (p->in_addr.sin_addr.s_addr == laddr->s_addr) - break; - if (p == NULL) { - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; - } - switch (Var->name[LEN_SQ_MESH + 2]) { - case MESH_PTBL_NAME: - cp = p->host; - Answer = snmp_var_new(Var->name, Var->name_length); - Answer->type = ASN_OCTET_STR; - Answer->val_len = strlen(cp); - Answer->val.string = (u_char *) xstrdup(cp); - break; - case MESH_PTBL_IP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->in_addr.sin_addr.s_addr, - SMI_IPADDRESS); - break; - case MESH_PTBL_HTTP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->http_port, - ASN_INTEGER); - break; - case MESH_PTBL_ICP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->icp.port, - ASN_INTEGER); - break; - case MESH_PTBL_TYPE: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->type, - ASN_INTEGER); - break; - case MESH_PTBL_STATE: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) neighborUp(p), - ASN_INTEGER); - break; - case MESH_PTBL_SENT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.pings_sent, - ASN_INTEGER); - break; - case MESH_PTBL_PACKED: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.pings_acked, - ASN_INTEGER); - break; - case MESH_PTBL_FETCHES: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.fetches, - SMI_COUNTER32); - break; - case MESH_PTBL_RTT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.rtt, - ASN_INTEGER); - break; - case MESH_PTBL_IGN: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.ignored_replies, - SMI_COUNTER32); - break; - case MESH_PTBL_KEEPAL_S: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.n_keepalives_sent, - SMI_COUNTER32); - break; - case MESH_PTBL_KEEPAL_R: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - p->stats.n_keepalives_recv, - SMI_COUNTER32); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - return Answer; -} - -variable_list * -snmp_prfSysFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - static struct rusage rusage; - debug(49, 5) ("snmp_prfSysFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF + 1]); - *ErrP = SNMP_ERR_NOERROR; - switch (Var->name[LEN_SQ_PRF + 1]) { - case PERF_SYS_PF: - squid_getrusage(&rusage); - Answer = snmp_var_new_integer(Var->name, Var->name_length, - rusage_pagefaults(&rusage), - SMI_COUNTER32); - break; - case PERF_SYS_NUMR: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - IOStats.Http.reads, - SMI_COUNTER32); - break; - case PERF_SYS_MEMUSAGE: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statMemoryAccounted() >> 10, - ASN_INTEGER); - break; - case PERF_SYS_CPUTIME: - squid_getrusage(&rusage); - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) rusage_cputime(&rusage), - ASN_INTEGER); - break; - case PERF_SYS_CPUUSAGE: - squid_getrusage(&rusage); - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)), - ASN_INTEGER); - break; - case PERF_SYS_MAXRESSZ: - squid_getrusage(&rusage); - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) rusage_maxrss(&rusage), - ASN_INTEGER); - break; - case PERF_SYS_CURLRUEXP: - /* No global LRU info anymore */ - Answer = snmp_var_new_integer(Var->name, Var->name_length, - 0, - SMI_TIMETICKS); - break; - case PERF_SYS_CURUNLREQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.unlink.requests, - SMI_COUNTER32); - break; - case PERF_SYS_CURUNUSED_FD: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) Squid_MaxFD - Number_FD, - SMI_GAUGE32); - break; - case PERF_SYS_CURRESERVED_FD: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) RESERVED_FD, - SMI_GAUGE32); - break; - case PERF_SYS_NUMOBJCNT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) memInUse(MEM_STOREENTRY), - SMI_COUNTER32); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - return Answer; -} - -variable_list * -snmp_prfProtoFn(variable_list * Var, snint * ErrP) -{ - variable_list *Answer = NULL; - static StatCounters *f = NULL; - static StatCounters *l = NULL; - double x; - int minutes; - debug(49, 5) ("snmp_prfProtoFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF]); - *ErrP = SNMP_ERR_NOERROR; - switch (Var->name[LEN_SQ_PRF + 1]) { - case PERF_PROTOSTAT_AGGR: /* cacheProtoAggregateStats */ - switch (Var->name[LEN_SQ_PRF + 2]) { - case PERF_PROTOSTAT_AGGR_HTTP_REQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.requests, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_HTTP_HITS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.hits, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_HTTP_ERRORS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.errors, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.kbytes_in.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.kbytes_out.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_ICP_S: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.icp.pkts_sent, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_ICP_R: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.icp.pkts_recv, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_ICP_SKB: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.icp.kbytes_sent.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_ICP_RKB: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.icp.kbytes_recv.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_REQ: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.server.all.requests, - SMI_INTEGER); - break; - case PERF_PROTOSTAT_AGGR_ERRORS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.server.all.errors, - SMI_INTEGER); - break; - case PERF_PROTOSTAT_AGGR_KBYTES_IN: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.server.all.kbytes_in.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_KBYTES_OUT: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.server.all.kbytes_out.kb, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_CURSWAP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) store_swap_size, - SMI_COUNTER32); - break; - case PERF_PROTOSTAT_AGGR_CLIENTS: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) statCounter.client_http.clients, - SMI_COUNTER32); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - break; - } - return Answer; - case PERF_PROTOSTAT_MEDIAN: - if (Var->name_length == LEN_SQ_PRF + 5) - minutes = Var->name[LEN_SQ_PRF + 4]; - else - break; - if ((minutes < 1) || (minutes > 60)) - break; - f = snmpStatGet(0); - l = snmpStatGet(minutes); - debug(49, 8) ("median: min= %d, %d l= %p , f = %p\n", minutes, - Var->name[LEN_SQ_PRF + 3], l, f); - debug(49, 8) ("median: l= %p , f = %p\n", l, f); - switch (Var->name[LEN_SQ_PRF + 3]) { - case PERF_MEDIAN_TIME: - x = minutes; - break; - case PERF_MEDIAN_HTTP_ALL: - x = statHistDeltaMedian(&l->client_http.all_svc_time, - &f->client_http.all_svc_time); - break; - case PERF_MEDIAN_HTTP_MISS: - x = statHistDeltaMedian(&l->client_http.miss_svc_time, - &f->client_http.miss_svc_time); - break; - case PERF_MEDIAN_HTTP_NM: - x = statHistDeltaMedian(&l->client_http.nm_svc_time, - &f->client_http.nm_svc_time); - break; - case PERF_MEDIAN_HTTP_HIT: - x = statHistDeltaMedian(&l->client_http.hit_svc_time, - &f->client_http.hit_svc_time); - break; - case PERF_MEDIAN_ICP_QUERY: - x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time); - break; - case PERF_MEDIAN_ICP_REPLY: - x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time); - break; - case PERF_MEDIAN_DNS: - x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time); - break; - case PERF_MEDIAN_RHR: - x = statRequestHitRatio(minutes); - break; - case PERF_MEDIAN_BHR: - x = statByteHitRatio(minutes); - break; - default: - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; - } - return snmp_var_new_integer(Var->name, Var->name_length, - (snint) x, - SMI_INTEGER); - } - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/snmp_agent.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,462 @@ + +/* + * $Id: snmp_agent.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 49 SNMP Interface + * AUTHOR: Kostas Anagnostakis + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + + +#include "squid.h" +#include "cache_snmp.h" + +/************************************************************************ + + SQUID MIB Implementation + + ************************************************************************/ + +variable_list * +snmp_sysFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + debug(49, 5) ("snmp_sysFn: Processing request:\n"); + snmpDebugOid(5, Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_SYS]) { + case SYSVMSIZ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + store_mem_size >> 10, + ASN_INTEGER); + break; + case SYSSTOR: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + store_swap_size, + ASN_INTEGER); + break; + case SYS_UPTIME: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + tvSubDsec(squid_start, current_time) * 100, + SMI_TIMETICKS); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + return Answer; +} + +variable_list * +snmp_confFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + const char *cp = NULL; + debug(49, 5) ("snmp_confFn: Processing request with magic %d!\n", Var->name[8]); + *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_CONF]) { + case CONF_ADMIN: + Answer = snmp_var_new(Var->name, Var->name_length); + Answer->type = ASN_OCTET_STR; + Answer->val_len = strlen(Config.adminEmail); + Answer->val.string = (u_char *) xstrdup(Config.adminEmail); + break; + case CONF_VERSION: + Answer = snmp_var_new(Var->name, Var->name_length); + Answer->type = ASN_OCTET_STR; + Answer->val_len = strlen(appname); + Answer->val.string = (u_char *) xstrdup(appname); + break; + case CONF_VERSION_ID: + Answer = snmp_var_new(Var->name, Var->name_length); + Answer->type = ASN_OCTET_STR; + Answer->val_len = strlen(VERSION); + Answer->val.string = (u_char *) xstrdup(VERSION); + break; + case CONF_STORAGE: + switch (Var->name[LEN_SQ_CONF + 1]) { + case CONF_ST_MMAXSZ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) Config.memMaxSize >> 20, + ASN_INTEGER); + break; + case CONF_ST_SWMAXSZ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) Config.Swap.maxSize >> 10, + ASN_INTEGER); + break; + case CONF_ST_SWHIWM: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) Config.Swap.highWaterMark, + ASN_INTEGER); + break; + case CONF_ST_SWLOWM: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) Config.Swap.lowWaterMark, + ASN_INTEGER); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + break; + case CONF_LOG_FAC: + Answer = snmp_var_new(Var->name, Var->name_length); + if (!(cp = Config.debugOptions)) + cp = "None"; + Answer->type = ASN_OCTET_STR; + Answer->val_len = strlen(cp); + Answer->val.string = (u_char *) xstrdup(cp); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + return Answer; +} + +variable_list * +snmp_meshPtblFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + struct in_addr *laddr; + char *cp = NULL; + peer *p = NULL; + int cnt = 0; + debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var->name[LEN_SQ_MESH + 3]); + *ErrP = SNMP_ERR_NOERROR; + laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]); + for (p = Config.peers; p != NULL; p = p->next, cnt++) + if (p->in_addr.sin_addr.s_addr == laddr->s_addr) + break; + if (p == NULL) { + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; + } + switch (Var->name[LEN_SQ_MESH + 2]) { + case MESH_PTBL_NAME: + cp = p->host; + Answer = snmp_var_new(Var->name, Var->name_length); + Answer->type = ASN_OCTET_STR; + Answer->val_len = strlen(cp); + Answer->val.string = (u_char *) xstrdup(cp); + break; + case MESH_PTBL_IP: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) p->in_addr.sin_addr.s_addr, + SMI_IPADDRESS); + break; + case MESH_PTBL_HTTP: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) p->http_port, + ASN_INTEGER); + break; + case MESH_PTBL_ICP: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) p->icp.port, + ASN_INTEGER); + break; + case MESH_PTBL_TYPE: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) p->type, + ASN_INTEGER); + break; + case MESH_PTBL_STATE: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) neighborUp(p), + ASN_INTEGER); + break; + case MESH_PTBL_SENT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.pings_sent, + ASN_INTEGER); + break; + case MESH_PTBL_PACKED: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.pings_acked, + ASN_INTEGER); + break; + case MESH_PTBL_FETCHES: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.fetches, + SMI_COUNTER32); + break; + case MESH_PTBL_RTT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.rtt, + ASN_INTEGER); + break; + case MESH_PTBL_IGN: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.ignored_replies, + SMI_COUNTER32); + break; + case MESH_PTBL_KEEPAL_S: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.n_keepalives_sent, + SMI_COUNTER32); + break; + case MESH_PTBL_KEEPAL_R: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + p->stats.n_keepalives_recv, + SMI_COUNTER32); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + return Answer; +} + +variable_list * +snmp_prfSysFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + static struct rusage rusage; + debug(49, 5) ("snmp_prfSysFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF + 1]); + *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_PRF + 1]) { + case PERF_SYS_PF: + squid_getrusage(&rusage); + Answer = snmp_var_new_integer(Var->name, Var->name_length, + rusage_pagefaults(&rusage), + SMI_COUNTER32); + break; + case PERF_SYS_NUMR: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + IOStats.Http.reads, + SMI_COUNTER32); + break; + case PERF_SYS_MEMUSAGE: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statMemoryAccounted() >> 10, + ASN_INTEGER); + break; + case PERF_SYS_CPUTIME: + squid_getrusage(&rusage); + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) rusage_cputime(&rusage), + ASN_INTEGER); + break; + case PERF_SYS_CPUUSAGE: + squid_getrusage(&rusage); + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time)), + ASN_INTEGER); + break; + case PERF_SYS_MAXRESSZ: + squid_getrusage(&rusage); + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) rusage_maxrss(&rusage), + ASN_INTEGER); + break; + case PERF_SYS_CURLRUEXP: + /* No global LRU info anymore */ + Answer = snmp_var_new_integer(Var->name, Var->name_length, + 0, + SMI_TIMETICKS); + break; + case PERF_SYS_CURUNLREQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.unlink.requests, + SMI_COUNTER32); + break; + case PERF_SYS_CURUNUSED_FD: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) Squid_MaxFD - Number_FD, + SMI_GAUGE32); + break; + case PERF_SYS_CURRESERVED_FD: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) RESERVED_FD, + SMI_GAUGE32); + break; + case PERF_SYS_NUMOBJCNT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) memInUse(MEM_STOREENTRY), + SMI_COUNTER32); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + return Answer; +} + +variable_list * +snmp_prfProtoFn(variable_list * Var, snint * ErrP) +{ + variable_list *Answer = NULL; + static StatCounters *f = NULL; + static StatCounters *l = NULL; + double x; + int minutes; + debug(49, 5) ("snmp_prfProtoFn: Processing request with magic %d!\n", Var->name[LEN_SQ_PRF]); + *ErrP = SNMP_ERR_NOERROR; + switch (Var->name[LEN_SQ_PRF + 1]) { + case PERF_PROTOSTAT_AGGR: /* cacheProtoAggregateStats */ + switch (Var->name[LEN_SQ_PRF + 2]) { + case PERF_PROTOSTAT_AGGR_HTTP_REQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.requests, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_HTTP_HITS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.hits, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_HTTP_ERRORS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.errors, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.kbytes_in.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.kbytes_out.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_ICP_S: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.icp.pkts_sent, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_ICP_R: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.icp.pkts_recv, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_ICP_SKB: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.icp.kbytes_sent.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_ICP_RKB: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.icp.kbytes_recv.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_REQ: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.server.all.requests, + SMI_INTEGER); + break; + case PERF_PROTOSTAT_AGGR_ERRORS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.server.all.errors, + SMI_INTEGER); + break; + case PERF_PROTOSTAT_AGGR_KBYTES_IN: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.server.all.kbytes_in.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_KBYTES_OUT: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.server.all.kbytes_out.kb, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_CURSWAP: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) store_swap_size, + SMI_COUNTER32); + break; + case PERF_PROTOSTAT_AGGR_CLIENTS: + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint) statCounter.client_http.clients, + SMI_COUNTER32); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + break; + } + return Answer; + case PERF_PROTOSTAT_MEDIAN: + if (Var->name_length == LEN_SQ_PRF + 5) + minutes = Var->name[LEN_SQ_PRF + 4]; + else + break; + if ((minutes < 1) || (minutes > 60)) + break; + f = snmpStatGet(0); + l = snmpStatGet(minutes); + debug(49, 8) ("median: min= %d, %d l= %p , f = %p\n", minutes, + Var->name[LEN_SQ_PRF + 3], l, f); + debug(49, 8) ("median: l= %p , f = %p\n", l, f); + switch (Var->name[LEN_SQ_PRF + 3]) { + case PERF_MEDIAN_TIME: + x = minutes; + break; + case PERF_MEDIAN_HTTP_ALL: + x = statHistDeltaMedian(&l->client_http.all_svc_time, + &f->client_http.all_svc_time); + break; + case PERF_MEDIAN_HTTP_MISS: + x = statHistDeltaMedian(&l->client_http.miss_svc_time, + &f->client_http.miss_svc_time); + break; + case PERF_MEDIAN_HTTP_NM: + x = statHistDeltaMedian(&l->client_http.nm_svc_time, + &f->client_http.nm_svc_time); + break; + case PERF_MEDIAN_HTTP_HIT: + x = statHistDeltaMedian(&l->client_http.hit_svc_time, + &f->client_http.hit_svc_time); + break; + case PERF_MEDIAN_ICP_QUERY: + x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time); + break; + case PERF_MEDIAN_ICP_REPLY: + x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time); + break; + case PERF_MEDIAN_DNS: + x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time); + break; + case PERF_MEDIAN_RHR: + x = statRequestHitRatio(minutes); + break; + case PERF_MEDIAN_BHR: + x = statByteHitRatio(minutes); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; + } + return snmp_var_new_integer(Var->name, Var->name_length, + (snint) x, + SMI_INTEGER); + } + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; +} --- squid/src/store_swapmeta.c Wed Feb 14 01:07:37 2007 +++ /dev/null Wed Feb 14 01:07:22 2007 @@ -1,160 +0,0 @@ - -/* - * $Id: store_swapmeta.c,v 1.8.44.1 2002/10/04 07:07:29 rbcollins Exp $ - * - * DEBUG: section 20 Storage Manager Swapfile Metadata - * AUTHOR: Kostas Anagnostakis - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#include "squid.h" -#include "Store.h" - -static tlv ** -storeSwapTLVAdd(int type, const void *ptr, size_t len, tlv ** tail) -{ - tlv *t = memAllocate(MEM_TLV); - t->type = (char) type; - t->length = (int) len; - t->value = xmalloc(len); - xmemcpy(t->value, ptr, len); - *tail = t; - return &t->next; /* return new tail pointer */ -} - -void -storeSwapTLVFree(tlv * n) -{ - tlv *t; - while ((t = n) != NULL) { - n = t->next; - xfree(t->value); - memFree(t, MEM_TLV); - } -} - -/* - * Build a TLV list for a StoreEntry - */ -tlv * -storeSwapMetaBuild(StoreEntry * e) -{ - tlv *TLV = NULL; /* we'll return this */ - tlv **T = &TLV; - const char *url; - const char *vary; - assert(e->mem_obj != NULL); - assert(e->swap_status == SWAPOUT_WRITING); - url = storeUrl(e); - debug(20, 3) ("storeSwapMetaBuild: %s\n", url); - T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, MD5_DIGEST_CHARS, T); - T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T); - T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T); - vary = e->mem_obj->vary_headers; - if (vary) - T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T); - return TLV; -} - -char * -storeSwapMetaPack(tlv * tlv_list, int *length) -{ - int buflen = 0; - tlv *t; - off_t j = 0; - char *buf; - assert(length != NULL); - buflen++; /* STORE_META_OK */ - buflen += sizeof(int); /* size of header to follow */ - for (t = tlv_list; t; t = t->next) - buflen += sizeof(char) + sizeof(int) + t->length; - buflen++; /* STORE_META_END */ - buf = xmalloc(buflen); - buf[j++] = (char) STORE_META_OK; - xmemcpy(&buf[j], &buflen, sizeof(int)); - j += sizeof(int); - for (t = tlv_list; t; t = t->next) { - buf[j++] = (char) t->type; - xmemcpy(&buf[j], &t->length, sizeof(int)); - j += sizeof(int); - xmemcpy(&buf[j], t->value, t->length); - j += t->length; - } - buf[j++] = (char) STORE_META_END; - assert((int) j == buflen); - *length = buflen; - return buf; -} - -tlv * -storeSwapMetaUnpack(const char *buf, int *hdr_len) -{ - tlv *TLV; /* we'll return this */ - tlv **T = &TLV; - char type; - int length; - int buflen; - off_t j = 0; - assert(buf != NULL); - assert(hdr_len != NULL); - if (buf[j++] != (char) STORE_META_OK) - return NULL; - xmemcpy(&buflen, &buf[j], sizeof(int)); - j += sizeof(int); - /* - * sanity check on 'buflen' value. It should be at least big - * enough to hold one type and one length. - */ - if (buflen <= (sizeof(char) + sizeof(int))) - return NULL; - while (buflen - j > (sizeof(char) + sizeof(int))) { - type = buf[j++]; - /* VOID is reserved, but allow some slack for new types.. */ - if (type <= STORE_META_VOID || type > STORE_META_END + 10) { - debug(20, 0) ("storeSwapMetaUnpack: bad type (%d)!\n", type); - break; - } - xmemcpy(&length, &buf[j], sizeof(int)); - if (length < 0 || length > (1 << 16)) { - debug(20, 0) ("storeSwapMetaUnpack: insane length (%d)!\n", length); - break; - } - j += sizeof(int); - if (j + length > buflen) { - debug(20, 0) ("storeSwapMetaUnpack: overflow!\n"); - debug(20, 0) ("\ttype=%d, length=%d, buflen=%d, offset=%d\n", - type, length, buflen, (int) j); - break; - } - T = storeSwapTLVAdd(type, &buf[j], (size_t) length, T); - j += length; - } - *hdr_len = buflen; - return TLV; -} --- /dev/null Wed Feb 14 01:07:22 2007 +++ squid/src/store_swapmeta.cc Wed Feb 14 01:07:37 2007 @@ -0,0 +1,160 @@ + +/* + * $Id: store_swapmeta.cc,v 1.1.2.1 2002/10/09 00:23:16 rbcollins Exp $ + * + * DEBUG: section 20 Storage Manager Swapfile Metadata + * AUTHOR: Kostas Anagnostakis + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "Store.h" + +static tlv ** +storeSwapTLVAdd(int type, const void *ptr, size_t len, tlv ** tail) +{ + tlv *t = (tlv *)memAllocate(MEM_TLV); + t->type = (char) type; + t->length = (int) len; + t->value = xmalloc(len); + xmemcpy(t->value, ptr, len); + *tail = t; + return &t->next; /* return new tail pointer */ +} + +void +storeSwapTLVFree(tlv * n) +{ + tlv *t; + while ((t = n) != NULL) { + n = t->next; + xfree(t->value); + memFree(t, MEM_TLV); + } +} + +/* + * Build a TLV list for a StoreEntry + */ +tlv * +storeSwapMetaBuild(StoreEntry * e) +{ + tlv *TLV = NULL; /* we'll return this */ + tlv **T = &TLV; + const char *url; + const char *vary; + assert(e->mem_obj != NULL); + assert(e->swap_status == SWAPOUT_WRITING); + url = storeUrl(e); + debug(20, 3) ("storeSwapMetaBuild: %s\n", url); + T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, MD5_DIGEST_CHARS, T); + T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T); + T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T); + vary = e->mem_obj->vary_headers; + if (vary) + T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T); + return TLV; +} + +char * +storeSwapMetaPack(tlv * tlv_list, int *length) +{ + int buflen = 0; + tlv *t; + off_t j = 0; + char *buf; + assert(length != NULL); + buflen++; /* STORE_META_OK */ + buflen += sizeof(int); /* size of header to follow */ + for (t = tlv_list; t; t = t->next) + buflen += sizeof(char) + sizeof(int) + t->length; + buflen++; /* STORE_META_END */ + buf = (char *)xmalloc(buflen); + buf[j++] = (char) STORE_META_OK; + xmemcpy(&buf[j], &buflen, sizeof(int)); + j += sizeof(int); + for (t = tlv_list; t; t = t->next) { + buf[j++] = (char) t->type; + xmemcpy(&buf[j], &t->length, sizeof(int)); + j += sizeof(int); + xmemcpy(&buf[j], t->value, t->length); + j += t->length; + } + buf[j++] = (char) STORE_META_END; + assert((int) j == buflen); + *length = buflen; + return buf; +} + +tlv * +storeSwapMetaUnpack(const char *buf, int *hdr_len) +{ + tlv *TLV; /* we'll return this */ + tlv **T = &TLV; + char type; + int length; + int buflen; + off_t j = 0; + assert(buf != NULL); + assert(hdr_len != NULL); + if (buf[j++] != (char) STORE_META_OK) + return NULL; + xmemcpy(&buflen, &buf[j], sizeof(int)); + j += sizeof(int); + /* + * sanity check on 'buflen' value. It should be at least big + * enough to hold one type and one length. + */ + if (buflen <= (off_t) (sizeof(char) + sizeof(int))) + return NULL; + while (buflen - j > (off_t)(sizeof(char) + sizeof(int))) { + type = buf[j++]; + /* VOID is reserved, but allow some slack for new types.. */ + if (type <= STORE_META_VOID || type > STORE_META_END + 10) { + debug(20, 0) ("storeSwapMetaUnpack: bad type (%d)!\n", type); + break; + } + xmemcpy(&length, &buf[j], sizeof(int)); + if (length < 0 || length > (1 << 16)) { + debug(20, 0) ("storeSwapMetaUnpack: insane length (%d)!\n", length); + break; + } + j += sizeof(int); + if (j + length > buflen) { + debug(20, 0) ("storeSwapMetaUnpack: overflow!\n"); + debug(20, 0) ("\ttype=%d, length=%d, buflen=%d, offset=%d\n", + type, length, buflen, (int) j); + break; + } + T = storeSwapTLVAdd(type, &buf[j], (size_t) length, T); + j += length; + } + *hdr_len = buflen; + return TLV; +}