--------------------- PatchSet 3 Date: 2000/01/26 03:23:09 Author: hno Branch: NLANR Tag: s2_2_s5 Log: Imported Squid-2.2.STABLE5 sources Members: CONTRIBUTORS:1.1.1.1->1.1.1.2 CREDITS:1.1.1.1->1.1.1.2 ChangeLog:1.1.1.1->1.1.1.2 acconfig.h:1.1.1.1->1.1.1.2 configure:1.1.1.1->1.1.1.2 configure.in:1.1.1.1->1.1.1.2 makefile.in:1.1.1.1->1.1.1.2 auth_modules/SMB/COPYING-2.0:1.1->1.1.1.1 auth_modules/SMB/Changelog:1.1->1.1.1.1 auth_modules/SMB/Makefile:1.1->1.1.1.1 auth_modules/SMB/README:1.1.1.1->1.1.1.2 auth_modules/SMB/smb_auth.c:1.1->1.1.1.1 auth_modules/SMB/smb_auth.sh:1.1->1.1.1.1 auth_modules/getpwnam/Makefile.in:1.1->1.1.1.1 auth_modules/getpwnam/getpwnam_auth.c:1.1->1.1.1.1 cfgaux/config.guess:1.1.1.1->1.1.1.2 cfgaux/config.sub:1.1.1.1->1.1.1.2 doc/Programming-Guide/Makefile:1.1->1.1.1.1 doc/Programming-Guide/prog-guide.sgml:1.1->1.1.1.1 errors/Bulgarian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Bulgarian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Bulgarian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Bulgarian/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Czech/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Czech/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Czech/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Czech/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Dutch/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Dutch/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Dutch/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Dutch/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/English/ERR_FTP_FAILURE:1.1.1.1->1.1.1.2 errors/English/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/English/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/English/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/English/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Estonian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Estonian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Estonian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Estonian/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Estonian/ERR_ZERO_SIZE_OBJECT:1.1.1.1->1.1.1.2 errors/French/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/French/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/French/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/French/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/German/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/German/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/German/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/German/ERR_READ_TIMEOUT:1.1.1.1->1.1.1.2 errors/German/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Hungarian/ERR_CANNOT_FORWARD:1.1.1.1->1.1.1.2 errors/Hungarian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Hungarian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Hungarian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Hungarian/ERR_ONLY_IF_CACHED_MISS:1.1.1.1->1.1.1.2 errors/Hungarian/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Italian/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Italian/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Italian/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Italian/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Japanese/ERR_ACCESS_DENIED:1.1->1.1.1.1 errors/Japanese/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1 errors/Japanese/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1 errors/Japanese/ERR_CANNOT_FORWARD:1.1->1.1.1.1 errors/Japanese/ERR_CONNECT_FAIL:1.1->1.1.1.1 errors/Japanese/ERR_DNS_FAIL:1.1->1.1.1.1 errors/Japanese/ERR_FORWARDING_DENIED:1.1->1.1.1.1 errors/Japanese/ERR_FTP_DISABLED:1.1->1.1.1.1 errors/Japanese/ERR_FTP_FAILURE:1.1->1.1.1.1 errors/Japanese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Japanese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Japanese/ERR_FTP_PUT_CREATED:1.1->1.1.1.1 errors/Japanese/ERR_FTP_PUT_ERROR:1.1->1.1.1.1 errors/Japanese/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1 errors/Japanese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Japanese/ERR_INVALID_REQ:1.1->1.1.1.1 errors/Japanese/ERR_INVALID_URL:1.1->1.1.1.1 errors/Japanese/ERR_LIFETIME_EXP:1.1->1.1.1.1 errors/Japanese/ERR_NO_RELAY:1.1->1.1.1.1 errors/Japanese/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1 errors/Japanese/ERR_READ_ERROR:1.1->1.1.1.1 errors/Japanese/ERR_READ_TIMEOUT:1.1->1.1.1.1 errors/Japanese/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Japanese/ERR_SOCKET_FAILURE:1.1->1.1.1.1 errors/Japanese/ERR_UNSUP_REQ:1.1->1.1.1.1 errors/Japanese/ERR_URN_RESOLVE:1.1->1.1.1.1 errors/Japanese/ERR_WRITE_ERROR:1.1->1.1.1.1 errors/Japanese/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1 errors/Japanese/README:1.1->1.1.1.1 errors/Japanese/generic:1.1->1.1.1.1 errors/Polish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Polish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Polish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Polish/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Portuguese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Portuguese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Portuguese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Portuguese/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Russian-1251/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Russian-1251/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Russian-1251/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Russian-1251/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Russian-koi8-r/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Russian-koi8-r/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Russian-koi8-r/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Russian-koi8-r/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Slovak/ERR_ACCESS_DENIED:1.1->1.1.1.1 errors/Slovak/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1 errors/Slovak/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1 errors/Slovak/ERR_CANNOT_FORWARD:1.1->1.1.1.1 errors/Slovak/ERR_CONNECT_FAIL:1.1->1.1.1.1 errors/Slovak/ERR_DNS_FAIL:1.1->1.1.1.1 errors/Slovak/ERR_FORWARDING_DENIED:1.1->1.1.1.1 errors/Slovak/ERR_FTP_DISABLED:1.1->1.1.1.1 errors/Slovak/ERR_FTP_FAILURE:1.1->1.1.1.1 errors/Slovak/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Slovak/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Slovak/ERR_FTP_PUT_CREATED:1.1->1.1.1.1 errors/Slovak/ERR_FTP_PUT_ERROR:1.1->1.1.1.1 errors/Slovak/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1 errors/Slovak/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Slovak/ERR_INVALID_REQ:1.1->1.1.1.1 errors/Slovak/ERR_INVALID_URL:1.1->1.1.1.1 errors/Slovak/ERR_LIFETIME_EXP:1.1->1.1.1.1 errors/Slovak/ERR_NO_RELAY:1.1->1.1.1.1 errors/Slovak/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1 errors/Slovak/ERR_READ_ERROR:1.1->1.1.1.1 errors/Slovak/ERR_READ_TIMEOUT:1.1->1.1.1.1 errors/Slovak/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Slovak/ERR_SOCKET_FAILURE:1.1->1.1.1.1 errors/Slovak/ERR_UNSUP_REQ:1.1->1.1.1.1 errors/Slovak/ERR_URN_RESOLVE:1.1->1.1.1.1 errors/Slovak/ERR_WRITE_ERROR:1.1->1.1.1.1 errors/Slovak/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1 errors/Slovak/README:1.1->1.1.1.1 errors/Slovak/generic:1.1->1.1.1.1 errors/Spanish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Spanish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Spanish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Spanish/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_ACCESS_DENIED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_CACHE_ACCESS_DENIED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_CACHE_MGR_ACCESS_DENIED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_CANNOT_FORWARD:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_CONNECT_FAIL:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_DNS_FAIL:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FORWARDING_DENIED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_DISABLED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_FAILURE:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_PUT_CREATED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_PUT_ERROR:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_PUT_MODIFIED:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_INVALID_REQ:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_INVALID_URL:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_LIFETIME_EXP:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_NO_RELAY:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_ONLY_IF_CACHED_MISS:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_READ_ERROR:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_READ_TIMEOUT:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_SHUTTING_DOWN:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_SOCKET_FAILURE:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_UNSUP_REQ:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_URN_RESOLVE:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_WRITE_ERROR:1.1->1.1.1.1 errors/Traditional_Chinese/ERR_ZERO_SIZE_OBJECT:1.1->1.1.1.1 errors/Traditional_Chinese/README:1.1->1.1.1.1 errors/Traditional_Chinese/generic:1.1->1.1.1.1 errors/Turkish/ERR_FTP_FORBIDDEN:1.1->1.1.1.1 errors/Turkish/ERR_FTP_NOT_FOUND:1.1->1.1.1.1 errors/Turkish/ERR_FTP_UNAVAILABLE:1.1->1.1.1.1 errors/Turkish/ERR_SHUTTING_DOWN:1.1->1.1.1.1 icons/Makefile.in:1.1.1.1->1.1.1.2 icons/anthony-binhex.gif:1.1->1.1.1.1 icons/anthony-bomb.gif:1.1->1.1.1.1 icons/anthony-box.gif:1.1->1.1.1.1 icons/anthony-box2.gif:1.1->1.1.1.1 icons/anthony-c.gif:1.1->1.1.1.1 icons/anthony-compressed.gif:1.1->1.1.1.1 icons/anthony-dir.gif:1.1->1.1.1.1 icons/anthony-dirup.gif:1.1->1.1.1.1 icons/anthony-dvi.gif:1.1->1.1.1.1 icons/anthony-f.gif:1.1->1.1.1.1 icons/anthony-image.gif:1.1->1.1.1.1 icons/anthony-image2.gif:1.1->1.1.1.1 icons/anthony-layout.gif:1.1->1.1.1.1 icons/anthony-link.gif:1.1->1.1.1.1 icons/anthony-movie.gif:1.1->1.1.1.1 icons/anthony-pdf.gif:1.1->1.1.1.1 icons/anthony-portal.gif:1.1->1.1.1.1 icons/anthony-ps.gif:1.1->1.1.1.1 icons/anthony-quill.gif:1.1->1.1.1.1 icons/anthony-script.gif:1.1->1.1.1.1 icons/anthony-sound.gif:1.1->1.1.1.1 icons/anthony-tar.gif:1.1->1.1.1.1 icons/anthony-tex.gif:1.1->1.1.1.1 icons/anthony-text.gif:1.1->1.1.1.1 icons/anthony-unknown.gif:1.1->1.1.1.1 icons/anthony-xbm.gif:1.1->1.1.1.1 icons/anthony-xpm.gif:1.1->1.1.1.1 include/GNUregex.h:1.1.1.1->1.1.1.2 include/autoconf.h.in:1.1.1.1->1.1.1.2 include/cache_snmp.h:1.1.1.1->1.1.1.2 include/config.h.in:1.1.1.1->1.1.1.2 include/snmp_debug.h:1.1.1.1->1.1.1.2 include/util.h:1.1.1.1->1.1.1.2 include/version.h:1.1.1.1->1.1.1.2 lib/hash.c:1.1.1.1->1.1.1.2 lib/inet_ntoa.c:1.1->1.1.1.1 lib/radix.c:1.1.1.1->1.1.1.2 lib/rfc1123.c:1.1.1.1->1.1.1.2 lib/safe_inet_addr.c:1.1.1.1->1.1.1.2 lib/snprintf.c:1.1.1.1->1.1.1.2 lib/util.c:1.1.1.1->1.1.1.2 scripts/RunAccel.in:1.1.1.1->1.1.1.2 scripts/RunCache.in:1.1.1.1->1.1.1.2 scripts/convert.configure.to.os2:1.1->1.1.1.1 scripts/udp-banger.pl:1.1.1.1->1.1.1.2 snmplib/parse.c:1.1.1.1->1.1.1.2 snmplib/snmplib_debug.c:1.1.1.1->1.1.1.2 src/CacheDigest.c:1.1.1.1->1.1.1.2 src/HttpHdrCc.c:1.1.1.1->1.1.1.2 src/HttpHdrContRange.c:1.1.1.1->1.1.1.2 src/HttpHdrExtField.c:1.1.1.1->1.1.1.2 src/HttpHdrRange.c:1.1.1.1->1.1.1.2 src/HttpHeader.c:1.1.1.1->1.1.1.2 src/HttpHeaderTools.c:1.1.1.1->1.1.1.2 src/HttpReply.c:1.1.1.1->1.1.1.2 src/HttpRequest.c:1.1.1.1->1.1.1.2 src/HttpStatusLine.c:1.1.1.1->1.1.1.2 src/Makefile.in:1.1.1.1->1.1.1.2 src/MemBuf.c:1.1.1.1->1.1.1.2 src/MemPool.c:1.1.1.1->1.1.1.2 src/Packer.c:1.1.1.1->1.1.1.2 src/StatHist.c:1.1.1.1->1.1.1.2 src/access_log.c:1.1.1.1->1.1.1.2 src/acl.c:1.1.1.1->1.1.1.2 src/aiops.c:1.1.1.1->1.1.1.2 src/asn.c:1.1.1.1->1.1.1.2 src/async_io.c:1.1.1.1->1.1.1.2 src/authenticate.c:1.1.1.1->1.1.1.2 src/cache_cf.c:1.1.1.1->1.1.1.2 src/cache_manager.c:1.1.1.1->1.1.1.2 src/cachemgr.c:1.1.1.1->1.1.1.2 src/cbdata.c:1.1.1.1->1.1.1.2 src/cf.data.pre:1.1.1.1->1.1.1.2 src/cf_gen.c:1.1.1.1->1.1.1.2 src/client.c:1.1.1.1->1.1.1.2 src/client_db.c:1.1.1.1->1.1.1.2 src/client_side.c:1.1.1.1->1.1.1.2 src/comm.c:1.1.1.1->1.1.1.2 src/comm_select.c:1.1.1.1->1.1.1.2 src/debug.c:1.1.1.1->1.1.1.2 src/defines.h:1.1.1.1->1.1.1.2 src/delay_pools.c:1.1.1.1->1.1.1.2 src/disk.c:1.1.1.1->1.1.1.2 src/dns.c:1.1.1.1->1.1.1.2 src/dnsserver.c:1.1.1.1->1.1.1.2 src/enums.h:1.1.1.1->1.1.1.2 src/errorpage.c:1.1.1.1->1.1.1.2 src/event.c:1.1.1.1->1.1.1.2 src/fd.c:1.1.1.1->1.1.1.2 src/forward.c:1.1.1.1->1.1.1.2 src/fqdncache.c:1.1.1.1->1.1.1.2 src/ftp.c:1.1.1.1->1.1.1.2 src/globals.h:1.1.1.1->1.1.1.2 src/gopher.c:1.1.1.1->1.1.1.2 src/helper.c:1.1.1.1->1.1.1.2 src/http.c:1.1.1.1->1.1.1.2 src/icmp.c:1.1.1.1->1.1.1.2 src/icp_v2.c:1.1.1.1->1.1.1.2 src/icp_v3.c:1.1.1.1->1.1.1.2 src/ident.c:1.1.1.1->1.1.1.2 src/internal.c:1.1.1.1->1.1.1.2 src/ipc.c:1.1.1.1->1.1.1.2 src/ipcache.c:1.1.1.1->1.1.1.2 src/leakfinder.c:1.1->1.1.1.1 src/main.c:1.1.1.1->1.1.1.2 src/mem.c:1.1.1.1->1.1.1.2 src/mib.txt:1.1.1.1->1.1.1.2 src/mime.c:1.1.1.1->1.1.1.2 src/mime.conf:1.1.1.1->1.1.1.2 src/neighbors.c:1.1.1.1->1.1.1.2 src/net_db.c:1.1.1.1->1.1.1.2 src/pconn.c:1.1.1.1->1.1.1.2 src/peer_digest.c:1.1.1.1->1.1.1.2 src/peer_select.c:1.1.1.1->1.1.1.2 src/pinger.c:1.1.1.1->1.1.1.2 src/protos.h:1.1.1.1->1.1.1.2 src/pump.c:1.1.1.1->1.1.1.2 src/redirect.c:1.1.1.1->1.1.1.2 src/refresh.c:1.1.1.1->1.1.1.2 src/send-announce.c:1.1.1.1->1.1.1.2 src/snmp_agent.c:1.1.1.1->1.1.1.2 src/snmp_core.c:1.1.1.1->1.1.1.2 src/squid.h:1.1.1.1->1.1.1.2 src/ssl.c:1.1.1.1->1.1.1.2 src/stat.c:1.1.1.1->1.1.1.2 src/stmem.c:1.1.1.1->1.1.1.2 src/store.c:1.1.1.1->1.1.1.2 src/store_clean.c:1.1.1.1->1.1.1.2 src/store_client.c:1.1.1.1->1.1.1.2 src/store_digest.c:1.1.1.1->1.1.1.2 src/store_dir.c:1.1.1.1->1.1.1.2 src/store_key_md5.c:1.1.1.1->1.1.1.2 src/store_rebuild.c:1.1.1.1->1.1.1.2 src/store_swapin.c:1.1.1.1->1.1.1.2 src/store_swapout.c:1.1.1.1->1.1.1.2 src/structs.h:1.1.1.1->1.1.1.2 src/tools.c:1.1.1.1->1.1.1.2 src/typedefs.h:1.1.1.1->1.1.1.2 src/unlinkd.c:1.1.1.1->1.1.1.2 src/url.c:1.1.1.1->1.1.1.2 src/urn.c:1.1.1.1->1.1.1.2 src/useragent.c:1.1.1.1->1.1.1.2 src/wais.c:1.1.1.1->1.1.1.2 src/whois.c:1.1.1.1->1.1.1.2 test-suite/tcp-banger2.c:1.1.1.1->1.1.1.2 test-suite/tcp-banger3.c:1.1.1.1->1.1.1.2 Index: squid/CONTRIBUTORS =================================================================== RCS file: /cvsroot/squid-sf//squid/CONTRIBUTORS,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/CONTRIBUTORS 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/CONTRIBUTORS 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -68,6 +68,7 @@ Eric Stern Michael Lupp Niall Doherty + Pedro Ribeiro Development of this caching software is funded by the National Science Foundation (grants NCR-9616602 and NCR-9521745). Paid staff members on Index: squid/CREDITS =================================================================== RCS file: /cvsroot/squid-sf//squid/CREDITS,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/CREDITS 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/CREDITS 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -1,4 +1,4 @@ -$Id: CREDITS,v 1.1.1.1 2000/01/26 03:21:46 hno Exp $ +$Id: CREDITS,v 1.1.1.2 2000/01/26 03:23:09 hno Exp $ ============================================================================== @@ -248,3 +248,48 @@ From Linux libc-5.4.46. ============================================================================== + +mcast_encode() in src/access_log.c is derived from Mark Atkinson's +(mark_a@cix.compulink.co.uk) "Tiny Encryption Algorithm". +http://www.io.com/~paulhart/game/algorithms/tea.html + +============================================================================== + +lib/inet_ntoa.c: + +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static char sccsid[] = "@(#)inet_ntoa.c 5.6 (Berkeley) 2/24/91"; + +============================================================================== Index: squid/ChangeLog =================================================================== RCS file: /cvsroot/squid-sf//squid/ChangeLog,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/ChangeLog 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/ChangeLog 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -1,3 +1,255 @@ +Changes to Squid-2.2 (April 19, 1999): + + - Removed all SNMP specific ACL code + SNMP now uses generic squid ACL's + - Removed view-based access control + - Cleaned up and simplified SNMP section of squid.conf + - Changed the SNMP code to use a tree structure. + - Added objects to MIB: + Request Hit Ratio's + Byte Hit Ratio's + Number of Clients + - Changed SNMP Agent to return object instances correctly. + - Added our own assert() macro so we can use debug() instead of + printing to stderr. + - Added eventFreeMemory(). + - Fixed ipcCreate() bug when debug_log has FD <= 2. + - Changed watchChild() and related code in main.c so that + Squid can behave more like a proper daemon process. + - Added 'prefer_direct' option (enabled by default) so that + people can give parents higher preference than direct. + - Fixed ipc.c close() bug for async IO. On FreeBSD, + comm_close() doesn't work for child processes when async IO is + used. + - Fixed setting the public key for large ``icons'' (Henrik + Nordstrom). + - Rewrote peer digest module to fix memory leaks on reconfigure + and clean the code. Increased "current" digest version to 5 + ("required" version is still 3). Revised "Peer Select" cache + manager stats. + - Added "-k parse" command line option: parses the config file + but does not send a signal unlike other -k options. + - Revamped storeAbort() calling. Only store_client.c has all + the right information to determine if the request should + be aborted. Now client and server modules just storeUnregister + without ever needing to call storeAbort. + - Small change of Squid output for FTP (Andrew Filonov, + Henrik Nordstrom). + - clientGetsOldEntry() sends old entry if new request status + is in the 500-range (Henrik Nordstrom). + - Changed configure so it works with IRIX6.4 C compiler (broken?) + option -OPT:fast_io=ON. + - Fixed comm_connect_addr() non-blocking connections for + SONY NEWSOS (Makoto MATSUSHITA). + - Changed "#ifdef __STDC__" to "#if STDC_HEADERS" as recommended + by autoconf documentation. + - Fixed client-side cache-control max-age (Henrik Nordstrom). + - Added a new error page: ERR_SHUTTING_DOWN. fwdStart() returns + this error if it is called while squid is in the process of + shutting down. + - Added support for linuxthreads package under FreeBSD (Tony Finch). + - Fixed HP-UX StatHist.c assertions by making the "hbase_f" + functions non-static (Michael Pelletier). + - Fixed logging of authenticated usernames even if the + authorization is not cached (Dancer). + - Fixed pconnPush() bug that prevented holding on to + persistent connections (Manfred Bathelt). + - Pid file now rewritten on SIGHUP. + - Numerous Ident changes: + - Ident lookups will now be done on demand if you use the + 'ident' ACL type. + - The 'ident_lookup on|off' option has been replaced with + an access list, so you can do lookups only for some + client addresses. + - Added an 'ident_timeout' option to specify the amount + of time to wait for an ident lookup. + - Added a (local) hit rate to mempool metering. + - FTP Restarts (REST command) is now supported. + - Check for libintl.a on SCO3.2. + - Disable poll() on SCO3.2. + - Numerous Async IO enhancements from Henrik. + - Removed cache_mem_low and cache_mem_high options (Henrik + Nordstrom). + - Replaced 'persistent_client_posts' with 'broken_posts' access + list. + - Rewrote the anonymizer. + - Removed the http_anonymizer option. + - Added the anonymize_headers option to allow individual + referencing of headers for addition or removal. See + 'anonymize_headers' in squid.conf for additional + configuration. + - Fixed config file parser's handing of optional directives. + Some people might get new warnings about unknown config + directives. + - Added 'myip' ACL type. This is the local IP address for + connected sockets (Luyer). + - Fixed parsing of FTP DOS directory listings with spaces + (Nordstrom). + - Numerous DELAY_POOL changes/fixes from David Luyer: + - Makes no-delay neighbors for DELAY_POOLS work by + using a fd_set with the connections to no-delay + peers marked in it. + - Makes IP addresses ending in 0 and 255, and + network number 255, work with individual and + network delay pools (they were previously not + permitted, and documented as such). + - Massive overhaul of delay pools code - dynamically + allocated delay pools, as many as required. + - delayPoolsUpdate stops running if DELAY_POOLS is + configured but no delay pools are configured. + - Initial delay pool levels are now configurable + as a percentage of the maximum for the pool in + question (used to be all set to 1 second worth + of traffic). Pools are restored to this level + on reconfiguration. + - Changed storeClientCopy to give a swap-in failure if + the number of open disk FD's is above the 'max_open_disk_fds' + limit. Otherwise, a very loaded cache will end up with + all disk files open for reading, and none for writing. + - Added lib/inet_ntoa.c from BSD Unix for systems that have + broken inet_ntoa(). (Erik Hofman). + - Added more specific FTP error messages for "permission + denied, "file not found," and "service unavailable." + (Tony Finch) + - Added xisspace(), xisdigit(), etc, macros to cast function + args and eliminate compiler warnings. + - Fixed case-sensitive comparisons of domain names (Henrik + Nordstrom). + - Added proxy-authentication to cachemgr.cgi's requests + (Henrik Nordstrom). + - Changed Squid to *truncate* rather than *unlink* purged + swap files. Can be reversed by undefining + USE_TRUNCATE_NOT_UNLINK in src/defines.h. + - Changed internal icon headers to use Cache-control + Max-age instead of Expires. + - Changed storeMaintainSwapSpace behavior to be adjusted + smoothly, instead of discretely, between store_swap_low + and store_swap_high. This includes the number of + objects to scan, number to remove, and time until the + next storeMaintainSwapSpace event. + - Fixed a quick_abort bug that incorrectly calculated + content lengths. + - Added getpwnam() auth module from Erik Hofman. + - Added 'coredump_dir' option. + - Fixed a peerDestroy() assertion that required peer->digest + to be NULL at the end of peerDestroy(). + - configure script now automatically enables dlmalloc for + Solaris/x86. + - configure enables poll() on linux 2.2 and later (Henrik). + - Icon files are now distributed in binary format, install + will not need to run 'sh' and 'uudecode'. + - Fixed some bugs with large responses (>READ_AHEAD_GAP) and + re-forwarding requests and ENTRY_FWD_HDR_WAIT. + fwdCheckDeferRead() will NOT defer reading if the + ENTRY_FWD_HDR_WAIT bit is set. + - Fixed a "F->flags.open" assertion for aborted FTP PUT's. + - Fixed a (double) cast problem that caused statAvgTick() + events to be added as fast as possible. + - Changed httpPacked304Reply() to not include the Content-Length + header for 304 replies that Squid generates. We used to + include the length of the cached object, and this broke + persistent connections. + + 2.2.STABLE2: + + - Fixed configure bug for statvfs() checks. Configure reports + "test: =: unary operator expected" or similar because an + unquoted variable is not defined. + - Fixed aclDestroyAcls() assertion because some ACL types + are not listed in the switch statement. Occurs for + srcdom_regex and dstdom_regex ACL types during reconfigure. + - Typo "applicatoin" in src/mime.conf + - The unlinkd daemon never saw the USE_TRUNCATE_NOT_UNLINK + #define because it didn't include squid.h. + - Fixed commRetryFD() when bind() fails. commRetryFD was + closing the filedescriptor, but it is the upper layer's + job to close it. + - Changed configure's "maximum number of filedescriptors" + detection to only use getrlimit() for Linux. On AIX, + getrlimit returns RLIM_INFINITY. + - Fixed snmpInit() nesting bug. + - Fixed a bug with peerGetSomeParent(). It was adding + a parent to the FwdServers list, regardless of the + ps->direct value. This could cause every request to + go to a parent even when always_direct is used. + - Changed fwdServerClosed() to rotate the "forward servers" + list when a connection establishment fails. Otherwise + it always kept trying to connect to the first server + int the list. + + 2.2.STABLE3: + + - Fixed preprocessor problems for HP-UX in lib/safe_inet_addr.c. + - Avoid coredump in aclMatchAcl() if someone tries to use + proxy authentication with a non-HTTP request (e.g. icp_access). + - Moved 'ident_lookup_access' in squid.conf so it appears + after the ACL section. + - Fixed typo in squid.conf on "Config.Addrs.snmp_outgoing" + - Fixed a case in clientCacheHit() where we thought it + was a hit, but the reply status was not 200, so we + had to perform a cache miss. We forgot to change the + log_type and these were being recorded as TCP_HIT's. + - Fixed a void pointer subtraction bug in delayIdPtrHashCmp(). + - Fixed delay_pools coredump and memory leak bugs from + NULL delay_id values. + - Fixed a SEGV bug with delay_pools when requesting + 'objects' or 'vm_objects' from the cachemgr. + - Added a workaround for buggy FTP servers that return + a size of zero for non-zero-sized objects. + - Removed umask(0) call from main(). + - Fixed a peer selection bug that caused us to never select + a neighbor based on ICP replies if the ICP timeout occurs. + In conjunction with this, removed the PING_TIMEOUT state. + - Fixed a store_rebuild bug that caused us to get stuck trying + if a cache_dir subdirectory didn't exist. + - Fixed a buffer overrun bug in gb_to_str(). + + 2.2.STABLE4: + + - Fixed a dread_ctrl leak caused in store_client.c + - Fixed a memory leak in eventRun(). + - Fixed a memory leak of ErrorState structures due to + a bug in forward.c. + - Fixed detection of subdomain collisions for SPLAY trees. + - Fixed logging of hierarchy codes for SSL requests (Henrik + Nordstrom). + - Added some descriptions to mib.txt. + - Fixed a bug with non-hierarchical requests (e.g. POST) + and cache digests. We used to look up non-hierarchical + requests in peer digests. A false hit may cause Squid + to forward a request to a sibling. In combination with + 'Cache-control: only-if-cached, this generates 504 Gateway + Timeout responses and the request may not be re-forwardable. + - Fixed a filedescriptor leak for some aborted requests. + + 2.2.STABLE5: + + - Changed configure to look for IP-Filter header files + in both /usr/include and /usr/include/netinet. + - Fixed an ACL subdomain comparison bug (aclDomainCompare). + - Fixed an ACL host <=> domain comparison bug + (aclHostDomainCompare). + - Fixed a "xstrdup: tried to dup a NULL pointer!" bug + caused by illegal hostname characters when certain + ACL types are in use. + - Fixed res_init() bug in dnsserver. We used to call + res_init(), and then clear the RES_INIT bit in + _res.options. This caused res_init() to be + called again as soon as we use gethostbyname(), and + this second initialization wipes out our changing + the nameservers. The fix is just to NOT set + _res.options to RES_DEFAULT after calling res_init(). + - Changed FTP to close data sockets as soon as the transfer + ends, rather than waiting for the reply message on the + control socket (Alexander V. Lukyanov). + - Fixed some buffering problems between Squid and the + unlinkd process. By using file_write(), unlink requests + were being buffered and experiencing long delays under + heavy load. Now use use good ol' write() instead. Also + added some feedback from unlinkd to squid so we can track + the unlink request queue. If the queue becomes too large, + we block a little and wait for some acks from unlinkd. + Changes to Squid-2.1 (November 16, 1998): - Changed delayPoolsUpdate() to be called as an event. @@ -105,6 +357,9 @@ store_digest's stuck in memory. - Fixed clientProcessOnlyIfCachedMiss so it unlocks and unregisters from "cache hit" entries. + * Changes below have been made to SQUID_2_1_PATCH3 + - Fixed memory leak in clientHandleIMSReply for + storeClientCopy failures. Changes to Squid-2.0 (October 2, 1998): @@ -535,6 +790,12 @@ - Fixed "huge 304 reply" loop bug. - Fixed --enable-splaytree compile bugs. - Removed ASN lookup code in peer_select.c. + - Added warnings if ACL code detects subdomains in SPLAY + trees. + - Rewrote some bits of httpRequestFree() to eliminate + possible bugs that could cause an "e->lock_count" asseertion. + - Added value/bounds checking to _db_init() when setting + the debugLevels[] array. Changes to squid-1.2.beta19 (Apr 8, 1998): Index: squid/acconfig.h =================================================================== RCS file: /cvsroot/squid-sf//squid/Attic/acconfig.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/acconfig.h 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/acconfig.h 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -19,8 +19,8 @@ * in the Makefiles, wich is done automatically by configure. * */ -@TOP@ -/* $Id: acconfig.h,v 1.1.1.1 2000/01/26 03:21:46 hno Exp $ */ +@ TOP @ +/* $Id: acconfig.h,v 1.1.1.2 2000/01/26 03:23:09 hno Exp $ */ /********************************* * START OF CONFIGURABLE OPTIONS * @@ -199,6 +199,11 @@ #undef IPF_TRANSPARENT /* + * Enable code for assiting in finding memory leaks. Hacker stuff only. + */ +#undef USE_LEAKFINDER + +/* * type of fd_set array */ #undef fd_mask @@ -212,3 +217,18 @@ * If _res structure has ns_list member */ #undef HAVE_RES_NS_LIST + +/* + * Compile in support for Ident (RFC 931) lookups? Enabled by default. + */ +#define USE_IDENT 1 + +/* + * If your system has statvfs(), and if it actually works! + */ +#undef HAVE_STATVFS + +/* + * we check for struct mallinfo + */ +#undef HAVE_STRUCT_MALLINFO Index: squid/configure =================================================================== RCS file: /cvsroot/squid-sf//squid/Attic/configure,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/configure 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/configure 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -73,6 +73,16 @@ --enable-ipf-transparent Enable Transparent Proxy support for systems using IP-Filter network address redirection." +ac_help="$ac_help + --enable-leakfinder + Enable Leak Finding code. Enabling this alone + does nothing; you also have to modify the source + code to use the leak finding functions. Probably + Useful for hackers only." +ac_help="$ac_help + --disable-ident-lookups + This allows you to remove code that performs + Ident (RFC 931) lookups." # Initialize some variables set by options. # The variables have the same names as the options, with @@ -581,7 +591,7 @@ -# From configure.in Revision: 1.159.2.9 +# From configure.in Revision: 1.167.2.14 ac_aux_dir= for ac_dir in cfgaux $srcdir/cfgaux; do if test -f $ac_dir/install-sh; then @@ -609,7 +619,7 @@ fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:613: checking host system type" >&5 +echo "configure:623: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -641,7 +651,7 @@ fi case "$host_os" in -cygwin32) +cygwin32|os2) exec_suffix=".exe" cgi_suffix=".exe" ;; @@ -677,7 +687,7 @@ # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:681: checking for $ac_word" >&5 +echo "configure:691: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -706,7 +716,7 @@ # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:710: checking for $ac_word" >&5 +echo "configure:720: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -754,7 +764,7 @@ fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:758: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:768: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -764,11 +774,11 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -788,12 +798,12 @@ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:792: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:802: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:797: checking whether we are using GNU C" >&5 +echo "configure:807: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -802,7 +812,7 @@ yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:806: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:816: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -817,7 +827,7 @@ ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:821: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:831: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -877,6 +887,7 @@ ;; alpha-dec-osf4.*) # Mogul says DEC compilers take both -g and -O2 + CFLAGS=`echo $CFLAGS | sed -e 's/-g/-g3/'` CFLAGS="$CFLAGS -O2" ;; *) @@ -902,6 +913,15 @@ fi fi +if test "x$ac_cv_enabled_dlmalloc" = "x"; then + case "$host" in + i386-*-solaris2.*) + echo "Enabling dlmalloc for $host" + ac_cv_enabled_dlmalloc="yes" + ;; + esac +fi + # Check whether --enable-dlmalloc or --disable-dlmalloc was given. if test "${enable_dlmalloc+set}" = set; then enableval="$enable_dlmalloc" @@ -921,7 +941,6 @@ unset ac_cv_func_malloc_trim unset ac_cv_func_malloc_usable_size unset ac_cv_func_malloc_stats - unset ac_cv_func_mallinfo unset ac_cv_func_mallopt unset ac_cv_lib_gnumalloc unset ac_cv_header_gnumalloc_h @@ -944,7 +963,6 @@ ac_cv_func_malloc_trim="yes" ac_cv_func_malloc_usable_size="yes" ac_cv_func_malloc_stats="yes" - ac_cv_func_mallinfo="yes" ac_cv_func_mallopt="yes" ac_cv_lib_gnumalloc="no" ac_cv_header_gnumalloc_h="no" @@ -971,7 +989,6 @@ ac_cv_func_malloc_trim="yes" ac_cv_func_malloc_usable_size="yes" ac_cv_func_malloc_stats="yes" - ac_cv_func_mallinfo="yes" ac_cv_func_mallopt="yes" ac_cv_lib_gnumalloc="no" ac_cv_header_gnumalloc_h="no" @@ -998,7 +1015,6 @@ unset ac_cv_func_malloc_trim unset ac_cv_func_malloc_usable_size unset ac_cv_func_malloc_stats - unset ac_cv_func_mallinfo unset ac_cv_func_mallopt unset ac_cv_lib_gnumalloc unset ac_cv_header_gnumalloc_h @@ -1376,6 +1392,42 @@ fi +# Check whether --enable-leakfinder or --disable-leakfinder was given. +if test "${enable_leakfinder+set}" = set; then + enableval="$enable_leakfinder" + if test "$enableval" = "yes" ; then + echo "Leak-Finding enabled" + cat >> confdefs.h <<\EOF +#define USE_LEAKFINDER 1 +EOF + + LEAKFINDER_OBJS='$(LEAKFINDER_OBJS)' + USE_LEAKFINDER="yes" + fi + +fi + + + +# Check whether --enable-ident-lookups or --disable-ident-lookups was given. +if test "${enable_ident_lookups+set}" = set; then + enableval="$enable_ident_lookups" + if test "$enableval" = "no" ; then + echo "Disabling Ident Lookups" + cat >> confdefs.h <<\EOF +#define USE_IDENT 0 +EOF + + else + cat >> confdefs.h <<\EOF +#define USE_IDENT 1 +EOF + + fi + +fi + + # Force some compilers to use ANSI features # case "$host" in @@ -1396,7 +1448,7 @@ esac echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1400: checking how to run the C preprocessor" >&5 +echo "configure:1452: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1411,13 +1463,13 @@ # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1421: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1473: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1428,13 +1480,13 @@ rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1438: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1490: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1467,7 +1519,7 @@ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1471: checking for a BSD compatible install" >&5 +echo "configure:1523: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1519,7 +1571,7 @@ # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1523: checking for $ac_word" >&5 +echo "configure:1575: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1546,7 +1598,7 @@ fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:1550: checking whether ln -s works" >&5 +echo "configure:1602: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1569,7 +1621,7 @@ # Extract the first word of "sh", so it can be a program name with args. set dummy sh; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1573: checking for $ac_word" >&5 +echo "configure:1625: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1601,7 +1653,7 @@ # Extract the first word of "false", so it can be a program name with args. set dummy false; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1605: checking for $ac_word" >&5 +echo "configure:1657: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_FALSE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1633,7 +1685,7 @@ # Extract the first word of "true", so it can be a program name with args. set dummy true; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1637: checking for $ac_word" >&5 +echo "configure:1689: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_TRUE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1665,7 +1717,7 @@ # Extract the first word of "rm", so it can be a program name with args. set dummy rm; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1669: checking for $ac_word" >&5 +echo "configure:1721: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1697,7 +1749,7 @@ # Extract the first word of "mv", so it can be a program name with args. set dummy mv; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1701: checking for $ac_word" >&5 +echo "configure:1753: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MV'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1729,7 +1781,7 @@ # Extract the first word of "mkdir", so it can be a program name with args. set dummy mkdir; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1733: checking for $ac_word" >&5 +echo "configure:1785: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1761,7 +1813,7 @@ # Extract the first word of "ln", so it can be a program name with args. set dummy ln; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1765: checking for $ac_word" >&5 +echo "configure:1817: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LN'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1793,7 +1845,7 @@ # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1797: checking for $ac_word" >&5 +echo "configure:1849: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1825,7 +1877,7 @@ # Extract the first word of "makedepend", so it can be a program name with args. set dummy makedepend; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1829: checking for $ac_word" >&5 +echo "configure:1881: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MAKEDEPEND'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1857,7 +1909,7 @@ # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1861: checking for $ac_word" >&5 +echo "configure:1913: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1907,12 +1959,12 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:1911: checking for $ac_hdr that defines DIR" >&5 +echo "configure:1963: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -1920,7 +1972,7 @@ DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:1924: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1976: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -1945,7 +1997,7 @@ # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:1949: checking for opendir in -ldir" >&5 +echo "configure:2001: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1953,7 +2005,7 @@ ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2020: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1986,7 +2038,7 @@ else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:1990: checking for opendir in -lx" >&5 +echo "configure:2042: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1994,7 +2046,7 @@ ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2028,12 +2080,12 @@ fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2032: checking for ANSI C header files" >&5 +echo "configure:2084: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2041,7 +2093,7 @@ #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2045: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2058,7 +2110,7 @@ if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2076,7 +2128,7 @@ if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2097,7 +2149,7 @@ : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2108,7 +2160,7 @@ exit (0); } EOF -if { (eval echo configure:2112: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2164: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : else @@ -2133,7 +2185,6 @@ for ac_hdr in \ - alloca.h \ arpa/inet.h \ arpa/nameser.h \ assert.h \ @@ -2159,6 +2210,9 @@ netdb.h \ netinet/in.h \ netinet/tcp.h \ + netinet/ip_compat.h \ + netinet/ip_fil.h \ + netinet/ip_nat.h \ poll.h \ pwd.h \ regex.h \ @@ -2193,17 +2247,17 @@ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2197: checking for $ac_hdr" >&5 +echo "configure:2251: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2207: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2261: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -2231,12 +2285,12 @@ echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:2235: checking for working const" >&5 +echo "configure:2289: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2343: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -2306,14 +2360,14 @@ fi echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:2310: checking whether byte ordering is bigendian" >&5 +echo "configure:2364: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -2324,11 +2378,11 @@ #endif ; return 0; } EOF -if { (eval echo configure:2328: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -2339,7 +2393,7 @@ #endif ; return 0; } EOF -if { (eval echo configure:2343: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -2359,7 +2413,7 @@ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -2397,20 +2451,20 @@ echo $ac_n "checking if ANSI prototypes work""... $ac_c" 1>&6 -echo "configure:2401: checking if ANSI prototypes work" >&5 +echo "configure:2455: checking if ANSI prototypes work" >&5 if eval "test \"`echo '$''{'ac_cv_have_ansi_prototypes'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2468: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_ansi_prototypes="yes" else @@ -2432,13 +2486,13 @@ fi echo $ac_n "checking for tm->tm_gmtoff""... $ac_c" 1>&6 -echo "configure:2436: checking for tm->tm_gmtoff" >&5 +echo "configure:2490: checking for tm->tm_gmtoff" >&5 if eval "test \"`echo '$''{'ac_cv_have_tm_gmoff'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2447,7 +2501,7 @@ foo.tm_gmtoff = 0; ; return 0; } EOF -if { (eval echo configure:2451: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2505: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_tm_gmoff="yes" else @@ -2468,14 +2522,60 @@ fi +echo $ac_n "checking for struct mallinfo""... $ac_c" 1>&6 +echo "configure:2527: checking for struct mallinfo" >&5 +if eval "test \"`echo '$''{'ac_cv_have_struct_mallinfo'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext < +#if HAVE_MALLOC_H +#include +#endif +int main() { +struct mallinfo foo; + foo.arena = 0; + foo.ordblks = 0; + foo.smblks = 0; + foo.hblks = 0; + foo.hblkhd = 0; + foo.uordblks = 0; + foo.fordblks = 0; + foo.keepcost = 0; +; return 0; } +EOF +if { (eval echo configure:2551: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_have_struct_mallinfo="yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_have_struct_mallinfo="no" +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_have_struct_mallinfo" 1>&6 +if test $ac_cv_have_struct_mallinfo = "yes" ; then + cat >> confdefs.h <<\EOF +#define HAVE_STRUCT_MALLINFO 1 +EOF + +fi + echo $ac_n "checking for extended mallinfo""... $ac_c" 1>&6 -echo "configure:2473: checking for extended mallinfo" >&5 +echo "configure:2573: checking for extended mallinfo" >&5 if eval "test \"`echo '$''{'ac_cv_have_ext_mallinfo'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2484,7 +2584,7 @@ foo.mxfast = 0; ; return 0; } EOF -if { (eval echo configure:2488: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2588: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_ext_mallinfo="yes" else @@ -2506,13 +2606,13 @@ fi echo $ac_n "checking for struct rusage""... $ac_c" 1>&6 -echo "configure:2510: checking for struct rusage" >&5 +echo "configure:2610: checking for struct rusage" >&5 if eval "test \"`echo '$''{'ac_cv_have_struct_rusage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_struct_rusage="yes" else @@ -2547,13 +2647,13 @@ fi echo $ac_n "checking for ip->ip_hl""... $ac_c" 1>&6 -echo "configure:2551: checking for ip->ip_hl" >&5 +echo "configure:2651: checking for ip->ip_hl" >&5 if eval "test \"`echo '$''{'ac_cv_have_ip_hl'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -2570,7 +2670,7 @@ ip.ip_hl= 0; ; return 0; } EOF -if { (eval echo configure:2574: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2674: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_ip_hl="yes" else @@ -2592,7 +2692,7 @@ fi echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:2596: checking size of int" >&5 +echo "configure:2696: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2600,7 +2700,7 @@ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -2611,7 +2711,7 @@ exit(0); } EOF -if { (eval echo configure:2615: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2715: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else @@ -2631,7 +2731,7 @@ echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:2635: checking size of long" >&5 +echo "configure:2735: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2639,7 +2739,7 @@ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -2650,7 +2750,7 @@ exit(0); } EOF -if { (eval echo configure:2654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2754: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long=`cat conftestval` else @@ -2669,23 +2769,62 @@ EOF +echo $ac_n "checking size of void *""... $ac_c" 1>&6 +echo "configure:2774: checking size of void *" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext < +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(void *)); + exit(0); +} +EOF +if { (eval echo configure:2793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_void_p=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_void_p=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_void_p" 1>&6 +cat >> confdefs.h <&6 -echo "configure:2677: checking for working alloca.h" >&5 +echo "configure:2816: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:2689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2828: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -2706,12 +2845,12 @@ fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2710: checking for alloca" >&5 +echo "configure:2849: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -2766,12 +2905,12 @@ echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2770: checking whether alloca needs Cray hooks" >&5 +echo "configure:2909: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 -echo "configure:2800: checking for $ac_func" >&5 +echo "configure:2939: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2851,7 +2990,7 @@ fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2855: checking stack direction for C alloca" >&5 +echo "configure:2994: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2859,7 +2998,7 @@ ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3021: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -2901,12 +3040,12 @@ echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:2905: checking for pid_t" >&5 +echo "configure:3044: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2934,12 +3073,12 @@ fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2938: checking for size_t" >&5 +echo "configure:3077: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2967,12 +3106,12 @@ fi echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:2971: checking for ssize_t" >&5 +echo "configure:3110: checking for ssize_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3000,12 +3139,12 @@ fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:3004: checking for off_t" >&5 +echo "configure:3143: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3033,12 +3172,12 @@ fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:3037: checking for mode_t" >&5 +echo "configure:3176: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3066,12 +3205,12 @@ fi echo $ac_n "checking for fd_mask""... $ac_c" 1>&6 -echo "configure:3070: checking for fd_mask" >&5 +echo "configure:3209: checking for fd_mask" >&5 if eval "test \"`echo '$''{'ac_cv_type_fd_mask'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -3100,13 +3239,13 @@ echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 -echo "configure:3104: checking for socklen_t" >&5 +echo "configure:3243: checking for socklen_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_socklen_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -3137,7 +3276,7 @@ fi echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6 -echo "configure:3141: checking for main in -lnsl" >&5 +echo "configure:3280: checking for main in -lnsl" >&5 ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3145,14 +3284,14 @@ ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3295: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3180,7 +3319,7 @@ fi echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6 -echo "configure:3184: checking for main in -lsocket" >&5 +echo "configure:3323: checking for main in -lsocket" >&5 ac_lib_var=`echo socket'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3188,14 +3327,14 @@ ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3338: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3227,7 +3366,7 @@ echo "skipping libmalloc check (--enable-dlmalloc specified)" else echo $ac_n "checking for main in -lgnumalloc""... $ac_c" 1>&6 -echo "configure:3231: checking for main in -lgnumalloc" >&5 +echo "configure:3370: checking for main in -lgnumalloc" >&5 ac_lib_var=`echo gnumalloc'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3235,14 +3374,14 @@ ac_save_LIBS="$LIBS" LIBS="-lgnumalloc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3285,7 +3424,7 @@ *) echo $ac_n "checking for main in -lmalloc""... $ac_c" 1>&6 -echo "configure:3289: checking for main in -lmalloc" >&5 +echo "configure:3428: checking for main in -lmalloc" >&5 ac_lib_var=`echo malloc'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3293,14 +3432,14 @@ ac_save_LIBS="$LIBS" LIBS="-lmalloc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3443: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3333,7 +3472,7 @@ fi echo $ac_n "checking for main in -lbsd""... $ac_c" 1>&6 -echo "configure:3337: checking for main in -lbsd" >&5 +echo "configure:3476: checking for main in -lbsd" >&5 ac_lib_var=`echo bsd'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3341,14 +3480,14 @@ ac_save_LIBS="$LIBS" LIBS="-lbsd $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3491: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3376,7 +3515,7 @@ fi echo $ac_n "checking for main in -lregex""... $ac_c" 1>&6 -echo "configure:3380: checking for main in -lregex" >&5 +echo "configure:3519: checking for main in -lregex" >&5 ac_lib_var=`echo regex'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3384,14 +3523,14 @@ ac_save_LIBS="$LIBS" LIBS="-lregex $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3534: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3412,7 +3551,7 @@ fi echo $ac_n "checking for gethostbyname in -lbind""... $ac_c" 1>&6 -echo "configure:3416: checking for gethostbyname in -lbind" >&5 +echo "configure:3555: checking for gethostbyname in -lbind" >&5 ac_lib_var=`echo bind'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3420,7 +3559,7 @@ ac_save_LIBS="$LIBS" LIBS="-lbind $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3465,7 +3604,7 @@ ;; *) echo $ac_n "checking for inet_aton in -lresolv""... $ac_c" 1>&6 -echo "configure:3469: checking for inet_aton in -lresolv" >&5 +echo "configure:3608: checking for inet_aton in -lresolv" >&5 ac_lib_var=`echo resolv'_'inet_aton | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3473,7 +3612,7 @@ ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3500,7 +3639,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 echo $ac_n "checking for inet_aton in -l44bsd""... $ac_c" 1>&6 -echo "configure:3504: checking for inet_aton in -l44bsd" >&5 +echo "configure:3643: checking for inet_aton in -l44bsd" >&5 ac_lib_var=`echo 44bsd'_'inet_aton | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3508,7 +3647,7 @@ ac_save_LIBS="$LIBS" LIBS="-l44bsd $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3551,7 +3690,7 @@ fi echo $ac_n "checking for main in -lresolv""... $ac_c" 1>&6 -echo "configure:3555: checking for main in -lresolv" >&5 +echo "configure:3694: checking for main in -lresolv" >&5 ac_lib_var=`echo resolv'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3559,14 +3698,14 @@ ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3597,7 +3736,7 @@ esac fi echo $ac_n "checking for main in -lm""... $ac_c" 1>&6 -echo "configure:3601: checking for main in -lm" >&5 +echo "configure:3740: checking for main in -lm" >&5 ac_lib_var=`echo m'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3605,14 +3744,14 @@ ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3755: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3641,7 +3780,7 @@ echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 -echo "configure:3645: checking for crypt in -lcrypt" >&5 +echo "configure:3784: checking for crypt in -lcrypt" >&5 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3649,7 +3788,7 @@ ac_save_LIBS="$LIBS" LIBS="-lcrypt $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3803: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3693,7 +3832,7 @@ echo $ac_n "checking for main in -lpthread""... $ac_c" 1>&6 -echo "configure:3697: checking for main in -lpthread" >&5 +echo "configure:3836: checking for main in -lpthread" >&5 ac_lib_var=`echo pthread'_'main | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3701,14 +3840,14 @@ ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:3851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3741,6 +3880,58 @@ case "$host" in + *-pc-sco3.2*) + echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 +echo "configure:3886: checking for strftime in -lintl" >&5 +ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo intl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + ;; +esac + +case "$host" in i386-*-solaris2.*) if test "$GCC" = "yes"; then echo "Removing -O for gcc on $host" @@ -3775,7 +3966,7 @@ EOF ;; - *-sony-newsos56*) + *-sony-newsos[56]*) cat >> confdefs.h <<\EOF #define GETTIMEOFDAY_NO_TZP 1 EOF @@ -3811,14 +4002,23 @@ # Henrik Nordstrom (hno@hem.passagen.se) 19980817 # poll is problematic on Linux. We disable it # by default until Linux gets it right. - echo "disabling poll for $host..." - ac_cv_func_poll='no' + rev=`uname -r | awk -F. '{printf "%03d%03d",$1,$2}'` + if test $rev -lt 002002; then + echo "disabling poll for $host < 2.2..." + ac_cv_func_poll='no' + fi ;; powerpc-ibm-aix4.1.*) # Mike Laster (mlaster@metavillage.com) 19981021 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; + *-pc-sco3.2*) + # Robert Side + # Mon, 18 Jan 1999 17:48:00 GMT + echo "disabling poll for $host..." + ac_cv_func_poll='no' + ;; esac fi @@ -3851,12 +4051,12 @@ seteuid \ setpgrp \ setrlimit \ + getrlimit \ setsid \ sigaction \ snprintf \ srand48 \ srandom \ - statvfs \ sysconf \ syslog \ tempnam \ @@ -3865,12 +4065,12 @@ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3869: checking for $ac_func" >&5 +echo "configure:4069: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3926,12 +4126,12 @@ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3930: checking for $ac_func" >&5 +echo "configure:4130: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3981,7 +4181,7 @@ fi echo $ac_n "checking if setresuid is implemented""... $ac_c" 1>&6 -echo "configure:3985: checking if setresuid is implemented" >&5 +echo "configure:4185: checking if setresuid is implemented" >&5 if eval "test \"`echo '$''{'ac_cv_func_setresuid'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3989,7 +4189,7 @@ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < @@ -4002,7 +4202,7 @@ } EOF -if { (eval echo configure:4006: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_func_setresuid="yes" else @@ -4027,21 +4227,29 @@ if test "$IPF_TRANSPARENT" ; then echo $ac_n "checking if IP-Filter header files are installed""... $ac_c" 1>&6 -echo "configure:4031: checking if IP-Filter header files are installed" >&5 - if test "$ac_cv_header_ip_compat_h" = "no" || - test "$ac_cv_header_ip_fil_h" = "no" || - test "$ac_cv_header_ip_nat_h" = "no" ; then - IPF_TRANSPARENT="no" +echo "configure:4231: checking if IP-Filter header files are installed" >&5 + if test "$ac_cv_header_ip_compat_h" = "yes" && + test "$ac_cv_header_ip_fil_h" = "yes" && + test "$ac_cv_header_ip_nat_h" = "yes" ; then + IPF_TRANSPARENT="yes" cat >> confdefs.h <<\EOF -#define IPF_TRANSPARENT 0 +#define IPF_TRANSPARENT 1 EOF - else + elif test "$ac_cv_header_netinet_ip_compat_h" = "yes" && + test "$ac_cv_header_netinet_ip_fil_h" = "yes" && + test "$ac_cv_header_netinet_ip_nat_h" = "yes" ; then IPF_TRANSPARENT="yes" cat >> confdefs.h <<\EOF #define IPF_TRANSPARENT 1 EOF + else + IPF_TRANSPARENT="no" + cat >> confdefs.h <<\EOF +#define IPF_TRANSPARENT 0 +EOF + fi echo "$ac_t""$IPF_TRANSPARENT" 1>&6 fi @@ -4062,13 +4270,13 @@ esac fi echo $ac_n "checking if GNUregex needs to be compiled""... $ac_c" 1>&6 -echo "configure:4066: checking if GNUregex needs to be compiled" >&5 +echo "configure:4274: checking if GNUregex needs to be compiled" >&5 if test -z "$USE_GNUREGEX"; then if test "$ac_cv_func_regcomp" = "no" || test "$USE_GNUREGEX" = "yes" ; then USE_GNUREGEX="yes" else cat > conftest.$ac_ext < #include @@ -4076,7 +4284,7 @@ regex_t t; regcomp(&t,"",0); ; return 0; } EOF -if { (eval echo configure:4080: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4288: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* USE_GNUREGEX="no" else @@ -4107,12 +4315,12 @@ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4111: checking for $ac_func" >&5 +echo "configure:4319: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4347: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -4163,12 +4371,12 @@ echo $ac_n "checking Default FD_SETSIZE value""... $ac_c" 1>&6 -echo "configure:4167: checking Default FD_SETSIZE value" >&5 +echo "configure:4375: checking Default FD_SETSIZE value" >&5 if test "$cross_compiling" = yes; then DEFAULT_FD_SETSIZE=256 else cat > conftest.$ac_ext < #endif main() { - fprintf (fopen("conftestval", "w"), "%d\n", FD_SETSIZE); + FILE *fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", FD_SETSIZE); exit(0); } EOF -if { (eval echo configure:4196: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then DEFAULT_FD_SETSIZE=`cat conftestval` else @@ -4211,12 +4420,12 @@ echo $ac_n "checking Maximum number of filedescriptors we can open""... $ac_c" 1>&6 -echo "configure:4215: checking Maximum number of filedescriptors we can open" >&5 +echo "configure:4424: checking Maximum number of filedescriptors we can open" >&5 if test "$cross_compiling" = yes; then SQUID_MAXFD=256 else cat > conftest.$ac_ext < @@ -4225,6 +4434,7 @@ #include #include main() { + FILE *fp; int i,j; #if __CYGWIN32__ /* getrlimit and sysconf returns bogous values on cygwin32. @@ -4254,7 +4464,12 @@ } #endif /* RLIMIT_NOFILE */ #endif /* HAVE_SETRLIMIT */ -#if HAVE_SYSCONF && defined(_SC_OPEN_MAX) +#if defined(__linux__) && HAVE_GETRLIMIT && defined(RLIMIT_NOFILE) + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { + perror("getrlimit: RLIMIT_NOFILE"); + } + i = rl.rlim_cur; +#elif HAVE_SYSCONF && defined(_SC_OPEN_MAX) i = sysconf(_SC_OPEN_MAX); #elif HAVE_GETDTABLESIZE && !defined(__linux__) i = getdtablesize(); @@ -4270,12 +4485,13 @@ i++; #endif #endif /* __CYGWIN32__ */ - fprintf (fopen("conftestval", "w"), "%d\n", i); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", i); exit(0); } EOF -if { (eval echo configure:4279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then SQUID_MAXFD=`cat conftestval` else @@ -4301,12 +4517,12 @@ fi echo $ac_n "checking Default UDP send buffer size""... $ac_c" 1>&6 -echo "configure:4305: checking Default UDP send buffer size" >&5 +echo "configure:4521: checking Default UDP send buffer size" >&5 if test "$cross_compiling" = yes; then SQUID_UDP_SO_SNDBUF=16384 else cat > conftest.$ac_ext < @@ -4316,16 +4532,18 @@ #include main () { + FILE *fp; int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1); if (val<=0) exit(1); - fprintf (fopen("conftestval", "w"), "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } EOF -if { (eval echo configure:4329: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4547: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then SQUID_UDP_SO_SNDBUF=`cat conftestval` else @@ -4344,12 +4562,12 @@ echo $ac_n "checking Default UDP receive buffer size""... $ac_c" 1>&6 -echo "configure:4348: checking Default UDP receive buffer size" >&5 +echo "configure:4566: checking Default UDP receive buffer size" >&5 if test "$cross_compiling" = yes; then SQUID_UDP_SO_RCVBUF=16384 else cat > conftest.$ac_ext < @@ -4359,16 +4577,18 @@ #include main () { + FILE *fp; int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fprintf (fopen("conftestval", "w"), "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } EOF -if { (eval echo configure:4372: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then SQUID_UDP_SO_RCVBUF=`cat conftestval` else @@ -4387,12 +4607,12 @@ echo $ac_n "checking Default TCP send buffer size""... $ac_c" 1>&6 -echo "configure:4391: checking Default TCP send buffer size" >&5 +echo "configure:4611: checking Default TCP send buffer size" >&5 if test "$cross_compiling" = yes; then SQUID_TCP_SO_SNDBUF=16384 else cat > conftest.$ac_ext < @@ -4402,18 +4622,18 @@ #include main () { - int fd,val=0,len=sizeof(int); FILE *fp; + int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fp = fopen("conftestval", "w"); - fprintf (fp, "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } EOF -if { (eval echo configure:4417: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then SQUID_TCP_SO_SNDBUF=`cat conftestval` else @@ -4432,12 +4652,12 @@ echo $ac_n "checking Default TCP receive buffer size""... $ac_c" 1>&6 -echo "configure:4436: checking Default TCP receive buffer size" >&5 +echo "configure:4656: checking Default TCP receive buffer size" >&5 if test "$cross_compiling" = yes; then SQUID_TCP_SO_RCVBUF=16384 else cat > conftest.$ac_ext < @@ -4447,18 +4667,18 @@ #include main () { - int fd,val=0,len=sizeof(int); FILE *fp; + int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fp = fopen("conftestval", "w"); - fprintf (fp, "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } EOF -if { (eval echo configure:4462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then SQUID_TCP_SO_RCVBUF=`cat conftestval` else @@ -4477,19 +4697,19 @@ echo $ac_n "checking if sys_errlist is already defined""... $ac_c" 1>&6 -echo "configure:4481: checking if sys_errlist is already defined" >&5 +echo "configure:4701: checking if sys_errlist is already defined" >&5 if eval "test \"`echo '$''{'ac_cv_needs_sys_errlist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *s = sys_errlist0; ; return 0; } EOF -if { (eval echo configure:4493: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4713: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_needs_sys_errlist="no" else @@ -4511,16 +4731,16 @@ fi echo $ac_n "checking for libresolv _dns_ttl_ hack""... $ac_c" 1>&6 -echo "configure:4515: checking for libresolv _dns_ttl_ hack" >&5 +echo "configure:4735: checking for libresolv _dns_ttl_ hack" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:4744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -4536,12 +4756,12 @@ rm -f conftest* echo $ac_n "checking if inet_ntoa() actually works""... $ac_c" 1>&6 -echo "configure:4540: checking if inet_ntoa() actually works" >&5 +echo "configure:4760: checking if inet_ntoa() actually works" >&5 if test "$cross_compiling" = yes; then INET_NTOA_RESULT="broken" else cat > conftest.$ac_ext < @@ -4551,14 +4771,16 @@ #include main () { + FILE *fp; struct in_addr in; in.s_addr = inet_addr("1.2.3.4"); - fprintf (fopen("conftestval", "w"), "%s\n", inet_ntoa(in)); + fp = fopen("conftestval", "w"); + fprintf (fp, "%s\n", inet_ntoa(in)); exit(0); } EOF -if { (eval echo configure:4562: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then INET_NTOA_RESULT=`cat conftestval` else @@ -4574,17 +4796,19 @@ echo "$ac_t"""yes"" 1>&6 else echo "$ac_t"""no"" 1>&6 - echo "WARNING: This looks bad, and probably prevents Squid from working." - echo " If you're on IRIX and using GCC 2.8, you probably need" - echo " to use the IRIX C compiler instead." - sleep 10 + echo "Will use our own inet_ntoa()." + LIBOBJS="$LIBOBJS inet_ntoa.o" +# echo "WARNING: This looks bad, and probably prevents Squid from working." +# echo " If you're on IRIX and using GCC 2.8, you probably need" +# echo " to use the IRIX C compiler instead." +# sleep 10 fi -if test "$ac_cv_func_statvfs" = "yes" ; then +if test "$ac_cv_header_sys_statvfs_h" = "yes" ; then echo $ac_n "checking for working statvfs() interface""... $ac_c" 1>&6 -echo "configure:4586: checking for working statvfs() interface" >&5 +echo "configure:4810: checking for working statvfs() interface" >&5 cat > conftest.$ac_ext < @@ -4601,7 +4825,7 @@ ; return 0; } EOF -if { (eval echo configure:4605: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4829: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_func_statvfs=yes else @@ -4612,15 +4836,21 @@ fi rm -f conftest* echo "$ac_t""$ac_cv_func_statvfs" 1>&6 +if test "$ac_cv_func_statvfs" = "yes" ; then + cat >> confdefs.h <<\EOF +#define HAVE_STATVFS 1 +EOF + +fi fi echo $ac_n "checking for _res.nsaddr_list""... $ac_c" 1>&6 -echo "configure:4619: checking for _res.nsaddr_list" >&5 +echo "configure:4849: checking for _res.nsaddr_list" >&5 if eval "test \"`echo '$''{'ac_cv_have_res_nsaddr_list'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4877: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_res_nsaddr_list="yes" else @@ -4665,12 +4895,12 @@ if test $ac_cv_have_res_nsaddr_list = "no" ; then echo $ac_n "checking for _res.ns_list""... $ac_c" 1>&6 -echo "configure:4669: checking for _res.ns_list" >&5 +echo "configure:4899: checking for _res.ns_list" >&5 if eval "test \"`echo '$''{'ac_cv_have_res_ns_list'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:4927: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_res_ns_list="yes" else @@ -4852,6 +5082,7 @@ ./errors/Makefile \ ./auth_modules/dummy \ ./auth_modules/NCSA/Makefile \ + ./auth_modules/getpwnam/Makefile \ include/autoconf.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF Index: squid/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid/configure.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/configure.in 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/configure.in 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -3,13 +3,13 @@ dnl dnl Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9) dnl -dnl $Id: configure.in,v 1.1.1.1 2000/01/26 03:21:46 hno Exp $ +dnl $Id: configure.in,v 1.1.1.2 2000/01/26 03:23:09 hno Exp $ dnl dnl dnl AC_INIT(src/main.c) AC_CONFIG_HEADER(include/autoconf.h) -AC_REVISION($Revision: 1.1.1.1 $)dnl +AC_REVISION($Revision: 1.1.1.2 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AC_CONFIG_AUX_DIR(cfgaux) @@ -28,7 +28,7 @@ dnl use .exe suffix for executables on cygwin32 platform case "$host_os" in -cygwin32) +cygwin32|os2) exec_suffix=".exe" cgi_suffix=".exe" ;; @@ -97,6 +97,7 @@ ;; alpha-dec-osf4.*) # Mogul says DEC compilers take both -g and -O2 + CFLAGS=`echo $CFLAGS | sed -e 's/-g/-g3/'` CFLAGS="$CFLAGS -O2" ;; *) @@ -123,6 +124,15 @@ fi fi +if test "x$ac_cv_enabled_dlmalloc" = "x"; then + case "$host" in + i386-*-solaris2.*) + echo "Enabling dlmalloc for $host" + ac_cv_enabled_dlmalloc="yes" + ;; + esac +fi + dnl Enable optional modules AC_ARG_ENABLE(dlmalloc, [ --enable-dlmalloc[=LIB] Compile & use the malloc package by Doug Lea], @@ -142,7 +152,6 @@ unset ac_cv_func_malloc_trim unset ac_cv_func_malloc_usable_size unset ac_cv_func_malloc_stats - unset ac_cv_func_mallinfo unset ac_cv_func_mallopt unset ac_cv_lib_gnumalloc unset ac_cv_header_gnumalloc_h @@ -165,7 +174,6 @@ ac_cv_func_malloc_trim="yes" ac_cv_func_malloc_usable_size="yes" ac_cv_func_malloc_stats="yes" - ac_cv_func_mallinfo="yes" ac_cv_func_mallopt="yes" ac_cv_lib_gnumalloc="no" ac_cv_header_gnumalloc_h="no" @@ -192,7 +200,6 @@ ac_cv_func_malloc_trim="yes" ac_cv_func_malloc_usable_size="yes" ac_cv_func_malloc_stats="yes" - ac_cv_func_mallinfo="yes" ac_cv_func_mallopt="yes" ac_cv_lib_gnumalloc="no" ac_cv_header_gnumalloc_h="no" @@ -217,7 +224,6 @@ unset ac_cv_func_malloc_trim unset ac_cv_func_malloc_usable_size unset ac_cv_func_malloc_stats - unset ac_cv_func_mallinfo unset ac_cv_func_mallopt unset ac_cv_lib_gnumalloc unset ac_cv_header_gnumalloc_h @@ -478,6 +484,35 @@ fi ]) +dnl Enable Leak Finding Functions +AC_ARG_ENABLE(leakfinder, +[ --enable-leakfinder + Enable Leak Finding code. Enabling this alone + does nothing; you also have to modify the source + code to use the leak finding functions. Probably + Useful for hackers only.], +[ if test "$enableval" = "yes" ; then + echo "Leak-Finding enabled" + AC_DEFINE(USE_LEAKFINDER) + LEAKFINDER_OBJS='$(LEAKFINDER_OBJS)' + USE_LEAKFINDER="yes" + fi +]) +AC_SUBST(LEAKFINDER_OBJS) + +dnl Disable HTTP violations +AC_ARG_ENABLE(ident-lookups, +[ --disable-ident-lookups + This allows you to remove code that performs + Ident (RFC 931) lookups.], +[ if test "$enableval" = "no" ; then + echo "Disabling Ident Lookups" + AC_DEFINE(USE_IDENT, 0) + else + AC_DEFINE(USE_IDENT, 1) + fi +]) + # Force some compilers to use ANSI features # case "$host" in @@ -534,7 +569,6 @@ AC_HEADER_STDC AC_CHECK_HEADERS( \ - alloca.h \ arpa/inet.h \ arpa/nameser.h \ assert.h \ @@ -560,6 +594,9 @@ netdb.h \ netinet/in.h \ netinet/tcp.h \ + netinet/ip_compat.h \ + netinet/ip_fil.h \ + netinet/ip_nat.h \ poll.h \ pwd.h \ regex.h \ @@ -617,6 +654,27 @@ AC_DEFINE(HAVE_TM_GMTOFF) fi +AC_CACHE_CHECK(for struct mallinfo,ac_cv_have_struct_mallinfo, [ + AC_TRY_COMPILE([#include +#if HAVE_MALLOC_H +#include +#endif], + [struct mallinfo foo; + foo.arena = 0; + foo.ordblks = 0; + foo.smblks = 0; + foo.hblks = 0; + foo.hblkhd = 0; + foo.uordblks = 0; + foo.fordblks = 0; + foo.keepcost = 0;], + ac_cv_have_struct_mallinfo="yes", + ac_cv_have_struct_mallinfo="no") +]) +if test $ac_cv_have_struct_mallinfo = "yes" ; then + AC_DEFINE(HAVE_STRUCT_MALLINFO) +fi + AC_CACHE_CHECK(for extended mallinfo,ac_cv_have_ext_mallinfo, [ AC_TRY_COMPILE([#include #include ], @@ -668,6 +726,7 @@ dnl Check for typedefs AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(void *) dnl Check for special functions AC_FUNC_ALLOCA @@ -755,6 +814,15 @@ fi AC_SUBST(PTHREADLIB) +dnl -lintl is needed on SCO version 3.2v4.2 for strftime() +dnl Robert Side +dnl Mon, 18 Jan 1999 17:48:00 GMT +case "$host" in + *-pc-sco3.2*) + AC_CHECK_LIB(intl, strftime) + ;; +esac + dnl System-specific library modifications dnl case "$host" in @@ -793,7 +861,7 @@ [*-*-solaris2.[0-4]]) AC_DEFINE(GETTIMEOFDAY_NO_TZP) ;; - *-sony-newsos[56]*) + [*-sony-newsos[56]*]) AC_DEFINE(GETTIMEOFDAY_NO_TZP) ;; esac @@ -827,14 +895,23 @@ # Henrik Nordstrom (hno@hem.passagen.se) 19980817 # poll is problematic on Linux. We disable it # by default until Linux gets it right. - echo "disabling poll for $host..." - ac_cv_func_poll='no' + rev=`uname -r | awk -F. '{printf "%03d%03d",$1,$2}'` + if test $rev -lt 002002; then + echo "disabling poll for $host < 2.2..." + ac_cv_func_poll='no' + fi ;; [powerpc-ibm-aix4.1.*]) # Mike Laster (mlaster@metavillage.com) 19981021 echo "disabling poll for $host..." ac_cv_func_poll='no' ;; + [*-pc-sco3.2*]) + # Robert Side + # Mon, 18 Jan 1999 17:48:00 GMT + echo "disabling poll for $host..." + ac_cv_func_poll='no' + ;; esac fi @@ -868,12 +945,12 @@ seteuid \ setpgrp \ setrlimit \ + getrlimit \ setsid \ sigaction \ snprintf \ srand48 \ srandom \ - statvfs \ sysconf \ syslog \ tempnam \ @@ -913,14 +990,19 @@ dnl installed by default, so we need to check for them if test "$IPF_TRANSPARENT" ; then AC_MSG_CHECKING(if IP-Filter header files are installed) - if test "$ac_cv_header_ip_compat_h" = "no" || - test "$ac_cv_header_ip_fil_h" = "no" || - test "$ac_cv_header_ip_nat_h" = "no" ; then + if test "$ac_cv_header_ip_compat_h" = "yes" && + test "$ac_cv_header_ip_fil_h" = "yes" && + test "$ac_cv_header_ip_nat_h" = "yes" ; then + IPF_TRANSPARENT="yes" + AC_DEFINE(IPF_TRANSPARENT, 1) + elif test "$ac_cv_header_netinet_ip_compat_h" = "yes" && + test "$ac_cv_header_netinet_ip_fil_h" = "yes" && + test "$ac_cv_header_netinet_ip_nat_h" = "yes" ; then + IPF_TRANSPARENT="yes" + AC_DEFINE(IPF_TRANSPARENT, 1) + else IPF_TRANSPARENT="no" AC_DEFINE(IPF_TRANSPARENT, 0) - else - IPF_TRANSPARENT="yes" - AC_DEFINE(IPF_TRANSPARENT) fi AC_MSG_RESULT($IPF_TRANSPARENT) fi @@ -985,7 +1067,8 @@ #include #endif main() { - fprintf (fopen("conftestval", "w"), "%d\n", FD_SETSIZE); + FILE *fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", FD_SETSIZE); exit(0); } ], @@ -1004,6 +1087,7 @@ #include #include main() { + FILE *fp; int i,j; #if __CYGWIN32__ /* getrlimit and sysconf returns bogous values on cygwin32. @@ -1033,7 +1117,12 @@ } #endif /* RLIMIT_NOFILE */ #endif /* HAVE_SETRLIMIT */ -#if HAVE_SYSCONF && defined(_SC_OPEN_MAX) +#if defined(__linux__) && HAVE_GETRLIMIT && defined(RLIMIT_NOFILE) + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { + perror("getrlimit: RLIMIT_NOFILE"); + } + i = rl.rlim_cur; +#elif HAVE_SYSCONF && defined(_SC_OPEN_MAX) i = sysconf(_SC_OPEN_MAX); #elif HAVE_GETDTABLESIZE && !defined(__linux__) i = getdtablesize(); @@ -1049,7 +1138,8 @@ i++; #endif #endif /* __CYGWIN32__ */ - fprintf (fopen("conftestval", "w"), "%d\n", i); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", i); exit(0); } ], @@ -1076,11 +1166,13 @@ #include main () { + FILE *fp; int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1); if (val<=0) exit(1); - fprintf (fopen("conftestval", "w"), "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } ], @@ -1100,11 +1192,13 @@ #include main () { + FILE *fp; int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fprintf (fopen("conftestval", "w"), "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } ], @@ -1124,13 +1218,13 @@ #include main () { - int fd,val=0,len=sizeof(int); FILE *fp; + int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fp = fopen("conftestval", "w"); - fprintf (fp, "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } ], @@ -1150,13 +1244,13 @@ #include main () { - int fd,val=0,len=sizeof(int); FILE *fp; + int fd,val=0,len=sizeof(int); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(1); if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, &len) < 0) exit(1); if (val <= 0) exit(1); - fp = fopen("conftestval", "w"); - fprintf (fp, "%d\n", val); + fp = fopen("conftestval", "w"); + fprintf (fp, "%d\n", val); exit(0); } ], @@ -1191,9 +1285,11 @@ #include main () { + FILE *fp; struct in_addr in; in.s_addr = inet_addr("1.2.3.4"); - fprintf (fopen("conftestval", "w"), "%s\n", inet_ntoa(in)); + fp = fopen("conftestval", "w"); + fprintf (fp, "%s\n", inet_ntoa(in)); exit(0); } ], @@ -1204,13 +1300,15 @@ AC_MSG_RESULT("yes") else AC_MSG_RESULT("no") - echo "WARNING: This looks bad, and probably prevents Squid from working." - echo " If you're on IRIX and using GCC 2.8, you probably need" - echo " to use the IRIX C compiler instead." - sleep 10 + echo "Will use our own inet_ntoa()." + LIBOBJS="$LIBOBJS inet_ntoa.o" +# echo "WARNING: This looks bad, and probably prevents Squid from working." +# echo " If you're on IRIX and using GCC 2.8, you probably need" +# echo " to use the IRIX C compiler instead." +# sleep 10 fi -if test "$ac_cv_func_statvfs" = "yes" ; then +if test "$ac_cv_header_sys_statvfs_h" = "yes" ; then AC_MSG_CHECKING(for working statvfs() interface) AC_TRY_COMPILE([ #include @@ -1227,6 +1325,9 @@ ac_cv_func_statvfs=yes, ac_cv_func_statvfs=no) AC_MSG_RESULT($ac_cv_func_statvfs) +if test "$ac_cv_func_statvfs" = "yes" ; then + AC_DEFINE(HAVE_STATVFS) +fi fi AC_CACHE_CHECK(for _res.nsaddr_list, ac_cv_have_res_nsaddr_list, @@ -1323,4 +1424,5 @@ ./errors/Makefile \ ./auth_modules/dummy \ ./auth_modules/NCSA/Makefile \ + ./auth_modules/getpwnam/Makefile \ ) Index: squid/makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/Attic/makefile.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/makefile.in 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/makefile.in 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -1,4 +1,4 @@ -# $Id: makefile.in,v 1.1.1.1 2000/01/26 03:21:46 hno Exp $ +# $Id: makefile.in,v 1.1.1.2 2000/01/26 03:23:09 hno Exp $ # srcdir = @srcdir@ @@ -37,7 +37,7 @@ almostclean: clean rm -f config.log makefile rm -f include/paths.h include/autoconf.h include/config.h - rm -f auth_modules/NCSA/Makefile + rm -f auth_modules/NCSA/Makefile auth_modules/dummy @for dir in $(SUBDIRS) contrib; do \ echo Making distclean in $$dir; \ (cd $$dir; $(MAKE) $(MFLAGS) prefix="$(prefix)" distclean); \ Index: squid/auth_modules/SMB/README =================================================================== RCS file: /cvsroot/squid-sf//squid/auth_modules/SMB/Attic/README,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/auth_modules/SMB/README 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/auth_modules/SMB/README 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -1,71 +1,3 @@ -============================================================================== -From: Richard Huveneers -To: squid-users@ircache.net -Subject: Announce: SMB proxy authentication -Date: Fri, 31 Jul 1998 22:37:58 +0200 -============================================================================== +For documentation, please refer to - - -I've written an authenticator for use with Arjan de Vet's -external proxy authentication patch. This authenticator -uses the SMB protocol to authenticate against a NT server, -Samba server, etc. - -This authenticator has been in use in our network for two -weeks now without a single problem. - -Please let me know if you are using this authenticator, so -that I know it's worth spending time on. - -INSTALL: - -(this procedure can be much smoother, and I will spend time -on that if there is sufficient interest) - -- First, you need the smbvalid.a library. - - download pam_smb from http://www.csn.ul.ie/~airlied/pam_smb/ - - Type: ./configure - - Edit the Makefile and remove -fPIC - - Type: make smbvalid - -- Download ftp://ftp.hacom.nl/pub/users/richard/smb_auth-0.1.c - -- Specify your NT domain(s) in the "ntd" array. If you change - the number of domains, then don't forget to change the - NUMNTDOMAINS define too. - -- Compile the program with - gcc -Ismbval -o smb_auth -O2 -Wall smb_auth-0.1.c smbval/smbvalid.a - -- Copy the smb_auth binary to /usr/local/bin and use it in your - squid.conf file. - -USAGE: - -If you have more than one NT domain on your network (like me) -than the authenticator needs a hint which NT domain to -authenticate against. - -This must be done by appending \domainname to the username when -entering the username and password in the browser. If there is -no backslash in the username, than the authenticator picks the NT -domain which has an empty abbreviation in the ntd array. - -So if you have just one NT domain, then leave the abbreviation -for this domain blank and your users don't have to specify any -domain. - -The authenticator accepts any valid account in the NT domain, -so check your domain for unwanted guest accounts. - -TODO list: - -- move the domain defines to the arguments so they can be - specified in the squid.conf file. -- smoothen installation -- only accept members of a specific group -- write documentation -- write a web page for this proggie - -Richard. + http://www.hacom.nl/~richard/software/smb_auth.html Index: squid/auth_modules/getpwnam/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/auth_modules/getpwnam/Attic/Makefile.in,v retrieving revision 1.1 retrieving revision 1.1.1.1 diff -u -r1.1 -r1.1.1.1 --- squid/auth_modules/getpwnam/Makefile.in 26 Jan 2000 03:23:09 -0000 1.1 +++ squid/auth_modules/getpwnam/Makefile.in 26 Jan 2000 03:23:09 -0000 1.1.1.1 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.1 2000/01/26 03:23:09 hno Exp $ +# $Id: Makefile.in,v 1.1.1.1 2000/01/26 03:23:09 hno Exp $ # # Uncomment and customize the following to suit your needs: # Index: squid/cfgaux/config.guess =================================================================== RCS file: /cvsroot/squid-sf//squid/cfgaux/Attic/config.guess,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/cfgaux/config.guess 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/cfgaux/config.guess 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -555,6 +555,9 @@ news*:NEWS-OS:[56].*:*) echo mips-sony-newsos${UNAME_RELEASE} exit 0 ;; + i?86:OS/2:*:*) + echo ${UNAME_MACHINE}-ibm-os2 + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 Index: squid/cfgaux/config.sub =================================================================== RCS file: /cvsroot/squid-sf//squid/cfgaux/Attic/config.sub,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/cfgaux/config.sub 26 Jan 2000 03:21:46 -0000 1.1.1.1 +++ squid/cfgaux/config.sub 26 Jan 2000 03:23:09 -0000 1.1.1.2 @@ -755,6 +755,8 @@ ;; -none) ;; + -os2) + ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` Index: squid/errors/English/ERR_FTP_FAILURE =================================================================== RCS file: /cvsroot/squid-sf//squid/errors/English/ERR_FTP_FAILURE,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/errors/English/ERR_FTP_FAILURE 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/errors/English/ERR_FTP_FAILURE 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -14,9 +14,5 @@ and then received this reply
%F
%g
-

-This might be caused by an FTP URL with an absolute path (which does -not comply with RFC 1738). If this is the cause, then the file -can be found at %B.

Index: squid/errors/Estonian/ERR_ZERO_SIZE_OBJECT =================================================================== RCS file: /cvsroot/squid-sf//squid/errors/Estonian/ERR_ZERO_SIZE_OBJECT,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/errors/Estonian/ERR_ZERO_SIZE_OBJECT 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/errors/Estonian/ERR_ZERO_SIZE_OBJECT 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -12,7 +12,7 @@
  • -Null pikkusega vastus +Vastus on tühi
Index: squid/errors/German/ERR_READ_TIMEOUT =================================================================== RCS file: /cvsroot/squid-sf//squid/errors/German/ERR_READ_TIMEOUT,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/errors/German/ERR_READ_TIMEOUT 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/errors/German/ERR_READ_TIMEOUT 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -19,7 +19,7 @@
    %E
zurück.

-Bei des Versuches, Daten vom Netzwerk zu lesen, mußte zu lange +Bei dem Versuch Daten vom Netzwerk zu lesen, mußte zu lange gewartet werden (timeout). Das Netzwerk oder der Server könnten deaktiviert oder überlastet sein. Bitte versuchen Sie Ihre Anfrage erneut. Index: squid/errors/Hungarian/ERR_CANNOT_FORWARD =================================================================== RCS file: /cvsroot/squid-sf//squid/errors/Hungarian/ERR_CANNOT_FORWARD,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/errors/Hungarian/ERR_CANNOT_FORWARD 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/errors/Hungarian/ERR_CANNOT_FORWARD 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -22,6 +22,6 @@

  • A cache adminisztrátor nem engedélyezi a forrás szerverekhez való közvetlen kapcsolat felépítését és -
  • minden általunk használt szülõ cache szerver nem érhetõ el jelenleg. +
  • egyik általunk használt szülõ cache szerver sem érhetõ el jelenleg.

Index: squid/errors/Hungarian/ERR_ONLY_IF_CACHED_MISS =================================================================== RCS file: /cvsroot/squid-sf//squid/errors/Hungarian/ERR_ONLY_IF_CACHED_MISS,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/errors/Hungarian/ERR_ONLY_IF_CACHED_MISS 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/errors/Hungarian/ERR_ONLY_IF_CACHED_MISS 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -21,6 +21,6 @@ Olyan kérést küldött el, amelyben only-if-cached cache vezérlõ direktíva található. A dokumentum nincs a cache-ben vagy a dokumentum -érvényesség-ellenõrzést igényelt volna, ezt azonban a only-if-cached +érvényesség-ellenõrzést igényelt volna, ezt azonban az only-if-cached direktíva megtiltotta.

Index: squid/icons/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/icons/Attic/Makefile.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/icons/Makefile.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/icons/Makefile.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: Makefile.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ # prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -17,7 +17,6 @@ INSTALL_FILE = @INSTALL_DATA@ DEFAULT_ICON_DIR = $(sysconfdir)/icons -SHARFILE = $(srcdir)/icons.shar ICONS = anthony-binhex.gif \ anthony-bomb.gif \ anthony-box.gif \ @@ -46,12 +45,9 @@ anthony-xbm.gif \ anthony-xpm.gif -all: anthony-xpm.gif +all: -anthony-xpm.gif: $(SHARFILE) - $(SH) $(SHARFILE) - -$(SHARFILE): +icons.shar: shar --no-timestamp $(ICONS) > $@ install: install-mkdirs anthony-xpm.gif @@ -79,7 +75,7 @@ fi clean: - $(RM) -f $(ICONS) + distclean: clean -rm -f Makefile Index: squid/include/GNUregex.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/GNUregex.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/GNUregex.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/GNUregex.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: GNUregex.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: GNUregex.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ /* Definitions for data structures and routines for the regular @@ -389,7 +389,7 @@ * unfortunately clutters up the declarations a bit, but I think it's * worth it. */ -#ifdef __STDC__ +#if STDC_HEADERS #define _RE_ARGS(args) args Index: squid/include/autoconf.h.in =================================================================== RCS file: /cvsroot/squid-sf//squid/include/Attic/autoconf.h.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/autoconf.h.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/autoconf.h.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,25 +1,4 @@ /* include/autoconf.h.in. Generated automatically from configure.in by autoheader. */ -/* - * All configurable options are enabled by using --enable-.... - * when running configure. See configure --help for a list - * of all available options. - * - * You are free to edit this file, but it will be overwritten - * each time you run configure. You may need to edit this file - * if configure falsely picks up a library function or structure - * that doesn't really work on your system. - * - * Another way to block a function that should not be detected - * is to - * setenv ac_cv_func_ no - * before running configure, as in - * setenv ac_cv_func_setresuid no - * - * It is possible to enable some of the configurable options - * by editing this file alone, but some of them requires changes - * in the Makefiles, wich is done automatically by configure. - * - */ /* Define if using alloca.c. */ #undef C_ALLOCA @@ -238,6 +217,11 @@ #undef IPF_TRANSPARENT /* + * Enable code for assiting in finding memory leaks. Hacker stuff only. + */ +#undef USE_LEAKFINDER + +/* * type of fd_set array */ #undef fd_mask @@ -252,12 +236,30 @@ */ #undef HAVE_RES_NS_LIST +/* + * Compile in support for Ident (RFC 931) lookups? Enabled by default. + */ +#define USE_IDENT 1 + +/* + * If your system has statvfs(), and if it actually works! + */ +#undef HAVE_STATVFS + +/* + * we check for struct mallinfo + */ +#undef HAVE_STRUCT_MALLINFO + /* The number of bytes in a int. */ #undef SIZEOF_INT /* The number of bytes in a long. */ #undef SIZEOF_LONG +/* The number of bytes in a void *. */ +#undef SIZEOF_VOID_P + /* Define if you have the bcopy function. */ #undef HAVE_BCOPY @@ -276,6 +278,9 @@ /* Define if you have the getpagesize function. */ #undef HAVE_GETPAGESIZE +/* Define if you have the getrlimit function. */ +#undef HAVE_GETRLIMIT + /* Define if you have the getrusage function. */ #undef HAVE_GETRUSAGE @@ -366,9 +371,6 @@ /* Define if you have the srandom function. */ #undef HAVE_SRANDOM -/* Define if you have the statvfs function. */ -#undef HAVE_STATVFS - /* Define if you have the strerror function. */ #undef HAVE_STRERROR @@ -387,9 +389,6 @@ /* Define if you have the vsnprintf function. */ #undef HAVE_VSNPRINTF -/* Define if you have the header file. */ -#undef HAVE_ALLOCA_H - /* Define if you have the header file. */ #undef HAVE_ARPA_INET_H @@ -468,6 +467,15 @@ /* Define if you have the header file. */ #undef HAVE_NETINET_IN_H +/* Define if you have the header file. */ +#undef HAVE_NETINET_IP_COMPAT_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IP_FIL_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IP_NAT_H + /* Define if you have the header file. */ #undef HAVE_NETINET_TCP_H @@ -582,6 +590,9 @@ /* Define if you have the gnumalloc library (-lgnumalloc). */ #undef HAVE_LIBGNUMALLOC +/* Define if you have the intl library (-lintl). */ +#undef HAVE_LIBINTL + /* Define if you have the m library (-lm). */ #undef HAVE_LIBM Index: squid/include/cache_snmp.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/cache_snmp.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/cache_snmp.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/cache_snmp.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: cache_snmp.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cache_snmp.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ #ifdef SQUID_SNMP @@ -20,18 +20,8 @@ #include "snmp_impl.h" #include "asn1.h" #include "snmp_api.h" -#if 0 -#include "snmp_client.h" -#include "mib.h" -#endif -#include "snmp_vars.h" -#include "snmp_oidlist.h" -/* mib stuff here */ - -#ifndef CURRENT_MIB_VERSION -#define CURRENT_MIB_VERSION "-- v 1.16 1998/09/22 glenn@ircache.net" -#endif +#include "snmp_vars.h" /* MIB definitions * SQUID-MIB @@ -45,6 +35,9 @@ #define SQUIDMIB 1, 3, 6, 1, 4, 1, 3495, 1 #define LEN_SQUIDMIB 8 +#define INSTANCE 0 +#define TIME_INDEX 1, 5, 60 +#define TIME_INDEX_LEN 3 /* basic groups under .squid */ @@ -71,6 +64,9 @@ SYS_END }; +#define LEN_SYS LEN_SQ_SYS + 1 +#define LEN_SYS_INST LEN_SQ_SYS + 2 + /* cacheConfig group */ @@ -85,17 +81,21 @@ CONF_END }; +#define LEN_CONF LEN_SQ_CONF + 1 +#define LEN_CONF_INST LEN_SQ_CONF + 2 + enum { CONF_ST_START, CONF_ST_MMAXSZ, - CONF_ST_MHIWM, - CONF_ST_MLOWM, CONF_ST_SWMAXSZ, CONF_ST_SWHIWM, CONF_ST_SWLOWM, CONF_ST_END }; +#define LEN_CONF_ST LEN_CONF + 1 +#define LEN_CONF_ST_INST LEN_CONF + 2 + /* cacheMesh group */ @@ -144,6 +144,14 @@ */ enum { + NET_START, + NET_IP_CACHE, + NET_FQDN_CACHE, + NET_DNS_CACHE, + NET_END +}; + +enum { IP_START, IP_ENT, IP_REQ, @@ -153,7 +161,6 @@ IP_MISS, IP_GHBN, IP_LOC, - IP_LENG, IP_END }; @@ -166,7 +173,6 @@ FQDN_NEGHIT, FQDN_MISS, FQDN_GHBN, - FQDN_LENG, FQDN_END }; @@ -186,7 +192,6 @@ PERF_START, PERF_SYS, PERF_PROTO, - PERF_PEER, PERF_END }; @@ -194,8 +199,8 @@ PERF_SYS_START, PERF_SYS_PF, PERF_SYS_NUMR, - PERF_SYS_DEFR, PERF_SYS_MEMUSAGE, + PERF_SYS_CPUTIME, PERF_SYS_CPUUSAGE, PERF_SYS_MAXRESSZ, PERF_SYS_NUMOBJCNT, @@ -229,6 +234,7 @@ PERF_PROTOSTAT_AGGR_KBYTES_IN, PERF_PROTOSTAT_AGGR_KBYTES_OUT, PERF_PROTOSTAT_AGGR_CURSWAP, + PERF_PROTOSTAT_AGGR_CLIENTS, PERF_PROTOSTAT_AGGR_END }; @@ -242,75 +248,10 @@ PERF_MEDIAN_ICP_QUERY, PERF_MEDIAN_ICP_REPLY, PERF_MEDIAN_DNS, + PERF_MEDIAN_RHR, + PERF_MEDIAN_BHR, PERF_MEDIAN_END }; -/* First, we have a huge array of MIBs this agent knows about */ - -struct MIBListEntry { - oid Name[10]; /* This needs to be fixed, a static is ugly */ - snint NameLen; - oid_GetFn *GetFn; - oid_GetNextFn *GetNextFn; -}; - -variable_list *snmp_basicFn(variable_list *, snint *); -variable_list *snmp_confFn(variable_list *, snint *); -variable_list *snmp_sysFn(variable_list *, snint *); -variable_list *snmp_prfSysFn(variable_list *, snint *); -variable_list *snmp_prfProtoFn(variable_list *, snint *); -variable_list *snmp_prfPeerFn(variable_list *, snint *); -variable_list *snmp_netIpFn(variable_list *, snint *); -variable_list *snmp_netFqdnFn(variable_list *, snint *); -variable_list *snmp_netDnsFn(variable_list *, snint *); -variable_list *snmp_meshPtblFn(variable_list *, snint *); -variable_list *snmp_meshCtblFn(variable_list *, snint *); - - -extern int snmpInitAgentAuth(); -extern void snmpAgentParse(void *); -extern int snmpDefaultAuth(); -extern int get_median_svc(int, int); -extern void snmpAgentParseDone(int, void *); -extern int meshCtblGetRowFn(oid *, oid *); -extern struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU); -extern void snmpAclCheckStart(void *); -extern struct snmp_session *Session; -extern oid_ParseFn *genericGetNextFn(oid * Src, snint SrcLen, oid ** Dest, snint * DestLen, - oid * MIBRoot, int MIBRootLen, oid_GetRowFn * getRowFn, int tblen, oid * MIBTail, - oid_ParseFn * mygetFn, int MIBTailLen, int MIB_ACTION_INDEX); - -extern int oidcmp(oid * A, snint ALen, oid * B, snint BLen); -extern int oidncmp(oid * A, snint ALen, oid * B, snint BLen, snint CompLen); -extern oid *oiddup(oid * A, snint ALen); - - -/* group handler definition */ - -extern oid_ParseFn *sysGetFn(oid *, snint); -extern oid_ParseFn *sysGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *confGetFn(oid *, snint); -extern oid_ParseFn *confGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *confStGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *prfSysGetFn(oid *, snint); -extern oid_ParseFn *prfSysGetFn(oid *, snint); -extern oid_ParseFn *prfSysGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *prfProtoGetFn(oid *, snint); -extern oid_ParseFn *prfProtoGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *netIpGetFn(oid *, snint); -extern oid_ParseFn *netDnsGetFn(oid *, snint); -extern oid_ParseFn *netFqdnGetFn(oid *, snint); -extern oid_ParseFn *netFqdnGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *netIpGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *netDnsGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *meshGetFn(oid *, snint); -extern oid_ParseFn *meshPtblGetNextFn(oid *, snint, oid **, snint *); -extern oid_ParseFn *meshCtblGetNextFn(oid *, snint, oid **, snint *); -extern int meshPtblGetRowFn(oid *, oid *); -extern int sysConnGetRowFn(oid *, oid *); -extern int meshCtblGetRowFn(oid *, oid *); - -extern struct in_addr *gen_getMax(); - #endif #endif Index: squid/include/config.h.in =================================================================== RCS file: /cvsroot/squid-sf//squid/include/Attic/config.h.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/config.h.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/config.h.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: config.h.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: config.h.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * AUTHOR: Duane Wessels * @@ -46,9 +46,9 @@ #endif /* define the _SQUID_TYPE_ based on a guess of the OS */ -#if defined(__sun__) /* SUN */ +#if defined(__sun__) || defined(__sun) /* SUN */ #define _SQUID_SUN_ -#if defined(_SQUID_SYSV_) /* SOLARIS */ +#if defined(__SVR4) /* SOLARIS */ #define _SQUID_SOLARIS_ #else /* SUNOS */ #define _SQUID_SUNOS_ @@ -69,9 +69,15 @@ #elif defined(__linux__) /* Linux */ #define _SQUID_LINUX_ +#if USE_ASYNC_IO +#define _SQUID_LINUX_THREADS_ +#endif #elif defined(__FreeBSD__) /* FreeBSD */ #define _SQUID_FREEBSD_ +#if USE_ASYNC_IO && defined(LINUXTHREADS) +#define _SQUID_LINUX_THREADS_ +#endif #elif defined(__sgi__) || defined(sgi) || defined(__sgi) /* SGI */ #define _SQUID_SGI_ @@ -94,6 +100,22 @@ #elif defined(__CYGWIN32__) || defined(WIN32) || defined(WINNT) || defined(__WIN32__) || defined(__WIN32) #define _SQUID_MSWIN_ +#elif defined(sony_news) && defined(__svr4) +#define _SQUID_NEWSOS6_ + +#elif defined(__EMX__) || defined(OS2) || defined(__OS2__) +#define _SQUID_OS2_ +/* + * FIXME: the os2 port of bash seems to have problems checking + * the return codes of programs in if statements. These options + * need to be overridden. + */ +#ifndef socklen_t +#define socklen_t int +#endif +#ifndef fd_mask +#define fd_mask unsigned long +#endif #endif #if !defined(CACHE_HTTP_PORT) @@ -132,6 +154,14 @@ #define xmemmove(d,s,n) bcopy((s),(d),(n)) #endif +#define xisspace(x) isspace((unsigned char)x) +#define xtoupper(x) toupper((unsigned char)x) +#define xtolower(x) tolower((unsigned char)x) +#define xisdigit(x) isdigit((unsigned char)x) +#define xisascii(x) isascii((unsigned char)x) +#define xislower(x) islower((unsigned char)x) +#define xisalpha(x) isalpha((unsigned char)x) + #if defined(O_NONBLOCK) && !defined(_SQUID_SUNOS_) && !defined(_SQUID_SOLARIS_) #define SQUID_NONBLOCK O_NONBLOCK #else Index: squid/include/snmp_debug.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/snmp_debug.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/snmp_debug.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/snmp_debug.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,11 +1,11 @@ /* - * $Id: snmp_debug.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: snmp_debug.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ #ifndef SNMP_DEBUG_H #define SNMP_DEBUG_H -#ifdef __STDC__ +#if STDC_HEADERS extern void snmplib_debug(int, char *,...); #else extern void snmplib_debug(va_alist); Index: squid/include/util.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/util.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/util.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/util.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: util.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: util.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * AUTHOR: Harvest Derived * @@ -113,4 +113,8 @@ extern const char *xitoa(int num); +#if !HAVE_DRAND48 +double drand48(void); +#endif + #endif /* ndef _UTIL_H_ */ Index: squid/include/version.h =================================================================== RCS file: /cvsroot/squid-sf//squid/include/version.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/include/version.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/include/version.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,12 +1,12 @@ /* - * $Id: version.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: version.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * SQUID_VERSION - String for version id of this distribution */ #ifndef SQUID_VERSION -#define SQUID_VERSION "2.1.PATCH2" +#define SQUID_VERSION "2.2.STABLE5" #endif #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 913240045 +#define SQUID_RELEASE_TIME 938113298 #endif Index: squid/lib/hash.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/hash.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/hash.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/hash.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: hash.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: hash.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 Hash Tables * AUTHOR: Harvest Derived Index: squid/lib/radix.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/radix.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/radix.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/radix.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: radix.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: radix.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 53 Radix tree data structure implementation * AUTHOR: NetBSD Derived Index: squid/lib/rfc1123.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/rfc1123.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/rfc1123.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/rfc1123.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: rfc1123.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: rfc1123.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: * AUTHOR: Harvest Derived @@ -93,9 +93,9 @@ int i; char month[3]; - month[0] = toupper(*s); - month[1] = tolower(*(s + 1)); - month[2] = tolower(*(s + 2)); + month[0] = xtoupper(*s); + month[1] = xtolower(*(s + 1)); + month[2] = xtolower(*(s + 2)); for (i = 0; i < 12; i++) if (!strncmp(month_names[i], month, 3)) @@ -119,7 +119,7 @@ s++; /* or: Thu, 10 Jan 1993 01:29:59 GMT */ while (*s == ' ') s++; - if (isdigit(*s) && !isdigit(*(s+1))) /* backoff if only one digit */ + if (xisdigit(*s) && !xisdigit(*(s+1))) /* backoff if only one digit */ s--; if (strchr(s, '-')) { /* First format */ if ((int) strlen(s) < 18) Index: squid/lib/safe_inet_addr.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/safe_inet_addr.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/safe_inet_addr.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/safe_inet_addr.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: safe_inet_addr.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: safe_inet_addr.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ #include "config.h" @@ -35,7 +35,18 @@ int a1 = 0, a2 = 0, a3 = 0, a4 = 0; struct in_addr A; char x; +#if defined(_SQUID_HPUX_) + /* + * MIYOSHI Tsutomu says scanning 'buf' + * causes a bus error on hppa1.1-hp-hpux9.07, so we + * have a broad hack for all HP systems. + */ + static char buftmp[32]; + snprintf(buftmp, 32, "%s", buf); + if (sscanf(buftmp, "%d.%d.%d.%d%c", &a1, &a2, &a3, &a4, &x) != 4) +#else if (sscanf(buf, "%d.%d.%d.%d%c", &a1, &a2, &a3, &a4, &x) != 4) +#endif return 0; if (a1 < 0 || a1 > 255) return 0; Index: squid/lib/snprintf.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/snprintf.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/snprintf.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/snprintf.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: snprintf.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: snprintf.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */ /* ==================================================================== @@ -302,7 +302,7 @@ #define STR_TO_DEC( str, num ) \ num = NUM( *str++ ) ; \ - while ( isdigit( *str ) ) \ + while ( xisdigit( *str ) ) \ { \ num *= 10 ; \ num += NUM( *str++ ) ; \ @@ -422,7 +422,7 @@ /* * Check for Infinity and NaN */ - if (isalpha(*p)) { + if (xisalpha(*p)) { *len = strlen(strcpy(buf, p)); *is_negative = FALSE; return (buf); @@ -577,7 +577,7 @@ /* * Try to avoid checking for flags, width or precision */ - if (isascii(*fmt) && !islower(*fmt)) { + if (xisascii(*fmt) && !xislower(*fmt)) { /* * Recognize flags: -, #, BLANK, + */ @@ -599,7 +599,7 @@ /* * Check if a width was specified */ - if (isdigit(*fmt)) { + if (xisdigit(*fmt)) { STR_TO_DEC(fmt, min_width); adjust_width = YES; } else if (*fmt == '*') { @@ -623,7 +623,7 @@ if (*fmt == '.') { adjust_precision = YES; fmt++; - if (isdigit(*fmt)) { + if (xisdigit(*fmt)) { STR_TO_DEC(fmt, precision); } else if (*fmt == '*') { precision = va_arg(ap, int); Index: squid/lib/util.c =================================================================== RCS file: /cvsroot/squid-sf//squid/lib/util.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/lib/util.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/lib/util.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: util.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: util.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: * AUTHOR: Harvest Derived @@ -678,7 +678,7 @@ { size_t count = 0; if (str) { - while (isspace(*str)) { + while (xisspace(*str)) { str++; count++; } Index: squid/scripts/RunAccel.in =================================================================== RCS file: /cvsroot/squid-sf//squid/scripts/Attic/RunAccel.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/scripts/RunAccel.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/scripts/RunAccel.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ #!/bin/sh # -# $Id: RunAccel.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: RunAccel.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ # enable HTTP requests on port 80 port="-a 80" @@ -20,7 +20,7 @@ while : ; do echo "Running: squid $port -s $conf >> $logdir/squid.out 2>&1" start=`date '+%d%H%M%S'` - squid $port -s $conf >> $logdir/squid.out 2>&1 + squid -N $port -s $conf >> $logdir/squid.out 2>&1 stop=`date '+%d%H%M%S'` t=`expr $stop - $start` if test 0 -le $t -a $t -lt 5 ; then Index: squid/scripts/RunCache.in =================================================================== RCS file: /cvsroot/squid-sf//squid/scripts/RunCache.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/scripts/RunCache.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/scripts/RunCache.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ #!/bin/sh # -# $Id: RunCache.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: RunCache.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ prefix=@prefix@ exec_prefix=@exec_prefix@ @@ -19,7 +19,7 @@ echo "Running: squid -sY $conf >> $logdir/squid.out 2>&1" echo "Startup: `date`" >> $logdir/squid.out start=`date '+%d%H%M%S'` - squid -sY $conf >> $logdir/squid.out 2>&1 + squid -NsY $conf >> $logdir/squid.out 2>&1 stop=`date '+%d%H%M%S'` t=`expr $stop - $start` if test 0 -le $t -a $t -lt 5 ; then Index: squid/scripts/udp-banger.pl =================================================================== RCS file: /cvsroot/squid-sf//squid/scripts/udp-banger.pl,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/scripts/udp-banger.pl 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/scripts/udp-banger.pl 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -88,7 +88,7 @@ $myip, # a4 shostid $_); # a%d payload die "send: $!\n" unless - send($sock, $request, 0, $them); + send($sock, $request, 0); $nsent++; $rin = ''; vec($rin,fileno($sock),1) = 1; Index: squid/snmplib/parse.c =================================================================== RCS file: /cvsroot/squid-sf//squid/snmplib/parse.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/snmplib/parse.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/snmplib/parse.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1098,13 +1098,13 @@ return (NULL); } mbuf[0] = '\0'; - while ((p = fgets(mbuf, 256, fp)) && strncmp(mbuf, CURRENT_MIB_VERSION, - strlen(CURRENT_MIB_VERSION))); + while ((p = fgets(mbuf, 256, fp)) && strncmp(mbuf, "DUMMY", + strlen("DUMMY"))); if (!p) { snmplib_debug(0, "Bad MIB version or tag missing, install original!\n"); return NULL; } - if (!strcmp(mbuf, CURRENT_MIB_VERSION)) { + if (!strcmp(mbuf, "DUMMY")) { snmplib_debug(0, "You need to update your MIB!\n"); return NULL; } Index: squid/snmplib/snmplib_debug.c =================================================================== RCS file: /cvsroot/squid-sf//squid/snmplib/snmplib_debug.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/snmplib/snmplib_debug.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/snmplib/snmplib_debug.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -5,7 +5,7 @@ #if HAVE_SYS_TYPES_H #include #endif -#ifdef __STDC__ +#if STDC_HEADERS #include #else #include @@ -15,14 +15,14 @@ #include "snprintf.h" #endif -#ifdef __STDC__ +#if STDC_HEADERS void (*snmplib_debug_hook) (int, char *,...) = NULL; #else void (*snmplib_debug_hook) (va_alist) = NULL; #endif extern void -#ifdef __STDC__ +#if STDC_HEADERS snmplib_debug(int lvl, char *fmt,...) { char buf[BUFSIZ]; Index: squid/src/CacheDigest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/CacheDigest.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/CacheDigest.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/CacheDigest.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: CacheDigest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: CacheDigest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 70 Cache Digest * AUTHOR: Alex Rousskov @@ -88,7 +88,7 @@ { assert(cd); cacheDigestClean(cd); - memFree(MEM_CACHE_DIGEST, cd); + memFree(cd, MEM_CACHE_DIGEST); } CacheDigest * @@ -249,10 +249,13 @@ assert(label); assert(tot_count == hit_count + miss_count); /* paranoid */ + if (!tot_count) { + storeAppendPrintf(sentry, "no guess stats for %s available\n", label); + return; + } storeAppendPrintf(sentry, "Digest guesses stats for %s:\n", label); storeAppendPrintf(sentry, "guess\t hit\t\t miss\t\t total\t\t\n"); storeAppendPrintf(sentry, " \t #\t %%\t #\t %%\t #\t %%\t\n"); - storeAppendPrintf(sentry, "true\t %d\t %.2f\t %d\t %.2f\t %d\t %.2f\n", stats->true_hits, xpercent(stats->true_hits, tot_count), stats->true_misses, xpercent(stats->true_misses, tot_count), Index: squid/src/HttpHdrCc.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHdrCc.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHdrCc.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHdrCc.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrCc.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHdrCc.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 65 HTTP Cache Control Header * AUTHOR: Alex Rousskov @@ -144,7 +144,7 @@ httpHdrCcDestroy(HttpHdrCc * cc) { assert(cc); - memFree(MEM_HTTP_HDR_CC, cc); + memFree(cc, MEM_HTTP_HDR_CC); } HttpHdrCc * Index: squid/src/HttpHdrContRange.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHdrContRange.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHdrContRange.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHdrContRange.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrContRange.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHdrContRange.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 68 HTTP Content-Range Header * AUTHOR: Alex Rousskov @@ -162,7 +162,7 @@ httpHdrContRangeDestroy(HttpHdrContRange * range) { assert(range); - memFree(MEM_HTTP_HDR_CONTENT_RANGE, range); + memFree(range, MEM_HTTP_HDR_CONTENT_RANGE); } HttpHdrContRange * Index: squid/src/HttpHdrExtField.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHdrExtField.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHdrExtField.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHdrExtField.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrExtField.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHdrExtField.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 69 HTTP Header: Extension Field * AUTHOR: Alex Rousskov @@ -73,7 +73,7 @@ value_start = name_end + 1; /* skip ':' */ /* skip white space */ - while (value_start < field_end && isspace(*value_start)) + while (value_start < field_end && xisspace(*value_start)) value_start++; return httpHdrExtFieldDoCreate( Index: squid/src/HttpHdrRange.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHdrRange.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHdrRange.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHdrRange.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHdrRange.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHdrRange.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 64 HTTP Range Header * AUTHOR: Alex Rousskov @@ -119,7 +119,7 @@ static void httpHdrRangeSpecDestroy(HttpHdrRangeSpec * spec) { - memFree(MEM_HTTP_HDR_RANGE_SPEC, spec); + memFree(spec, MEM_HTTP_HDR_RANGE_SPEC); } @@ -265,7 +265,7 @@ while (range->specs.count) httpHdrRangeSpecDestroy(stackPop(&range->specs)); stackClean(&range->specs); - memFree(MEM_HTTP_HDR_RANGE, range); + memFree(range, MEM_HTTP_HDR_RANGE); } HttpHdrRange * @@ -409,21 +409,49 @@ return 0; } -/* hack: returns offset of first range spec */ +/* Returns lowest known offset in range spec(s), or range_spec_unknown */ +/* this is used for size limiting */ size_t httpHdrRangeFirstOffset(const HttpHdrRange * range) { + size_t offset = range_spec_unknown; HttpHdrRangePos pos = HttpHdrRangeInitPos; const HttpHdrRangeSpec *spec; assert(range); while ((spec = httpHdrRangeGetSpec(range, &pos))) { - if (!known_spec(spec->offset)) /* ignore unknowns */ - continue; - return spec->offset; + if (spec->offset < offset || !known_spec(offset)) + offset = spec->offset; } - return 0; + return offset; } +/* Returns lowest offset in range spec(s), 0 if unknown */ +/* This is used for finding out where we need to start if all + * ranges are combined into one, for example FTP REST. + * Use 0 for size if unknown + */ +size_t +httpHdrRangeLowestOffset(const HttpHdrRange * range, size_t size) +{ + size_t offset = range_spec_unknown; + size_t current; + HttpHdrRangePos pos = HttpHdrRangeInitPos; + const HttpHdrRangeSpec *spec; + assert(range); + while ((spec = httpHdrRangeGetSpec(range, &pos))) { + current = spec->offset; + if (!known_spec(current)) { + if (spec->length > size || !known_spec(spec->length)) + return 0; /* Unknown. Assume start of file */ + current = size - spec->length; + } + if (current < offset || !known_spec(offset)) + offset = current; + } + return known_spec(offset) ? offset : 0; +} + + /* generates a "unique" boundary string for multipart responses * the caller is responsible for cleaning the string */ String Index: squid/src/HttpHeader.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHeader.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHeader.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHeader.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpHeader.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHeader.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 55 HTTP Header * AUTHOR: Alex Rousskov @@ -234,15 +234,16 @@ assert(8 * sizeof(HttpHeaderMask) >= HDR_ENUM_END); /* all headers must be described */ assert(countof(HeadersAttrs) == HDR_ENUM_END); - Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + if (!Headers) + Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); /* create masks */ - httpHeaderMaskInit(&ListHeadersMask); + httpHeaderMaskInit(&ListHeadersMask, 0); httpHeaderCalcMask(&ListHeadersMask, (const int *) ListHeadersArr, countof(ListHeadersArr)); - httpHeaderMaskInit(&ReplyHeadersMask); + httpHeaderMaskInit(&ReplyHeadersMask, 0); httpHeaderCalcMask(&ReplyHeadersMask, (const int *) ReplyHeadersArr, countof(ReplyHeadersArr)); httpHeaderCalcMask(&ReplyHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr)); httpHeaderCalcMask(&ReplyHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr)); - httpHeaderMaskInit(&RequestHeadersMask); + httpHeaderMaskInit(&RequestHeadersMask, 0); httpHeaderCalcMask(&RequestHeadersMask, (const int *) RequestHeadersArr, countof(RequestHeadersArr)); httpHeaderCalcMask(&RequestHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr)); httpHeaderCalcMask(&RequestHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr)); @@ -488,7 +489,7 @@ int count = 0; HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; - httpHeaderMaskInit(&hdr->mask); /* temporal inconsistency */ + httpHeaderMaskInit(&hdr->mask, 0); /* temporal inconsistency */ debug(55, 7) ("deleting '%s' fields in hdr %p\n", name, hdr); while ((e = httpHeaderGetEntry(hdr, &pos))) { if (!strCaseCmp(e->name, name)) { @@ -818,7 +819,7 @@ if (!l || strncasecmp(field, authScheme, l)) /* wrong scheme */ return NULL; field += l; - if (!isspace(*field)) /* wrong scheme */ + if (!xisspace(*field)) /* wrong scheme */ return NULL; /* skip white space */ field += xcountws(field); @@ -897,7 +898,7 @@ assert(Headers[e->id].stat.aliveCount); Headers[e->id].stat.aliveCount--; e->id = -1; - memFree(MEM_HTTP_HDR_ENTRY, e); + memFree(e, MEM_HTTP_HDR_ENTRY); } /* parses and inits header entry, returns new entry on success */ @@ -932,7 +933,7 @@ else e->name = Headers[id].name; /* trim field value */ - while (value_start < field_end && isspace(*value_start)) + while (value_start < field_end && xisspace(*value_start)) value_start++; /* set field value */ stringLimitInit(&e->value, value_start, field_end - value_start); @@ -1061,3 +1062,25 @@ HttpHeaderStats[0].parsedCount); storeAppendPrintf(e, "Hdr Fields Parsed: %d\n", HeaderEntryParsedCount); } + +int +httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) +{ + int i; + for (i = 0; i < end; ++i) { + if (name_len >= 0 && name_len != strLen(info[i].name)) + continue; + if (!strncasecmp(name, strBuf(info[i].name), + name_len < 0 ? strLen(info[i].name) + 1 : name_len)) + return i; + } + return -1; +} + +int +httpHeaderIdByNameDef(const char *name, int name_len) +{ + if (!Headers) + Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END); + return httpHeaderIdByName(name, name_len, Headers, HDR_ENUM_END); +} Index: squid/src/HttpHeaderTools.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpHeaderTools.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpHeaderTools.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpHeaderTools.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,6 @@ + /* - * $Id: HttpHeaderTools.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpHeaderTools.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 66 HTTP Header Tools * AUTHOR: Alex Rousskov @@ -76,9 +77,9 @@ } void -httpHeaderMaskInit(HttpHeaderMask * mask) +httpHeaderMaskInit(HttpHeaderMask * mask, int value) { - memset(mask, 0, sizeof(*mask)); + memset(mask, value, sizeof(*mask)); } /* calculates a bit mask of a given array; does not reset mask! */ @@ -95,23 +96,8 @@ } } - -int -httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end) -{ - int i; - for (i = 0; i < end; ++i) { - if (name_len >= 0 && name_len != strLen(info[i].name)) - continue; - if (!strncasecmp(name, strBuf(info[i].name), - name_len < 0 ? strLen(info[i].name) + 1 : name_len)) - return i; - } - return -1; -} - /* same as httpHeaderPutStr, but formats the string using snprintf first */ -#ifdef __STDC__ +#if STDC_HEADERS void httpHeaderPutStrf(HttpHeader * hdr, http_hdr_type id, const char *fmt,...) { @@ -255,7 +241,7 @@ *pos = *item + strlen(*item); len = *pos - *item; /* *pos points to del or '\0' */ /* rtrim */ - while (len > 0 && isspace((*item)[len - 1])) + while (len > 0 && xisspace((*item)[len - 1])) len--; if (ilen) *ilen = len; @@ -282,7 +268,7 @@ { assert(value); *value = atoi(start); - if (!*value && !isdigit(*start)) { + if (!*value && !xisdigit(*start)) { debug(66, 2) ("failed to parse an int header field near '%s'\n", start); return 0; } @@ -322,7 +308,7 @@ hstr = p + 1; } /* skip invalid first line if any */ - if (isspace(*hstr)) { + if (xisspace(*hstr)) { const char *p = strchr(hstr, '\n'); if (p) hstr = p + 1; @@ -367,8 +353,8 @@ if (!strncasecmp(h1, h2, len)) return 0; while (1) { - const char c1 = toupper(h1[len1 += xcountws(h1 + len1)]); - const char c2 = toupper(h2[len2 += xcountws(h2 + len2)]); + const char c1 = xtoupper(h1[len1 += xcountws(h1 + len1)]); + const char c2 = xtoupper(h2[len2 += xcountws(h2 + len2)]); if (c1 < c2) return -len1; if (c1 > c2) Index: squid/src/HttpReply.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpReply.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpReply.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpReply.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpReply.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -62,7 +62,7 @@ void httpReplyInitModule() { - httpHeaderMaskInit(&Denied304HeadersMask); + httpHeaderMaskInit(&Denied304HeadersMask, 0); httpHeaderCalcMask(&Denied304HeadersMask, (const int *) Denied304HeadersArr, countof(Denied304HeadersArr)); } @@ -141,7 +141,7 @@ /* put a 0-terminator */ xstrncpy(headers, buf, 4096); success = httpReplyParseStep(rep, headers, 0); - memFree(MEM_4K_BUF, headers); + memFree(headers, MEM_4K_BUF); return success == 1; } @@ -198,7 +198,7 @@ httpPacked304Reply(const HttpReply * rep) { static const http_hdr_type ImsEntries[] = - {HDR_DATE, HDR_CONTENT_LENGTH, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER}; + {HDR_DATE, HDR_CONTENT_TYPE, HDR_EXPIRES, HDR_LAST_MODIFIED, /* eof */ HDR_OTHER}; int t; MemBuf mb; Packer p; @@ -279,7 +279,7 @@ static void httpReplyDoDestroy(HttpReply * rep) { - memFree(MEM_HTTP_REPLY, rep); + memFree(rep, MEM_HTTP_REPLY); } /* sync this routine when you update HttpReply struct */ Index: squid/src/HttpRequest.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpRequest.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpRequest.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpRequest.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpRequest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -43,11 +43,7 @@ req->protocol = protocol; if (urlpath) stringReset(&req->urlpath, urlpath); - req->max_age = -1; req->max_forwards = -1; -#if DELAY_POOLS - req->delay_id = 0; -#endif httpHeaderInit(&req->header, hoRequest); return req; } @@ -64,7 +60,7 @@ httpHdrCcDestroy(req->cache_control); if (req->range) httpHdrRangeDestroy(req->range); - memFree(MEM_REQUEST_T, req); + memFree(req, MEM_REQUEST_T); } request_t * @@ -147,14 +143,11 @@ httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConn) { assert(e); - /* check connection header first */ + /* check with anonymizer tables */ + if (CBIT_TEST(Config.anonymize_headers, e->id)) + return 0; + /* check connection header */ if (strConn && strListIsMember(strConn, strBuf(e->name), ',')) return 0; - /* check with anonymizer tables */ - if (Config.onoff.anonymizer == ANONYMIZER_PARANOID) { - return httpAnonHdrAllowed(e->id); - } else if (Config.onoff.anonymizer == ANONYMIZER_STANDARD) { - return !httpAnonHdrDenied(e->id); - } return 1; } Index: squid/src/HttpStatusLine.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/HttpStatusLine.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/HttpStatusLine.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/HttpStatusLine.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: HttpStatusLine.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: HttpStatusLine.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 57 HTTP Status-line * AUTHOR: Alex Rousskov @@ -83,7 +83,7 @@ if (strncasecmp(start, "HTTP/", 5)) return 0; start += 5; - if (!isdigit(*start)) + if (!xisdigit(*start)) return 0; sline->version = atof(start); if (!(start = strchr(start, ' '))) Index: squid/src/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/Makefile.in,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/Makefile.in 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/Makefile.in 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: Makefile.in,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ # # Uncomment and customize the following to suit your needs: # @@ -110,7 +110,6 @@ helper.o \ @HTCP_OBJS@ \ http.o \ - http-anon.o \ HttpStatusLine.o \ HttpHdrCc.o \ HttpHdrRange.o \ @@ -128,6 +127,7 @@ internal.o \ ipc.o \ ipcache.o \ + @LEAKFINDER_OBJS@ \ main.o \ mem.o \ MemPool.o \ @@ -173,10 +173,7 @@ SNMP_OBJS = \ snmp_core.o \ - snmp_oidlist.o \ - snmp_agent.o \ - snmp_config.o \ - snmp_auth.o + snmp_agent.o HTCP_OBJS = htcp.o @@ -186,6 +183,9 @@ aiops.o \ async_io.o +LEAKFINDER_OBJS = \ + leakfinder.o + DEFAULTS = \ -DDEFAULT_CONFIG_FILE=\"$(DEFAULT_CONFIG_FILE)\" @@ -216,7 +216,7 @@ $(CACHEMGR_EXE): cachemgr.o $(CC) -o $@ $(LDFLAGS) cachemgr.o $(CLIENT_LIBS) -$(PINGER_EXE): pinger.o +$(PINGER_EXE): pinger.o debug.o globals.o $(CC) -o $@ $(LDFLAGS) pinger.o debug.o globals.o $(PINGER_LIBS) $(UNLINKD_EXE): unlinkd-daemon.o @@ -237,7 +237,7 @@ ./cf_gen cf.data cf_gen: cf_gen.o - $(CC) -o $@ cf_gen.o $(STD_APP_LIBS) + $(CC) -o $@ $(LDFLAGS) cf_gen.o $(STD_APP_LIBS) cf.data: cf.data.pre Makefile sed "\ Index: squid/src/MemBuf.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/MemBuf.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/MemBuf.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/MemBuf.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: MemBuf.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: MemBuf.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 59 auto-growing Memory Buffer with printf * AUTHOR: Alex Rousskov @@ -199,7 +199,7 @@ } /* calls memBufVPrintf */ -#ifdef __STDC__ +#if STDC_HEADERS void memBufPrintf(MemBuf * mb, const char *fmt,...) { Index: squid/src/MemPool.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/MemPool.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/MemPool.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/MemPool.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: MemPool.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: MemPool.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 63 Low Level Memory Pool Management * AUTHOR: Alex Rousskov @@ -160,7 +160,7 @@ int alloc_count, int inuse_count, int idle_count, StoreEntry * e) { assert(pm); - storeAppendPrintf(e, "%d\t %d\t %d\t %.2f\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n", + storeAppendPrintf(e, "%d\t %d\t %d\t %.2f\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\t %d\n", /* alloc */ alloc_count, toKB(obj_size * pm->alloc.level), @@ -179,8 +179,8 @@ /* (int)rint(xpercent(pm->idle.level, pm->alloc.level)), */ /* saved */ xpercentInt(pm->saved.count, mem_traffic_volume.count), - xpercentInt(obj_size * gb_to_double(&pm->saved), gb_to_double(&mem_traffic_volume))); - /* (int)rint(xpercent(obj_size * pm->saved.level, mem_traffic_volume))); */ + xpercentInt(obj_size * gb_to_double(&pm->saved), gb_to_double(&mem_traffic_volume)), + xpercentInt(pm->saved.count, pm->total.count)); } /* MemMeter */ @@ -227,6 +227,8 @@ { assert(pool); memMeterInc(pool->meter.inuse); + gb_inc(&pool->meter.total, 1); + gb_inc(&TheMeter.total, pool->obj_size); memMeterAdd(TheMeter.inuse, pool->obj_size); gb_inc(&mem_traffic_volume, pool->obj_size); if (pool->pstack.count) { @@ -338,12 +340,13 @@ storeAppendPrintf(e, "Current memory usage:\n"); /* heading */ storeAppendPrintf(e, "Pool\t Obj Size\t" - "Allocated\t\t\t\t\t In Use\t\t\t\t Idle\t\t\t Allocations Saved\t\t\n" + "Allocated\t\t\t\t\t In Use\t\t\t\t Idle\t\t\t Allocations Saved\t\t Hit Rate\t\n" " \t (bytes)\t" "(#)\t (KB)\t high (KB)\t high (hrs)\t impact (%%total)\t" "(#)\t (KB)\t high (KB)\t portion (%%alloc)\t" "(#)\t (KB)\t high (KB)\t" - "(%%number)\t (%%volume)" + "(%%number)\t (%%volume)\t" + "(%%number)" "\n"); /* main table */ for (i = 0; i < Pools.count; i++) { Index: squid/src/Packer.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Packer.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/Packer.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/Packer.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: Packer.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: Packer.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 60 Packer: A uniform interface to store-like modules * AUTHOR: Alex Rousskov @@ -141,7 +141,7 @@ p->append(p->real_handler, buf, sz); } -#ifdef __STDC__ +#if STDC_HEADERS void packerPrintf(Packer * p, const char *fmt,...) { Index: squid/src/StatHist.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/StatHist.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/StatHist.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/StatHist.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: StatHist.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: StatHist.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 62 Generic Histogram * AUTHOR: Duane Wessels @@ -52,9 +52,15 @@ static int statHistBin(const StatHist * H, double v); static double statHistVal(const StatHist * H, int bin); static StatHistBinDumper statHistBinDumper; +#if !defined(_SQUID_HPUX_) || !defined(__GNUC__) + /* + * HP-UX and GCC (2.8?) give strange errors when these simple + * functions are static. + */ static hbase_f Log; static hbase_f Exp; static hbase_f Null; +#endif /* low level init, higher level functions has less params */ static void @@ -237,17 +243,25 @@ } /* log based histogram */ -static double +#if !defined(_SQUID_HPUX_) || !defined(__GNUC__) +static +#endif +double Log(double x) { assert((x + 1.0) >= 0.0); return log(x + 1.0); } -static double + +#if !defined(_SQUID_HPUX_) || !defined(__GNUC__) +static +#endif +double Exp(double x) { return exp(x) - 1.0; } + void statHistLogInit(StatHist * H, int capacity, double min, double max) { @@ -256,7 +270,10 @@ /* linear histogram for enums */ /* we want to be have [-1,last_enum+1] range to track out of range enums */ -static double +#if !defined(_SQUID_HPUX_) || !defined(__GNUC__) +static +#endif +double Null(double x) { return x; Index: squid/src/access_log.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/access_log.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/access_log.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/access_log.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: access_log.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: access_log.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 46 Access Log * AUTHOR: Duane Wessels @@ -42,6 +42,12 @@ static void accessLogSquid(AccessLogEntry * al, MemBuf * mb); static void accessLogCommon(AccessLogEntry * al, MemBuf * mb); +#if MULTICAST_MISS_STREAM +static int mcast_miss_fd = -1; +static struct sockaddr_in mcast_miss_to; +static void mcast_encode(unsigned int *, size_t, const unsigned int *); +#endif + const char *log_tags[] = { "NONE", @@ -164,7 +170,7 @@ { const char *client = NULL; if (Config.onoff.log_fqdn) - client = fqdncache_gethostbyaddr(al->cache.caddr, 0); + client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); if (client == NULL) client = inet_ntoa(al->cache.caddr); memBufPrintf(mb, "%9d.%03d %6d %s %s/%03d %d %s %s %s %s%s/%s %s", @@ -213,7 +219,7 @@ LogfileFD = file_open(LogfileName, O_WRONLY | O_CREAT, NULL, NULL, NULL); if (LogfileFD == DISK_ERROR) { debug(50, 0) ("%s: %s\n", LogfileName, xstrerror()); - fatal("Cannot open logfile."); + fatalf("Cannot open %s: %s", LogfileName, xstrerror()); } LogfileStatus = LOG_ENABLE; } @@ -261,6 +267,27 @@ } file_write_mbuf(LogfileFD, -1, mb, NULL, NULL); safe_free(xbuf); +#if MULTICAST_MISS_STREAM + if (al->cache.code != LOG_TCP_MISS) + (void) 0; + else if (al->http.method != METHOD_GET) + (void) 0; + else if (mcast_miss_fd < 0) + (void) 0; + else { + unsigned int ibuf[365]; + size_t isize; + xstrncpy((char *) ibuf, al->url, 364 * sizeof(int)); + isize = ((strlen(al->url) + 8) / 8) * 2; + if (isize > 364) + isize = 364; + mcast_encode((unsigned int *) ibuf, isize, + (const unsigned int *) Config.mcast_miss.encode_key); + comm_udp_sendto(mcast_miss_fd, + &mcast_miss_to, sizeof(mcast_miss_to), + ibuf, isize * sizeof(int)); + } +#endif } void @@ -290,18 +317,17 @@ rename(from, to); } /* Rotate the current log to .0 */ + file_close(LogfileFD); /* always close */ if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", fname, 0); rename(fname, to); } - /* Close and reopen the log. It may have been renamed "manually" - * before HUP'ing us. */ - file_close(LogfileFD); + /* Reopen the log. It may have been renamed "manually" */ LogfileFD = file_open(fname, O_WRONLY | O_CREAT, NULL, NULL, NULL); if (LogfileFD == DISK_ERROR) { debug(46, 0) ("accessLogRotate: Cannot open logfile: %s\n", fname); LogfileStatus = LOG_DISABLE; - fatal("Cannot open logfile."); + fatalf("Cannot open %s: %s", fname, xstrerror()); } } @@ -314,15 +340,11 @@ void hierarchyNote(HierarchyLogEntry * hl, hier_code code, - ping_data * pingdata, const char *cache_peer) { assert(hl != NULL); hl->code = code; - if (pingdata) - hl->ping = *pingdata; xstrncpy(hl->host, cache_peer, SQUIDHOSTNAMELEN); - hl->ping.stop = current_time; } void @@ -333,6 +355,27 @@ #if FORW_VIA_DB fvdbInit(); #endif +#if MULTICAST_MISS_STREAM + if (Config.mcast_miss.addr.s_addr != no_addr.s_addr) { + memset(&mcast_miss_to, '\0', sizeof(mcast_miss_to)); + mcast_miss_to.sin_family = AF_INET; + mcast_miss_to.sin_port = htons(Config.mcast_miss.port); + mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr; + mcast_miss_fd = comm_open(SOCK_DGRAM, + 0, + Config.Addrs.udp_incoming, + Config.mcast_miss.port, + COMM_NONBLOCKING, + "Multicast Miss Stream"); + if (mcast_miss_fd < 0) + fatal("Cannot open Multicast Miss Stream Socket"); + debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n", + mcast_miss_fd); + mcastSetTtl(mcast_miss_fd, 128); + if (strlen(Config.mcast_miss.encode_key) < 16) + fatal("mcast_encode_key is too short, must be 16 characters"); + } +#endif } const char * @@ -436,3 +479,41 @@ } #endif + +#if MULTICAST_MISS_STREAM +/* + * From http://www.io.com/~paulhart/game/algorithms/tea.html + * + * size of 'ibuf' must be a multiple of 2. + * size of 'key' must be 4. + * 'ibuf' is modified in place, encrypted data is written in + * network byte order. + */ +static void +mcast_encode(unsigned int *ibuf, size_t isize, const unsigned int *key) +{ + unsigned int y; + unsigned int z; + unsigned int sum; + const unsigned int delta = 0x9e3779b9; + unsigned int n = 32; + const unsigned int k0 = htonl(key[0]); + const unsigned int k1 = htonl(key[1]); + const unsigned int k2 = htonl(key[2]); + const unsigned int k3 = htonl(key[3]); + int i; + for (i = 0; i < isize; i += 2) { + y = htonl(ibuf[i]); + z = htonl(ibuf[i + 1]); + sum = 0; + for (n = 32; n; n--) { + sum += delta; + y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1; + z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3; + } + ibuf[i] = htonl(y); + ibuf[i + 1] = htonl(z); + } +} + +#endif Index: squid/src/acl.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/acl.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/acl.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/acl.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: acl.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: acl.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -47,13 +47,13 @@ static void aclParseProtoList(void *curlist); static void aclParseMethodList(void *curlist); static void aclParseTimeSpec(void *curlist); -static void aclParseSnmpComm(void *curlist); static void aclParseIntRange(void *curlist); static char *strtokFile(void); static void aclDestroyAclList(acl_list * list); static void aclDestroyTimeList(acl_time_data * data); static void aclDestroyIntRange(intrange *); static FREE aclFreeProxyAuthUser; +static struct _acl *aclFindByName(const char *name); static int aclMatchAcl(struct _acl *, aclCheck_t *); static int aclMatchIntegerRange(intrange * data, int i); static int aclMatchTime(acl_time_data * data, time_t when); @@ -61,10 +61,16 @@ static int aclMatchIp(void *dataptr, struct in_addr c); static int aclMatchDomainList(void *dataptr, const char *); static int aclMatchIntegerRange(intrange * data, int i); +#if SQUID_SNMP +static int aclMatchWordList(wordlist *, const char *); +#endif static squid_acl aclStrToType(const char *s); static int decode_addr(const char *, struct in_addr *, struct in_addr *); static void aclCheck(aclCheck_t * checklist); static void aclCheckCallback(aclCheck_t * checklist, allow_t answer); +#if USE_IDENT +static IDCB aclLookupIdentDone; +#endif static IPH aclLookupDstIPDone; static IPH aclLookupDstIPforASNDone; static FQDNH aclLookupSrcFQDNDone; @@ -147,6 +153,8 @@ return ACL_SRC_IP; if (!strcmp(s, "dst")) return ACL_DST_IP; + if (!strcmp(s, "myip")) + return ACL_MY_IP; if (!strcmp(s, "domain")) return ACL_DST_DOMAIN; if (!strcmp(s, "dstdomain")) @@ -167,8 +175,10 @@ return ACL_URL_REGEX; if (!strcmp(s, "port")) return ACL_URL_PORT; +#if USE_IDENT if (!strcmp(s, "ident")) return ACL_IDENT; +#endif if (!strncmp(s, "proto", 5)) return ACL_PROTO; if (!strcmp(s, "method")) @@ -181,8 +191,10 @@ return ACL_SRC_ASN; if (!strcmp(s, "dst_as")) return ACL_DST_ASN; +#if SQUID_SNMP if (!strcmp(s, "snmp_community")) - return ACL_SNMP_COMM; + return ACL_SNMP_COMMUNITY; +#endif if (!strcmp(s, "src_rtt")) return ACL_NETDB_SRC_RTT; #if USE_ARP_ACL @@ -199,6 +211,8 @@ return "src"; if (type == ACL_DST_IP) return "dst"; + if (type == ACL_MY_IP) + return "myip"; if (type == ACL_DST_DOMAIN) return "dstdomain"; if (type == ACL_SRC_DOMAIN) @@ -215,8 +229,10 @@ return "url_regex"; if (type == ACL_URL_PORT) return "port"; +#if USE_IDENT if (type == ACL_IDENT) return "ident"; +#endif if (type == ACL_PROTO) return "proto"; if (type == ACL_METHOD) @@ -229,8 +245,10 @@ return "src_as"; if (type == ACL_DST_ASN) return "dst_as"; - if (type == ACL_SNMP_COMM) +#if SQUID_SNMP + if (type == ACL_SNMP_COMMUNITY) return "snmp_community"; +#endif if (type == ACL_NETDB_SRC_RTT) return "src_rtt"; #if USE_ARP_ACL @@ -240,7 +258,7 @@ return "ERROR"; } -acl * +static acl * aclFindByName(const char *name) { acl *a; @@ -609,23 +627,6 @@ } } -static void -aclParseSnmpComm(void *data) -{ - acl_snmp_comm **q = data; - acl_snmp_comm *p; - char *t; - t = strtok(NULL, w_space); - if (t) { - p = xcalloc(1, sizeof(acl_snmp_comm)); - p->name = xstrdup(t); - p->community = NULL; - *q = p; - } - t = strtok(NULL, w_space); - return; -} - void aclParseAclLine(acl ** head) { @@ -672,9 +673,15 @@ debug(28, 3) ("aclParseAclLine: Appending to '%s'\n", aclname); new_acl = 0; } + /* + * Here we set AclMatchedName in case we need to use it in a + * warning message in aclDomainCompare(). + */ + AclMatchedName = aclname; /* ugly */ switch (A->type) { case ACL_SRC_IP: case ACL_DST_IP: + case ACL_MY_IP: aclParseIpList(&A->data); break; case ACL_SRC_DOMAIN: @@ -686,6 +693,7 @@ break; case ACL_URL_REGEX: case ACL_URLPATH_REGEX: + case ACL_BROWSER: case ACL_SRC_DOM_REGEX: case ACL_DST_DOM_REGEX: aclParseRegexList(&A->data); @@ -698,19 +706,17 @@ case ACL_URL_PORT: aclParseIntRange(&A->data); break; +#if USE_IDENT case ACL_IDENT: - Config.onoff.ident_lookup = 1; aclParseWordList(&A->data); break; +#endif case ACL_PROTO: aclParseProtoList(&A->data); break; case ACL_METHOD: aclParseMethodList(&A->data); break; - case ACL_BROWSER: - aclParseRegexList(&A->data); - break; case ACL_PROXY_AUTH: aclParseWordList(&A->data); if (!proxy_auth_cache) { @@ -719,9 +725,11 @@ assert(proxy_auth_cache); } break; - case ACL_SNMP_COMM: - aclParseSnmpComm(&A->data); +#if SQUID_SNMP + case ACL_SNMP_COMMUNITY: + aclParseWordList(&A->data); break; +#endif #if USE_ARP_ACL case ACL_SRC_ARP: aclParseArpList(&A->data); @@ -732,6 +740,10 @@ fatal("Bad ACL type"); break; } + /* + * Clear AclMatchedName from our temporary hack + */ + AclMatchedName = NULL; /* ugly */ if (!new_acl) return; if (A->data == NULL) { @@ -770,6 +782,17 @@ return -1; } +/* does name lookup, returns if it is a proxy_auth acl */ +int +aclIsProxyAuth(const char *name) +{ + acl *a = aclFindByName(name); + if (a) + return a->type == ACL_PROXY_AUTH; + return 0; +} + + /* maex@space.net (05.09.96) * get the info for redirecting "access denied" to info pages * TODO (probably ;-) @@ -887,7 +910,7 @@ for (B = *head, T = head; B; T = &B->next, B = B->next); *T = A; /* We lock _acl_access structures in aclCheck() */ - cbdataAdd(A, MEM_ACL_ACCESS); + cbdataAdd(A, memFree, MEM_ACL_ACCESS); } /**************/ @@ -956,7 +979,7 @@ debug(28, 3) ("aclMatchUser: checking '%s'\n", user); while (data) { debug(28, 3) ("aclMatchUser: looking for '%s'\n", data->key); - if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0') + if (strcmp(data->key, "REQUIRED") == 0 && *user != '\0' && strcmp(user, "-") != 0) return 1; if (strcmp(data->key, user) == 0) return 1; @@ -980,7 +1003,7 @@ /* Trim trailing \n before decoding */ strtok(sent_auth, "\n"); /* Trim leading whitespace before decoding */ - while (isspace(*proxy_auth)) + while (xisspace(*proxy_auth)) proxy_auth++; cleartext = uudecode(sent_auth); xfree(sent_auth); @@ -998,14 +1021,15 @@ } /* aclMatchProxyAuth can return three exit codes: - * 0 : No such user; invalid Proxy-authorization: header; - * ask for Proxy-Authorization: header + * 0 : user denied access * 1 : user validated OK * -1 : check the password for this user via an external authenticator + * -2 : invalid Proxy-authorization: header; + * ask for Proxy-Authorization: header */ static int -aclMatchProxyAuth(const char *proxy_auth, acl_proxy_auth_user * auth_user, aclCheck_t * checklist) +aclMatchProxyAuth(wordlist * data, const char *proxy_auth, acl_proxy_auth_user * auth_user, aclCheck_t * checklist) { /* checklist is used to register user name when identified, nothing else */ LOCAL_ARRAY(char, login_buf, USER_IDENT_SZ); @@ -1013,56 +1037,66 @@ if (!aclDecodeProxyAuth(proxy_auth, &user, &password, login_buf, sizeof(login_buf))) /* No or invalid Proxy-Auth header */ - return 0; + return -2; debug(28, 5) ("aclMatchProxyAuth: checking user '%s'\n", user); - if (!auth_user) { - /* see if we already know this user */ - auth_user = hash_lookup(proxy_auth_cache, user); - if (!auth_user) { - /* user not yet known, ask external authenticator */ - debug(28, 4) ("aclMatchProxyAuth: user '%s' not yet known\n", user); - return -1; - } else if ((0 == strcmp(auth_user->passwd, password)) && - (auth_user->expiretime > current_time.tv_sec)) { - /* user already known and valid */ - debug(28, 5) ("aclMatchProxyAuth: user '%s' previously validated\n", - user); - /* copy username to request for logging on client-side */ - xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); - return 1; - } else { - /* password mismatch/timeout */ - debug(28, 4) ("aclMatchProxyAuth: user '%s' password mismatch/timeout\n", + if (auth_user) { + /* This should be optimized to a boolean argument indicating that the + * password is invalid, instead of passing full acl_proxy_auth_user + * structures, and all messing with checklist->proxy_auth should + * be restricted the functions that deal with the authenticator. + */ + assert(auth_user == checklist->auth_user); + checklist->auth_user = NULL; /* get rid of that special reference */ + /* Check result from external validation */ + if (auth_user->passwd_ok != 1) { + /* password was checked but did not match */ + assert(auth_user->passwd_ok == 0); + debug(28, 4) ("aclMatchProxyAuth: authentication failed for user '%s'\n", user); - /* remove this user from the hash, making him unknown */ - hash_remove_link(proxy_auth_cache, (hash_link *) auth_user); aclFreeProxyAuthUser(auth_user); /* copy username to request for logging on client-side unless ident * is known (do not override ident with false proxy auth names) */ if (!*checklist->request->user_ident) xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); - return -1; - } - /* NOTREACHED */ - } else { - /* Check result from external validation */ - if (checklist->auth_user->passwd_ok != 1) { - /* password was checked but did not match */ - assert(checklist->auth_user->passwd_ok == 0); - debug(28, 4) ("aclMatchProxyAuth: authentication failed for user '%s'\n", - user); - return 0; + return -2; + } else { + /* password was checked and did match */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' validated OK\n", user); + /* store validated user in hash, after filling in expiretime */ + xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); + auth_user->expiretime = current_time.tv_sec + Config.authenticateTTL; + hash_join(proxy_auth_cache, (hash_link *) auth_user); + /* Continue checking below, as normal */ } - debug(28, 4) ("aclMatchProxyAuth: user '%s' validated OK\n", user); - /* store validated user in hash, after filling in expiretime */ - checklist->auth_user->expiretime = current_time.tv_sec + Config.authenticateTTL; - hash_join(proxy_auth_cache, (hash_link *) checklist->auth_user); - - return 1; } + /* see if we already know this user */ + auth_user = hash_lookup(proxy_auth_cache, user); + if (!auth_user) { + /* user not yet known, ask external authenticator */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' not yet known\n", user); + return -1; + } else if ((0 == strcmp(auth_user->passwd, password)) && + (auth_user->expiretime > current_time.tv_sec)) { + /* user already known and valid */ + debug(28, 5) ("aclMatchProxyAuth: user '%s' previously validated\n", + user); + /* copy username to request for logging on client-side */ + xstrncpy(checklist->request->user_ident, user, USER_IDENT_SZ); + return aclMatchUser(data, user); + } else { + /* password mismatch/timeout */ + debug(28, 4) ("aclMatchProxyAuth: user '%s' password mismatch/timeout\n", + user); + /* remove this user from the hash, making him unknown */ + hash_remove_link(proxy_auth_cache, (hash_link *) auth_user); + aclFreeProxyAuthUser(auth_user); + /* ask the external authenticator in case the password is changed */ + /* wrong password will be trapped above so this does not loop */ + return -1; + } /* NOTREACHED */ } @@ -1175,6 +1209,21 @@ return data->weekbits & (1 << tm.tm_wday) ? 1 : 0; } +#if SQUID_SNMP +static int +aclMatchWordList(wordlist * w, const char *word) +{ + debug(28, 3) ("aclMatchWordList: looking for '%s'\n", word); + while (w != NULL) { + debug(28, 3) ("aclMatchWordList: checking '%s'\n", w->key); + if (!strcmp(w->key, word)) + return 1; + w = w->next; + } + return 0; +} +#endif + static int aclMatchAcl(acl * ae, aclCheck_t * checklist) { @@ -1182,6 +1231,7 @@ const ipcache_addrs *ia = NULL; const char *fqdn = NULL; char *esc_buf; + const char *header; int k; if (!ae) return 0; @@ -1190,6 +1240,9 @@ case ACL_SRC_IP: return aclMatchIp(&ae->data, checklist->src_addr); /* NOTREACHED */ + case ACL_MY_IP: + return aclMatchIp(&ae->data, checklist->my_addr); + /* NOTREACHED */ case ACL_DST_IP: ia = ipcache_gethostbyname(r->host, IP_LOOKUP_IF_MISS); if (ia) { @@ -1279,9 +1332,16 @@ case ACL_URL_PORT: return aclMatchIntegerRange(ae->data, r->port); /* NOTREACHED */ +#if USE_IDENT case ACL_IDENT: - return aclMatchUser(ae->data, checklist->ident); + if (checklist->ident[0]) { + return aclMatchUser(ae->data, checklist->ident); + } else { + checklist->state[ACL_IDENT] = ACL_LOOKUP_NEEDED; + return 0; + } /* NOTREACHED */ +#endif case ACL_PROTO: return aclMatchInteger(ae->data, r->protocol); /* NOTREACHED */ @@ -1292,31 +1352,43 @@ return aclMatchRegex(ae->data, checklist->browser); /* NOTREACHED */ case ACL_PROXY_AUTH: - if (!r->flags.accelerated) { + if (NULL == r) { + return -1; + } else if (!r->flags.accelerated) { /* Proxy authorization on proxy requests */ - k = aclMatchProxyAuth(httpHeaderGetStr(&checklist->request->header, - HDR_PROXY_AUTHORIZATION), - checklist->auth_user, - checklist); + header = httpHeaderGetStr(&checklist->request->header, + HDR_PROXY_AUTHORIZATION); } else if (r->flags.internal) { /* WWW authorization on accelerated internal requests */ - k = aclMatchProxyAuth(httpHeaderGetStr(&checklist->request->header, - HDR_AUTHORIZATION), - checklist->auth_user, - checklist); + header = httpHeaderGetStr(&checklist->request->header, + HDR_AUTHORIZATION); } else { #if AUTH_ON_ACCELERATION /* WWW authorization on accelerated requests */ - k = aclMatchProxyAuth(httpHeaderGetStr(&checklist->request->header, - HDR_AUTHORIZATION), - checklist->auth_user, - checklist); + header = httpHeaderGetStr(&checklist->request->header, + HDR_AUTHORIZATION); #else debug(28, 1) ("aclMatchAcl: proxy_auth %s not applicable on accelerated requests.\n", ae->name); return -1; #endif } - if (k == 0) { + /* + * Register that we used the proxy authentication header so that + * it is not forwarded to the next proxy + */ + r->flags.used_proxy_auth = 1; + /* Check the password */ + switch (aclMatchProxyAuth(ae->data, + header, + checklist->auth_user, + checklist)) { + case 0: + /* Correct password, but was not allowed in this ACL */ + return 0; + case 1: + /* user validated OK */ + return 1; + case -2: /* no such user OR we need a proxy authentication header */ checklist->state[ACL_PROXY_AUTH] = ACL_PROXY_AUTH_NEEDED; /* @@ -1324,15 +1396,7 @@ * return codes here */ return 0; - } else if (k == 1) { - /* - * Authentication successful. Register that we used the proxy - * authentication header so that it is not forwarded to the - * next proxy - */ - r->flags.used_proxy_auth = 1; - return 1; - } else if (k == -1) { + case -1: /* * we need to validate the password */ @@ -1340,8 +1404,10 @@ return 0; } /* NOTREACHED */ - case ACL_SNMP_COMM: - return asnMatchIp(ae->data, checklist->src_addr); +#if SQUID_SNMP + case ACL_SNMP_COMMUNITY: + return aclMatchWordList(ae->data, checklist->snmp_community); +#endif case ACL_SRC_ASN: return asnMatchIp(ae->data, checklist->src_addr); case ACL_DST_ASN: @@ -1466,12 +1532,24 @@ */ allow = ACCESS_REQ_PROXY_AUTH; match = -1; - } else if (checklist->state[ACL_IDENT] == ACL_LOOKUP_NEEDED) { + } +#if USE_IDENT + else if (checklist->state[ACL_IDENT] == ACL_LOOKUP_NEEDED) { debug(28, 3) ("aclCheck: Doing ident lookup\n"); - /* XXX how to do ident lookup? */ - checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING; - return; + if (cbdataValid(checklist->conn)) { + identStart(&checklist->conn->me, &checklist->conn->peer, + aclLookupIdentDone, checklist); + checklist->state[ACL_IDENT] = ACL_LOOKUP_PENDING; + return; + } else { + debug(28, 1) ("aclCheck: Can't start ident lookup. No client connection\n"); + cbdataUnlock(checklist->conn); + checklist->conn = NULL; + allow = 0; + match = -1; + } } +#endif /* * We are done with this _acl_access entry. Either the request * is allowed, denied, requires authentication, or we move on to @@ -1506,6 +1584,12 @@ if (checklist->request) requestUnlink(checklist->request); checklist->request = NULL; +#if USE_IDENT + if (checklist->conn) { + cbdataUnlock(checklist->conn); + checklist->conn = NULL; + } +#endif cbdataFree(checklist); } @@ -1521,6 +1605,27 @@ aclChecklistFree(checklist); } +#if USE_IDENT +static void +aclLookupIdentDone(const char *ident, void *data) +{ + aclCheck_t *checklist = data; + if (ident) { + xstrncpy(checklist->ident, ident, sizeof(checklist->ident)); + xstrncpy(checklist->request->user_ident, ident, sizeof(checklist->request->user_ident)); + } else { + xstrncpy(checklist->ident, "-", sizeof(checklist->ident)); + } + /* + * Cache the ident result in the connection, to avoid redoing ident lookup + * over and over on persistent connections + */ + if (cbdataValid(checklist->conn) && !checklist->conn->ident[0]) + xstrncpy(checklist->conn->ident, checklist->ident, sizeof(checklist->conn->ident)); + aclCheck(checklist); +} +#endif + static void aclLookupDstIPDone(const ipcache_addrs * ia, void *data) { @@ -1571,12 +1676,13 @@ aclChecklistCreate(const acl_access * A, request_t * request, struct in_addr src_addr, + struct in_addr my_addr, const char *user_agent, const char *ident) { int i; aclCheck_t *checklist = memAllocate(MEM_ACLCHECK_T); - cbdataAdd(checklist, MEM_ACLCHECK_T); + cbdataAdd(checklist, memFree, MEM_ACLCHECK_T); checklist->access_list = A; /* * aclCheck() makes sure checklist->access_list is a valid @@ -1586,12 +1692,15 @@ if (request != NULL) checklist->request = requestLink(request); checklist->src_addr = src_addr; + checklist->my_addr = my_addr; for (i = 0; i < ACL_ENUM_MAX; i++) checklist->state[i] = ACL_LOOKUP_NONE; if (user_agent) xstrncpy(checklist->browser, user_agent, BROWSERNAMELEN); +#if USE_IDENT if (ident) xstrncpy(checklist->ident, ident, USER_IDENT_SZ); +#endif checklist->auth_user = NULL; /* init to NULL */ return checklist; } @@ -1621,7 +1730,7 @@ acl_time_data *next = NULL; for (; data; data = next) { next = data->next; - memFree(MEM_ACL_TIME_DATA, data); + memFree(data, MEM_ACL_TIME_DATA); } } @@ -1633,7 +1742,7 @@ next = data->next; regfree(&data->regex); safe_free(data->pattern); - memFree(MEM_RELIST, data); + memFree(data, MEM_RELIST); } } @@ -1643,13 +1752,13 @@ acl_proxy_auth_user *u = data; xfree(u->user); xfree(u->passwd); - memFree(MEM_ACL_PROXY_AUTH_USER, u); + memFree(u, MEM_ACL_PROXY_AUTH_USER); } static void aclFreeIpData(void *p) { - memFree(MEM_ACL_IP_DATA, p); + memFree(p, MEM_ACL_IP_DATA); } void @@ -1663,6 +1772,7 @@ switch (a->type) { case ACL_SRC_IP: case ACL_DST_IP: + case ACL_MY_IP: splay_destroy(a->data, aclFreeIpData); break; case ACL_SRC_ARP: @@ -1670,7 +1780,12 @@ case ACL_SRC_DOMAIN: splay_destroy(a->data, xfree); break; +#if SQUID_SNMP + case ACL_SNMP_COMMUNITY: +#endif +#if USE_IDENT case ACL_IDENT: +#endif case ACL_PROXY_AUTH: wordlistDestroy((wordlist **) & a->data); break; @@ -1680,12 +1795,15 @@ case ACL_URL_REGEX: case ACL_URLPATH_REGEX: case ACL_BROWSER: + case ACL_SRC_DOM_REGEX: + case ACL_DST_DOM_REGEX: aclDestroyRegexList(a->data); break; case ACL_PROTO: case ACL_METHOD: case ACL_SRC_ASN: case ACL_DST_ASN: + case ACL_NETDB_SRC_RTT: intlistDestroy((intlist **) & a->data); break; case ACL_URL_PORT: @@ -1693,11 +1811,11 @@ break; case ACL_NONE: default: - assert(0); + debug(28, 1) ("aclDestroyAcls: no case for ACL type %d\n", a->type); break; } safe_free(a->cfgline); - memFree(MEM_ACL, a); + memFree(a, MEM_ACL); } *head = NULL; } @@ -1708,7 +1826,7 @@ acl_list *next = NULL; for (; list; list = next) { next = list->next; - memFree(MEM_ACL_LIST, list); + memFree(list, MEM_ACL_LIST); } } @@ -1772,15 +1890,33 @@ { const char *d1 = data; const char *d2 = n->data; - int l1 = strlen(d1); - int l2 = strlen(d2); - while (d1[l1] == d2[l2]) { + int l1; + int l2; + while ('.' == *d1) + d1++; + while ('.' == *d2) + d2++; + l1 = strlen(d1); + l2 = strlen(d2); + while (d1[--l1] == d2[--l2]) { if ((l1 == 0) && (l2 == 0)) return 0; /* d1 == d2 */ - if (l1-- == 0) + if (0 == l1) { + if ('.' == d2[l2 - 1]) { + debug(28, 0) ("WARNING: %s is a subdomain of %s\n", d2, d1); + debug(28, 0) ("WARNING: This may break Splay tree searching\n"); + debug(28, 0) ("WARNING: You should remove '%s' from the ACL named '%s'\n", d2, AclMatchedName); + } return -1; /* d1 < d2 */ - if (l2-- == 0) + } + if (0 == l2) { + if ('.' == d1[l1 - 1]) { + debug(28, 0) ("WARNING: %s is a subdomain of %s\n", d1, d2); + debug(28, 0) ("WARNING: This may break Splay tree searching\n"); + debug(28, 0) ("WARNING: You should remove '%s' from the ACL named '%s'\n", d1, AclMatchedName); + } return 1; /* d1 > d2 */ + } } return (d1[l1] - d2[l2]); } @@ -1799,20 +1935,18 @@ l1 = strlen(h); l2 = strlen(d); /* h != d */ - while (h[l1] == d[l2]) { + while (xtolower(h[--l1]) == xtolower(d[--l2])) { if (l1 == 0) break; if (l2 == 0) break; - l1--; - l2--; } /* a '.' is a special case */ - if ((h[l1] == '.') || (l1 == 0)) + if ((h[l1] == '.') && (l1 == 0)) return -1; /* domain(h) < d */ - if ((d[l2] == '.') || (l2 == 0)) + if ((d[l2] == '.') && (l2 == 0)) return 1; /* domain(h) > d */ - return (h[l1] - d[l2]); + return (xtolower(h[l1]) - xtolower(d[l2])); } /* compare two network specs @@ -1987,13 +2121,21 @@ switch (a->type) { case ACL_SRC_IP: case ACL_DST_IP: + case ACL_MY_IP: return aclDumpIpList(a->data); break; case ACL_SRC_DOMAIN: case ACL_DST_DOMAIN: + return aclDumpDomainList(a->data); + break; +#if SQUID_SNMP + case ACL_SNMP_COMMUNITY: +#endif +#if USE_IDENT case ACL_IDENT: +#endif case ACL_PROXY_AUTH: - return aclDumpDomainList(a->data); + return wordlistDup(a->data); break; case ACL_TIME: return aclDumpTimeSpecList(a->data); @@ -2001,6 +2143,8 @@ case ACL_URL_REGEX: case ACL_URLPATH_REGEX: case ACL_BROWSER: + case ACL_SRC_DOM_REGEX: + case ACL_DST_DOM_REGEX: return aclDumpRegexList(a->data); break; case ACL_SRC_ASN: @@ -2023,6 +2167,7 @@ #endif case ACL_NONE: default: + debug(28, 1) ("aclDumpGeneric: no case for ACL type %d\n", a->type); break; } return NULL; @@ -2057,8 +2202,6 @@ * Original (BSD-specific) code no longer works. */ -#include "squid.h" - #include #ifdef _SQUID_LINUX_ #include Index: squid/src/aiops.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/aiops.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/aiops.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/aiops.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: aiops.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: aiops.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 43 AIOPS * AUTHOR: Stewart Forster @@ -128,12 +128,11 @@ static void aio_debug(aio_request_t *); static void aio_poll_threads(void); -static aio_thread_t thread[NUMTHREADS]; +static aio_thread_t *threads; static int aio_initialised = 0; static int request_queue_len = 0; -static aio_request_t *free_requests = NULL; -static int num_free_requests = 0; +static MemPool *aio_request_pool = NULL; static aio_request_t *request_queue_head = NULL; static aio_request_t *request_queue_tail = NULL; static aio_request_t *request_done_head = NULL; @@ -169,9 +168,10 @@ #endif /* Create threads and get them to sit in their wait loop */ + threads = xcalloc(NUMTHREADS, sizeof(aio_thread_t)); for (i = 0; i < NUMTHREADS; i++) { - threadp = thread + i; + threadp = &threads[i]; threadp->status = _THREAD_STARTING; if (pthread_mutex_init(&(threadp->mutex), NULL)) { threadp->status = _THREAD_FAILED; @@ -195,6 +195,9 @@ #endif } + /* Create request pool */ + aio_request_pool = memPoolCreate("aio_request", sizeof(aio_request_t)); + aio_initialised = 1; } @@ -215,7 +218,7 @@ sigemptyset(&new); sigaddset(&new, SIGPIPE); sigaddset(&new, SIGCHLD); -#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO) +#ifdef _SQUID_LINUX_THREADS_ sigaddset(&new, SIGQUIT); sigaddset(&new, SIGTRAP); #else @@ -291,42 +294,6 @@ } /* while */ } /* aio_thread_loop */ - -static aio_request_t * -aio_alloc_request() -{ - aio_request_t *req; - - if ((req = free_requests) != NULL) { - free_requests = req->next; - num_free_requests--; - req->next = NULL; - return req; - } - return (aio_request_t *) xmalloc(sizeof(aio_request_t)); -} /* aio_alloc_request */ - - -static void -aio_free_request(aio_request_t * req) -{ - /* Below doesn't have to be NUMTHREADS but it's a kinda cute value since */ - /* it reflects the sort of load the squid server will experience. A */ - /* higher load will mean a need for more threads, which will in turn mean */ - /* a need for a bigger free request pool. */ - /* Threads <-> requests are now partially asyncronous, use NUMTHREADS * 2 */ - - if (num_free_requests >= NUMTHREADS * 2) { - xfree(req); - return; - } - memset(req, 0, sizeof(*req)); - req->next = free_requests; - free_requests = req; - num_free_requests++; -} /* aio_free_request */ - - static void aio_do_request(aio_request_t * requestp) { @@ -335,7 +302,6 @@ exit(-1); } aio_queue_request(requestp); - aio_process_request_queue(); } /* aio_do_request */ @@ -344,6 +310,8 @@ { aio_request_t *rp; static int last_warn = 0; + static int high_start = 0; + static int queue_high, queue_low; int i; /* Mark it as not executed (failing result, no error) */ @@ -362,33 +330,47 @@ /* Poll done threads if needed */ if (wait_threads == NULL) aio_poll_threads(); + /* Kick it rolling */ + aio_process_request_queue(); /* Warn if out of threads */ - if (request_queue_len > (NUMTHREADS << 1)) { - if (squid_curtime > (last_warn + 15)) { - debug(43, 1) ("aio_queue_request: WARNING - Request queue growing\n" - "\tQueue Length = %d\n", request_queue_len); - debug(43, 1) ("aio_queue_request: Perhaps you should increase NUMTHREADS in aiops.c\n"); - debug(43, 1) ("aio_queue_request: First %d items on request queue\n", NUMTHREADS); + if (request_queue_len > (NUMTHREADS >> 1)) { + if (high_start == 0) { + high_start = squid_curtime; + queue_high = request_queue_len; + queue_low = request_queue_len; + } + if (request_queue_len > queue_high) + queue_high = request_queue_len; + if (request_queue_len < queue_low) + queue_low = request_queue_len; + if (squid_curtime >= (last_warn + 15) && + squid_curtime >= (high_start + 1)) { + debug(43, 1) ("aio_queue_request: WARNING - Running out of I/O theads\n"); + debug(43, 2) ("aio_queue_request: Queue Length: current=%d, high=%d, low=%d, duration=%d\n", + request_queue_len, queue_high, queue_low, squid_curtime - high_start); + debug(43, 1) ("aio_queue_request: Perhaps you should increase NUMTHREADS\n"); + debug(43, 1) ("aio_queue_request: Or install more disks to share the load\n"); + debug(43, 3) ("aio_queue_request: First %d items on request queue\n", NUMTHREADS); rp = request_queue_head; for (i = 1; i <= NUMTHREADS; i++) { switch (rp->request_type) { case _AIO_OP_OPEN: - debug(43, 1) ("aio_queue_request: %d : open -> %s\n", i, rp->path); + debug(43, 3) ("aio_queue_request: %d : open -> %s\n", i, rp->path); break; case _AIO_OP_READ: - debug(43, 1) ("aio_queue_request: %d : read -> FD = %d\n", i, rp->fd); + debug(43, 3) ("aio_queue_request: %d : read -> FD = %d\n", i, rp->fd); break; case _AIO_OP_WRITE: - debug(43, 1) ("aio_queue_request: %d : write -> FD = %d\n", i, rp->fd); + debug(43, 3) ("aio_queue_request: %d : write -> FD = %d\n", i, rp->fd); break; case _AIO_OP_CLOSE: - debug(43, 1) ("aio_queue_request: %d : close -> FD = %d\n", i, rp->fd); + debug(43, 3) ("aio_queue_request: %d : close -> FD = %d\n", i, rp->fd); break; case _AIO_OP_UNLINK: - debug(43, 1) ("aio_queue_request: %d : unlink -> %s\n", i, rp->path); + debug(43, 3) ("aio_queue_request: %d : unlink -> %s\n", i, rp->path); break; case _AIO_OP_STAT: - debug(43, 1) ("aio_queue_request: %d : stat -> %s\n", i, rp->path); + debug(43, 3) ("aio_queue_request: %d : stat -> %s\n", i, rp->path); break; default: debug(43, 1) ("aio_queue_request: %d : Unimplemented request type: %d\n", i, rp->request_type); @@ -399,6 +381,8 @@ } last_warn = squid_curtime; } + } else { + high_start = 0; } if (request_queue_len > RIDICULOUS_LENGTH) { debug(43, 0) ("aio_queue_request: Async request queue growing uncontrollably!\n"); @@ -489,7 +473,7 @@ resultp->aio_return = requestp->ret; resultp->aio_errno = requestp->err; } - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); } /* aio_cleanup_request */ @@ -529,13 +513,13 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } len = strlen(path) + 1; if ((requestp->path = (char *) xmalloc(len)) == NULL) { - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -566,14 +550,14 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } requestp->fd = fd; requestp->bufferp = bufp; if ((requestp->tmpbufp = (char *) xmalloc(bufs)) == NULL) { - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -605,13 +589,13 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } requestp->fd = fd; if ((requestp->tmpbufp = (char *) xmalloc(bufs)) == NULL) { - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -643,7 +627,7 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } @@ -673,13 +657,13 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } len = strlen(path) + 1; if ((requestp->path = (char *) xmalloc(len)) == NULL) { - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -687,7 +671,7 @@ requestp->statp = sb; if ((requestp->tmpstatp = (struct stat *) xmalloc(sizeof(struct stat))) == NULL) { xfree(requestp->path); - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -716,13 +700,13 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } len = strlen(path) + 1; if ((requestp->path = (char *) xmalloc(len)) == NULL) { - aio_free_request(requestp); + memPoolFree(aio_request_pool, requestp); errno = ENOMEM; return -1; } @@ -755,7 +739,7 @@ if (!aio_initialised) aio_init(); - if ((requestp = aio_alloc_request()) == NULL) { + if ((requestp = memPoolAlloc(aio_request_pool)) == NULL) { errno = ENOMEM; return -1; } @@ -782,7 +766,7 @@ prev = NULL; threadp = busy_threads_head; while (threadp) { - debug(43, 3) ("%d: %d -> %d\n", + debug(43, 5) ("%d: %d -> %d\n", threadp->thread, threadp->processed_req->request_type, threadp->status); @@ -798,7 +782,7 @@ threadp = threadp->next; } if (threadp == NULL) - return; + break; if (prev == NULL) busy_threads_head = busy_threads_head->next; @@ -844,32 +828,41 @@ resultp = requestp->resultp; cancelled = requestp->cancelled; aio_debug(requestp); - debug(43, 3) ("DONE: %d -> %d\n", requestp->ret, requestp->err); + debug(43, 5) ("DONE: %d -> %d\n", requestp->ret, requestp->err); aio_cleanup_request(requestp); if (cancelled) goto AIO_REPOLL; return resultp; } /* aio_poll_done */ +int +aio_operations_pending(void) +{ + if (request_done_head) + return 1; + if (busy_threads_head) + return 1; + return 0; +} static void aio_debug(aio_request_t * requestp) { switch (requestp->request_type) { case _AIO_OP_OPEN: - debug(43, 3) ("OPEN of %s to FD %d\n", requestp->path, requestp->ret); + debug(43, 5) ("OPEN of %s to FD %d\n", requestp->path, requestp->ret); break; case _AIO_OP_READ: - debug(43, 3) ("READ on fd: %d\n", requestp->fd); + debug(43, 5) ("READ on fd: %d\n", requestp->fd); break; case _AIO_OP_WRITE: - debug(43, 3) ("WRITE on fd: %d\n", requestp->fd); + debug(43, 5) ("WRITE on fd: %d\n", requestp->fd); break; case _AIO_OP_CLOSE: - debug(43, 3) ("CLOSE of fd: %d\n", requestp->fd); + debug(43, 5) ("CLOSE of fd: %d\n", requestp->fd); break; case _AIO_OP_UNLINK: - debug(43, 3) ("UNLINK of %s\n", requestp->path); + debug(43, 5) ("UNLINK of %s\n", requestp->path); break; default: break; Index: squid/src/asn.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/asn.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/asn.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/asn.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: asn.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: asn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 53 AS Number handling * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -108,16 +108,21 @@ lh = ntohl(addr.s_addr); debug(53, 3) ("asnMatchIp: Called for %s.\n", inet_ntoa(addr)); - if (AS_tree_head == 0 || !memcmp(&addr, &no_addr, sizeof(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 = rn_match(m_addr, AS_tree_head); - if (rn == 0) { + 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) { @@ -148,8 +153,10 @@ asnInit(void) { extern int max_keylen; + static int inited = 0; max_keylen = 40; - rn_init(); + if (0 == inited++) + rn_init(); rn_inithead((void **) &AS_tree_head, 8); asnAclInitialize(Config.aclList); cachemgrRegister("asndb", "AS Number Database", asnStats, 0, 1); @@ -179,7 +186,7 @@ StoreEntry *e; request_t *req; ASState *asState = xcalloc(1, sizeof(ASState)); - cbdataAdd(asState, MEM_NONE); + cbdataAdd(asState, cbdataXfree, 0); debug(53, 3) ("asnCacheStart: AS %d\n", as); snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as); asState->as_number = as; @@ -189,7 +196,7 @@ if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { e = storeCreateEntry(asres, asres, null_request_flags, METHOD_GET); storeClientListAdd(e, asState); - fwdStart(-1, e, asState->request, no_addr); + fwdStart(-1, e, asState->request, no_addr, no_addr); } else { storeLockObject(e); storeClientListAdd(e, asState); @@ -214,27 +221,27 @@ char *s; char *t; debug(53, 3) ("asHandleReply: Called with size=%d\n", size); - if (e->store_status == STORE_ABORTED) { - memFree(MEM_4K_BUF, buf); + if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { + memFree(buf, MEM_4K_BUF); asStateFree(asState); return; } if (size == 0 && e->mem_obj->inmem_hi > 0) { - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); asStateFree(asState); return; } else if (size < 0) { debug(53, 1) ("asHandleReply: Called with size=%d\n", size); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); asStateFree(asState); return; } s = buf; while (s - buf < size && *s != '\0') { - while (*s && isspace(*s)) + while (*s && xisspace(*s)) s++; for (t = s; *t; t++) { - if (isspace(*t)) + if (xisspace(*t)) break; } if (*t == '\0') { @@ -270,7 +277,7 @@ asState); } else { debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); - memFree(MEM_4K_BUF, buf); + memFree(buf, MEM_4K_BUF); asStateFree(asState); } } Index: squid/src/async_io.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/async_io.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/async_io.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/async_io.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: async_io.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: async_io.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 32 Asynchronous Disk I/O * AUTHOR: Pete Bentley @@ -56,31 +56,35 @@ void *tag; } aio_ctrl_t; +struct { + int open; + int close; + int cancel; + int write; + int read; + int stat; + int unlink; + int check_callback; +} aio_counts; typedef struct aio_unlinkq_t { char *path; struct aio_unlinkq_t *next; } aio_unlinkq_t; -static aio_ctrl_t *free_list = NULL; static aio_ctrl_t *used_list = NULL; -static aio_ctrl_t pool[SQUID_MAXFD]; static int initialised = 0; -static int outunlink = 0; +static OBJH aioStats; +static MemPool *aio_ctrl_pool; static void aioInit() { - int i; - aio_ctrl_t *node; - if (initialised) return; - for (i = 0; i < SQUID_MAXFD; i++) { - node = pool + i; - node->next = free_list; - free_list = node; - } + aio_ctrl_pool = memPoolCreate("aio_ctrl", sizeof(aio_ctrl_t)); + cachemgrRegister("aio_counts", "Async IO Function Counters", + aioStats, 0, 1); initialised = 1; } @@ -93,13 +97,8 @@ if (!initialised) aioInit(); - if (free_list == NULL) { - ret = open(path, oflag, mode); - if (callback) - (callback) (-1, callback_data, ret, errno); - return; - } - ctrlp = free_list; + aio_counts.open++; + ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = -2; ctrlp->tag = tag; ctrlp->done_handler = callback; @@ -109,15 +108,14 @@ ret = open(path, oflag, mode); if (callback) (callback) (ctrlp->fd, callback_data, ret, errno); + memPoolFree(aio_ctrl_pool, ctrlp); return; } - free_list = free_list->next; ctrlp->next = used_list; used_list = ctrlp; return; } - void aioClose(int fd) { @@ -125,12 +123,9 @@ if (!initialised) aioInit(); + aio_counts.close++; aioCancel(fd, NULL); - if (free_list == NULL) { - close(fd); - return; - } - ctrlp = free_list; + ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = fd; ctrlp->tag = NULL; ctrlp->done_handler = NULL; @@ -138,26 +133,28 @@ ctrlp->operation = _AIO_CLOSE; if (aio_close(fd, &(ctrlp->result)) < 0) { close(fd); /* Can't create thread - do a normal close */ + memPoolFree(aio_ctrl_pool, ctrlp); + fd_was_closed(fd); return; } - free_list = free_list->next; ctrlp->next = used_list; used_list = ctrlp; return; } - void aioCancel(int fd, void *tag) { aio_ctrl_t *curr; aio_ctrl_t *prev; + aio_ctrl_t *next; if (!initialised) aioInit(); + aio_counts.cancel++; prev = NULL; curr = used_list; - for (;;) { + for (curr = used_list;; curr = next) { while (curr != NULL) { if (curr->fd == fd) break; @@ -173,21 +170,14 @@ if (curr->done_handler) (curr->done_handler) (fd, curr->done_handler_data, -2, -2); - if (curr->operation == _AIO_UNLINK) - outunlink--; + next = curr->next; if (prev == NULL) - used_list = curr->next; + used_list = next; else - prev->next = curr->next; - - curr->next = free_list; - free_list = curr; + prev->next = next; - if (prev == NULL) - curr = used_list; - else - curr = prev->next; + memPoolFree(aio_ctrl_pool, curr); } } @@ -200,14 +190,9 @@ if (!initialised) aioInit(); - if (free_list == NULL) { - errno = EWOULDBLOCK; - if (callback) - (callback) (fd, callback_data, -1, errno); - return; - } + aio_counts.write++; for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next) - if (ctrlp->fd == fd && ctrlp->operation == _AIO_WRITE) + if (ctrlp->fd == fd) break; if (ctrlp != NULL) { errno = EWOULDBLOCK; @@ -215,7 +200,7 @@ (callback) (fd, callback_data, -1, errno); return; } - ctrlp = free_list; + ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = fd; ctrlp->tag = NULL; ctrlp->done_handler = callback; @@ -232,9 +217,9 @@ errno = EWOULDBLOCK; if (callback) (callback) (fd, callback_data, -1, errno); + memPoolFree(aio_ctrl_pool, ctrlp); return; } - free_list = free_list->next; ctrlp->next = used_list; used_list = ctrlp; return; @@ -249,14 +234,9 @@ if (!initialised) aioInit(); - if (free_list == NULL) { - errno = EWOULDBLOCK; - if (callback) - (callback) (fd, callback_data, -1, errno); - return; - } + aio_counts.read++; for (ctrlp = used_list; ctrlp != NULL; ctrlp = ctrlp->next) - if (ctrlp->fd == fd && ctrlp->operation == _AIO_READ) + if (ctrlp->fd == fd) break; if (ctrlp != NULL) { errno = EWOULDBLOCK; @@ -264,7 +244,7 @@ (callback) (fd, callback_data, -1, errno); return; } - ctrlp = free_list; + ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = fd; ctrlp->tag = NULL; ctrlp->done_handler = callback; @@ -281,9 +261,9 @@ errno = EWOULDBLOCK; if (callback) (callback) (fd, callback_data, -1, errno); + memPoolFree(aio_ctrl_pool, ctrlp); return; } - free_list = free_list->next; ctrlp->next = used_list; used_list = ctrlp; return; @@ -296,13 +276,8 @@ if (!initialised) aioInit(); - if (free_list == NULL) { - errno = EWOULDBLOCK; - if (callback) - (callback) (-1, callback_data, -1, errno); - return; - } - ctrlp = free_list; + aio_counts.stat++; + ctrlp = memPoolAlloc(aio_ctrl_pool); ctrlp->fd = -2; ctrlp->tag = tag; ctrlp->done_handler = callback; @@ -313,53 +288,38 @@ errno = EWOULDBLOCK; if (callback) (callback) (ctrlp->fd, callback_data, -1, errno); + memPoolFree(aio_ctrl_pool, ctrlp); return; } - free_list = free_list->next; ctrlp->next = used_list; used_list = ctrlp; return; } /* aioStat */ void -aioUnlink(const char *path, AIOCB * callback, void *callback_data) +aioUnlink(const char *pathname, AIOCB * callback, void *callback_data) { aio_ctrl_t *ctrlp; - static aio_unlinkq_t *uq = NULL; - aio_unlinkq_t *this; - + char *path; if (!initialised) aioInit(); - if (path) { - this = xmalloc(sizeof(aio_unlinkq_t)); - this->path = xstrdup(path); - this->next = uq; - uq = this; - } - while (uq != NULL) { - this = uq; - if (free_list == NULL || outunlink > 10) - return; - ctrlp = free_list; - ctrlp->fd = -2; - ctrlp->done_handler = callback; - ctrlp->done_handler_data = callback_data; - ctrlp->operation = _AIO_UNLINK; - if (aio_unlink(this->path, &(ctrlp->result)) < 0) { - if (errno == ENOMEM || errno == EAGAIN || errno == EINVAL) - return; - if (callback) - (callback) (ctrlp->fd, callback_data, -1, errno); - return; - } - free_list = free_list->next; - ctrlp->next = used_list; - used_list = ctrlp; - outunlink++; - uq = this->next; - xfree(this->path); - xfree(this); + aio_counts.unlink++; + ctrlp = memPoolAlloc(aio_ctrl_pool); + ctrlp->fd = -2; + ctrlp->done_handler = callback; + ctrlp->done_handler_data = callback_data; + ctrlp->operation = _AIO_UNLINK; + path = xstrdup(pathname); + if (aio_unlink(path, &(ctrlp->result)) < 0) { + int ret = unlink(path); + (callback) (ctrlp->fd, callback_data, ret, errno); + memPoolFree(aio_ctrl_pool, ctrlp); + xfree(path); + return; } + ctrlp->next = used_list; + used_list = ctrlp; + xfree(path); } /* aioUnlink */ @@ -369,10 +329,10 @@ aio_result_t *resultp; aio_ctrl_t *ctrlp; aio_ctrl_t *prev; - int callunlink = 0; if (!initialised) aioInit(); + aio_counts.check_callback++; for (;;) { if ((resultp = aio_poll_done()) == NULL) break; @@ -389,15 +349,38 @@ if (ctrlp->done_handler) (ctrlp->done_handler) (ctrlp->fd, ctrlp->done_handler_data, ctrlp->result.aio_return, ctrlp->result.aio_errno); - if (ctrlp->operation == _AIO_UNLINK) { - outunlink--; - callunlink = 1; - } - ctrlp->next = free_list; - free_list = ctrlp; + if (ctrlp->operation == _AIO_CLOSE) + fd_was_closed(ctrlp->fd); + memPoolFree(aio_ctrl_pool, ctrlp); } - if (callunlink) - aioUnlink(NULL, NULL, NULL); +} + +void +aioStats(StoreEntry * sentry) +{ + storeAppendPrintf(sentry, "ASYNC IO Counters:\n"); + storeAppendPrintf(sentry, "open\t%d\n", aio_counts.open); + storeAppendPrintf(sentry, "close\t%d\n", aio_counts.close); + storeAppendPrintf(sentry, "cancel\t%d\n", aio_counts.cancel); + storeAppendPrintf(sentry, "write\t%d\n", aio_counts.write); + storeAppendPrintf(sentry, "read\t%d\n", aio_counts.read); + storeAppendPrintf(sentry, "stat\t%d\n", aio_counts.stat); + storeAppendPrintf(sentry, "unlink\t%d\n", aio_counts.unlink); + storeAppendPrintf(sentry, "check_callback\t%d\n", aio_counts.check_callback); +} + +/* Flush all pending I/O */ +void +aioSync(void) +{ + if (!initialised) + return; /* nothing to do then */ + /* Flush all pending operations */ + debug(32, 1) ("aioSync: flushing pending I/O operations\n"); + do { + aioCheckCallbacks(); + } while (aio_operations_pending()); + debug(32, 1) ("aioSync: done\n"); } #endif /* USE_ASYNC_IO */ Index: squid/src/authenticate.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/authenticate.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/authenticate.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/authenticate.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: authenticate.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: authenticate.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Duane Wessels @@ -95,7 +95,7 @@ return; } r = xcalloc(1, sizeof(authenticateStateData)); - cbdataAdd(r, MEM_NONE); + cbdataAdd(r, cbdataXfree, 0); r->handler = handler; cbdataLock(data); r->data = data; Index: squid/src/cache_cf.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cache_cf.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cache_cf.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cache_cf.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cache_cf.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -56,18 +56,17 @@ static const char *const list_sep = ", \t\n\r"; +static int http_header_first = 0; + static void self_destruct(void); static void configDoConfigure(void); static void parse_refreshpattern(refresh_t **); static int parseTimeUnits(const char *unit); static void parseTimeLine(time_t * tptr, const char *units); +static void parse_ushort(u_short * var); static void parse_string(char **); static void parse_wordlist(wordlist **); -#if SQUID_SNMP -/* sigh, stringlist is only used for SNMP stuff now */ -static void parse_stringlist(wordlist **); -#endif static void default_all(void); static void defaults_if_none(void); static int parse_line(char *); @@ -76,6 +75,9 @@ static void free_all(void); static void requirePathnameExists(const char *name, const char *path); static OBJH dump_config; +static void dump_http_header(StoreEntry * entry, const char *name, HttpHeaderMask header); +static void parse_http_header(HttpHeaderMask * header); +static void free_http_header(HttpHeaderMask * header); static void self_destruct(void) @@ -91,7 +93,7 @@ while ((w = *list) != NULL) { *list = w->next; safe_free(w->key); - memFree(MEM_WORDLIST, w); + memFree(w, MEM_WORDLIST); } *list = NULL; } @@ -116,6 +118,17 @@ } } +wordlist * +wordlistDup(const wordlist * w) +{ + wordlist *D = NULL; + while (NULL != w) { + wordlistAdd(&D, w->key); + w = w->next; + } + return D; +} + void intlistDestroy(intlist ** list) { @@ -123,7 +136,7 @@ intlist *n = NULL; for (w = *list; w; w = n) { n = w->next; - memFree(MEM_INTLIST, w); + memFree(w, MEM_INTLIST); } *list = NULL; } @@ -157,6 +170,7 @@ FILE *fp = NULL; char *token = NULL; char *tmp_line; + int err_count = 0; free_all(); default_all(); if ((fp = fopen(file_name, "r")) == NULL) @@ -181,6 +195,7 @@ debug(3, 0) ("parseConfigFile: line %d unrecognized: '%s'\n", config_lineno, config_input_line); + err_count++; } safe_free(tmp_line); } @@ -191,7 +206,7 @@ "Current Squid Configuration", dump_config, 1, 1); - return 0; + return err_count; } static void @@ -206,7 +221,7 @@ fatal("No cache_dir's specified in config file"); /* calculate Config.Swap.maxSize */ storeDirConfigure(); - if (Config.Swap.maxSize < (Config.Mem.maxSize >> 10)) + if (Config.Swap.maxSize < (Config.memMaxSize >> 10)) fatal("cache_swap is lower than cache_mem"); if (Config.Announce.period > 0) { Config.onoff.announce = 1; @@ -264,6 +279,14 @@ uniqueHostname(), (int) Config.Port.http->i, full_appname_string); + /* + * the extra space is for loop detection in client_side.c -- we search + * for substrings in the Via header. + */ + snprintf(ThisCache2, sizeof(ThisCache), " %s:%d (%s)", + uniqueHostname(), + (int) Config.Port.http->i, + full_appname_string); if (!Config.udpMaxHitObjsz || Config.udpMaxHitObjsz > SQUID_UDP_SO_SNDBUF) Config.udpMaxHitObjsz = SQUID_UDP_SO_SNDBUF; if (Config.appendDomain) @@ -310,6 +333,14 @@ } } #endif + if (Config.Wais.relayHost) { + if (Config.Wais.peer) + cbdataFree(Config.Wais.peer); + Config.Wais.peer = memAllocate(MEM_PEER); + cbdataAdd(Config.Wais.peer, peerDestroy, MEM_PEER); + Config.Wais.peer->host = xstrdup(Config.Wais.relayHost); + Config.Wais.peer->http_port = Config.Wais.relayPort; + } } /* Parse a time specification from the config file. Store the @@ -438,31 +469,6 @@ aclDestroyAcls(ae); } -#if SQUID_SNMP - -static void -dump_snmp_access(StoreEntry * entry, const char *name, communityEntry * Head) -{ - acl_list *l; - communityEntry *cp; - acl_access *head; - - for (cp = Head; cp; cp = cp->next) { - head = cp->acls; - while (head != NULL) { - for (l = head->acl_list; l != NULL; l = l->next) { - storeAppendPrintf(entry, "%s %s %s %s%s\n", - name, cp->name, - head->allow ? "Allow" : "Deny", - l->op ? null_string : "!", - l->acl->name); - } - head = head->next; - } - } -} -#endif - static void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) { @@ -481,39 +487,6 @@ } } -#if SQUID_SNMP - -static void -parse_snmp_access(communityEntry ** head) -{ - char *t = NULL; - communityEntry *cp; -/* This is tricky: we need to define the communities here, assuming that - * communities and the MIB have already been defined */ - - if (!snmpInitConfig()) { - debug(15, 0) ("parse_snmp_access: Access lists NOT defined.\n"); - return; - } - t = strtok(NULL, w_space); - for (cp = *head; cp; cp = cp->next) - if (!strcmp(t, cp->name)) { - aclParseAccessLine(&cp->acls); - return; - } - debug(15, 0) ("parse_snmp_access: Unknown community %s!\n", t); -} - -static void -free_snmp_access(communityEntry ** Head) -{ - communityEntry *cp; - - for (cp = *Head; cp; cp = cp->next) - aclDestroyAccessList(&cp->acls); -} -#endif - static void parse_acl_access(acl_access ** head) { @@ -554,6 +527,224 @@ memset(addr, '\0', sizeof(struct in_addr)); } +#if DELAY_POOLS + +/* do nothing - free_delay_pool_count is the magic free function. + * this is why delay_pool_count isn't just marked TYPE: ushort + */ +#define free_delay_pool_class(X) +#define free_delay_pool_access(X) +#define free_delay_pool_rates(X) +#define dump_delay_pool_class(X, Y, Z) +#define dump_delay_pool_access(X, Y, Z) +#define dump_delay_pool_rates(X, Y, Z) + +static void +free_delay_pool_count(delayConfig * cfg) +{ + int i; + + if (!cfg->pools) + return; + for (i = 0; i < cfg->pools; i++) { + if (cfg->class[i]) { + delayFreeDelayPool(i); + safe_free(cfg->rates[i]); + } + aclDestroyAccessList(&cfg->access[i]); + } + delayFreeDelayData(); + xfree(cfg->class); + xfree(cfg->rates); + xfree(cfg->access); + memset(cfg, 0, sizeof(*cfg)); +} + +static void +dump_delay_pool_count(StoreEntry * entry, const char *name, delayConfig cfg) +{ + int i; + LOCAL_ARRAY(char, nom, 32); + + if (!cfg.pools) { + storeAppendPrintf(entry, "%s 0\n", name); + return; + } + storeAppendPrintf(entry, "%s %d\n", name, cfg.pools); + for (i = 0; i < cfg.pools; i++) { + storeAppendPrintf(entry, "delay_class %d %d\n", i + 1, cfg.class[i]); + snprintf(nom, 32, "delay_access %d", i + 1); + dump_acl_access(entry, nom, cfg.access[i]); + if (cfg.class[i] >= 1) + storeAppendPrintf(entry, "delay_parameters %d %d/%d", i + 1, + cfg.rates[i]->aggregate.restore_bps, + cfg.rates[i]->aggregate.max_bytes); + if (cfg.class[i] >= 3) + storeAppendPrintf(entry, " %d/%d", + cfg.rates[i]->network.restore_bps, + cfg.rates[i]->network.max_bytes); + if (cfg.class[i] >= 2) + storeAppendPrintf(entry, " %d/%d", + cfg.rates[i]->individual.restore_bps, + cfg.rates[i]->individual.max_bytes); + if (cfg.class[i] >= 1) + storeAppendPrintf(entry, "\n"); + } +} + +static void +parse_delay_pool_count(delayConfig * cfg) +{ + if (cfg->pools) { + debug(3, 0) ("parse_delay_pool_count: multiple delay_pools lines, aborting all previous delay_pools config\n"); + free_delay_pool_count(cfg); + } + parse_ushort(&cfg->pools); + delayInitDelayData(cfg->pools); + cfg->class = xcalloc(cfg->pools, sizeof(u_char)); + cfg->rates = xcalloc(cfg->pools, sizeof(delaySpecSet *)); + cfg->access = xcalloc(cfg->pools, sizeof(acl_access *)); +} + +static void +parse_delay_pool_class(delayConfig * cfg) +{ + ushort pool, class; + + parse_ushort(&pool); + if (pool < 1 || pool > cfg->pools) { + debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools); + return; + } + parse_ushort(&class); + if (class < 1 || class > 3) { + debug(3, 0) ("parse_delay_pool_class: Ignoring pool %d class %d not in 1 .. 3\n", pool, class); + return; + } + pool--; + if (cfg->class[pool]) { + delayFreeDelayPool(pool); + safe_free(cfg->rates[pool]); + } + cfg->rates[pool] = xmalloc(class * sizeof(delaySpec)); + cfg->class[pool] = class; + cfg->rates[pool]->aggregate.restore_bps = cfg->rates[pool]->aggregate.max_bytes = -1; + if (cfg->class[pool] >= 3) + cfg->rates[pool]->network.restore_bps = cfg->rates[pool]->network.max_bytes = -1; + if (cfg->class[pool] >= 2) + cfg->rates[pool]->individual.restore_bps = cfg->rates[pool]->individual.max_bytes = -1; + delayCreateDelayPool(pool, class); +} + +static void +parse_delay_pool_rates(delayConfig * cfg) +{ + ushort pool, class; + int i; + delaySpec *ptr; + char *token; + + parse_ushort(&pool); + if (pool < 1 || pool > cfg->pools) { + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools); + return; + } + pool--; + class = cfg->class[pool]; + if (class == 0) { + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d attempt to set rates with class not set\n", pool + 1); + return; + } + ptr = (delaySpec *) cfg->rates[pool]; + /* read in "class" sets of restore,max pairs */ + while (class--) { + token = strtok(NULL, "/"); + if (token == NULL) + self_destruct(); + if (sscanf(token, "%d", &i) != 1) + self_destruct(); + ptr->restore_bps = i; + GetInteger(i); + ptr->max_bytes = i; + ptr++; + } + class = cfg->class[pool]; + /* if class is 3, swap around network and individual */ + if (class == 3) { + delaySpec tmp; + + tmp = cfg->rates[pool]->individual; + cfg->rates[pool]->individual = cfg->rates[pool]->network; + cfg->rates[pool]->network = tmp; + } + /* initialize the delay pools */ + delayInitDelayPool(pool, class, cfg->rates[pool]); +} + +static void +parse_delay_pool_access(delayConfig * cfg) +{ + ushort pool; + + parse_ushort(&pool); + if (pool < 1 || pool > cfg->pools) { + debug(3, 0) ("parse_delay_pool_rates: Ignoring pool %d not in 1 .. %d\n", pool, cfg->pools); + return; + } + aclParseAccessLine(&cfg->access[pool - 1]); +} +#endif + +static void +dump_http_header(StoreEntry * entry, const char *name, HttpHeaderMask header) +{ + storeAppendPrintf(entry, "%s\n", name); +} + +static void +parse_http_header(HttpHeaderMask * header) +{ + int allowed, id; + char *t = NULL; + + if ((t = strtok(NULL, w_space)) == NULL) { + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header: missing 'allow' or 'deny'.\n"); + return; + } + if (!strcmp(t, "allow")) + allowed = 1; + else if (!strcmp(t, "deny")) + allowed = 0; + else { + debug(3, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(3, 0) ("parse_http_header: expecting 'allow' or 'deny', got '%s'.\n", t); + return; + } + + if (!http_header_first) { + http_header_first = 1; + if (allowed) + httpHeaderMaskInit(header, 0xFF); + } + while ((t = strtok(NULL, w_space))) { + if ((id = httpHeaderIdByNameDef(t, strlen(t))) == -1) + id = HDR_OTHER; + if (allowed) + CBIT_CLR(*header, id); + else + CBIT_SET(*header, id); + } +} + +static void +free_http_header(HttpHeaderMask * header) +{ + httpHeaderMaskInit(header, 0); +} + static void dump_cachedir(StoreEntry * entry, const char *name, cacheSwap swap) { @@ -591,7 +782,7 @@ int size; int l1; int l2; - int read_only = 0; + unsigned int read_only = 0; SwapDir *tmp = NULL; if ((path = strtok(NULL, w_space)) == NULL) self_destruct(); @@ -621,10 +812,10 @@ debug(3, 1) ("Cache dir '%s' size changed to %d KB\n", path, size); tmp->max_size = size; - if (tmp->read_only != read_only) + if (tmp->flags.read_only != read_only) debug(3, 1) ("Cache dir '%s' now %s\n", path, read_only ? "Read-Only" : "Read-Write"); - tmp->read_only = read_only; + tmp->flags.read_only = read_only; return; } } @@ -644,7 +835,7 @@ tmp->max_size = size; tmp->l1 = l1; tmp->l2 = l2; - tmp->read_only = read_only; + tmp->flags.read_only = read_only; tmp->swaplog_fd = -1; swap->n_configured++; } @@ -706,7 +897,7 @@ p->http_port, p->icp.port); dump_peer_options(entry, p); - for (d = p->pinglist; d; d = d->next) { + for (d = p->peer_domain; d; d = d->next) { storeAppendPrintf(entry, "cache_peer_domain %s %s%s\n", p->host, d->do_ping ? null_string : "!", @@ -734,7 +925,7 @@ int i; ushortlist *u; const char *me = null_string; /* XXX */ - p = xcalloc(1, sizeof(peer)); + p = memAllocate(MEM_PEER); p->http_port = CACHE_HTTP_PORT; p->icp.port = CACHE_ICP_PORT; p->weight = 1; @@ -811,15 +1002,20 @@ p->tcp_up = PEER_TCP_MAGIC_COUNT; #if USE_CARP if (p->carp.load_factor) { - /* - * calculate this peers hash for use in CARP - */ + /* calculate this peers hash for use in CARP */ p->carp.hash = 0; for (token = p->host; *token != 0; token++) p->carp.hash += (p->carp.hash << 19) + *token; } #endif - cbdataAdd(p, MEM_NONE); + /* This must preceed peerDigestCreate */ + cbdataAdd(p, peerDestroy, MEM_PEER); +#if USE_CACHE_DIGESTS + if (!p->options.no_digest) { + p->digest = peerDigestCreate(p); + cbdataLock(p->digest); /* so we know when/if digest disappears */ + } +#endif while (*head != NULL) head = &(*head)->next; *head = p; @@ -832,7 +1028,12 @@ peer *p; while ((p = *P) != NULL) { *P = p->next; - peerDestroy(p); +#if USE_CACHE_DIGESTS + if (p->digest) + cbdataUnlock(p->digest); + p->digest = NULL; +#endif + cbdataFree(p); } Config.npeers = 0; } @@ -842,7 +1043,10 @@ { wordlist *w; while (list != NULL) { - storeAppendPrintf(entry, "%s XXXXXXXXXX", name); + if (strcmp(list->passwd, "none") && strcmp(list->passwd, "disable")) + storeAppendPrintf(entry, "%s XXXXXXXXXX", name); + else + storeAppendPrintf(entry, "%s %s", name, list->passwd); for (w = list->actions; w != NULL; w = w->next) { storeAppendPrintf(entry, " %s", w->key); } @@ -954,7 +1158,7 @@ domain++; } l->domain = xstrdup(domain); - for (L = &(p->pinglist); *L; L = &((*L)->next)); + for (L = &(p->peer_domain); *L; L = &((*L)->next)); *L = l; } } @@ -987,38 +1191,6 @@ } static void -dump_httpanonymizer(StoreEntry * entry, const char *name, int var) -{ - switch (var) { - case ANONYMIZER_NONE: - storeAppendPrintf(entry, "%s off\n", name); - break; - case ANONYMIZER_STANDARD: - storeAppendPrintf(entry, "%s paranoid\n", name); - break; - case ANONYMIZER_PARANOID: - storeAppendPrintf(entry, "%s standard\n", name); - break; - } -} - -static void -parse_httpanonymizer(int *var) -{ - char *token; - token = strtok(NULL, w_space); - if (token == NULL) - self_destruct(); - if (!strcasecmp(token, "off")) - *var = ANONYMIZER_NONE; - else if (!strcasecmp(token, "paranoid")) - *var = ANONYMIZER_PARANOID; - else - *var = ANONYMIZER_STANDARD; -} - - -static void dump_ushortlist(StoreEntry * entry, const char *name, ushortlist * u) { while (u) { @@ -1386,17 +1558,11 @@ return w == NULL; } -#if SQUID_SNMP -static void -parse_stringlist(wordlist ** list) +static int +check_null_acl_access(acl_access * a) { - char *token; - while ((token = strtok(NULL, null_string))) - wordlistAdd(list, token); + return a == NULL; } -#define free_stringlist free_wordlist -#define dump_stringlist dump_wordlist -#endif /* SQUID_SNMP */ #define free_wordlist wordlistDestroy Index: squid/src/cache_manager.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cache_manager.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cache_manager.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cache_manager.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: cache_manager.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cache_manager.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 16 Cache Manager Objects * AUTHOR: Duane Wessels @@ -111,6 +111,14 @@ 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; Index: squid/src/cachemgr.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/cachemgr.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cachemgr.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cachemgr.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: cachemgr.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cachemgr.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 CGI Cache Manager * AUTHOR: Duane Wessels @@ -206,9 +206,9 @@ *str = NULL; /* trim */ len = strlen(tok); - while (len && isspace(tok[len - 1])) + while (len && xisspace(tok[len - 1])) tok[--len] = '\0'; - while (isspace(*tok)) + while (xisspace(*tok)) tok++; return tok; } else @@ -273,8 +273,8 @@ *statusStr = NULL; if (strncasecmp(sline, "HTTP/", 5) || !sp) return -1; - while (isspace(*++sp)); - if (!isdigit(*sp)) + while (xisspace(*++sp)); + if (!xisdigit(*sp)) return -1; if (statusStr) *statusStr = sp; @@ -725,6 +725,7 @@ make_auth_header(const cachemgr_request * req) { static char buf[1024]; + off_t l = 0; const char *str64; if (!req->passwd) return ""; @@ -734,6 +735,8 @@ req->passwd); str64 = base64_encode(buf); - snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); + l += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); + l += snprintf(&buf[l], sizeof(buf) - l, + "Proxy-Authorization: Basic %s\r\n", str64); return buf; } Index: squid/src/cbdata.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cbdata.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cbdata.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cbdata.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: cbdata.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cbdata.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 45 Callback Data Registry * AUTHOR: Duane Wessels @@ -75,7 +75,8 @@ struct _cbdata *next; int valid; int locks; - mem_type mem_type; + CBDUNL *unlock_func; + int id; #if CBDATA_DEBUG const char *file; int line; @@ -85,6 +86,7 @@ static HASHCMP cbdata_cmp; static HASHHASH cbdata_hash; static void cbdataReallyFree(cbdata * c); +static OBJH cbdataDump; static int cbdata_cmp(const void *p1, const void *p2) @@ -111,9 +113,9 @@ void #if CBDATA_DEBUG -cbdataAddDbg(const void *p, mem_type mem_type, const char *file, int line) +cbdataAddDbg(const void *p, CBDUNL * unlock_func, int id, const char *file, int line) #else -cbdataAdd(const void *p, mem_type mtype) +cbdataAdd(const void *p, CBDUNL * unlock_func, int id) #endif { cbdata *c; @@ -124,7 +126,8 @@ c = xcalloc(1, sizeof(cbdata)); c->key = p; c->valid = 1; - c->mem_type = mtype; + c->unlock_func = unlock_func; + c->id = id; #if CBDATA_DEBUG c->file = file; c->line = line; @@ -136,18 +139,15 @@ static void cbdataReallyFree(cbdata * c) { - mem_type mtype = c->mem_type; + CBDUNL *unlock_func = c->unlock_func; void *p = (void *) c->key; + int id = c->id; hash_remove_link(htable, (hash_link *) c); cbdataCount--; xfree(c); - if (mtype == MEM_DONTFREE) - return; debug(45, 3) ("cbdataReallyFree: Freeing %p\n", p); - if (mtype == MEM_NONE) - xfree(p); - else - memFree(mtype, p); + if (unlock_func) + unlock_func(p, id); } void @@ -208,8 +208,14 @@ return c->valid; } - void +cbdataXfree(void *p, int unused) +{ + xfree(p); +} + + +static void cbdataDump(StoreEntry * sentry) { hash_link *hptr; Index: squid/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cf.data.pre 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cf.data.pre 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ +# $Id: cf.data.pre,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ # # # SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -38,6 +38,14 @@ to look at http://cache.is.co.za/squid/ for documentation, or the Squid home page (http://squid.nlanr.net/) for the FAQ. + The default Squid config file shows what the defaults for + various options happen to be. If you don't need to change the + default, you shouldn't uncomment the line. Doing so may cause + run-time problems. In some cases "none" refers to no default + setting at all, whilst in other cases it refers to a valid + option - the comments for that keyword indicate if this is the + case. + COMMENT_END COMMENT_START @@ -84,6 +92,8 @@ and from neighbor caches. Default is 4827. To disable use "0". + To enable this option, you must use --enable-htcp with the + configure script. htcp_port 4827 DOC_END @@ -425,7 +435,7 @@ COMMENT: (bytes) TYPE: b_size_t DEFAULT: 8 MB -LOC: Config.Mem.maxSize +LOC: Config.memMaxSize DOC_START NOTE: THIS PARAMETER DOES NOT SPECIFY THE MAXIMUM PROCESS SIZE. IT PLACES A LIMIT ON ONE ASPECT OF SQUID'S MEMORY @@ -495,30 +505,6 @@ cache_swap_high 95 DOC_END - -NAME: cache_mem_low -COMMENT: (in percent, 0-100) -TYPE: int -DEFAULT: 75 -LOC: Config.Mem.lowWaterMark -DOC_NONE - -NAME: cache_mem_high -COMMENT: (in percent, 0-100) -TYPE: int -DEFAULT: 95 -LOC: Config.Mem.highWaterMark -DOC_START - The low- and high-water mark for cache memory storage. When - the amount of RAM used by the hot-object RAM cache reaches this - point, the cache starts throwing objects out of the RAM cache - (but they remain on disk). Defaults are 75% and 90%. - -cache_mem_low 75 -cache_mem_high 90 -DOC_END - - NAME: maximum_object_size COMMENT: (bytes) TYPE: b_size_t @@ -668,6 +654,21 @@ a directory. Since this is the index for the whole object list you CANNOT periodically rotate it! + If you have more than one 'cache_dir', these swap logs will + have names such as: + + cache_swap_log.00 + cache_swap_log.01 + cache_swap_log.02 + + The numbered extension (which is added automatically) + corresponds to the order of the 'cache_dir' lines in this + configuration file. If you change the order of the 'cache_dir' + lines in this file, then these log files will NOT correspond to + the correct 'cache_dir' entry (unless you manually rename + them). We recommend that you do NOT use this option. It is + better to keep these log files in each 'cache_dir' directory. + cache_swap_log DOC_END @@ -758,20 +759,6 @@ DOC_END -NAME: ident_lookup -COMMENT: on|off -TYPE: onoff -DEFAULT: off -LOC: Config.onoff.ident_lookup -DOC_START - If you wish to make an RFC931/ident lookup of the client - username for each connection, enable this. It is off by - default. - -ident_lookup off -DOC_END - - NAME: log_fqdn COMMENT: on|off TYPE: onoff @@ -1088,8 +1075,8 @@ description of Squid's refresh algorithm. Basically a cached object is: (the order is changed from 1.1.X) - STALE if age > max FRESH if expires < now, else STALE + STALE if age > max FRESH if lm-factor < percent, else STALE FRESH if age < min else STALE @@ -1099,7 +1086,9 @@ match, then the default will be used. Default: -refresh_pattern . 0 20% 4320 +refresh_pattern ^ftp: 1440 20% 10080 +refresh_pattern ^gopher: 1440 0% 1440 +refresh_pattern . 0 20% 4320 DOC_END @@ -1352,6 +1341,22 @@ pconn_timeout 120 seconds DOC_END +NAME: ident_timeout +TYPE: time_t +IFDEF: USE_IDENT +LOC: Config.Timeout.ident +DEFAULT: 10 seconds +DOC_START + Maximum time to wait for IDENT requests. If this is too high, + and you enabled 'ident_lookup', then you might be susceptible + to denial-of-service by having many ident requests going at + once. + + This option may be disabled by using --disable-ident with + the configure script. +ident_timeout 10 seconds +DOC_END + NAME: shutdown_lifetime COMMENT: time-units @@ -1388,14 +1393,18 @@ acltype is one of src dst srcdomain dstdomain url_pattern urlpath_pattern time port proto method browser user + By default, regular expressions are CASE-SENSITIVE. To make + them case-insensitive, use the -i option. + acl aclname src ip-address/netmask ... (clients IP address) acl aclname src addr1-addr2/netmask ... (range of addresses) acl aclname dst ip-address/netmask ... (URL host's IP address) + acl aclname myip ip-address/netmask ... (local socket IP address) acl aclname srcdomain foo.com ... # reverse lookup, client IP acl aclname dstdomain foo.com ... # Destination server from URL - acl aclname srcdom_regex xxx ... # regex matching client name - acl aclname dstdom_regex xxx ... # regex matching server + acl aclname srcdom_regex [-i] xxx ... # regex matching client name + acl aclname dstdom_regex [-i] xxx ... # regex matching server # For dstdomain and dstdom_regex a reverse lookup is tried if a IP # based URL is used. The name "none" is used if the reverse lookup # fails. @@ -1410,13 +1419,14 @@ F - Friday A - Saturday h1:m1 must be less than h2:m2 - acl aclname url_regex ^http:// ... # regex matching on whole URL - acl aclname urlpath_regex \.gif$ ... # regex matching on URL path + acl aclname url_regex [-i] ^http:// ... # regex matching on whole URL + acl aclname urlpath_regex [-i] \.gif$ ... # regex matching on URL path acl aclname port 80 70 21 ... acl aclname port 0-1024 ... # ranges allowed acl aclname proto HTTP FTP ... acl aclname method GET POST ... - acl aclname browser regexp + acl aclname browser [-i] regexp + # pattern match on User-Agent header acl aclname ident username ... # string match on ident output. # use REQUIRED to accept any non-null ident. @@ -1446,10 +1456,16 @@ # collides with any authentication done by origin servers. It may # seem like it works at first, but it doesn't. + acl aclname snmp_community string ... + # A community string to limit access to your SNMP Agent + # Example: + # + # acl snmppublic snmp_community public + Examples: acl myexample dst_as 1241 -acl password proxy_auth 300 +acl password proxy_auth REQUIRED Defaults: NOCOMMENT_START @@ -1466,6 +1482,7 @@ TYPE: acl_access LOC: Config.accessList.http DEFAULT: none +DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying access based on defined access lists @@ -1505,6 +1522,7 @@ TYPE: acl_access LOC: Config.accessList.icp DEFAULT: none +DEFAULT_IF_NONE: deny all DOC_START Reply to all ICP queries we receive @@ -1565,6 +1583,33 @@ DOC_END +NAME: ident_lookup_access +TYPE: acl_access +IFDEF: USE_IDENT +DEFAULT: none +DEFAULT_IF_NONE: deny all +LOC: Config.accessList.identLookup +DOC_START + A list of ACL elements which, if matched, cause an ident + (RFC 931) lookup to be performed for this request. For + example, you might choose to always perform ident lookups + for your main multi-user Unix boxes, but not for your Macs + and PCs. By default, ident lookups are not performed for + any requests. + + To enable ident lookups for specific client addresses, you + can follow this example: + + acl ident_aware_hosts src 198.168.1.0/255.255.255.0 + ident_lookup_access allow ident_aware_hosts + ident_lookup_access deny all + + This option may be disabled by using --disable-ident with + the configure script. +ident_lookup_access deny all +DOC_END + + COMMENT_START ADMINISTRATIVE PARAMETERS ----------------------------------------------------------------------------- @@ -2054,28 +2099,9 @@ Lowering this value increases the total number of buckets and also the storage maintenance rate. The default is 20. -store_objects_per_bucket 20 -DOC_END - - -NAME: http_anonymizer -TYPE: httpanonymizer -LOC: Config.onoff.anonymizer -DEFAULT: off -DOC_START - If you want to filter out certain HTTP request headers for - privacy reasons, enable this option. There are three - appropriate settings: - 'off' All HTTP request headers are passed. - 'standard' Specific headers are removed - 'paranoid' Only specific headers are allowed. - To see which headers are allowed or denied, please see the - http-anon.c source file. - -http_anonymizer off +store_objects_per_bucket 50 DOC_END - NAME: client_db COMMENT: on|off TYPE: onoff @@ -2186,6 +2212,8 @@ see also refresh_pattern for a more selective approach. + This option may be disabled by using --disable-http-violations + with the configure script. reload_into_ims off DOC_END @@ -2257,14 +2285,57 @@ and firewall_ip. DOC_END +NAME: anonymize_headers +TYPE: http_header +LOC: Config.anonymize_headers +DEFAULT: none +DOC_START + Usage: anonymize_headers allow|deny header_name ... + + This option replaces the old 'http_anonymizer' option with + something that is much more configurable. You may now + specify exactly which headers are to be allowed, or which + are to be removed from outgoing requests. + + There are two methods of using this option. You may either + allow specific headers (thus denying all others), or you + may deny specific headers (thus allowing all others). + + For example, to achieve the same behaviour as the old + 'http_anonymizer standard' option, you should use: + + anonymize_headers deny From Referer Server + anonymize_headers deny User-Agent WWW-Authenticate Link + + Or, to reproduce the old 'http_anonymizer paranoid' feature + you should use: + + anonymize_headers allow Allow Authorization Cache-Control + anonymize_headers allow Content-Encoding Content-Length + anonymize_headers allow Content-Type Date Expires Host + anonymize_headers allow If-Modified-Since Last-Modified + anonymize_headers allow Location Pragma Accept Charset + anonymize_headers allow Accept-Encoding Accept-Language + anonymize_headers allow Content-Language Mime-Version + anonymize_headers allow Retry-After Title Connection + anonymize_headers allow Proxy-Connection + + NOTE: You can not mix "allow" and "deny". All 'anonymize_headers' + lines must have the same second argument. + + By default, all headers are allowed (no anonymizing is + performed). + +anonymize_headers +DOC_END + NAME: fake_user_agent TYPE: eol LOC: Config.fake_ua DEFAULT: none DOC_START - If you use the paranoid http_anonymizer setting, Squid will strip - your User-agent string from the request. Some Web servers will - refuse your request without a User-agent string. Use this to + If you filter the User-Agent header with 'anonymize_headers' it + may cause some Web servers to refuse your request. Use this to fake one up. For example: fake_user_agent Nutscrape/1.0 (CP/M; 8-bit) @@ -2289,7 +2360,7 @@ DOC_START If you wish to create your own versions of the default (English) error files, either to customise them to suit your - language or company copy the template english files to anther + language or company copy the template english files to another directory and point this tag at them. DOC_END @@ -2348,19 +2419,6 @@ snmp_port 3401 DOC_END -NAME: snmp_do_queueing -TYPE: onoff -LOC: Config.Snmp.do_queueing -DEFAULT: on -IFDEF: SQUID_SNMP -DOC_START - If disabled, snmp packets will not be queued but delivered - immediately. This could be useful when you want to monitor a - cache in trouble, but this could also make Squid block, slowing - connections and possibly worsening the cache status. -snmp_do_queueing on -DOC_END - NAME: forward_snmpd_port TYPE: ushort LOC: Config.Snmp.localPort @@ -2382,78 +2440,28 @@ forward_snmpd_port 0 DOC_END -NAME: snmp_mib_path -TYPE: string -LOC: Config.Snmp.mibPath -DEFAULT: @DEFAULT_MIB_PATH@ -IFDEF: SQUID_SNMP -DOC_START - The location of Squid's mib. -snmp_mib_path @DEFAULT_MIB_PATH@ -DOC_END - -NAME: trap_sink -TYPE: string -LOC: Config.Snmp.trap_sink -DEFAULT: 127.0.0.1 -IFDEF: SQUID_SNMP -DOC_START - Hostname or ip address of trap sink for snmp -trap_sink 127.0.0.1 -DOC_END - -NAME: snmp_trap_community -TYPE: string -LOC: Config.Snmp.trap_community -DEFAULT: public +NAME: snmp_access +TYPE: acl_access +LOC: Config.accessList.snmp +DEFAULT: none +DEFAULT_IF_NONE: deny all IFDEF: SQUID_SNMP DOC_START - Community name for traps. -snmp_trap_community public -DOC_END + Allowing or denying access to the SNMP port. -NAME: snmp_enable_authen_traps -TYPE: onoff -LOC: Config.Snmp.conf_authtraps -DEFAULT: off -IFDEF: SQUID_SNMP -DOC_START - Enable SNMP authenticated traps. Set to 'off' or 'on'. -snmp_enable_authen_traps off -DOC_END + All access to the agent is denied by default. + usage: -NAME: snmp_agent_conf -TYPE: stringlist -LOC: Config.Snmp.snmpconf -DEFAULT: none -IFDEF: SQUID_SNMP -DOC_START - Define snmp views, users and communities - Example: - snmp_agent_conf view all .1.3.6 included - snmp_agent_conf view squid .1.3.6 included - snmp_agent_conf user squid - all all public - snmp_agent_conf user all all all all squid - snmp_agent_conf community public squid squid - snmp_agent_conf community readwrite all all -DOC_END + snmp_access allow|deny [!]aclname ... -NAME: snmp_acl -TYPE: snmp_access -LOC: Config.Snmp.communities -DEFAULT: none -IFDEF: SQUID_SNMP -DOC_START - Define access controls per community: - snmp_access communityname allow|deny [!]aclname ... - Example: - snmp_acl public allow adminsubnet - snmp_acl public deny all +Example: +snmp_access allow public localhost +snmp_access deny all DOC_END NAME: snmp_incoming_address TYPE: address -LOC: Config.Addrs.snmp_outgoing +LOC: Config.Addrs.snmp_incoming DEFAULT: 0.0.0.0 IFDEF: SQUID_SNMP DOC_NONE @@ -2492,186 +2500,153 @@ COMMENT_START DELAY POOL PARAMETERS (all require DELAY_POOLS compilation option) ----------------------------------------------------------------------------- - - A general note on delay pools - the first matched delay pool is used, - that is, if a request falls into class1 then it isn't checked for class2 - or class3 (and similarly a class2 request isn't checked for class3). COMMENT_END -NAME: delay_class1_access -TYPE: acl_access -DEFAULT: none +NAME: delay_pools +TYPE: delay_pool_count +DEFAULT: 0 IFDEF: DELAY_POOLS -LOC: Config.Delay.class1.access +LOC: Config.Delay DOC_START - This is used to select what client requests are processed via - the first ("class 1") delay pool. In this delay pool only the - aggregate traffic allowance is configurable. + This represents the number of delay pools to be used. For example, + if you have one class 2 delay pool and one class 3 delays pool, you + have a total of 2 delay pools. + + To enable this option, you must use --enable-delay-pools with the + configure script. +delay_pools 0 DOC_END -NAME: delay_class2_access -TYPE: acl_access +NAME: delay_class +TYPE: delay_pool_class DEFAULT: none IFDEF: DELAY_POOLS -LOC: Config.Delay.class2.access +LOC: Config.Delay DOC_START - This is used to select what client requests are processed via - the first ("class 2") delay pool. In this delay pool both the - aggregate and per-host traffic allowance are configurable. - There are 254 individual delay pools based on the last 8 bits - of the client IP address (addresses ending in 0 and 255 are not - permitted). + This defines the class of each delay pool. There must be exactly one + delay_class line for each delay pool. For example, to define two + delay pools, one of class 2 and one of class 3, the settings above + and here would be: + +delay_pools 2 # 2 delay pools +delay_class 1 2 # pool 1 is a class 2 pool +delay_class 2 3 # pool 2 is a class 3 pool + + The delay pool classes are: + + class 1 Everything is limited by a single aggregate + bucket. + + class 2 Everything is limited by a single aggregate + bucket as well as an "individual" bucket chosen + from bits 25 through 32 of the IP address. + + class 3 Everything is limited by a single aggregate + bucket as well as a "network" bucket chosen + from bits 17 through 24 of the IP address and a + "individual" bucket chosen from bits 17 through + 32 of the IP address. + + NOTE: If an IP address is a.b.c.d + -> bits 25 through 32 are "d" + -> bits 17 through 24 are "c" + -> bits 17 through 32 are "c * 256 + d" DOC_END -NAME: delay_class3_access -TYPE: acl_access +NAME: delay_access +TYPE: delay_pool_access DEFAULT: none IFDEF: DELAY_POOLS -LOC: Config.Delay.class3.access +LOC: Config.Delay DOC_START - This is used to select what client requests are processed via - the first ("class 3") delay pool. In this delay pool, the - aggregate, network and per-host traffic allowance are - configurable. There are 255 network delay pools based on the - 17th to 24th bit of the client IP address (network 255 is not - permitted), and individual delay pools based on the last 16 - bits of the client IP address (network 255 and hosts ending in - 0 and 255 are not permitted). + This is used to determine which delay pool a request falls into. + The first matched delay pool is always used, ie, if a request falls + into delay pool number one, no more delay are checked, otherwise the + rest are checked in order of their delay pool number until they have + all been checked. For example, if you want some_big_clients in delay + pool 1 and lotsa_little_clients in delay pool 2: + +delay_access 1 allow some_big_clients +delay_access 1 deny all +delay_access 2 allow lotsa_little_clients +delay_access 2 deny all DOC_END -NAME: delay_class1_aggregate_restore -TYPE: int -DEFAULT: -1 +NAME: delay_parameters +TYPE: delay_pool_rates +DEFAULT: none IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class1.aggregate.restore_bps +LOC: Config.Delay DOC_START - The number of bytes per second added to the class 1 aggregate - delay pool traffic allowance (-1 to disable the delay pool). -DOC_END + This defines the parameters for a delay pool. Each delay pool has + a number of "buckets" associated with it, as explained in the + description of delay_class. For a class 1 delay pool, the syntax is: -NAME: delay_class1_aggregate_max -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class1.aggregate.max_bytes -DOC_START - The maximum number of bytes which can be in the class 1 - aggregate delay pool traffic allowance. -DOC_END +delay_parameters pool aggregate -NAME: delay_class2_aggregate_restore -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class2.aggregate.restore_bps -DOC_START - The number of bytes per second added to the class 2 aggregate - delay pool traffic allowance (-1 to disable the delay pool). -DOC_END + For a class 2 delay pool: -NAME: delay_class2_aggregate_max -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class2.aggregate.max_bytes -DOC_START - The maximum number of bytes which can be in the class 2 - aggregate delay pool traffic allowance. -DOC_END +delay_parameters pool aggregate individual -NAME: delay_class2_individual_restore -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class2.individual.restore_bps -DOC_START - The number of bytes per second added to the class 2 individual - host delay pool traffic allowances (-1 to disable these delay - pools). -DOC_END + For a class 3 delay pool: -NAME: delay_class2_individual_max -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class2.individual.max_bytes -DOC_START - The maximum number of bytes which can be in the class 2 - individual host delay pool traffic allowances. -DOC_END +delay_parameters pool aggregate network individual -NAME: delay_class3_aggregate_restore -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class3.aggregate.restore_bps -DOC_START - The number of bytes per second added to the class 3 aggregate - delay pool traffic allowance (-1 to disable the delay pool). -DOC_END + The variables here are: -NAME: delay_class3_aggregate_max -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class3.aggregate.max_bytes -DOC_START - The maximum number of bytes which can be in the class 3 - aggregate delay pool traffic allowance. -DOC_END + pool a pool number - ie, a number between 1 and the + number specified in delay_pools as used in + delay_class lines. -NAME: delay_class3_network_restore -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class3.network.restore_bps -DOC_START - The number of bytes per second added to the class 3 8-bit - network delay pool traffic allowances (-1 to disable these - delay pools). -DOC_END + aggregate the "delay parameters" for the aggregate bucket + (class 1, 2, 3). -NAME: delay_class3_network_max -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class3.network.max_bytes -DOC_START - The maximum number of bytes which can be in the class 3 8-bit - network delay pool traffic allowances. -DOC_END + individual the "delay parameters" for the individual + buckets (class 2, 3). -NAME: delay_class3_individual_restore -TYPE: int -DEFAULT: -1 -IFDEF: DELAY_POOLS -COMMENT: (bps) -LOC: Config.Delay.class3.individual.restore_bps -DOC_START - The number of bytes per second added to the class 3 individual - host delay pool traffic allowances (-1 to disable these delay - pools). + network the "delay parameters" for the network buckets + (class 3). + + A pair of delay parameters is written restore/maximum, where restore is + the number of bytes (not bits - modem and network speeds are usually + quoted in bits) per second placed into the bucket, and maximum is the + maximum number of bytes which can be in the bucket at any time. + + For example, if delay pool number 1 is a class 2 delay pool as in the + above example, and is being used to strictly limit each host to 64kbps + (plus overheads), with no overall limit, the line is: + +delay_parameters 1 -1/-1 8000/8000 + + Note that the figure -1 is used to represent "unlimited". + + And, if delay pool number 2 is a class 3 delay pool as in the above + example, and you want to limit it to a total of 256kbps (strict limit) + with each 8-bit network permitted 64kbps (strict limit) and each + individual host permitted 4800bps with a bucket maximum size of 64kb + to permit a decent web page to be downloaded at a decent speed + (if the network is not being limited due to overuse) but slow down + large downloads more significantly: + +delay_parameters 2 32000/32000 8000/8000 600/64000 + + There must be one delay_parameters line for each delay pool. DOC_END -NAME: delay_class3_individual_max -TYPE: int -DEFAULT: -1 +NAME: delay_initial_bucket_level +COMMENT: (percent, 0-100) +TYPE: ushort +DEFAULT: 50 IFDEF: DELAY_POOLS -COMMENT: (bytes) -LOC: Config.Delay.class3.individual.max_bytes +LOC: Config.Delay.initial DOC_START - The maximum number of bytes which can be in the class 3 - individual host delay pool traffic allowances. + The initial bucket percentage is used to determine how much is put + in each bucket when squid starts, is reconfigured, or first notices + a host accessing it (in class 2 and class 3, individual hosts and + networks only have buckets associated with them once they have been + "seen" by squid). + +delay_initial_bucket_level 50 DOC_END NAME: incoming_icp_average @@ -2697,7 +2672,7 @@ DEFAULT: 8 LOC: Config.comm_incoming.http_min_poll DOC_START - Heavy voodoo here. I can't even beleve you are reading this. + Heavy voodoo here. I can't even believe you are reading this. Are you crazy? Don't even think about adjusting these unless you understand the algorithms in comm_select.c first! @@ -2746,16 +2721,95 @@ uri_whitespace deny DOC_END -NAME: persistent_client_posts +NAME: broken_posts +TYPE: acl_access +DEFAULT: none +LOC: Config.accessList.brokenPosts +DOC_START + A list of ACL elements which, if matched, causes Squid to send + a extra CRLF pair after the body of a PUT/POST request. + + Some HTTP servers has broken implementations of PUT/POST, + and rely on a extra CRLF pair sent by some WWW clients. + + Quote from RFC 2068 section 4.1 on this matter: + + Note: certain buggy HTTP/1.0 client implementations generate an + extra CRLF's after a POST request. To restate what is explicitly + forbidden by the BNF, an HTTP/1.1 client must not preface or follow + a request with an extra CRLF. + +acl buggy_server url_regex ^http://.... +broken_posts allow buggy_server +DOC_END + +NAME: mcast_miss_addr +IFDEF: MULTICAST_MISS_STREAM +TYPE: address +LOC: Config.mcast_miss.addr +DEFAULT: 255.255.255.255 +DOC_START + If you enable this option, every "cache miss" URL will + be sent out on the specified multicast address. + + Do not enable this option unless you are are absolutely + certain you understand what you are doing. +DOC_END + +NAME: mcast_miss_port +IFDEF: MULTICAST_MISS_STREAM +TYPE: ushort +LOC: Config.mcast_miss.port +DEFAULT: 3135 +DOC_START + This is the port number to be used in conjuction with + 'mcast_miss_addr'. +DOC_END + +NAME: mcast_miss_encode_key +IFDEF: MULTICAST_MISS_STREAM +TYPE: string +LOC: Config.mcast_miss.encode_key +DEFAULT: XXXXXXXXXXXXXXXX +DOC_START + The URLs that are sent in the multicast miss stream are + encrypted. This is the encryption key. +DOC_END + +NAME: prefer_direct TYPE: onoff -LOC: Config.onoff.persistent_client_posts +LOC: Config.onoff.prefer_direct DEFAULT: on DOC_START - Turn this 'off' to disable persistent connections for POST - requests. When you disable this, Squid reads all bytes - from the client request and sends them to the server. This - makes Squid work with broken HTTP servers which expect the - additional CRLF pair from broken web clients. -persistent_client_posts on + By default, if the ICP, HTCP, Cache Digest, etc. techniques + do not yield a parent cache, Squid gives higher preference + to forwarding the request direct to origin servers, rather + than selecting a parent cache anyway. + + If you want Squid to give higher precedence to a parent + cache, instead of going direct, then turn this option off. +prefer_direct on +DOC_END + +NAME: strip_query_terms +TYPE: onoff +LOC: Config.onoff.strip_query_terms +DEFAULT: on +DOC_START + By default, Squid strips query terms from requested URLs before + logging. This protects your user's privacy. +strip_query_terms on DOC_END + +NAME: coredump_dir +TYPE: string +LOC: Config.coredump_dir +DEFAULT: none +DOC_START + By default Squid leaves core files in the first cache_dir + directory. If you set 'coredump_dir' to a directory + that exists, Squid will chdir() to that directory at startup + and coredump files will be left there. +DOC_END + EOF Index: squid/src/cf_gen.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf_gen.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/cf_gen.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/cf_gen.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,5 +1,5 @@ /* - * $Id: cf_gen.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: cf_gen.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: none * AUTHOR: Max Okumoto @@ -119,13 +119,18 @@ 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, "r")) == NULL) { + if ((fp = fopen(input_filename, rmode)) == NULL) { perror(input_filename); exit(1); } @@ -172,17 +177,17 @@ (void) 0; } else if (!strncmp(buff, "COMMENT:", 8)) { ptr = buff + 8; - while (isspace(*ptr)) + while (xisspace(*ptr)) ptr++; curr->comment = xstrdup(ptr); } else if (!strncmp(buff, "DEFAULT:", 8)) { ptr = buff + 8; - while (isspace(*ptr)) + while (xisspace(*ptr)) ptr++; curr->default_value = xstrdup(ptr); } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { ptr = buff + 16; - while (isspace(*ptr)) + while (xisspace(*ptr)) ptr++; curr->default_if_none = xstrdup(ptr); } else if (!strncmp(buff, "LOC:", 4)) { @@ -428,21 +433,19 @@ "\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/* ignore empty lines */\n" - "\t\t(void) 0;\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; - fprintf(fp, - "\t} else if (!strcmp(token, \"%s\")) {\n", + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + fprintf(fp, "\telse if (!strcmp(token, \"%s\"))\n", entry->name ); assert(entry->loc); - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); if (strcmp(entry->loc, "none") == 0) { fprintf(fp, "\t\tparse_%s();\n", @@ -459,9 +462,8 @@ } fprintf(fp, - "\t} else {\n" + "\telse\n" "\t\tresult = 0; /* failure */\n" - "\t}\n" "\treturn(result);\n" "}\n\n" ); Index: squid/src/client.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/client.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/client.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/client.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,8 +1,6 @@ - - /* - * $Id: client.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: client.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 WWW Client * AUTHOR: Harvest Derived Index: squid/src/client_db.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_db.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/client_db.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/client_db.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: client_db.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: client_db.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 Client Database * AUTHOR: Duane Wessels @@ -189,7 +189,7 @@ { ClientInfo *c = data; safe_free(c->key); - memFree(MEM_CLIENT_INFO, c); + memFree(c, MEM_CLIENT_INFO); } void @@ -201,28 +201,31 @@ } #if SQUID_SNMP -int -meshCtblGetRowFn(oid * New, oid * Oid) +struct in_addr * +client_entry(struct in_addr *current) { ClientInfo *c = NULL; + char *key; - if (!Oid[0] && !Oid[1] && !Oid[2] && !Oid[3]) { + if (current) { + key = inet_ntoa(*current); hash_first(client_table); + while ((c = (ClientInfo *) hash_next(client_table))) { + if (!strcmp(key, c->key)) + break; + } c = (ClientInfo *) hash_next(client_table); - hash_last(client_table); } else { - char key[15]; - snprintf(key, sizeof(key), "%d.%d.%d.%d", Oid[0], Oid[1], Oid[2], Oid[3]); - c = (ClientInfo *) hash_lookup(client_table, key); - if (NULL != c) - c = c->next; + hash_first(client_table); + c = (ClientInfo *) hash_next(client_table); } - if (!c) - return 0; - addr2oid(c->addr, New); - return 1; -} + hash_last(client_table); + if (c) + return (&c->addr); + else + return (NULL); +} variable_list * snmp_meshCtblFn(variable_list * Var, snint * ErrP) @@ -236,6 +239,9 @@ Answer = snmp_var_new(Var->name, Var->name_length); *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); Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/client_side.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/client_side.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: client_side.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -41,9 +41,21 @@ #endif #include #include +#if HAVE_IP_COMPAT_H #include +#elif HAVE_NETINET_IP_COMPAT_H +#include +#endif +#if HAVE_IP_FIL_H #include +#elif HAVE_NETINET_IP_FIL_H +#include +#endif +#if HAVE_IP_NAT_H #include +#elif HAVE_NETINET_IP_NAT_H +#include +#endif #endif @@ -53,7 +65,6 @@ #endif static const char *const crlf = "\r\n"; -static const char *const proxy_auth_challenge_fmt = "Basic realm=\"%s\""; #define REQUEST_BUF_SIZE 4096 #define FAILURE_MODE_TIME 300 @@ -64,10 +75,8 @@ static PF clientReadRequest; static PF connStateFree; static PF requestTimeout; -static int CheckQuickAbort2(const clientHttpRequest *); static int clientCheckTransferDone(clientHttpRequest *); static int clientGotNotEnough(clientHttpRequest *); -static void CheckQuickAbort(clientHttpRequest *); static void checkFailureRatio(err_type, hier_code); static void clientProcessMiss(clientHttpRequest *); static void clientBuildReplyHeader(clientHttpRequest * http, HttpReply * rep); @@ -77,6 +86,9 @@ static STCB clientHandleIMSReply; static int clientGetsOldEntry(StoreEntry * new, StoreEntry * old, request_t * request); static int checkAccelOnly(clientHttpRequest *); +#if USE_IDENT +static IDCB clientIdentDone; +#endif static int clientOnlyIfCached(clientHttpRequest * http); static STCB clientSendMoreData; static STCB clientCacheHit; @@ -85,7 +97,6 @@ static void clientProcessRequest(clientHttpRequest *); static void clientProcessExpired(void *data); static void clientProcessOnlyIfCachedMiss(clientHttpRequest * http); -static HttpReply *clientConstructProxyAuthReply(clientHttpRequest * http); static int clientCachable(clientHttpRequest * http); static int clientHierarchical(clientHttpRequest * http); static int clientCheckContentLength(request_t * r); @@ -108,16 +119,24 @@ return 1; } +#if USE_IDENT +void +clientIdentDone(const char *ident, void *data) +{ + ConnStateData *conn = data; + if (ident) + xstrncpy(conn->ident, ident, sizeof(conn->ident)); + else + xstrncpy(conn->ident, "-", sizeof(conn->ident)); +} +#endif + void clientAccessCheck(void *data) { clientHttpRequest *http = data; ConnStateData *conn = http->conn; const char *browser; - if (Config.onoff.ident_lookup && conn->ident.state == IDENT_NONE) { - identStart(-1, conn, clientAccessCheck, http); - return; - } if (checkAccelOnly(http)) { clientAccessCheckDone(0, http); return; @@ -126,8 +145,17 @@ http->acl_checklist = aclChecklistCreate(Config.accessList.http, http->request, conn->peer.sin_addr, + conn->me.sin_addr, browser, - conn->ident.ident); + conn->ident); +#if USE_IDENT + /* + * hack for ident ACL. It needs to get full addresses, and a + * place to store the ident result on persistent connections... + */ + http->acl_checklist->conn = conn; + cbdataLock(http->acl_checklist->conn); +#endif aclNBCheck(http->acl_checklist, clientAccessCheckDone, http); } @@ -144,35 +172,6 @@ EBIT_TEST(r->cache_control->mask, CC_ONLY_IF_CACHED); } -static HttpReply * -clientConstructProxyAuthReply(clientHttpRequest * http) -{ - ErrorState *err; - HttpReply *rep; - if (!http->flags.accel) { - /* Proxy authorisation needed */ - err = errorCon(ERR_CACHE_ACCESS_DENIED, - HTTP_PROXY_AUTHENTICATION_REQUIRED); - } else { - /* WWW authorisation needed */ - err = errorCon(ERR_CACHE_ACCESS_DENIED, HTTP_UNAUTHORIZED); - } - err->request = requestLink(http->request); - rep = errorBuildReply(err); - errorStateFree(err); - /* add Authenticate header */ - if (!http->flags.accel) { - /* Proxy authorisation needed */ - httpHeaderPutStrf(&rep->header, HDR_PROXY_AUTHENTICATE, - proxy_auth_challenge_fmt, Config.proxyAuthRealm); - } else { - /* WWW Authorisation needed */ - httpHeaderPutStrf(&rep->header, HDR_WWW_AUTHENTICATE, - proxy_auth_challenge_fmt, Config.proxyAuthRealm); - } - return rep; -} - StoreEntry * clientCreateStoreEntry(clientHttpRequest * h, method_t m, request_flags flags) { @@ -182,25 +181,28 @@ * so make a fake one. */ if (h->request == NULL) - h->request = requestLink(requestCreate(m, PROTO_NONE, NULL)); + h->request = requestLink(requestCreate(m, PROTO_NONE, null_string)); e = storeCreateEntry(h->uri, h->log_uri, flags, m); storeClientListAdd(e, h); #if DELAY_POOLS - delaySetStoreClient(e, h, h->request->delay_id); + delaySetStoreClient(e, h, delayClient(h->request)); #endif storeClientCopy(e, 0, 0, CLIENT_SOCK_SZ, memAllocate(MEM_CLIENT_SOCK_BUF), clientSendMoreData, h); return e; } - void clientAccessCheckDone(int answer, void *data) { clientHttpRequest *http = data; int page_id = -1; + http_status status; ErrorState *err = NULL; - debug(33, 5) ("clientAccessCheckDone: '%s' answer=%d\n", http->uri, answer); + debug(33, 2) ("The request %s %s is %s, because it matched '%s'\n", + RequestMethodStr[http->request->method], http->uri, + answer ? "ALLOWED" : "DENIED", + AclMatchedName ? AclMatchedName : "NO ACL's"); http->acl_checklist = NULL; if (answer == ACCESS_ALLOWED) { safe_free(http->uri); @@ -208,29 +210,38 @@ assert(http->redirect_state == REDIRECT_NONE); http->redirect_state = REDIRECT_PENDING; redirectStart(http, clientRedirectDone, http); - } else if (answer == ACCESS_REQ_PROXY_AUTH) { - http->log_type = LOG_TCP_DENIED; - http->entry = clientCreateStoreEntry(http, http->request->method, - null_request_flags); - /* create appropriate response */ - http->entry->mem_obj->reply = clientConstructProxyAuthReply(http); - httpReplySwapOut(http->entry->mem_obj->reply, http->entry); - storeComplete(http->entry); } else { debug(33, 5) ("Access Denied: %s\n", http->uri); debug(33, 5) ("AclMatchedName = %s\n", AclMatchedName ? AclMatchedName : ""); + /* + * NOTE: get page_id here, based on AclMatchedName because + * if USE_DELAY_POOLS is enabled, then AclMatchedName gets + * clobbered in the clientCreateStoreEntry() call + * just below. Pedro Ribeiro + */ + page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName); http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); - page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName); - /* NOTE: don't use HTTP_UNAUTHORIZED because then the - * stupid browser wants us to authenticate */ - err = errorCon(ERR_ACCESS_DENIED, HTTP_FORBIDDEN); + if (answer == ACCESS_REQ_PROXY_AUTH || aclIsProxyAuth(AclMatchedName)) { + if (!http->flags.accel) { + /* Proxy authorisation needed */ + status = HTTP_PROXY_AUTHENTICATION_REQUIRED; + } else { + /* WWW authorisation needed */ + status = HTTP_UNAUTHORIZED; + } + if (page_id <= 0) + page_id = ERR_CACHE_ACCESS_DENIED; + } else { + status = HTTP_FORBIDDEN; + if (page_id <= 0) + page_id = ERR_ACCESS_DENIED; + } + err = errorCon(page_id, status); err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; - if (page_id > 0) - err->page_id = page_id; errorAppendEntry(http->entry, err); } } @@ -265,6 +276,7 @@ new_request->http_ver = old_request->http_ver; httpHeaderAppend(&new_request->header, &old_request->header); new_request->client_addr = old_request->client_addr; + new_request->my_addr = old_request->my_addr; new_request->flags.redirected = 1; if (old_request->body) { new_request->body = xmalloc(old_request->body_sz); @@ -298,16 +310,21 @@ } http->request->flags.refresh = 1; http->old_entry = http->entry; + /* + * Assert that 'http' is already a client of old_entry. If + * it is not, then the beginning of the object data might get + * freed from memory before we need to access it. + */ + assert(storeClientListSearch(http->old_entry->mem_obj, http)); entry = storeCreateEntry(url, http->log_uri, http->request->flags, http->request->method); /* NOTE, don't call storeLockObject(), storeCreateEntry() does it */ storeClientListAdd(entry, http); - storeClientListAdd(http->old_entry, http); #if DELAY_POOLS - delaySetStoreClient(entry, http, http->request->delay_id); - delaySetStoreClient(http->old_entry, http, http->request->delay_id); + /* delay_id is already set on original store client */ + delaySetStoreClient(entry, http, delayClient(http->request)); #endif entry->lastmod = http->old_entry->lastmod; debug(33, 5) ("clientProcessExpired: lastmod %d\n", (int) entry->lastmod); @@ -315,10 +332,10 @@ http->entry = entry; http->out.offset = 0; fwdStart(http->conn->fd, http->entry, http->request, - http->conn->peer.sin_addr); + http->conn->peer.sin_addr, http->conn->me.sin_addr); /* Register with storage manager to receive updates when data comes in. */ - if (entry->store_status == STORE_ABORTED) - debug(33, 0) ("clientProcessExpired: entry->swap_status == STORE_ABORTED\n"); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) + debug(33, 0) ("clientProcessExpired: found ENTRY_ABORTED object\n"); storeClientCopy(entry, http->out.offset, http->out.offset, @@ -336,6 +353,12 @@ debug(33, 5) ("clientGetsOldEntry: YES, broken HTTP reply\n"); return 1; } + /* If the reply is a failure then send the old object as a last + * resort */ + if (status >= 500 && status < 600) { + debug(33, 2) ("clientGetsOldEntry: YES, failure reply=%d\n", status); + return 1; + } /* If the reply is anything but "Not Modified" then * we must forward it to the client */ if (HTTP_NOT_MODIFIED != status) { @@ -365,46 +388,24 @@ { clientHttpRequest *http = data; StoreEntry *entry = http->entry; - MemObject *mem = entry->mem_obj; + MemObject *mem; const char *url = storeUrl(entry); int unlink_request = 0; StoreEntry *oldentry; int recopy = 1; - const http_status status = mem->reply->sline.status; + http_status status; debug(33, 3) ("clientHandleIMSReply: %s, %d bytes\n", url, (int) size); - if (size < 0 && entry->store_status != STORE_ABORTED) -#if OLD_CODE - /* - * This storeAbort() call causes wrong behaviour in some situations. - * If there are multiple clients hanging on this entry, the second - * client will not want the entry to be aborted. This shows up in - * the stack trace below: - * - * #0 0xef5f452c in kill () - * #1 0xef5ba620 in abort () - * #2 0x7d680 in __eprintf (string=0x82a70 "%s:%u: failed assertion `%s'\n", expression=0x82a90 "client_side.c", line=1111, filename=0x83468 "size > 0") - * #3 0x2ad7c in clientCacheHit (data=0x31ae318, buf=0x17f1450 "", size=0) at client_side.c:1111 - * #4 0x65cd4 in storeClientCopy2 (e=0x4c48c0, sc=0x2eedd70) at store_client.c:264 - * #5 0x665b0 in InvokeHandlers (e=0x4c48c0) at store_client.c:510 - * #6 0x63c90 in storeAbort (e=0x4c48c0, cbflag=1) at store.c:626 - * #7 0x29190 in clientHandleIMSReply (data=0x31e9518, buf=0x2268810 "", size=-1) at client_side.c:343 - * #8 0x66450 in storeUnregister (e=0x2910c, data=0x31e9518) at store_client.c:467 - * #9 0x29a54 in httpRequestFree (data=0x31e9518) at client_side.c:579 - * #10 0x29eb4 in connStateFree (fd=534528, data=0x314d0d0) at client_side.c:667 - * #11 0x2f27c in commCallCloseHandlers (fd=42) at comm.c:501 - * #12 0x2f410 in comm_close (fd=42) at comm.c:565 - * #13 0x2d054 in clientReadRequest (fd=42, data=0x314d0d0) at client_side.c:2038 - * #14 0x309c8 in comm_poll (msec=434) at comm_select.c:354 - * #15 0x4da64 in main (argc=5, argv=0xeffffd4c) at main.c:587 - */ - storeAbort(entry, 1); -#endif - /* - * Lets just try to return here and see what kind of problems that - * causes - */ - return; - if (entry->store_status == STORE_ABORTED) { + if (entry == NULL) { + memFree(buf, MEM_CLIENT_SOCK_BUF); + return; + } + if (size < 0 && !EBIT_TEST(entry->flags, ENTRY_ABORTED)) { + memFree(buf, MEM_CLIENT_SOCK_BUF); + return; + } + mem = entry->mem_obj; + status = mem->reply->sline.status; + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { debug(33, 3) ("clientHandleIMSReply: ABORTED '%s'\n", url); /* We have an existing entry, but failed to validate it */ /* Its okay to send the old one anyway */ @@ -472,7 +473,7 @@ recopy = 0; } http->old_entry = NULL; /* done with old_entry */ - assert(entry->store_status != STORE_ABORTED); + assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); if (recopy) { storeClientCopy(entry, http->out.offset, @@ -634,21 +635,22 @@ clientHttpRequest *http = data; clientHttpRequest **H; ConnStateData *conn = http->conn; - StoreEntry *entry = http->entry; + StoreEntry *e; request_t *request = http->request; MemObject *mem = NULL; - debug(33, 3) ("httpRequestFree: %s\n", storeUrl(entry)); + debug(33, 3) ("httpRequestFree: %s\n", storeUrl(http->entry)); if (!clientCheckTransferDone(http)) { - if (entry) - storeUnregister(entry, http); /* unregister BEFORE abort */ - CheckQuickAbort(http); - entry = http->entry; /* reset, IMS might have changed it */ - if (entry && entry->ping_status == PING_WAITING) - storeReleaseRequest(entry); + if ((e = http->entry)) { + http->entry = NULL; + storeUnregister(e, http); + storeUnlockObject(e); + } + if (http->entry && http->entry->ping_status == PING_WAITING) + storeReleaseRequest(http->entry); } assert(http->log_type < LOG_TYPE_MAX); - if (entry) - mem = entry->mem_obj; + if (http->entry) + mem = http->entry->mem_obj; if (http->out.size || http->log_type) { http->al.icp.opcode = ICP_INVALID; http->al.url = http->log_uri; @@ -664,7 +666,7 @@ if (request->user_ident[0]) http->al.cache.ident = request->user_ident; else - http->al.cache.ident = conn->ident.ident; + http->al.cache.ident = conn->ident; if (request) { Packer p; MemBuf mb; @@ -692,17 +694,17 @@ safe_free(http->al.headers.reply); safe_free(http->redirect.location); stringClean(&http->range_iter.boundary); - if (entry) { + if ((e = http->entry)) { http->entry = NULL; - storeUnregister(entry, http); - storeUnlockObject(entry); + storeUnregister(e, http); + storeUnlockObject(e); } /* old_entry might still be set if we didn't yet get the reply * code in clientHandleIMSReply() */ - if (http->old_entry) { - storeUnregister(http->old_entry, http); - storeUnlockObject(http->old_entry); + if ((e = http->old_entry)) { http->old_entry = NULL; + storeUnregister(e, http); + storeUnlockObject(e); } requestUnlink(http->request); assert(http != http->next); @@ -716,6 +718,7 @@ assert(*H != NULL); *H = http->next; http->next = NULL; + dlinkDelete(&http->active, &ClientActiveRequests); cbdataFree(http); } @@ -732,8 +735,6 @@ assert(connState->chr != connState->chr->next); httpRequestFree(http); } - if (connState->ident.fd > -1) - comm_close(connState->ident.fd); safe_free(connState->in.buf); /* XXX account connState->in.buf */ pconnHistCount(0, connState->nrequests); @@ -752,6 +753,7 @@ { request_t *request = http->request; const HttpHeader *req_hdr = &request->header; + int no_cache = 0; #if USE_USERAGENT_LOG const char *str; #endif @@ -761,17 +763,22 @@ request->flags.ims = 1; if (httpHeaderHas(req_hdr, HDR_PRAGMA)) { String s = httpHeaderGetList(req_hdr, HDR_PRAGMA); - if (strListIsMember(&s, "no-cache", ',')) { + if (strListIsMember(&s, "no-cache", ',')) + no_cache++; + stringClean(&s); + } + if (request->cache_control) + if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) + no_cache++; + if (no_cache) { #if HTTP_VIOLATIONS - if (Config.onoff.reload_into_ims) - request->flags.nocache_hack = 1; - else if (refresh_nocache_hack) - request->flags.nocache_hack = 1; - else + if (Config.onoff.reload_into_ims) + request->flags.nocache_hack = 1; + else if (refresh_nocache_hack) + request->flags.nocache_hack = 1; + else #endif - request->flags.nocache = 1; - } - stringClean(&s); + request->flags.nocache = 1; } /* ignore range header in non-GETs */ if (request->method == METHOD_GET) { @@ -785,8 +792,12 @@ request->flags.auth = 1; if (httpHeaderHas(req_hdr, HDR_VIA)) { String s = httpHeaderGetList(req_hdr, HDR_VIA); - /* ThisCache cannot be a member of Via header, "1.0 ThisCache" can */ - if (strListIsSubstr(&s, ThisCache, ',')) { + /* + * ThisCache cannot be a member of Via header, "1.0 ThisCache" can. + * Note ThisCache2 has a space prepended to the hostname so we don't + * accidentally match super-domains. + */ + if (strListIsSubstr(&s, ThisCache2, ',')) { debugObj(33, 1, "WARNING: Forwarding loop detected for:\n", request, (ObjPackMethod) & httpRequestPack); request->flags.loopdetect = 1; @@ -815,13 +826,6 @@ request->flags.cachable = 1; if (clientHierarchical(http)) request->flags.hierarchical = 1; -#if DELAY_POOLS - if (delayClient(http)) { - debug(33, 5) ("clientInterpretRequestHeaders: delay request class %d position %d\n", - request->delay_id >> 16, - request->delay_id & 0xFFFF); - } -#endif debug(33, 5) ("clientInterpretRequestHeaders: REQ_NOCACHE = %s\n", request->flags.nocache ? "SET" : "NOT SET"); debug(33, 5) ("clientInterpretRequestHeaders: REQ_CACHABLE = %s\n", @@ -847,9 +851,6 @@ RequestMethodStr[request->method]); if (httpMsgIsPersistent(request->http_ver, req_hdr)) request->flags.proxy_keepalive = 1; - if (request->method == METHOD_POST || request->method == METHOD_PUT) - if (!Config.onoff.persistent_client_posts) - request->flags.proxy_keepalive = 0; } static int @@ -880,6 +881,7 @@ * This may not work yet for 'dst' and 'dst_domain' ACLs. */ ch.src_addr = http->conn->peer.sin_addr; + ch.my_addr = http->conn->me.sin_addr; ch.request = http->request; /* * aclCheckFast returns 1 for ALLOW and 0 for DENY. The default @@ -1188,12 +1190,12 @@ request_t *r = http->request; debug(33, 3) ("clientCacheHit: %s, %d bytes\n", http->uri, (int) size); if (http->entry == NULL) { - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); debug(33, 3) ("clientCacheHit: request aborted\n"); return; } else if (size < 0) { /* swap in failure */ - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); debug(33, 3) ("clientCacheHit: swapin failure for %s\n", http->uri); http->log_type = LOG_TCP_SWAPFAIL_MISS; if ((e = http->entry)) { @@ -1206,17 +1208,17 @@ } assert(size > 0); mem = e->mem_obj; - assert(e->store_status != STORE_ABORTED); + assert(!EBIT_TEST(e->flags, ENTRY_ABORTED)); if (mem->reply->sline.status == 0) { /* * we don't have full reply headers yet; either wait for more or * punt to clientProcessMiss. */ if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) { - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); clientProcessMiss(http); } else if (size == CLIENT_SOCK_SZ && http->out.offset == 0) { - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); clientProcessMiss(http); } else { debug(33, 3) ("clientCacheHit: waiting for HTTP reply headers\n"); @@ -1288,7 +1290,7 @@ http->log_type = LOG_TCP_MISS; clientProcessMiss(http); } - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); } else if (r->flags.ims) { /* * Handle If-Modified-Since requests from the client @@ -1296,7 +1298,8 @@ if (mem->reply->sline.status != HTTP_OK) { debug(33, 4) ("clientCacheHit: Reply code %d != 200\n", mem->reply->sline.status); - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); + http->log_type = LOG_TCP_MISS; clientProcessMiss(http); } else if (modifiedSince(e, http->request)) { http->log_type = LOG_TCP_IMS_HIT; @@ -1304,7 +1307,7 @@ } else { MemBuf mb = httpPacked304Reply(e->mem_obj->reply); http->log_type = LOG_TCP_IMS_HIT; - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); storeUnregister(e, http); storeUnlockObject(e); e = clientCreateStoreEntry(http, http->request->method, null_request_flags); @@ -1467,27 +1470,29 @@ debug(33, 5) ("clientSendMoreData: %s, %d bytes\n", http->uri, (int) size); assert(size <= CLIENT_SOCK_SZ); assert(http->request != NULL); + dlinkDelete(&http->active, &ClientActiveRequests); + dlinkAdd(http, &http->active, &ClientActiveRequests); debug(33, 5) ("clientSendMoreData: FD %d '%s', out.offset=%d \n", fd, storeUrl(entry), (int) http->out.offset); if (conn->chr != http) { /* there is another object in progress, defer this one */ debug(33, 1) ("clientSendMoreData: Deferring %s\n", storeUrl(entry)); - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); return; - } else if (entry && entry->store_status == STORE_ABORTED) { + } else if (entry && EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); return; } else if (size < 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); return; } else if (size == 0) { /* call clientWriteComplete so the client socket gets closed */ clientWriteComplete(fd, NULL, 0, COMM_OK, http); - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); return; } if (http->out.offset == 0) { @@ -1568,7 +1573,7 @@ /* write */ comm_write_mbuf(fd, mb, clientWriteComplete, http); /* if we don't do it, who will? */ - memFree(MEM_CLIENT_SOCK_BUF, buf); + memFree(buf, MEM_CLIENT_SOCK_BUF); } static void @@ -1601,8 +1606,8 @@ conn->fd); assert(entry); if (0 == storeClientCopyPending(entry, http)) { - if (entry->store_status == STORE_ABORTED) - debug(33, 0) ("clientKeepaliveNextRequest: entry->swap_status == STORE_ABORTED\n"); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) + debug(33, 0) ("clientKeepaliveNextRequest: ENTRY_ABORTED\n"); storeClientCopy(entry, http->out.offset, http->out.offset, @@ -1635,7 +1640,7 @@ comm_close(fd); } else if (NULL == entry) { comm_close(fd); /* yuk */ - } else if (entry->store_status == STORE_ABORTED) { + } else if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); } else if ((done = clientCheckTransferDone(http)) != 0 || size == 0) { debug(33, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd); @@ -1658,8 +1663,8 @@ } else { /* More data will be coming from primary server; register with * storage manager. */ - if (entry->store_status == STORE_ABORTED) - debug(33, 0) ("clientWriteComplete 2: entry->swap_status == STORE_ABORTED\n"); + if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) + debug(33, 0) ("clientWriteComplete 2: ENTRY_ABORTED\n"); storeClientCopy(entry, http->out.offset, http->out.offset, @@ -1817,7 +1822,7 @@ storeCreateMemObject(http->entry, http->uri, http->log_uri); storeClientListAdd(http->entry, http); #if DELAY_POOLS - delaySetStoreClient(http->entry, http, http->request->delay_id); + delaySetStoreClient(http->entry, http, delayClient(r)); #endif http->entry->refcount++; storeClientCopy(http->entry, @@ -1886,20 +1891,22 @@ } if (http->flags.internal) r->protocol = PROTO_INTERNAL; - fwdStart(http->conn->fd, http->entry, r, http->conn->peer.sin_addr); + fwdStart(http->conn->fd, http->entry, r, + http->conn->peer.sin_addr, http->conn->me.sin_addr); } static clientHttpRequest * parseHttpRequestAbort(ConnStateData * conn, const char *uri) { clientHttpRequest *http = xcalloc(1, sizeof(clientHttpRequest)); - cbdataAdd(http, MEM_NONE); + cbdataAdd(http, cbdataXfree, 0); http->conn = conn; http->start = current_time; http->req_sz = conn->in.offset; http->uri = xstrdup(uri); http->log_uri = xstrndup(uri, MAX_URL); http->range_iter.boundary = StringNull; + dlinkAdd(http, &http->active, &ClientActiveRequests); return http; } @@ -1975,19 +1982,19 @@ debug(33, 1) ("parseHttpRequest: Missing URL\n"); return parseHttpRequestAbort(conn, "error:missing-url"); } - while (isspace(*url)) + while (xisspace(*url)) url++; t = url + strlen(url); assert(*t == '\0'); token = NULL; while (t > url) { t--; - if (isspace(*t) && !strncmp(t + 1, "HTTP/", 5)) { + if (xisspace(*t) && !strncmp(t + 1, "HTTP/", 5)) { token = t + 1; break; } } - while (t > url && isspace(*t)) + while (t > url && xisspace(*t)) *(t--) = '\0'; debug(33, 5) ("parseHttpRequest: URI is '%s'\n", url); if (token == NULL) { @@ -2024,7 +2031,7 @@ /* Ok, all headers are received */ http = xcalloc(1, sizeof(clientHttpRequest)); - cbdataAdd(http, MEM_NONE); + cbdataAdd(http, cbdataXfree, 0); http->http_ver = http_ver; http->conn = conn; http->start = current_time; @@ -2033,6 +2040,7 @@ *prefix_p = xmalloc(prefix_sz + 1); xmemcpy(*prefix_p, conn->in.buf, prefix_sz); *(*prefix_p + prefix_sz) = '\0'; + dlinkAdd(http, &http->active, &ClientActiveRequests); debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", (*prefix_p) + *req_line_sz_p); if ((t = strchr(url, '#'))) /* remove HTML anchors */ @@ -2201,7 +2209,7 @@ while (conn->in.offset > 0) { int nrequests; size_t req_line_sz; - while (conn->in.offset > 0 && isspace(conn->in.buf[0])) { + while (conn->in.offset > 0 && xisspace(conn->in.buf[0])) { xmemmove(conn->in.buf, conn->in.buf + 1, conn->in.offset - 1); conn->in.offset--; } @@ -2270,9 +2278,9 @@ request->flags.accelerated = http->flags.accel; if (!http->flags.internal) { if (internalCheck(strBuf(request->urlpath))) { - if (0 == strcasecmp(request->host, internalHostname())) { - if (request->port == Config.Port.http->i) - http->flags.internal = 1; + if (0 == strcasecmp(request->host, internalHostname()) && + request->port == Config.Port.http->i) { + http->flags.internal = 1; } else if (internalStaticCheck(strBuf(request->urlpath))) { xstrncpy(request->host, internalHostname(), SQUIDHOSTNAMELEN); request->port = Config.Port.http->i; @@ -2285,6 +2293,7 @@ safe_free(http->log_uri); http->log_uri = xstrdup(urlCanonicalClean(request)); request->client_addr = conn->peer.sin_addr; + request->my_addr = conn->me.sin_addr; request->http_ver = http->http_ver; if (!urlCheckRequest(request)) { err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED); @@ -2318,9 +2327,7 @@ */ if (request->method != METHOD_GET) { int cont_len = httpHeaderGetInt(&request->header, HDR_CONTENT_LENGTH); - int copy_len = conn->in.offset; - if (cont_len < copy_len && request->flags.proxy_keepalive) - copy_len = cont_len; + int copy_len = XMIN(conn->in.offset, cont_len); if (copy_len > 0) { assert(conn->in.offset >= copy_len); request->body_sz = copy_len; @@ -2437,6 +2444,9 @@ struct sockaddr_in peer; struct sockaddr_in me; int max = INCOMING_HTTP_MAX; +#if USE_IDENT + static aclCheck_t identChecklist; +#endif commSetSelect(sock, COMM_SELECT_READ, httpAccept, NULL, 0); while (max-- && !httpAcceptDefer()) { memset(&peer, '\0', sizeof(struct sockaddr_in)); @@ -2454,79 +2464,26 @@ connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; connState->me = me; connState->fd = fd; - connState->ident.fd = -1; connState->in.size = REQUEST_BUF_SIZE; connState->in.buf = xcalloc(connState->in.size, 1); - cbdataAdd(connState, MEM_NONE); + cbdataAdd(connState, cbdataXfree, 0); /* XXX account connState->in.buf */ comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(peer.sin_addr, FQDN_LOOKUP_IF_MISS); commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); +#if USE_IDENT + identChecklist.src_addr = peer.sin_addr; + identChecklist.my_addr = me.sin_addr; + if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) + identStart(&me, &peer, clientIdentDone, connState); +#endif commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0); commSetDefer(fd, clientReadDefer, connState); (*N)++; } } -/* return 1 if the request should be aborted */ -static int -CheckQuickAbort2(const clientHttpRequest * http) -{ - int curlen; - int minlen; - int expectlen; - - if (!http->request->flags.cachable) - return 1; - if (EBIT_TEST(http->entry->flags, KEY_PRIVATE)) - return 1; - if (http->entry->mem_obj == NULL) - return 1; - expectlen = http->entry->mem_obj->reply->content_length; - curlen = (int) http->entry->mem_obj->inmem_hi; - minlen = (int) Config.quickAbort.min << 10; - if (minlen < 0) - /* disabled */ - return 0; - if (curlen > expectlen) - /* bad content length */ - return 1; - if ((expectlen - curlen) < minlen) - /* only little more left */ - return 0; - if ((expectlen - curlen) > (Config.quickAbort.max << 10)) - /* too much left to go */ - return 1; - if (expectlen < 100) - /* avoid FPE */ - return 0; - if ((curlen / (expectlen / 100)) > Config.quickAbort.pct) - /* past point of no return */ - return 0; - return 1; -} - - -static void -CheckQuickAbort(clientHttpRequest * http) -{ - StoreEntry *entry = http->entry; - /* Note, set entry here because http->entry might get changed (for IMS - * requests) during the storeAbort() call */ - if (entry == NULL) - return; - if (storePendingNClients(entry) > 0) - return; - if (entry->store_status != STORE_PENDING) - return; - if (CheckQuickAbort2(http) == 0) - return; - debug(33, 3) ("CheckQuickAbort: ABORTING %s\n", storeUrl(entry)); - Counter.aborted_requests++; - storeAbort(entry, 1); -} - #define SENDING_BODY 0 #define SENDING_HDRSONLY 1 static int @@ -2546,10 +2503,10 @@ if (http->flags.done_copying) return 1; /* - * Handle STORE_OK and STORE_ABORTED objects. + * Handle STORE_OK objects. * objectLen(entry) will be set proprely. */ - if (entry->store_status != STORE_PENDING) { + if (entry->store_status == STORE_OK) { if (http->out.offset >= objectLen(entry)) return 1; else @@ -2579,8 +2536,7 @@ /* * Figure out how much data we are supposed to send. * If we are sending a body and we don't have a content-length, - * then we must wait for the object to become STORE_OK or - * STORE_ABORTED. + * then we must wait for the object to become STORE_OK. */ if (sending == SENDING_HDRSONLY) sendlen = reply->hdr_sz; Index: squid/src/comm.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/comm.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/comm.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/comm.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: comm.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: comm.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -107,7 +107,7 @@ fde *F = &fd_table[fd]; /* If the fd is closed already, just return */ - if (!F->open) { + if (!F->flags.open) { debug(5, 0) ("comm_local_port: FD %d has been closed.\n", fd); return 0; } @@ -155,7 +155,6 @@ { int new_socket; fde *F = NULL; - int tcp_rcv_bufsz = Config.tcpRcvBufsz; /* Create socket for accepting new connections. */ Counter.syscalls.sock.sockets++; @@ -202,8 +201,8 @@ if (sock_type == SOCK_STREAM) commSetTcpNoDelay(new_socket); #endif - if (tcp_rcv_bufsz > 0 && sock_type == SOCK_STREAM) - commSetTcpRcvbuf(new_socket, tcp_rcv_bufsz); + if (Config.tcpRcvBufsz > 0 && sock_type == SOCK_STREAM) + commSetTcpRcvbuf(new_socket, Config.tcpRcvBufsz); return new_socket; } @@ -232,7 +231,7 @@ { ConnectStateData *cs = xcalloc(1, sizeof(ConnectStateData)); debug(5, 3) ("commConnectStart: FD %d, %s:%d\n", fd, host, (int) port); - cbdataAdd(cs, MEM_NONE); + cbdataAdd(cs, cbdataXfree, 0); cs->fd = fd; cs->host = xstrdup(host); cs->port = port; @@ -306,6 +305,7 @@ return 0; Counter.syscalls.sock.sockets++; fd2 = socket(AF_INET, SOCK_STREAM, 0); + Counter.syscalls.sock.sockets++; if (fd2 < 0) { debug(5, 0) ("commResetFD: socket: %s\n", xstrerror()); fdAdjustReserved(); @@ -318,7 +318,22 @@ } close(fd2); fd_table[cs->fd].flags.called_connect = 0; + /* + * yuck, this has assumptions about comm_open() arguments for + * the original socket + */ + commSetCloseOnExec(cs->fd); + if (Config.Addrs.tcp_outgoing.s_addr != no_addr.s_addr) { + if (commBind(cs->fd, Config.Addrs.tcp_outgoing, 0) != COMM_OK) { + return 0; + } + } commSetNonBlocking(cs->fd); +#ifdef TCP_NODELAY + commSetTcpNoDelay(cs->fd); +#endif + if (Config.tcpRcvBufsz > 0) + commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz); return 1; } @@ -382,7 +397,7 @@ assert(fd >= 0); assert(fd < Squid_MaxFD); F = &fd_table[fd]; - assert(F->open); + assert(F->flags.open); if (timeout < 0) { F->timeout_handler = NULL; F->timeout_data = NULL; @@ -411,8 +426,19 @@ F->flags.called_connect = 1; Counter.syscalls.sock.connects++; x = connect(sock, (struct sockaddr *) address, sizeof(*address)); - debug(5, 9) ("connect FD %d: %s\n", sock, xstrerror()); + if (x < 0) + debug(5, 9) ("connect FD %d: %s\n", sock, xstrerror()); } else { +#if defined(_SQUID_NEWSOS6_) + /* Makoto MATSUSHITA */ + connect(sock, (struct sockaddr *) address, sizeof(*address)); + if (errno == EINVAL) { + errlen = sizeof(err); + x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); + if (x >= 0) + errno = x; + } +#else errlen = sizeof(err); x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen); if (x == 0) @@ -427,6 +453,7 @@ if (x < 0 && errno == EPIPE) errno = ENOTCONN; #endif +#endif } if (errno == 0 || errno == EISCONN) status = COMM_OK; @@ -551,9 +578,9 @@ F = &fd_table[fd]; if (F->flags.closing) return; - if (shutting_down && (!F->open || F->type == FD_FILE)) + if (shutting_down && (!F->flags.open || F->type == FD_FILE)) return; - assert(F->open); + assert(F->flags.open); assert(F->type != FD_FILE); #ifdef USE_ASYNC_IO if (F->flags.nolinger && F->flags.nonblocking) @@ -620,7 +647,7 @@ { fde *F = &fd_table[fd]; assert(fd >= 0); - assert(F->open == FD_OPEN); + assert(F->flags.open); debug(5, 5) ("commSetSelect: FD %d type %d\n", fd, type); if (type & COMM_SELECT_READ) { F->read_handler = handler; @@ -883,7 +910,7 @@ PF *callback; for (fd = 0; fd <= Biggest_FD; fd++) { F = &fd_table[fd]; - if (F->open != FD_OPEN) + if (!F->flags.open) continue; if (F->type != FD_SOCKET) continue; Index: squid/src/comm_select.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/comm_select.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/comm_select.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/comm_select.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: comm_select.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: comm_select.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 5 Socket Functions * @@ -49,7 +49,6 @@ #define FD_MASK_BYTES sizeof(fd_mask) #define FD_MASK_BITS (FD_MASK_BYTES*NBBY) - /* STATIC */ #if !HAVE_POLL static int examine_select(fd_set *, fd_set *); @@ -343,6 +342,7 @@ * more frequently to minimize losses due to the 5 connect * limit in SunOS */ for (i = 0; i < nfds; i++) { + fde *F; int revents; if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1)) continue; @@ -354,11 +354,12 @@ callhttp = 1; continue; } + F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { debug(5, 6) ("comm_poll: FD %d ready for reading\n", fd); - if ((hdl = fd_table[fd].read_handler)) { - fd_table[fd].read_handler = NULL; - hdl(fd, fd_table[fd].read_data); + if ((hdl = F->read_handler)) { + F->read_handler = NULL; + hdl(fd, F->read_data); Counter.select_fds++; } if (commCheckICPIncoming) @@ -368,9 +369,9 @@ } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { debug(5, 5) ("comm_poll: FD %d ready for writing\n", fd); - if ((hdl = fd_table[fd].write_handler)) { - fd_table[fd].write_handler = NULL; - hdl(fd, fd_table[fd].write_data); + if ((hdl = F->write_handler)) { + F->write_handler = NULL; + hdl(fd, F->write_data); Counter.select_fds++; } if (commCheckICPIncoming) @@ -380,10 +381,9 @@ } if (revents & POLLNVAL) { close_handler *ch; - fde *F = &fd_table[fd]; debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); - debug(5, 0) ("FD %d is a %s\n", fd, fdTypeStr[fd_table[fd].type]); - debug(5, 0) ("--> %s\n", fd_table[fd].desc); + debug(5, 0) ("FD %d is a %s\n", fd, fdTypeStr[F->type]); + debug(5, 0) ("--> %s\n", F->desc); debug(5, 0) ("tmout:%p read:%p write:%p\n", F->timeout_handler, F->read_handler, @@ -400,7 +400,7 @@ F->timeout_handler = NULL; F->read_handler = NULL; F->write_handler = NULL; - if (F->open != 0) + if (F->flags.open) fd_close(fd); } } @@ -551,6 +551,7 @@ static time_t last_timeout = 0; struct timeval poll_time; double timeout = current_dtime + (msec / 1000.0); + fde *F; do { #if !ALARM_UPDATES_TIME getCurrentTime(); @@ -600,6 +601,10 @@ } if (msec > MAX_POLL_TIME) msec = MAX_POLL_TIME; +#ifdef _SQUID_OS2_ + if (msec < 0) + msec = MAX_POLL_TIME; +#endif for (;;) { poll_time.tv_sec = msec / 1000; poll_time.tv_usec = (msec % 1000) * 1000; @@ -652,12 +657,13 @@ callhttp = 1; continue; } + F = &fd_table[fd]; debug(5, 6) ("comm_select: FD %d ready for reading\n", fd); - if (fd_table[fd].read_handler) { - hdl = fd_table[fd].read_handler; - fd_table[fd].read_handler = NULL; + if (F->read_handler) { + hdl = F->read_handler; + F->read_handler = NULL; commUpdateReadBits(fd, NULL); - hdl(fd, fd_table[fd].read_data); + hdl(fd, F->read_data); Counter.select_fds++; } if (commCheckICPIncoming) @@ -690,12 +696,13 @@ callhttp = 1; continue; } + F = &fd_table[fd]; debug(5, 5) ("comm_select: FD %d ready for writing\n", fd); - if (fd_table[fd].write_handler) { - hdl = fd_table[fd].write_handler; - fd_table[fd].write_handler = NULL; + if (F->write_handler) { + hdl = F->write_handler; + F->write_handler = NULL; commUpdateWriteBits(fd, NULL); - hdl(fd, fd_table[fd].write_data); + hdl(fd, F->write_data); Counter.select_fds++; } if (commCheckICPIncoming) @@ -774,7 +781,7 @@ debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd); debug(5, 0) ("FD %d is a %s called '%s'\n", fd, - fdTypeStr[fd_table[fd].type], + fdTypeStr[F->type], F->desc); debug(5, 0) ("tmout:%p read:%p write:%p\n", F->timeout_handler, @@ -807,7 +814,7 @@ PF *callback; for (fd = 0; fd <= Biggest_FD; fd++) { F = &fd_table[fd]; - if (F->open != FD_OPEN) + if (!F->flags.open) continue; if (F->timeout == 0) continue; Index: squid/src/debug.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/debug.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/debug.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/debug.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: debug.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: debug.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -40,7 +40,7 @@ static const char *debugLogTime(time_t); static void ctx_print(); -#ifdef __STDC__ +#if STDC_HEADERS void _db_print(const char *format,...) { @@ -61,7 +61,7 @@ LOCAL_ARRAY(char, tmpbuf, BUFSIZ); #endif -#ifdef __STDC__ +#if STDC_HEADERS va_start(args, format); #if defined(__QNX__) va_start(eargs, format); @@ -115,7 +115,6 @@ int s = 0; int l = 0; int i; - if (!strncasecmp(arg, "ALL", 3)) { s = -1; arg += 4; @@ -124,7 +123,12 @@ while (*arg && *arg++ != ','); } l = atoi(arg); - + assert(s >= -1); + assert(s < MAX_DEBUG_SECTIONS); + if (l < 0) + l = 0; + if (l > 10) + l = 10; if (s >= 0) { debugLevels[s] = l; return; @@ -230,6 +234,14 @@ return buf; } +void +xassert(const char *msg, const char *file, int line) +{ + debug(0, 0) ("assertion failed: %s:%d: \"%s\"\n", file, line, msg); + if (!shutting_down) + abort(); +} + /* * Context-based Debugging * Index: squid/src/defines.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/defines.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/defines.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/defines.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: defines.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: defines.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -121,9 +121,10 @@ #define ICP_VERSION_3 3 #define ICP_VERSION_CURRENT ICP_VERSION_2 -#define DIRECT_NO 0 -#define DIRECT_MAYBE 1 -#define DIRECT_YES 2 +#define DIRECT_UNKNOWN 0 +#define DIRECT_NO 1 +#define DIRECT_MAYBE 2 +#define DIRECT_YES 3 #define REDIRECT_AV_FACTOR 1000 @@ -200,7 +201,7 @@ #define SwapMetaType(x) (char)x[0] #define SwapMetaSize(x) &x[sizeof(char)] #define SwapMetaData(x) &x[STORE_META_TLD_START] -#define STORE_HDR_METASIZE (4*sizeof(time_t)+2*sizeof(u_short)+sizeof(int)) +#define STORE_HDR_METASIZE (4*sizeof(time_t)+2*sizeof(u_short)+sizeof(size_t)) #define STORE_ENTRY_WITH_MEMOBJ 1 #define STORE_ENTRY_WITHOUT_MEMOBJ 0 @@ -263,3 +264,9 @@ #define URI_WHITESPACE_ALLOW 1 #define URI_WHITESPACE_ENCODE 2 #define URI_WHITESPACE_CHOP 3 + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +#define USE_TRUNCATE_NOT_UNLINK 1 Index: squid/src/delay_pools.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/delay_pools.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/delay_pools.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/delay_pools.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: delay_pools.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: delay_pools.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: David Luyer @@ -38,308 +38,473 @@ #if DELAY_POOLS #include "squid.h" -struct _delayData { - int class1_aggregate; - int class2_aggregate; - /* 254 entries + 1 terminator byte */ - unsigned char class2_individual_map[255]; - /* 254 entries */ - int class2_individual[254]; - int class3_aggregate; +struct _class1DelayPool { + int aggregate; +}; + +struct _class2DelayPool { + int aggregate; + /* OK: -1 is terminator. individual[255] is always host 255. */ /* 255 entries + 1 terminator byte */ - unsigned char class3_network_map[256]; - /* 255 entries */ - int class3_network[255]; - /* 255 sets of (254 entries + 1 terminator byte) */ - unsigned char class3_individual_map[255][255]; - /* largest entry = (254<<8)+253 = 65277 */ - int class3_individual[65278]; + unsigned char individual_map[256]; + unsigned char individual_255_used; + /* 256 entries */ + int individual[256]; }; -static struct _delayData delay_data; -static OBJH delayPoolStats; +struct _class3DelayPool { + int aggregate; + /* OK: -1 is terminator. network[255] is always host 255. */ + /* 255 entries + 1 terminator byte */ + unsigned char network_map[256]; + unsigned char network_255_used; + /* 256 entries */ + int network[256]; + /* 256 sets of (255 entries + 1 terminator byte) */ + unsigned char individual_map[256][256]; + /* Pack this into one bit per net */ + unsigned char individual_255_used[32]; + /* largest entry = (255<<8)+255 = 65535 */ + int individual[65536]; +}; + +typedef struct _class1DelayPool class1DelayPool; +typedef struct _class2DelayPool class2DelayPool; +typedef struct _class3DelayPool class3DelayPool; + +union _delayPool { + class1DelayPool *class1; + class2DelayPool *class2; + class3DelayPool *class3; +}; + +typedef union _delayPool delayPool; + +static delayPool *delay_data = NULL; +static fd_set delay_no_delay; static time_t delay_pools_last_update = 0; -static delay_id delayId(unsigned char class, int position); +static hash_table *delay_id_ptr_hash = NULL; -static delay_id -delayId(unsigned char class, int position) +static OBJH delayPoolStats; + +static unsigned int +delayIdPtrHash(const void *key, unsigned int n) +{ + /* Hashes actual POINTER VALUE. + * Assumes <= 256 hash buckets & even hash size. + * Assumes the most variation in pointers to inside + * medium size objects occurs in the 2nd and 3rd + * least significant bytes. + */ + const char *ptr = (char *) &key; +#if SIZEOF_VOID_P == 4 + return (ptr[1] ^ ptr[2]) & (n - 1); +#elif SIZEOF_VOID_P == 8 +#if WORDS_BIGENDIAN + return (ptr[5] ^ ptr[6]) & (n - 1); +#else + return (ptr[1] ^ ptr[2]) & (n - 1); +#endif +#else +#error What kind of a sick architecture are you on anyway? +#endif +} + +static int +delayIdPtrHashCmp(const void *a, const void *b) +{ + /* + * Compare POINTER VALUE. + * Note, we can't subtract void pointers, but we don't need + * to anyway. All we need is a test for equality. + */ + return a != b; +} + +void +delayPoolsInit(void) +{ + delay_pools_last_update = getCurrentTime(); + FD_ZERO(&delay_no_delay); + cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1); +} + +void +delayInitDelayData(unsigned short pools) +{ + if (!pools) + return; + delay_data = xcalloc(pools, sizeof(delayPool)); + eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1); + delay_id_ptr_hash = hash_create(delayIdPtrHashCmp, 256, delayIdPtrHash); +} + +static void +delayIdZero(void *hlink) +{ + hash_link *h = hlink; + delay_id *id = (delay_id *) h->key; + *id = 0; + xfree(h); +} + +void +delayFreeDelayData() +{ + safe_free(delay_data); + if (!delay_id_ptr_hash) + return; + hashFreeItems(delay_id_ptr_hash, delayIdZero); + hashFreeMemory(delay_id_ptr_hash); + delay_id_ptr_hash = NULL; +} + +void +delayRegisterDelayIdPtr(delay_id * loc) +{ + hash_link *lnk; + if (!delay_id_ptr_hash) + return; + if (*loc == 0) + return; + lnk = xmalloc(sizeof(hash_link)); + lnk->key = (char *) loc; + hash_join(delay_id_ptr_hash, lnk); +} + +void +delayUnregisterDelayIdPtr(delay_id * loc) +{ + hash_link *lnk; + if (!delay_id_ptr_hash) + return; + /* + * If we went through a reconfigure, then all the delay_id's + * got set to zero, and they were removed from our hash + * table. + */ + if (*loc == 0) + return; + lnk = hash_lookup(delay_id_ptr_hash, loc); + assert(lnk); + hash_remove_link(delay_id_ptr_hash, lnk); + xxfree(lnk); +} + +void +delayCreateDelayPool(unsigned short pool, u_char class) +{ + switch (class) { + case 1: + delay_data[pool].class1 = xmalloc(sizeof(class1DelayPool)); + break; + case 2: + delay_data[pool].class2 = xmalloc(sizeof(class2DelayPool)); + break; + case 3: + delay_data[pool].class3 = xmalloc(sizeof(class3DelayPool)); + break; + default: + assert(0); + } +} + +void +delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates) { - assert(class <= 3); - return (class << 16) | (position & 0xFFFF); + /* delaySetSpec may be pointer to partial structure so MUST pass by + * reference. + */ + switch (class) { + case 1: + delay_data[pool].class1->aggregate = (rates->aggregate.max_bytes * + Config.Delay.initial) / 100; + break; + case 2: + delay_data[pool].class2->aggregate = (rates->aggregate.max_bytes * + Config.Delay.initial) / 100; + delay_data[pool].class2->individual_map[0] = 255; + delay_data[pool].class2->individual_255_used = 0; + break; + case 3: + delay_data[pool].class3->aggregate = (rates->aggregate.max_bytes * + Config.Delay.initial) / 100; + delay_data[pool].class3->network_map[0] = 255; + delay_data[pool].class3->network_255_used = 0; + memset(&delay_data[pool].class3->individual_255_used, '\0', + sizeof(delay_data[pool].class3->individual_255_used)); + break; + default: + assert(0); + } +} + +void +delayFreeDelayPool(unsigned short pool) +{ + /* this is a union - and all free() cares about is the pointer location */ + safe_free(delay_data[pool].class1); +} + +void +delaySetNoDelay(int fd) +{ + FD_SET(fd, &delay_no_delay); +} + +void +delayClearNoDelay(int fd) +{ + FD_CLR(fd, &delay_no_delay); } int -delayClient(clientHttpRequest * http) +delayIsNoDelay(int fd) +{ + return FD_ISSET(fd, &delay_no_delay); +} + +static delay_id +delayId(unsigned short pool, unsigned short position) +{ + return (pool << 16) | position; +} + +delay_id +delayClient(request_t * r) { aclCheck_t ch; int i; int j; unsigned int host; - unsigned char net; - unsigned char class = 0; - int position = 0; - request_t *r = http->request; + unsigned short pool, position; + unsigned char class, net; memset(&ch, '\0', sizeof(ch)); - ch.src_addr = http->conn->peer.sin_addr; + ch.src_addr = r->client_addr; + ch.my_addr = r->my_addr; ch.request = r; - if (aclCheckFast(Config.Delay.class1.access, &ch)) { - class = 1; - r->delay_id = delayId(class, position); - return 1; - } - if (aclCheckFast(Config.Delay.class2.access, &ch)) { - class = 2; + for (pool = 0; pool < Config.Delay.pools; pool++) { + if (aclCheckFast(Config.Delay.access[pool], &ch)) + break; + } + if (pool == Config.Delay.pools) + return delayId(0, 0); + class = Config.Delay.class[pool]; + if (class == 0) + return delayId(0, 0); + if (class == 1) + return delayId(pool + 1, 0); + if (class == 2) { host = ntohl(ch.src_addr.s_addr) & 0xff; - if (host == 255 || !host) { - debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr)); - class = 0; - r->delay_id = delayId(class, position); - return 0; + if (host == 255) { + if (!delay_data[pool].class2->individual_255_used) { + delay_data[pool].class2->individual_255_used = 1; + delay_data[pool].class2->individual[255] = + (Config.Delay.rates[pool]->individual.max_bytes * + Config.Delay.initial) / 100; + } + return delayId(pool + 1, 255); } for (i = 0;; i++) { - if (delay_data.class2_individual_map[i] == host) + if (delay_data[pool].class2->individual_map[i] == host) break; - if (delay_data.class2_individual_map[i] == 255) { - delay_data.class2_individual_map[i] = host; - delay_data.class2_individual_map[i + 1] = 255; - delay_data.class2_individual[i] = Config.Delay.class2.individual.restore_bps; + if (delay_data[pool].class2->individual_map[i] == 255) { + delay_data[pool].class2->individual_map[i] = host; + delay_data[pool].class2->individual_map[i + 1] = 255; + delay_data[pool].class2->individual[i] = + (Config.Delay.rates[pool]->individual.max_bytes * + Config.Delay.initial) / 100; break; } } - position = i; - r->delay_id = delayId(class, position); - return 1; - } - if (aclCheckFast(Config.Delay.class3.access, &ch)) { - class = 3; - host = ntohl(ch.src_addr.s_addr) & 0xffff; - net = host >> 8; - host &= 0xff; - if (host == 255 || !host || net == 255) { - debug(77, 0) ("ARGH: Delay requested for host %s\n", inet_ntoa(ch.src_addr)); - class = 0; - r->delay_id = delayId(class, position); - return 0; + return delayId(pool + 1, i); + } + /* class == 3 */ + host = ntohl(ch.src_addr.s_addr) & 0xffff; + net = host >> 8; + host &= 0xff; + if (net == 255) { + i = 255; + if (!delay_data[pool].class3->network_255_used) { + delay_data[pool].class3->network_255_used = 1; + delay_data[pool].class3->network[255] = + (Config.Delay.rates[pool]->network.max_bytes * + Config.Delay.initial) / 100; } + } else { for (i = 0;; i++) { - if (delay_data.class3_network_map[i] == net) + if (delay_data[pool].class3->network_map[i] == net) break; - if (delay_data.class3_network_map[i] == 255) { - delay_data.class3_network_map[i] = net; - delay_data.class3_individual_map[i][0] = 255; - delay_data.class3_network_map[i + 1] = 255; - delay_data.class3_network[i] = Config.Delay.class3.network.restore_bps; + if (delay_data[pool].class3->network_map[i] == 255) { + delay_data[pool].class3->network_map[i] = net; + delay_data[pool].class3->individual_map[i][0] = 255; + delay_data[pool].class3->network_map[i + 1] = 255; + delay_data[pool].class3->network[i] = + (Config.Delay.rates[pool]->network.max_bytes * + Config.Delay.initial) / 100; break; } } - position = i << 8; - for (j = 0;; j++) { - if (delay_data.class3_individual_map[i][j] == host) { - position |= j; - break; - } - if (delay_data.class3_individual_map[i][j] == 255) { - delay_data.class3_individual_map[i][j] = host; - delay_data.class3_individual_map[i][j + 1] = 255; - delay_data.class3_individual[position |= j] = - Config.Delay.class3.individual.restore_bps; - break; - } + } + position = i << 8; + if (host == 255) { + position |= 255; + if (!(delay_data[pool].class3->individual_255_used[i / 8] & (1 << (i % 8)))) { + delay_data[pool].class3->individual_255_used[i / 8] |= (1 << (i % 8)); + delay_data[pool].class3->individual[position] = + (Config.Delay.rates[pool]->individual.max_bytes * + Config.Delay.initial) / 100; + } + return delayId(pool + 1, position); + } + for (j = 0;; j++) { + if (delay_data[pool].class3->individual_map[i][j] == host) { + position |= j; + break; + } + if (delay_data[pool].class3->individual_map[i][j] == 255) { + delay_data[pool].class3->individual_map[i][j] = host; + delay_data[pool].class3->individual_map[i][j + 1] = 255; + delay_data[pool].class3->individual[position |= j] = + (Config.Delay.rates[pool]->individual.max_bytes * + Config.Delay.initial) / 100; + break; } - r->delay_id = delayId(class, position); - return 1; } - class = 0; - r->delay_id = delayId(class, position); - return 0; + return delayId(pool + 1, position); } +static void +delayUpdateClass1(class1DelayPool * class1, delaySpecSet * rates, int incr) +{ + /* delaySetSpec may be pointer to partial structure so MUST pass by + * reference. + */ + if (rates->aggregate.restore_bps != -1 && + (class1->aggregate += rates->aggregate.restore_bps * incr) > + rates->aggregate.max_bytes) + class1->aggregate = rates->aggregate.max_bytes; +} -void -delayPoolsUpdate(void *unused) +static void +delayUpdateClass2(class2DelayPool * class2, delaySpecSet * rates, int incr) { - int incr = squid_curtime - delay_pools_last_update; - int i; - int j; - int mpos; - int individual_restore_bytes; - int network_restore_bytes; - eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1); - if (incr < 1) + int restore_bytes; + unsigned char i; + /* delaySetSpec may be pointer to partial structure so MUST pass by + * reference. + */ + if (rates->aggregate.restore_bps != -1 && + (class2->aggregate += rates->aggregate.restore_bps * incr) > + rates->aggregate.max_bytes) + class2->aggregate = rates->aggregate.max_bytes; + if ((restore_bytes = rates->individual.restore_bps) == -1) return; - delay_pools_last_update = squid_curtime; - /* Increment 3 aggregate pools */ - if (Config.Delay.class1.aggregate.restore_bps != -1 && - (delay_data.class1_aggregate += - Config.Delay.class1.aggregate.restore_bps * incr) > - Config.Delay.class1.aggregate.max_bytes) - delay_data.class1_aggregate = Config.Delay.class1.aggregate.max_bytes; - if (Config.Delay.class2.aggregate.restore_bps != -1 && - (delay_data.class2_aggregate += - Config.Delay.class2.aggregate.restore_bps * incr) > - Config.Delay.class2.aggregate.max_bytes) - delay_data.class2_aggregate = Config.Delay.class2.aggregate.max_bytes; - if (Config.Delay.class3.aggregate.restore_bps != -1 && - (delay_data.class3_aggregate += - Config.Delay.class3.aggregate.restore_bps * incr) > - Config.Delay.class3.aggregate.max_bytes) - delay_data.class3_aggregate = Config.Delay.class3.aggregate.max_bytes; - /* Increment class 2 individual pools */ - if ((individual_restore_bytes = Config.Delay.class2.individual.restore_bps) != -1) { - individual_restore_bytes *= incr; - for (i = 0;; i++) { - if (delay_data.class2_individual_map[i] == 255) - break; - if (delay_data.class2_individual[i] == Config.Delay.class2.individual.max_bytes) - continue; - if ((delay_data.class2_individual[i] += individual_restore_bytes) > - Config.Delay.class2.individual.max_bytes) - delay_data.class2_individual[i] = Config.Delay.class2.individual.max_bytes; - } - } - /* Increment class 3 individual and network pools */ - if ((network_restore_bytes = Config.Delay.class3.network.restore_bps) != -1 || - (individual_restore_bytes = Config.Delay.class3.individual.restore_bps) != -1) { - individual_restore_bytes *= incr; - network_restore_bytes *= incr; - for (i = 0;; i++) { - if (delay_data.class3_network_map[i] == 255) - break; - if (individual_restore_bytes != -incr) { - for (j = 0, mpos = (i << 8);; j++, mpos++) { - if (delay_data.class3_individual_map[i][j] == 255) - break; - if (delay_data.class3_individual[mpos] == Config.Delay.class3.individual.max_bytes) - continue; - if ((delay_data.class3_individual[mpos] += individual_restore_bytes) > - Config.Delay.class3.individual.max_bytes) - delay_data.class3_individual[mpos] = Config.Delay.class3.individual.max_bytes; - } - } - if (network_restore_bytes == -incr || - delay_data.class3_network[i] == Config.Delay.class3.network.max_bytes) - continue; - if ((delay_data.class3_network[i] += network_restore_bytes) > - Config.Delay.class3.network.max_bytes) - delay_data.class3_network[i] = Config.Delay.class3.network.max_bytes; - } + restore_bytes *= incr; + if (class2->individual_255_used) + i = 255; + else + i = 0; + for (;;) { + if (i != 255 && class2->individual_map[i] == 255) + return; + if (class2->individual[i] != rates->individual.max_bytes && + (class2->individual[i] += restore_bytes) > rates->individual.max_bytes) + class2->individual[i] = rates->individual.max_bytes; + if (++i == 255) + return; } } - static void -delayPoolStats(StoreEntry * sentry) +delayUpdateClass3(class3DelayPool * class3, delaySpecSet * rates, int incr) { - int i; - int j; - storeAppendPrintf(sentry, "Class 1 Delay Pool Statistics:\n"); - if (Config.Delay.class1.aggregate.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\tAggregate:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class1.aggregate.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class1.aggregate.restore_bps); - storeAppendPrintf(sentry, "\t\tCurrent: %d\n", - delay_data.class1_aggregate); - } else { - storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n"); - } - storeAppendPrintf(sentry, "\nClass 2 Delay Pool Statistics:\n"); - if (Config.Delay.class2.aggregate.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\tAggregate:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class2.aggregate.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class2.aggregate.restore_bps); - storeAppendPrintf(sentry, "\t\tCurrent: %d\n", - delay_data.class2_aggregate); - } else { - storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n"); - } - if (Config.Delay.class2.individual.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\tIndividual:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class2.individual.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class2.individual.restore_bps); - storeAppendPrintf(sentry, "\t\tCurrent: "); - for (i = 0;; i++) { - if (delay_data.class2_individual_map[i] == 255) - break; - storeAppendPrintf(sentry, "%d:%d ", - delay_data.class2_individual_map[i], - delay_data.class2_individual[i]); - } - } else { - storeAppendPrintf(sentry, "\n\tIndividual:\n\tDisabled."); - } - storeAppendPrintf(sentry, "\n\nClass 3 Delay Pool Statistics:\n"); - if (Config.Delay.class3.aggregate.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\tAggregate:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class3.aggregate.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class3.aggregate.restore_bps); - storeAppendPrintf(sentry, "\t\tCurrent: %d\n", - delay_data.class3_aggregate); - } else { - storeAppendPrintf(sentry, "\n\tAggregate:\n\tDisabled.\n"); - } - if (Config.Delay.class3.network.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\tNetwork:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class3.network.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class3.network.restore_bps); - storeAppendPrintf(sentry, "\t\tCurrent: "); - for (i = 0;; i++) { - if (delay_data.class3_network_map[i] == 255) - break; - storeAppendPrintf(sentry, "%d:%d ", - delay_data.class3_network_map[i], - delay_data.class3_network[i]); - } - } else { - storeAppendPrintf(sentry, "\n\tNetwork:\n\tDisabled."); - } - if (Config.Delay.class3.individual.restore_bps != -1) { - storeAppendPrintf(sentry, "\n\n\tIndividual:\n"); - storeAppendPrintf(sentry, "\t\tMax: %d\n", - Config.Delay.class3.individual.max_bytes); - storeAppendPrintf(sentry, "\t\tRate: %d\n", - Config.Delay.class3.individual.restore_bps); - for (i = 0;; i++) { - if (delay_data.class3_network_map[i] == 255) - break; - storeAppendPrintf(sentry, "\t\tCurrent [Network %d]: ", - delay_data.class3_network_map[i]); - for (j = 0;; j++) { - if (delay_data.class3_individual_map[i][j] == 255) + int individual_restore_bytes, network_restore_bytes; + int mpos; + unsigned char i, j; + /* delaySetSpec may be pointer to partial structure so MUST pass by + * reference. + */ + if (rates->aggregate.restore_bps != -1 && + (class3->aggregate += rates->aggregate.restore_bps * incr) > + rates->aggregate.max_bytes) + class3->aggregate = rates->aggregate.max_bytes; + /* the following line deliberately uses &, not &&, in an if statement + * to avoid conditional execution + */ + if (((network_restore_bytes = rates->network.restore_bps) == -1) & + ((individual_restore_bytes = rates->individual.restore_bps) == -1)) + return; + individual_restore_bytes *= incr; + network_restore_bytes *= incr; + if (class3->network_255_used) + i = 255; + else + i = 0; + for (;;) { + if (i != 255 && class3->network_map[i] == 255) + return; + if (individual_restore_bytes != -incr) { + mpos = i << 8; + if (class3->individual_255_used[i / 8] & (1 << (i % 8))) + j = 255; + else + j = 0; + for (;;) { + if (j != 255 && class3->individual_map[i][j] == 255) + break; + if (class3->individual[mpos] != rates->individual.max_bytes && + (class3->individual[mpos] += individual_restore_bytes) > + rates->individual.max_bytes) + class3->individual[mpos] = rates->individual.max_bytes; + mpos++; + if (j == 255) + mpos -= 256; + if (++j == 255) break; - storeAppendPrintf(sentry, "%d:%d ", - delay_data.class3_individual_map[i][j], - delay_data.class3_individual[(i << 8) + j]); } - storeAppendPrintf(sentry, "\n"); } - } else { - storeAppendPrintf(sentry, "\n\n\tIndividual:\n\tDisabled.\n"); + if (network_restore_bytes != -incr && + class3->network[i] != rates->network.max_bytes && + (class3->network[i] += network_restore_bytes) > + rates->network.max_bytes) + class3->network[i] = rates->network.max_bytes; + if (++i == 255) + return; } - storeAppendPrintf(sentry, "\n"); } void -delayPoolsInit(void) +delayPoolsUpdate(void *unused) { - delay_pools_last_update = getCurrentTime(); - delay_data.class1_aggregate = Config.Delay.class1.aggregate.restore_bps; - delay_data.class2_aggregate = Config.Delay.class2.aggregate.restore_bps; - delay_data.class2_individual_map[0] = 255; - delay_data.class3_aggregate = Config.Delay.class3.aggregate.restore_bps; - delay_data.class3_network_map[0] = 255; - cachemgrRegister("delay", "Delay Pool Levels", delayPoolStats, 0, 1); + int incr = squid_curtime - delay_pools_last_update; + unsigned short i; + unsigned char class; + if (!Config.Delay.pools) + return; eventAdd("delayPoolsUpdate", delayPoolsUpdate, NULL, 1.0, 1); + if (incr < 1) + return; + delay_pools_last_update = squid_curtime; + for (i = 0; i < Config.Delay.pools; i++) { + class = Config.Delay.class[i]; + if (!class) + continue; + switch (class) { + case 1: + delayUpdateClass1(delay_data[i].class1, Config.Delay.rates[i], incr); + break; + case 2: + delayUpdateClass2(delay_data[i].class2, Config.Delay.rates[i], incr); + break; + case 3: + delayUpdateClass3(delay_data[i].class3, Config.Delay.rates[i], incr); + break; + default: + assert(0); + } + } } /* @@ -349,32 +514,34 @@ int delayBytesWanted(delay_id d, int min, int max) { - int position = d & 0xFFFF; - unsigned char class = (d & 0xFF0000) >> 16; + unsigned short position = d & 0xFFFF; + unsigned short pool = (d >> 16) - 1; + unsigned char class = (pool == 0xFFFF) ? 0 : Config.Delay.class[pool]; int nbytes = max; + switch (class) { case 0: break; case 1: - if (Config.Delay.class1.aggregate.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class1_aggregate); + if (Config.Delay.rates[pool]->aggregate.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class1->aggregate); break; case 2: - if (Config.Delay.class2.aggregate.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class2_aggregate); - if (Config.Delay.class2.individual.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class2_individual[position]); + if (Config.Delay.rates[pool]->aggregate.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class2->aggregate); + if (Config.Delay.rates[pool]->individual.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class2->individual[position]); break; case 3: - if (Config.Delay.class3.aggregate.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class3_aggregate); - if (Config.Delay.class3.individual.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class3_individual[position]); - if (Config.Delay.class3.network.restore_bps != -1) - nbytes = XMIN(nbytes, delay_data.class3_network[position >> 8]); + if (Config.Delay.rates[pool]->aggregate.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class3->aggregate); + if (Config.Delay.rates[pool]->individual.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class3->individual[position]); + if (Config.Delay.rates[pool]->network.restore_bps != -1) + nbytes = XMIN(nbytes, delay_data[pool].class3->network[position >> 8]); break; default: @@ -382,8 +549,6 @@ break; } nbytes = XMAX(min, nbytes); - assert(nbytes >= min); - assert(nbytes <= max); return nbytes; } @@ -395,25 +560,28 @@ void delayBytesIn(delay_id d, int qty) { - int position = d & 0xFFFF; - unsigned char class = (d & 0xFF0000) >> 16; - if (class == 0) + unsigned short position = d & 0xFFFF; + unsigned short pool = (d >> 16) - 1; + unsigned char class; + + if (pool == 0xFFFF) return; - if (class == 1) { - delay_data.class1_aggregate -= qty; + class = Config.Delay.class[pool]; + switch (class) { + case 1: + delay_data[pool].class1->aggregate -= qty; return; - } - if (class == 2) { - delay_data.class2_aggregate -= qty; - delay_data.class2_individual[position] -= qty; + case 2: + delay_data[pool].class2->aggregate -= qty; + delay_data[pool].class2->individual[position] -= qty; return; - } - if (class == 3) { - delay_data.class3_aggregate -= qty; - delay_data.class3_network[position >> 8] -= qty; - delay_data.class3_individual[position] -= qty; + case 3: + delay_data[pool].class3->aggregate -= qty; + delay_data[pool].class3->network[position >> 8] -= qty; + delay_data[pool].class3->individual[position] -= qty; return; } + fatalf("delayBytesWanted: Invalid class %d\n", class); assert(0); } @@ -461,6 +629,167 @@ store_client *sc = storeClientListSearch(e->mem_obj, data); assert(sc != NULL); sc->delay_id = delay_id; + delayRegisterDelayIdPtr(&sc->delay_id); +} + +static void +delayPoolStatsAg(StoreEntry * sentry, delaySpecSet * rate, int ag) +{ + /* note - always pass delaySpecSet's by reference as may be incomplete */ + if (rate->aggregate.restore_bps == -1) { + storeAppendPrintf(sentry, "\tAggregate:\n\t\tDisabled.\n\n"); + return; + } + storeAppendPrintf(sentry, "\tAggregate:\n"); + storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->aggregate.max_bytes); + storeAppendPrintf(sentry, "\t\tRestore: %d\n", rate->aggregate.restore_bps); + storeAppendPrintf(sentry, "\t\tCurrent: %d\n\n", ag); +} + +static void +delayPoolStats1(StoreEntry * sentry, unsigned short pool) +{ + /* must be a reference only - partially malloc()d struct */ + delaySpecSet *rate = Config.Delay.rates[pool]; + + storeAppendPrintf(sentry, "Pool: %d\n\tClass: 1\n\n", pool + 1); + delayPoolStatsAg(sentry, rate, delay_data[pool].class1->aggregate); +} + +static void +delayPoolStats2(StoreEntry * sentry, unsigned short pool) +{ + /* must be a reference only - partially malloc()d struct */ + delaySpecSet *rate = Config.Delay.rates[pool]; + class2DelayPool *class2 = delay_data[pool].class2; + unsigned char shown = 0, i; + + storeAppendPrintf(sentry, "Pool: %d\n\tClass: 2\n\n", pool + 1); + delayPoolStatsAg(sentry, rate, class2->aggregate); + if (rate->individual.restore_bps == -1) { + storeAppendPrintf(sentry, "\tIndividual:\n\t\tDisabled.\n\n"); + return; + } + storeAppendPrintf(sentry, "\tIndividual:\n"); + storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->individual.max_bytes); + storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->individual.restore_bps); + storeAppendPrintf(sentry, "\t\tCurrent: "); + for (i = 0;; i++) { + if (class2->individual_map[i] == 255) + break; + storeAppendPrintf(sentry, "%d:%d ", class2->individual_map[i], + class2->individual[i]); + shown = 1; + } + if (class2->individual_255_used) { + storeAppendPrintf(sentry, "%d:%d ", 255, class2->individual[255]); + shown = 1; + } + if (!shown) + storeAppendPrintf(sentry, "Not used yet."); + storeAppendPrintf(sentry, "\n\n"); +} + +static void +delayPoolStats3(StoreEntry * sentry, unsigned short pool) +{ + /* fully malloc()d struct in this case only */ + delaySpecSet *rate = Config.Delay.rates[pool]; + class3DelayPool *class3 = delay_data[pool].class3; + unsigned char shown = 0, i, j; + + storeAppendPrintf(sentry, "Pool: %d\n\tClass: 3\n\n", pool + 1); + delayPoolStatsAg(sentry, rate, class3->aggregate); + if (rate->network.restore_bps == -1) { + storeAppendPrintf(sentry, "\tNetwork:\n\t\tDisabled."); + } else { + storeAppendPrintf(sentry, "\tNetwork:\n"); + storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->network.max_bytes); + storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->network.restore_bps); + storeAppendPrintf(sentry, "\t\tCurrent: "); + for (i = 0;; i++) { + if (class3->network_map[i] == 255) + break; + storeAppendPrintf(sentry, "%d:%d ", class3->network_map[i], + class3->network[i]); + shown = 1; + } + if (class3->network_255_used) { + storeAppendPrintf(sentry, "%d:%d ", 255, class3->network[255]); + shown = 1; + } + if (!shown) + storeAppendPrintf(sentry, "Not used yet."); + } + storeAppendPrintf(sentry, "\n\n"); + shown = 0; + if (rate->individual.restore_bps == -1) { + storeAppendPrintf(sentry, "\tIndividual:\n\t\tDisabled.\n\n"); + return; + } + storeAppendPrintf(sentry, "\tIndividual:\n"); + storeAppendPrintf(sentry, "\t\tMax: %d\n", rate->individual.max_bytes); + storeAppendPrintf(sentry, "\t\tRate: %d\n", rate->individual.restore_bps); + for (i = 0;; i++) { + if (class3->network_map[i] == 255) + break; + storeAppendPrintf(sentry, "\t\tCurrent [Network %d]: ", class3->network_map[i]); + shown = 1; + for (j = 0;; j++) { + if (class3->individual_map[i][j] == 255) + break; + storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[i][j], + class3->individual[(i << 8) | j]); + } + if (class3->individual_255_used[i / 8] & (1 << (i % 8))) { + storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(i << 8) | 255]); + } + storeAppendPrintf(sentry, "\n"); + } + if (class3->network_255_used) { + storeAppendPrintf(sentry, "\t\tCurrent [Network 255]: "); + shown = 1; + for (j = 0;; j++) { + if (class3->individual_map[255][j] == 255) + break; + storeAppendPrintf(sentry, "%d:%d ", class3->individual_map[255][j], + class3->individual[(255 << 8) | j]); + } + if (class3->individual_255_used[255 / 8] & (1 << (255 % 8))) { + storeAppendPrintf(sentry, "%d:%d ", 255, class3->individual[(255 << 8) | 255]); + } + storeAppendPrintf(sentry, "\n"); + } + if (!shown) + storeAppendPrintf(sentry, "\t\tCurrent [All networks]: Not used yet.\n"); + storeAppendPrintf(sentry, "\n"); +} + +static void +delayPoolStats(StoreEntry * sentry) +{ + unsigned short i; + + storeAppendPrintf(sentry, "Delay pools configured: %d\n\n", Config.Delay.pools); + for (i = 0; i < Config.Delay.pools; i++) { + switch (Config.Delay.class[i]) { + case 0: + storeAppendPrintf(sentry, "Pool: %d\n\tClass: 0\n\n", i + 1); + storeAppendPrintf(sentry, "\tMisconfigured pool.\n\n"); + break; + case 1: + delayPoolStats1(sentry, i); + break; + case 2: + delayPoolStats2(sentry, i); + break; + case 3: + delayPoolStats3(sentry, i); + break; + default: + assert(0); + } + } } #endif Index: squid/src/disk.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/disk.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/disk.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/disk.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: disk.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: disk.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 6 Disk I/O Routines * AUTHOR: Harvest Derived @@ -75,6 +75,7 @@ mode |= SQUID_NONBLOCK; /* Open file */ + Opening_FD++; #if USE_ASYNC_IO if (callback != NULL) { aioOpen(path, mode, 0644, fileOpenComplete, ctrlp, tag); @@ -97,6 +98,7 @@ debug(6, 5) ("fileOpenComplete: FD %d, data %p, errcode %d\n", fd, data, errcode); Counter.syscalls.disk.opens++; + Opening_FD--; if (fd == -2 && errcode == -2) { /* Cancelled - clean up */ if (ctrlp->callback) (ctrlp->callback) (ctrlp->callback_data, fd, errcode); @@ -137,21 +139,31 @@ #else assert(fd >= 0); #endif - assert(F->open); + assert(F->flags.open); if ((callback = F->read_handler)) { F->read_handler = NULL; callback(-1, F->read_data); } if (F->flags.write_daemon) { +#if defined(_SQUID_MSWIN_) || defined(_SQUID_OS2_) + /* + * on some operating systems, you can not delete or rename + * open files, so we won't allow delayed close. + */ + while (!diskWriteIsComplete(fd)) + diskHandleWrite(fd, NULL); +#else F->flags.close_request = 1; debug(6, 2) ("file_close: FD %d, delaying close\n", fd); return; +#endif } /* * Assert there is no write callback. Otherwise we might be * leaking write state data by closing the descriptor */ assert(F->write_handler == NULL); + F->flags.closing = 1; #if USE_ASYNC_IO aioClose(fd); #else @@ -162,7 +174,9 @@ #endif debug(6, F->flags.close_request ? 2 : 5) ("file_close: FD %d, really closing\n", fd); +#if !USE_ASYNC_IO fd_close(fd); +#endif Counter.syscalls.disk.closes++; } @@ -275,7 +289,7 @@ debug(50, 0) ("KARMA: (%d, %d, %d FD %d)\n", q->buf_offset, q->len, len, fd); debug(50, 0) ("KARMA: desc %s, type %d, open %d, flags 0x%x\n", - F->desc, F->type, F->open, F->flags); + F->desc, F->type, F->flags.open, F->flags); debug(50, 0) ("KARMA: (%d, %d)\n", p->buf_offset, p->len); len = -1; errcode = EFAULT; @@ -399,7 +413,7 @@ dwrite_q *wq = NULL; fde *F = &fd_table[fd]; assert(fd >= 0); - assert(F->open); + assert(F->flags.open); /* if we got here. Caller is eligible to write. */ wq = xcalloc(1, sizeof(dwrite_q)); wq->file_offset = file_offset; @@ -465,7 +479,7 @@ * the state data. */ if (fd < 0) { - memFree(MEM_DREAD_CTRL, ctrl_dat); + memFree(ctrl_dat, MEM_DREAD_CTRL); return; } #if USE_ASYNC_IO @@ -503,7 +517,7 @@ errno = errcode; if (len == -2 && errcode == -2) { /* Read cancelled - cleanup */ cbdataUnlock(ctrl_dat->client_data); - memFree(MEM_DREAD_CTRL, ctrl_dat); + memFree(ctrl_dat, MEM_DREAD_CTRL); return; } fd_bytes(fd, len, FD_READ); @@ -527,7 +541,7 @@ F->flags.calling_io_handler = 0; #endif /* OPTIMISTIC_IO */ cbdataUnlock(ctrl_dat->client_data); - memFree(MEM_DREAD_CTRL, ctrl_dat); + memFree(ctrl_dat, MEM_DREAD_CTRL); } Index: squid/src/dns.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/dns.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/dns.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/dns.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: dns.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: dns.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 34 Dnsserver interface * AUTHOR: Harvest Derived Index: squid/src/dnsserver.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/dnsserver.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/dnsserver.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/dnsserver.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: dnsserver.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: dnsserver.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 0 DNS Resolver * AUTHOR: Harvest Derived @@ -158,6 +158,11 @@ 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) @@ -261,9 +266,6 @@ #if HAVE_RES_INIT res_init(); -#ifdef RES_DEFAULT - _res.options = RES_DEFAULT; -#endif #ifdef RES_DEFNAMES _res.options &= ~RES_DEFNAMES; #endif Index: squid/src/enums.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/enums.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/enums.h 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/enums.h 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: enums.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: enums.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ @@ -60,7 +60,7 @@ ERR_LIFETIME_EXP, ERR_READ_ERROR, ERR_WRITE_ERROR, - ERR_CLIENT_ABORT, + ERR_SHUTTING_DOWN, ERR_CONNECT_FAIL, ERR_INVALID_REQ, ERR_UNSUP_REQ, @@ -81,6 +81,9 @@ ERR_FTP_PUT_CREATED, /* !error,a note that the file was created */ ERR_FTP_PUT_MODIFIED, /* modified, !created */ ERR_FTP_PUT_ERROR, + ERR_FTP_NOT_FOUND, + ERR_FTP_FORBIDDEN, + ERR_FTP_UNAVAILABLE, ERR_ONLY_IF_CACHED_MISS, /* failure to satisfy only-if-cached request */ ERR_MAX } err_type; @@ -89,6 +92,7 @@ ACL_NONE, ACL_SRC_IP, ACL_DST_IP, + ACL_MY_IP, ACL_SRC_DOMAIN, ACL_DST_DOMAIN, ACL_SRC_DOM_REGEX, @@ -97,7 +101,9 @@ ACL_URLPATH_REGEX, ACL_URL_REGEX, ACL_URL_PORT, +#if USE_IDENT ACL_IDENT, +#endif ACL_PROTO, ACL_METHOD, ACL_BROWSER, @@ -105,7 +111,7 @@ ACL_SRC_ASN, ACL_DST_ASN, ACL_SRC_ARP, - ACL_SNMP_COMM, + ACL_SNMP_COMMUNITY, ACL_NETDB_SRC_RTT, ACL_ENUM_MAX } squid_acl; @@ -133,11 +139,6 @@ }; enum { - FD_CLOSE, - FD_OPEN -}; - -enum { FQDN_CACHED, FQDN_NEGATIVE_CACHED, FQDN_PENDING, /* waiting to be dispatched */ @@ -280,7 +281,6 @@ DEFAULT_PARENT, SINGLE_PARENT, FIRSTUP_PARENT, - NO_PARENT_DIRECT, FIRST_PARENT_MISS, CLOSEST_PARENT_MISS, CLOSEST_PARENT, @@ -290,7 +290,6 @@ ROUNDROBIN_PARENT, #if USE_CACHE_DIGESTS CACHE_DIGEST_HIT, - NO_CACHE_DIGEST_DIRECT, #endif #if USE_CARP CARP, @@ -335,14 +334,12 @@ enum { PING_NONE, PING_WAITING, - PING_TIMEOUT, PING_DONE }; enum { STORE_OK, - STORE_PENDING, - STORE_ABORTED + STORE_PENDING }; enum { @@ -446,14 +443,11 @@ ENTRY_CACHABLE, ENTRY_DISPATCHED, KEY_PRIVATE, -#ifndef PPNR_WIP - ENTRY_UNUSED_08, -#else ENTRY_FWD_HDR_WAIT, -#endif /* PPNR_WIP */ ENTRY_NEGCACHED, ENTRY_VALIDATED, - ENTRY_BAD_LENGTH + ENTRY_BAD_LENGTH, + ENTRY_ABORTED }; typedef enum { @@ -543,6 +537,9 @@ MEM_NET_DB_NAME, MEM_NET_DB_PEER, MEM_PEER, +#if USE_CACHE_DIGESTS + MEM_PEER_DIGEST, +#endif MEM_PINGERECHODATA, MEM_PINGERREPLYDATA, MEM_PS_STATE, Index: squid/src/errorpage.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/errorpage.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/errorpage.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/errorpage.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: errorpage.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: errorpage.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -52,6 +52,8 @@ /* local constant and vars */ +static const char *const proxy_auth_challenge_fmt = "Basic realm=\"%s\""; + /* * note: hard coded error messages are not appended with %S automagically * to give you more control on the format @@ -234,7 +236,7 @@ ErrorState * errorCon(err_type type, http_status status) { - ErrorState *err = xcalloc(1, sizeof(ErrorState)); + ErrorState *err = memAllocate(MEM_ERRORSTATE); err->page_id = type; /* has to be reset manually if needed */ err->type = type; err->http_status = status; @@ -260,22 +262,48 @@ { HttpReply *rep; MemObject *mem = entry->mem_obj; - /* - * Kostas sez PUT "success" replies might not be STORE_PENDING? - */ - /* assert(entry->store_status == STORE_PENDING); */ assert(mem != NULL); assert(mem->inmem_hi == 0); + if (entry->store_status != STORE_PENDING) { + /* + * If the entry is not STORE_PENDING, then no clients + * care about it, and we don't need to generate an + * error message + */ + assert(EBIT_TEST(entry->flags, ENTRY_ABORTED)); + assert(mem->nclients == 0); + errorStateFree(err); + return; + } + storeLockObject(entry); storeBuffer(entry); rep = errorBuildReply(err); + /* Add authentication header */ + switch (err->http_status) { + case HTTP_PROXY_AUTHENTICATION_REQUIRED: + /* Proxy authorisation needed */ + httpHeaderPutStrf(&rep->header, HDR_PROXY_AUTHENTICATE, + proxy_auth_challenge_fmt, Config.proxyAuthRealm); + break; + case HTTP_UNAUTHORIZED: + /* WWW Authorisation needed */ + httpHeaderPutStrf(&rep->header, HDR_WWW_AUTHENTICATE, + proxy_auth_challenge_fmt, Config.proxyAuthRealm); + break; + default: + /* Keep GCC happy */ + break; + } httpReplySwapOut(rep, entry); httpReplyDestroy(rep); mem->reply->sline.status = err->http_status; mem->reply->content_length = -1; + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); storeBufferFlush(entry); storeComplete(entry); storeNegativeCache(entry); storeReleaseRequest(entry); + storeUnlockObject(entry); errorStateFree(err); } @@ -312,7 +340,7 @@ err->request->err_type = err->type; /* moved in front of errorBuildBuf @?@ */ err->flags.flag_cbdata = 1; - cbdataAdd(err, MEM_NONE); + cbdataAdd(err, memFree, MEM_ERRORSTATE); rep = errorBuildReply(err); comm_write_mbuf(fd, httpReplyPack(rep), errorSendComplete, err); httpReplyDestroy(rep); @@ -353,7 +381,7 @@ if (err->flags.flag_cbdata) cbdataFree(err); else - safe_free(err); + memFree(err, MEM_ERRORSTATE); } #define CVT_BUF_SZ 512 @@ -518,7 +546,7 @@ p = "%"; break; default: - p = "%UNKNOWN%"; + memBufPrintf(&mb, "%%%c", token); break; } if (!p) Index: squid/src/event.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/event.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/event.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/event.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: event.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: event.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 41 Event Processing * AUTHOR: Henrik Nordstrom @@ -135,8 +135,10 @@ if (NULL != arg) { int valid = cbdataValid(arg); cbdataUnlock(arg); - if (!valid) + if (!valid) { + safe_free(event); return; + } } weight += event->weight; debug(41, 5) ("eventRun: Running '%s', id %d\n", event->name, event->id); @@ -175,6 +177,18 @@ } } +void +eventFreeMemory(void) +{ + struct ev_entry *event; + while ((event = tasks)) { + if (NULL != event->arg) + cbdataUnlock(event->arg); + xfree(event); + } + tasks = NULL; +} + int eventFind(EVH * func, void *arg) { Index: squid/src/fd.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/fd.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/fd.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/fd.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: fd.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: fd.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 51 Filedescriptor Functions * AUTHOR: Duane Wessels @@ -45,24 +45,30 @@ "Unknown" }; -static void fdUpdateBiggest(int fd, unsigned int status); +static void fdUpdateBiggest(int fd, int); static void -fdUpdateBiggest(int fd, unsigned int status) +fdUpdateBiggest(int fd, int opening) { if (fd < Biggest_FD) return; assert(fd < Squid_MaxFD); if (fd > Biggest_FD) { - if (status != FD_OPEN) - debug(51, 1) ("fdUpdateBiggest: status != FD_OPEN\n"); + /* + * assert that we are not closing a FD bigger than + * our known biggest FD + */ + assert(opening); Biggest_FD = fd; return; } /* if we are here, then fd == Biggest_FD */ - if (status != FD_CLOSE) - debug(51, 1) ("fdUpdateBiggest: status != FD_CLOSE\n"); - while (fd_table[Biggest_FD].open != FD_OPEN) + /* + * assert that we are closing the biggest FD; we can't be + * re-opening it + */ + assert(!opening); + while (!fd_table[Biggest_FD].flags.open) Biggest_FD--; } @@ -75,34 +81,48 @@ assert(F->write_handler == NULL); } debug(51, 3) ("fd_close FD %d %s\n", fd, F->desc); - fdUpdateBiggest(fd, F->open = FD_CLOSE); + F->flags.open = 0; + fdUpdateBiggest(fd, 0); Number_FD--; - if (F->type == FD_FILE) - open_disk_fd--; commUpdateReadBits(fd, NULL); commUpdateWriteBits(fd, NULL); memset(F, '\0', sizeof(fde)); F->timeout = 0; } +#if USE_ASYNC_IO +void +fd_was_closed(int fd) +{ + fde *F = &fd_table[fd]; + if (F->flags.closing) + fd_close(fd); +} +#endif + void fd_open(int fd, unsigned int type, const char *desc) { fde *F = &fd_table[fd]; assert(fd >= 0); - if (F->open != 0) { +#if USE_ASYNC_IO + if (F->flags.closing) { + /* Reuse of a closed FD before we have noticed it is closed */ + fd_close(fd); + } +#endif + if (F->flags.open) { debug(51, 1) ("WARNING: Closing open FD %4d\n", fd); fd_close(fd); } - assert(F->open == 0); + assert(!F->flags.open); debug(51, 3) ("fd_open FD %d %s\n", fd, desc); F->type = type; - fdUpdateBiggest(fd, F->open = FD_OPEN); + F->flags.open = 1; + fdUpdateBiggest(fd, 1); if (desc) xstrncpy(F->desc, desc, FD_DESC_SZ); Number_FD++; - if (type == FD_FILE) - open_disk_fd++; } void @@ -138,12 +158,14 @@ fde *F; for (i = 0; i < Squid_MaxFD; i++) { F = &fd_table[i]; - if (!F->open) + if (!F->flags.open) continue; if (i == fileno(debug_log)) continue; - debug(51, 1) ("Open FD %s %4d %s\n", - F->type == FD_READ ? "reading" : "writing", + debug(51, 1) ("Open FD %-10s %4d %s\n", + F->bytes_read && F->bytes_written ? "READ/WRITE" : + F->bytes_read ? "READING" : + F->bytes_written ? "WRITING" : null_string, i, F->desc); } } @@ -151,7 +173,7 @@ int fdNFree(void) { - return Squid_MaxFD - Number_FD; + return Squid_MaxFD - Number_FD - Opening_FD; } /* Called when we runs out of file descriptors */ Index: squid/src/forward.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/forward.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/forward.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/forward.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: forward.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: forward.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -36,46 +36,56 @@ #include "squid.h" -static void fwdStartComplete(peer * p, void *data); -static void fwdStartFail(peer * p, void *data); +static PSC fwdStartComplete; static void fwdDispatch(FwdState *); -static void fwdConnectStart(FwdState * fwdState); +static void fwdConnectStart(void *); /* should be same as EVH */ static void fwdStateFree(FwdState * fwdState); static PF fwdConnectTimeout; static PF fwdServerClosed; static CNCB fwdConnectDone; static int fwdCheckRetry(FwdState * fwdState); +static int fwdReforward(FwdState *); +static void fwdStartFail(FwdState *); +static void fwdLogReplyStatus(int tries, http_status status); +static OBJH fwdStats; +static STABH fwdAbort; + +#define MAX_FWD_STATS_IDX 9 +static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1]; + +static void +fwdServerFree(FwdServer * fs) +{ + if (fs->peer) + cbdataUnlock(fs->peer); + memFree(fs, MEM_FWD_SERVER); +} static void fwdStateFree(FwdState * fwdState) { - FwdServer *s; - FwdServer *n = fwdState->servers; StoreEntry *e = fwdState->entry; - ErrorState *err; int sfd; - static int loop_detect = 0; - assert(loop_detect++ == 0); + debug(17, 3) ("fwdStateFree: %p\n", fwdState); assert(e->mem_obj); if (e->store_status == STORE_PENDING) { if (e->mem_obj->inmem_hi == 0) { - assert(fwdState->fail.err_code); - err = errorCon(fwdState->fail.err_code, fwdState->fail.http_code); - err->request = requestLink(fwdState->request); - err->xerrno = fwdState->fail.xerrno; - errorAppendEntry(e, err); + assert(fwdState->err); + errorAppendEntry(e, fwdState->err); + fwdState->err = NULL; } else { - storeAbort(e, 0); + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); + storeComplete(e); + storeReleaseRequest(e); } } - while ((s = n)) { - n = s->next; - xfree(s->host); - memFree(MEM_FWD_SERVER, s); - } - fwdState->servers = NULL; + if (storePendingNClients(e) > 0) + assert(!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)); + fwdServersFree(&fwdState->servers); requestUnlink(fwdState->request); fwdState->request = NULL; + if (fwdState->err) + errorStateFree(fwdState->err); storeUnregisterAbort(e); storeUnlockObject(e); fwdState->entry = NULL; @@ -87,7 +97,6 @@ comm_close(sfd); } cbdataFree(fwdState); - loop_detect--; } static int @@ -101,6 +110,8 @@ return 0; if (squid_curtime - fwdState->start > 120) return 0; + if (fwdState->flags.dont_retry) + return 0; if (pumpMethod(fwdState->request->method)) if (0 == pumpRestart(fwdState->request)) return 0; @@ -111,14 +122,24 @@ fwdServerClosed(int fd, void *data) { FwdState *fwdState = data; - debug(17, 3) ("fwdServerClosed: FD %d %s\n", fd, storeUrl(fwdState->entry)); + debug(17, 2) ("fwdServerClosed: FD %d %s\n", fd, storeUrl(fwdState->entry)); assert(fwdState->server_fd == fd); fwdState->server_fd = -1; if (fwdCheckRetry(fwdState)) { debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n", fwdState->n_tries, (int) (squid_curtime - fwdState->start)); - fwdConnectStart(fwdState); + if (fwdState->servers->next) { + /* cycle */ + FwdServer *fs = fwdState->servers; + FwdServer **T; + fwdState->servers = fs->next; + for (T = &fwdState->servers; *T; T = &(*T)->next); + *T = fs; + fs->next = NULL; + } + /* use eventAdd to break potential call sequence loops */ + eventAdd("fwdConnectStart", fwdConnectStart, fwdState, 0.0, 1); } else { fwdStateFree(fwdState); } @@ -128,32 +149,45 @@ fwdConnectDone(int server_fd, int status, void *data) { FwdState *fwdState = data; + static FwdState *current = NULL; + FwdServer *fs = fwdState->servers; ErrorState *err; + request_t *request = fwdState->request; + assert(current != fwdState); + current = fwdState; assert(fwdState->server_fd == server_fd); if (status == COMM_ERR_DNS) { + fwdState->flags.dont_retry = 1; debug(17, 4) ("fwdConnectDone: Unknown host: %s\n", - fwdState->request->host); + request->host); err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE); err->dnsserver_msg = xstrdup(dns_error_message); - err->request = requestLink(fwdState->request); - errorAppendEntry(fwdState->entry, err); + err->request = requestLink(request); + fwdFail(fwdState, err); comm_close(server_fd); } else if (status != COMM_OK) { + assert(fs); err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); err->xerrno = errno; - err->host = xstrdup(fwdState->servers->host); - err->port = fwdState->servers->port; - err->request = requestLink(fwdState->request); - errorAppendEntry(fwdState->entry, err); - assert(fwdState->servers); - if (fwdState->servers->peer) - peerCheckConnectStart(fwdState->servers->peer); + if (fs->peer) { + err->host = xstrdup(fs->peer->host); + err->port = fs->peer->http_port; + } else { + err->host = xstrdup(request->host); + err->port = request->port; + } + err->request = requestLink(request); + fwdFail(fwdState, err); + if (fs->peer) + peerCheckConnectStart(fs->peer); comm_close(server_fd); } else { + debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(fwdState->entry)); fd_note(server_fd, storeUrl(fwdState->entry)); fd_table[server_fd].uses++; fwdDispatch(fwdState); } + current = NULL; } static void @@ -162,31 +196,42 @@ FwdState *fwdState = data; StoreEntry *entry = fwdState->entry; ErrorState *err; - debug(17, 3) ("fwdConnectTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); + debug(17, 2) ("fwdConnectTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); assert(fd == fwdState->server_fd); if (entry->mem_obj->inmem_hi == 0) { - err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT); + err = errorCon(ERR_CONNECT_FAIL, HTTP_GATEWAY_TIMEOUT); err->request = requestLink(fwdState->request); - errorAppendEntry(entry, err); - } else { - storeAbort(entry, 0); + err->xerrno = ETIMEDOUT; + fwdFail(fwdState, err); } comm_close(fd); } static void -fwdConnectStart(FwdState * fwdState) +fwdConnectStart(void *data) { + FwdState *fwdState = data; const char *url = storeUrl(fwdState->entry); int fd; ErrorState *err; - FwdServer *srv = fwdState->servers; - assert(srv); + FwdServer *fs = fwdState->servers; + const char *host; + unsigned short port; + assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); - if ((fd = pconnPop(srv->host, srv->port)) >= 0) { + if (fs->peer) { + host = fs->peer->host; + port = fs->peer->http_port; + } else { + host = fwdState->request->host; + port = fwdState->request->port; + } + hierarchyNote(&fwdState->request->hier, fs->code, host); + if ((fd = pconnPop(host, port)) >= 0) { debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd); fwdState->server_fd = fd; + fwdState->n_tries++; comm_add_close_handler(fd, fwdServerClosed, fwdState); fwdConnectDone(fd, COMM_OK, fwdState); return; @@ -202,7 +247,7 @@ err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(fwdState->request); - errorAppendEntry(fwdState->entry, err); + fwdFail(fwdState, err); fwdStateFree(fwdState); return; } @@ -213,47 +258,31 @@ Config.Timeout.connect, fwdConnectTimeout, fwdState); - commConnectStart(fd, - srv->host, - srv->port, - fwdConnectDone, - fwdState); + commConnectStart(fd, host, port, fwdConnectDone, fwdState); } static void -fwdStartComplete(peer * p, void *data) +fwdStartComplete(FwdServer * servers, void *data) { FwdState *fwdState = data; - FwdServer *s; - s = memAllocate(MEM_FWD_SERVER); - if (NULL != p) { - s->host = xstrdup(p->host); - s->port = p->http_port; - s->peer = p; - } else if (fwdState->request->protocol == PROTO_WAIS) { - if (!Config.Wais.relayHost) { - fwdStartFail(NULL, fwdState); - return; - } else { - s->host = xstrdup(Config.Wais.relayHost); - s->port = Config.Wais.relayPort; - } + debug(17, 3) ("fwdStartComplete: %s\n", storeUrl(fwdState->entry)); + if (servers != NULL) { + fwdState->servers = servers; + fwdConnectStart(fwdState); } else { - s->host = xstrdup(fwdState->request->host); - s->port = fwdState->request->port; + fwdStartFail(fwdState); } - fwdState->servers = s; - fwdConnectStart(fwdState); } static void -fwdStartFail(peer * peernotused, void *data) +fwdStartFail(FwdState * fwdState) { - FwdState *fwdState = data; ErrorState *err; + debug(17, 3) ("fwdStartFail: %s\n", storeUrl(fwdState->entry)); err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); err->request = requestLink(fwdState->request); - errorAppendEntry(fwdState->entry, err); + err->xerrno = errno; + fwdFail(fwdState, err); fwdStateFree(fwdState); } @@ -263,7 +292,7 @@ peer *p; request_t *request = fwdState->request; StoreEntry *entry = fwdState->entry; - debug(17, 5) ("fwdDispatch: FD %d: Fetching '%s %s'\n", + debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n", fwdState->client_fd, RequestMethodStr[request->method], storeUrl(entry)); @@ -280,20 +309,20 @@ assert(fwdState->server_fd > -1); if (fwdState->servers && (p = fwdState->servers->peer)) { p->stats.fetches++; - httpStart(fwdState, fwdState->server_fd); + httpStart(fwdState); } else { switch (request->protocol) { case PROTO_HTTP: - httpStart(fwdState, fwdState->server_fd); + httpStart(fwdState); break; case PROTO_GOPHER: - gopherStart(entry, fwdState->server_fd); + gopherStart(fwdState); break; case PROTO_FTP: - ftpStart(request, entry, fwdState->server_fd); + ftpStart(fwdState); break; case PROTO_WAIS: - waisStart(request, entry, fwdState->server_fd); + waisStart(fwdState); break; case PROTO_CACHEOBJ: case PROTO_INTERNAL: @@ -301,44 +330,86 @@ fatal_dump("Should never get here"); break; case PROTO_WHOIS: - whoisStart(fwdState, fwdState->server_fd); + whoisStart(fwdState); break; default: debug(17, 1) ("fwdDispatch: Cannot retrieve '%s'\n", storeUrl(entry)); - fwdFail(fwdState, ERR_UNSUP_REQ, HTTP_BAD_REQUEST, -1); + fwdFail(fwdState, errorCon(ERR_UNSUP_REQ, HTTP_BAD_REQUEST)); comm_close(fwdState->server_fd); break; } } } +static int +fwdReforward(FwdState * fwdState) +{ + StoreEntry *e = fwdState->entry; + FwdServer *fs = fwdState->servers; + http_status s; + assert(e->store_status == STORE_PENDING); + assert(e->mem_obj); + debug(17, 3) ("fwdReforward: %s?\n", storeUrl(e)); + if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { + debug(17, 3) ("fwdReforward: No, ENTRY_FWD_HDR_WAIT isn't set\n"); + return 0; + } + if (fwdState->n_tries > 9) + return 0; + if (pumpMethod(fwdState->request->method)) + if (0 == pumpRestart(fwdState->request)) + return 0; + assert(fs); + fwdState->servers = fs->next; + fwdServerFree(fs); + if (fwdState->servers == NULL) { + debug(17, 3) ("fwdReforward: No forward-servers left\n"); + return 0; + } + s = e->mem_obj->reply->sline.status; + debug(17, 3) ("fwdReforward: status %d\n", (int) s); + return fwdReforwardableStatus(s); +} + /* PUBLIC FUNCTIONS */ void -fwdStart(int fd, StoreEntry * e, request_t * r, struct in_addr peer_addr) +fwdServersFree(FwdServer ** FS) +{ + FwdServer *fs; + while ((fs = *FS)) { + *FS = fs->next; + fwdServerFree(fs); + } +} + +void +fwdStart(int fd, StoreEntry * e, request_t * r, struct in_addr client_addr, + struct in_addr my_addr) { FwdState *fwdState; aclCheck_t ch; int answer; ErrorState *err; /* - * peer_addr == no_addr indicates this is an "internal" request + * client_addr == no_addr indicates this is an "internal" request * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ - if (peer_addr.s_addr != no_addr.s_addr) { + if (client_addr.s_addr != no_addr.s_addr) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ memset(&ch, '\0', sizeof(aclCheck_t)); - ch.src_addr = peer_addr; + ch.src_addr = client_addr; + ch.my_addr = my_addr; ch.request = r; answer = aclCheckFast(Config.accessList.miss, &ch); if (answer == 0) { err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN); err->request = requestLink(r); - err->src_addr = peer_addr; + err->src_addr = client_addr; errorAppendEntry(e, err); return; } @@ -346,6 +417,13 @@ debug(17, 3) ("fwdStart: '%s'\n", storeUrl(e)); e->mem_obj->request = requestLink(r); e->mem_obj->fd = fd; + if (shutting_down) { + /* more yuck */ + err = errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE); + err->request = requestLink(r); + errorAppendEntry(e, err); + return; + } switch (r->protocol) { /* * Note, don't create fwdState for these requests @@ -363,46 +441,51 @@ break; } fwdState = memAllocate(MEM_FWD_STATE); - cbdataAdd(fwdState, MEM_FWD_STATE); + cbdataAdd(fwdState, memFree, MEM_FWD_STATE); fwdState->entry = e; fwdState->client_fd = fd; fwdState->server_fd = -1; fwdState->request = requestLink(r); fwdState->start = squid_curtime; storeLockObject(e); + EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT); storeRegisterAbort(e, fwdAbort, fwdState); - peerSelect(r, e, fwdStartComplete, fwdStartFail, fwdState); + peerSelect(r, e, fwdStartComplete, fwdState); } int -fwdCheckDeferRead(int fdnotused, void *data) +fwdCheckDeferRead(int fd, void *data) { StoreEntry *e = data; MemObject *mem = e->mem_obj; if (mem == NULL) return 0; #if DELAY_POOLS - if (delayMostBytesWanted(mem, 1) == 0) + if (fd < 0) + (void) 0; + else if (delayIsNoDelay(fd)) + (void) 0; + else if (delayMostBytesWanted(mem, 1) == 0) return 1; #endif + if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) + return 0; if (mem->inmem_hi - storeLowestMemReaderOffset(e) < READ_AHEAD_GAP) return 0; return 1; } void -fwdFail(FwdState * fwdState, int err_code, http_status http_code, int xerrno) +fwdFail(FwdState * fwdState, ErrorState * errorState) { -#ifdef PPNR_WIP assert(EBIT_TEST(fwdState->entry->flags, ENTRY_FWD_HDR_WAIT)); -#endif /* PPNR_WIP */ debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n", - err_type_str[err_code], - httpStatusString(http_code), + err_type_str[errorState->type], + httpStatusString(errorState->http_status), storeUrl(fwdState->entry)); - fwdState->fail.err_code = err_code; - fwdState->fail.http_code = http_code; - fwdState->fail.xerrno = xerrno; + if (fwdState->err) + errorStateFree(fwdState->err); + fwdState->err = errorState; } /* @@ -412,7 +495,7 @@ fwdAbort(void *data) { FwdState *fwdState = data; - debug(17, 3) ("fwdAbort: %s\n", storeUrl(fwdState->entry)); + debug(17, 2) ("fwdAbort: %s\n", storeUrl(fwdState->entry)); fwdStateFree(fwdState); } @@ -424,7 +507,101 @@ { debug(17, 3) ("fwdUnregister: %s\n", storeUrl(fwdState->entry)); assert(fd = fwdState->server_fd); + assert(fd > -1); comm_remove_close_handler(fd, fwdServerClosed, fwdState); fwdState->server_fd = -1; - fwdStateFree(fwdState); +} + +/* + * server-side modules call fwdComplete() when they are done + * downloading an object. Then, we either 1) re-forward the + * request somewhere else if needed, or 2) call storeComplete() + * to finish it off + */ +void +fwdComplete(FwdState * fwdState) +{ + StoreEntry *e = fwdState->entry; + assert(e->store_status == STORE_PENDING); + debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e), + e->mem_obj->reply->sline.status); + fwdLogReplyStatus(fwdState->n_tries, e->mem_obj->reply->sline.status); + if (fwdReforward(fwdState)) { + debug(17, 3) ("fwdComplete: re-forwarding %d %s\n", + e->mem_obj->reply->sline.status, + storeUrl(e)); + if (fwdState->server_fd > -1) + fwdUnregister(fwdState->server_fd, fwdState); + storeEntryReset(e); + fwdStartComplete(fwdState->servers, fwdState); + } else { + debug(17, 3) ("fwdComplete: not re-forwarding status %d\n", + e->mem_obj->reply->sline.status); + EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT); + storeComplete(e); + /* + * If fwdState isn't associated with a server FD, it + * won't get freed unless we do it here. + */ + if (fwdState->server_fd < 0) + fwdStateFree(fwdState); + } +} + +void +fwdInit(void) +{ + cachemgrRegister("forward", + "Request Forwarding Statistics", + fwdStats, 0, 1); +} + +static void +fwdLogReplyStatus(int tries, http_status status) +{ + if (status > HTTP_INVALID_HEADER) + return; + assert(tries); + tries--; + if (tries > MAX_FWD_STATS_IDX) + tries = MAX_FWD_STATS_IDX; + FwdReplyCodes[tries][status]++; +} + +static void +fwdStats(StoreEntry * s) +{ + int i; + int j; + storeAppendPrintf(s, "Status"); + for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { + storeAppendPrintf(s, "\ttry#%d", j + 1); + } + storeAppendPrintf(s, "\n"); + for (i = 0; i <= (int) HTTP_INVALID_HEADER; i++) { + if (FwdReplyCodes[0][i] == 0) + continue; + storeAppendPrintf(s, "%3d", i); + for (j = 0; j <= MAX_FWD_STATS_IDX; j++) { + storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]); + } + storeAppendPrintf(s, "\n"); + } +} + +int +fwdReforwardableStatus(http_status s) +{ + switch (s) { + case HTTP_FORBIDDEN: + case HTTP_INTERNAL_SERVER_ERROR: + case HTTP_NOT_IMPLEMENTED: + case HTTP_BAD_GATEWAY: + case HTTP_SERVICE_UNAVAILABLE: + case HTTP_GATEWAY_TIMEOUT: + return 1; + default: + return 0; + } + /* NOTREACHED */ } Index: squid/src/fqdncache.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/fqdncache.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/fqdncache.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/fqdncache.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,7 +1,7 @@ /* - * $Id: fqdncache.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: fqdncache.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 35 FQDN Cache * AUTHOR: Harvest Derived @@ -98,7 +98,7 @@ dlinkDelete(&f->lru, &lru_list); safe_free(f->name); safe_free(f->error_message); - memFree(MEM_FQDNCACHE_ENTRY, f); + memFree(f, MEM_FQDNCACHE_ENTRY); } /* return match for given name */ @@ -151,7 +151,7 @@ fqdncache_release(f); removed++; } - debug(35, 3) ("fqdncache_purgelru: removed %d entries\n", removed); + debug(35, 9) ("fqdncache_purgelru: removed %d entries\n", removed); } /* create blank fqdncache_entry */ @@ -213,7 +213,7 @@ p->handler((f->status == FQDN_CACHED) ? f->names[0] : NULL, p->handlerData); } - memFree(MEM_FQDNCACHE_PENDING, p); + memFree(p, MEM_FQDNCACHE_PENDING); } f->pending_head = NULL; /* nuke list */ debug(35, 10) ("fqdncache_call_pending: Called %d handlers.\n", nhandler); @@ -229,7 +229,7 @@ static fqdncache_entry f; int ttl; xstrncpy(buf, inbuf, DNS_INBUF_SZ); - debug(35, 5) ("fqdncacheParse: parsing:\n%s", buf); + debug(35, 5) ("fqdncacheParse: parsing: {%s}\n", buf); memset(&f, '\0', sizeof(f)); f.expires = squid_curtime; f.status = FQDN_NEGATIVE_CACHED; @@ -366,7 +366,7 @@ /* for HIT, PENDING, DISPATCHED we've returned. For MISS we submit */ c = xcalloc(1, sizeof(*c)); c->data = f; - cbdataAdd(c, MEM_NONE); + cbdataAdd(c, cbdataXfree, 0); f->status = FQDN_DISPATCHED; fqdncacheLockEntry(f); /* lock while FQDN_DISPATCHED */ dnsSubmit(f->name, fqdncacheHandleReply, c); @@ -554,13 +554,13 @@ int k; while ((p = f->pending_head)) { f->pending_head = p->next; - memFree(MEM_FQDNCACHE_PENDING, p); + memFree(p, MEM_FQDNCACHE_PENDING); } for (k = 0; k < (int) f->name_count; k++) safe_free(f->names[k]); safe_free(f->name); safe_free(f->error_message); - memFree(MEM_FQDNCACHE_ENTRY, f); + memFree(f, MEM_FQDNCACHE_ENTRY); } void @@ -658,12 +658,6 @@ case FQDN_GHBN: *(Answer->val.integer) = FqdncacheStats.ghba_calls; break; -#if DELETE_ME - case FQDN_LENG: - *(Answer->val.integer) = queue_length; - Answer->type = SMI_GAUGE32; - break; -#endif default: *ErrP = SNMP_ERR_NOSUCHNAME; snmp_var_free(Answer); Index: squid/src/ftp.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ftp.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- squid/src/ftp.c 26 Jan 2000 03:21:47 -0000 1.1.1.1 +++ squid/src/ftp.c 26 Jan 2000 03:23:10 -0000 1.1.1.2 @@ -1,6 +1,6 @@ /* - * $Id: ftp.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $ + * $Id: ftp.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -60,24 +60,24 @@ } ftp_state_t; struct _ftp_flags { - int isdir:1; - int pasv_supported:1; - int skip_whitespace:1; - int rest_supported:1; - int pasv_only:1; - int authenticated:1; - int http_header_sent:1; - int tried_nlst:1; - int use_base:1; - int root_dir:1; - int no_dotdot:1; - int html_header_sent:1; - int binary:1; - int try_slash_hack:1; - int put:1; - int put_mkdir:1; - int listformat_unknown:1; - int datachannel_hack:1; + unsigned int isdir:1; + unsigned int pasv_supported:1; + unsigned int skip_whitespace:1; + unsigned int rest_supported:1; + unsigned int pasv_only:1; + unsigned int authenticated:1; + unsigned int http_header_sent:1; + unsigned int tried_nlst:1; + unsigned int use_base:1; + unsigned int root_dir:1; + unsigned int no_dotdot:1; + unsigned int html_header_sent:1; + unsigned int binary:1; + unsigned int try_slash_hack:1; + unsigned int put:1; + unsigned int put_mkdir:1; + unsigned int listformat_unknown:1; + unsigned int datachannel_hack:1; }; typedef struct _Ftpdata { @@ -96,6 +96,7 @@ wordlist *pathcomps; char *filepath; int restart_offset; + int restarted_offset; int rest_att; char *proxy_host; size_t list_width; @@ -125,6 +126,7 @@ u_short port; } data; struct _ftp_flags flags; + FwdState *fwd; } FtpStateData; typedef struct { @@ -145,11 +147,13 @@ static CNCB ftpPasvCallback; static PF ftpDataRead; static PF ftpStateFree; +static PF ftpPumpClosedData; static PF ftpTimeout; static PF ftpReadControlReply; static CWCB ftpWriteCommandCallback; static void ftpLoginParser(const char *, FtpStateData *, int escaped); static wordlist *ftpParseControlReply(char *, size_t, int *, int *); +static int ftpRestartable(FtpStateData * ftpState); static void ftpAppendSuccessHeader(FtpStateData * ftpState); static void ftpAuthRequired(HttpReply * reply, request_t * request, const char *realm); static void ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState); @@ -260,14 +264,24 @@ storeUnregisterAbort(ftpState->entry); storeUnlockObject(ftpState->entry); if (ftpState->reply_hdr) { - memFree(MEM_8K_BUF, ftpState->reply_hdr); + memFree(ftpState->reply_hdr, MEM_8K_BUF); + /* this seems unnecessary, but people report SEGV's + * when freeing memory in this function */ ftpState->reply_hdr = NULL; } requestUnlink(ftpState->request); - if (ftpState->ctrl.buf) + if (ftpState->ctrl.buf) { ftpState->ctrl.freefunc(ftpState->ctrl.buf); - if (ftpState->data.buf) + /* this seems unnecessary, but people report SEGV's + * when freeing memory in this function */ + ftpState->ctrl.buf = NULL; + } + if (ftpState->data.buf) { ftpState->data.freefunc(ftpState->data.buf); + /* this seems unnecessary, but people report SEGV's + * when freeing memory in this function */ + ftpState->data.buf = NULL; + } if (ftpState->pathcomps) wordlistDestroy(&ftpState->pathcomps); if (ftpState->ctrl.message) @@ -315,15 +329,11 @@ { FtpStateData *ftpState = data; StoreEntry *entry = ftpState->entry; - ErrorState *err; debug(9, 4) ("ftpTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); if (entry->store_status == STORE_PENDING) { if (entry->mem_obj->inmem_hi == 0) { - err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT); - err->request = requestLink(ftpState->request); - errorAppendEntry(entry, err); - } else { - storeAbort(entry, 0); + fwdFail(ftpState->fwd, + errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); } } if (ftpState->data.fd > -1) { @@ -340,6 +350,7 @@ StoreEntry *e = ftpState->entry; wordlist *w; char *dirup; + int i, j, k; storeBuffer(e); storeAppendPrintf(e, "\n", version_string); @@ -361,7 +372,32 @@ wordlistDestroy(&ftpState->cwd_message); } storeAppendPrintf(e, "

\n"); - storeAppendPrintf(e, "FTP Directory: %s\n", ftpState->title_url); + storeAppendPrintf(e, "FTP Directory: "); + /* "ftp://" == 6 characters */ + assert(strlen(ftpState->title_url) >= 6); + for (i = 6, j = 0; ftpState->title_url[i]; j = i) { + storeAppendPrintf(e, "title_url[i], "/"); + if (ftpState->title_url[i] == '/') + i++; + for (k = 0; k < i; k++) + storeAppendPrintf(e, "%c", ftpState->title_url[k]); + storeAppendPrintf(e, "\">"); + for (k = j; k < i - 1; k++) + storeAppendPrintf(e, "%c", ftpState->title_url[k]); + if (ftpState->title_url[k] != '/') + storeAppendPrintf(e, "%c", ftpState->title_url[k++]); + storeAppendPrintf(e, ""); + if (k < i) + storeAppendPrintf(e, "%c", ftpState->title_url[k++]); + if (i == j) { + /* Error guard, or "assert" */ + storeAppendPrintf(e, "ERROR: Failed to parse URL: %s\n", + ftpState->title_url); + debug(9, 0) ("Failed to parse URL: %s\n", ftpState->title_url); + break; + } + } storeAppendPrintf(e, "

\n"); storeAppendPrintf(e, "
\n");
     dirup = ftpHtmlifyListEntry("", ftpState);
@@ -456,7 +492,7 @@
 	tokens[n_tokens++] = xstrdup(t);
     xfree(xbuf);
     /* locate the Month field */
-    for (i = 3; i < n_tokens - 3; i++) {
+    for (i = 3; i < n_tokens - 2; i++) {
 	if (!is_month(tokens[i]))	/* Month */
 	    continue;
 	if (!sscanf(tokens[i - 1], SCAN_FTP1, sbuf))	/* Size */
@@ -506,7 +542,23 @@
 	}
 	snprintf(sbuf, 128, "%s %s", tokens[0], tokens[1]);
 	p->date = xstrdup(sbuf);
-	p->name = xstrdup(tokens[3]);
+	if (p->type == 'd') {
+	    /* Directory.. name begins with first printable after  */
+	    ct = strstr(buf, tokens[2]);
+	    ct += strlen(tokens[2]);
+	    while (xisspace(*ct))
+		ct++;
+	    if (!*ct)
+		ct = NULL;
+	} else {
+	    /* A file. Name begins after size, with a space in between */
+	    snprintf(sbuf, 128, " %s %s", tokens[2], tokens[3]);
+	    ct = strstr(buf, sbuf);
+	    if (ct) {
+		ct += strlen(tokens[2]) + 2;
+	    }
+	}
+	p->name = xstrdup(ct ? ct : tokens[3]);
     }
     /* Try EPLF format; carson@lehman.com */
     if (p->name == NULL && buf[0] == '+') {
@@ -625,8 +677,8 @@
     if ((parts = ftpListParseParts(line, ftpState->flags)) == NULL) {
 	char *p;
 	snprintf(html, 8192, "%s\n", line);
-	for (p = line; *p && isspace(*p); p++);
-	if (*p && !isspace(*p))
+	for (p = line; *p && xisspace(*p); p++);
+	if (*p && !xisspace(*p))
 	    ftpState->flags.listformat_unknown = 1;
 	return html;
     }
@@ -770,7 +822,7 @@
 	xstrncpy(ftpState->data.buf, line, ftpState->data.size);
 	ftpState->data.offset = strlen(ftpState->data.buf);
     }
-    memFree(MEM_4K_BUF, line);
+    memFree(line, MEM_4K_BUF);
     xfree(sbuf);
 }
 
@@ -778,12 +830,20 @@
 ftpReadComplete(FtpStateData * ftpState)
 {
     debug(9, 3) ("ftpReadComplete\n");
+    if (ftpState->data.fd > -1) {
+	/*
+	 * close data socket so it does not occupy resources while
+	 * we wait
+	 */
+	comm_close(ftpState->data.fd);
+	ftpState->data.fd = -1;
+    }
     /* Connection closed; retrieval done. */
     if (ftpState->flags.html_header_sent)
 	ftpListingFinish(ftpState);
     if (!ftpState->flags.put) {
 	storeTimestampsSet(ftpState->entry);
-	storeComplete(ftpState->entry);
+	fwdComplete(ftpState->fwd);
     }
     /* expect the "transfer complete" message on the control socket */
     ftpScheduleReadControlReply(ftpState, 1);
@@ -803,6 +863,10 @@
     delay_id delay_id = delayMostBytesAllowed(mem);
 #endif
     assert(fd == ftpState->data.fd);
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	comm_close(ftpState->ctrl.fd);
+	return;
+    }
     errno = 0;
     read_sz = ftpState->data.size - ftpState->data.offset;
 #if DELAY_POOLS
@@ -840,7 +904,6 @@
 		Config.Timeout.read);
 	} else {
 	    assert(mem->inmem_hi > 0);
-	    storeAbort(entry, 0);
 	    ftpDataTransferDone(ftpState);
 	}
     } else if (len == 0) {
@@ -953,16 +1016,19 @@
 }
 
 void
-ftpStart(request_t * request, StoreEntry * entry, int fd)
+ftpStart(FwdState * fwd)
 {
+    request_t *request = fwd->request;
+    StoreEntry *entry = fwd->entry;
+    int fd = fwd->server_fd;
     LOCAL_ARRAY(char, realm, 8192);
     const char *url = storeUrl(entry);
     FtpStateData *ftpState = xcalloc(1, sizeof(FtpStateData));
     HttpReply *reply;
     StoreEntry *pe = NULL;
     const cache_key *key = NULL;
-    cbdataAdd(ftpState, MEM_NONE);
-    debug(9, 3) ("FtpStart: '%s'\n", url);
+    cbdataAdd(ftpState, cbdataXfree, 0);
+    debug(9, 3) ("ftpStart: '%s'\n", url);
     Counter.server.all.requests++;
     Counter.server.ftp.requests++;
     storeLockObject(entry);
@@ -971,8 +1037,11 @@
     ftpState->ctrl.fd = fd;
     ftpState->data.fd = -1;
     ftpState->size = -1;
+    ftpState->mdtm = -1;
     ftpState->flags.pasv_supported = 1;
     ftpState->flags.rest_supported = 1;
+    ftpState->fwd = fwd;
+    comm_add_close_handler(fd, ftpStateFree, ftpState);
     if (ftpState->request->method == METHOD_PUT)
 	ftpState->flags.put = 1;
     if (!ftpCheckAuth(ftpState, &request->header)) {
@@ -993,17 +1062,17 @@
 	/* create appropriate reply */
 	ftpAuthRequired(reply, request, realm);
 	httpReplySwapOut(reply, entry);
-	storeComplete(entry);
-	ftpStateFree(-1, ftpState);
+	fwdComplete(ftpState->fwd);
+	comm_close(fd);
 	return;
     }
     ftpCheckUrlpath(ftpState);
     ftpBuildTitleUrl(ftpState);
-    debug(9, 5) ("FtpStart: host=%s, path=%s, user=%s, passwd=%s\n",
+    debug(9, 5) ("ftpStart: host=%s, path=%s, user=%s, passwd=%s\n",
 	ftpState->request->host, strBuf(ftpState->request->urlpath),
 	ftpState->user, ftpState->password);
-    comm_add_close_handler(fd, ftpStateFree, ftpState);
     ftpState->state = BEGIN;
+    ftpState->ctrl.last_command = xstrdup("Connect to server");
     ftpState->ctrl.buf = memAllocate(MEM_4K_BUF);
     ftpState->ctrl.freefunc = memFree4K;
     ftpState->ctrl.size = 4096;
@@ -1054,8 +1123,6 @@
 	    err->request = requestLink(ftpState->request);
 	    errorAppendEntry(entry, err);
 	}
-	if (entry->store_status == STORE_PENDING)
-	    storeAbort(entry, 0);
 	comm_close(ftpState->ctrl.fd);
     }
 }
@@ -1171,8 +1238,6 @@
 		err->request = requestLink(ftpState->request);
 		errorAppendEntry(entry, err);
 	    }
-	    if (entry->store_status == STORE_PENDING)
-		storeAbort(entry, 0);
 	    comm_close(ftpState->ctrl.fd);
 	}
 	return;
@@ -1201,7 +1266,7 @@
 ftpHandleControlReply(FtpStateData * ftpState)
 {
     char *oldbuf;
-    wordlist **W, **T;
+    wordlist **W;
     int bytes_used = 0;
     wordlistDestroy(&ftpState->ctrl.message);
     ftpState->ctrl.message = ftpParseControlReply(ftpState->ctrl.buf,
@@ -1228,21 +1293,11 @@
 	xmemmove(ftpState->ctrl.buf, ftpState->ctrl.buf + bytes_used,
 	    ftpState->ctrl.offset);
     }
-    /* Extract reply message (last line) */
-    for (T = NULL, W = &ftpState->ctrl.message; *W && (*W)->next; W = &(*W)->next) {
-	/* Skip trailing blank lines */
-	if (strlen((*W)->key) == 0) {
-	    if (T == NULL)
-		T = W;
-	} else if ((*W)->next) {
-	    T = NULL;
-	}
-    }
+    /* Find the last line of the reply message */
+    for (W = &ftpState->ctrl.message; (*W)->next; W = &(*W)->next);
     safe_free(ftpState->ctrl.last_reply);
     ftpState->ctrl.last_reply = (*W)->key;
     safe_free(*W);
-    if (T)
-	wordlistDestroy(T);
     debug(9, 8) ("ftpReadControlReply: state=%d, code=%d\n", ftpState->state,
 	ftpState->ctrl.replycode);
     FTP_SM_FUNCS[ftpState->state] (ftpState);
@@ -1358,6 +1413,8 @@
     }
     if (mode == 'I')
 	ftpState->flags.binary = 1;
+    else
+	ftpState->flags.binary = 0;
     snprintf(cbuf, 1024, "TYPE %c\r\n", mode);
     ftpWriteCommand(cbuf, ftpState);
     ftpState->state = SENT_TYPE;
@@ -1368,11 +1425,17 @@
 {
     int code = ftpState->ctrl.replycode;
     char *path;
-    char *d;
+    char *d, *p;
     debug(9, 3) ("This is ftpReadType\n");
     if (code == 200) {
-	path = xstrdup(strBuf(ftpState->request->urlpath));
-	for (d = strtok(path, "/"); d; d = strtok(NULL, "/")) {
+	p = path = xstrdup(strBuf(ftpState->request->urlpath));
+	if (*p == '/')
+	    p++;
+	while (*p) {
+	    d = p;
+	    p += strcspn(p, "/");
+	    if (*p)
+		*p++ = '\0';
 	    rfc1738_unescape(d);
 	    wordlistAdd(&ftpState->pathcomps, d);
 	}
@@ -1425,7 +1488,10 @@
     } else {
 	ftpState->flags.no_dotdot = 0;
     }
-    snprintf(cbuf, 1024, "CWD %s\r\n", path);
+    if (*path)
+	snprintf(cbuf, 1024, "CWD %s\r\n", path);
+    else
+	snprintf(cbuf, 1024, "CWD\r\n");
     ftpWriteCommand(cbuf, ftpState);
     ftpState->state = SENT_CWD;
 }
@@ -1549,6 +1615,12 @@
     if (code == 213) {
 	ftpUnhack(ftpState);
 	ftpState->size = atoi(ftpState->ctrl.last_reply);
+	if (ftpState->size == 0) {
+	    debug(9, 2) ("ftpReadSize: SIZE reported %s on %s\n",
+		ftpState->ctrl.last_reply,
+		ftpState->title_url);
+	    ftpState->size = -1;
+	}
     } else if (code < 0) {
 	ftpFail(ftpState);
     }
@@ -1763,6 +1835,7 @@
 	/* Fall back on using the same port as the control connection */
 	debug(9, 3) ("PORT not supported by remote end\n");
 	comm_close(ftpState->data.fd);
+	ftpState->data.fd = -1;
 	ftpOpenListenSocket(ftpState, 1);
     }
     ftpRestOrList(ftpState);
@@ -1789,6 +1862,7 @@
     ftpState->data.fd = fd;
     ftpState->data.port = ntohs(peer.sin_port);
     ftpState->data.host = xstrdup(inet_ntoa(peer.sin_addr));
+    commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL);
     commSetTimeout(ftpState->data.fd, Config.Timeout.read, ftpTimeout,
 	ftpState);
     /* XXX We should have a flag to track connect state...
@@ -1814,7 +1888,7 @@
 	ftpState->flags.use_base = 1;
     } else if (ftpState->flags.isdir)
 	ftpSendList(ftpState);
-    else if (ftpState->restart_offset > 0)
+    else if (ftpRestartable(ftpState))
 	ftpSendRest(ftpState);
     else
 	ftpSendRetr(ftpState);
@@ -1863,6 +1937,24 @@
     ftpState->state = SENT_REST;
 }
 
+static int
+ftpRestartable(FtpStateData * ftpState)
+{
+    if (ftpState->restart_offset > 0)
+	return 1;
+    if (!ftpState->request->range)
+	return 0;
+    if (!ftpState->flags.binary)
+	return 0;
+    if (ftpState->size <= 0)
+	return 0;
+
+    ftpState->restart_offset = httpHdrRangeLowestOffset(ftpState->request->range, (size_t) ftpState->size);
+    if (ftpState->restart_offset <= 0)
+	return 0;
+    return 1;
+}
+
 static void
 ftpReadRest(FtpStateData * ftpState)
 {
@@ -1870,10 +1962,12 @@
     debug(9, 3) ("This is ftpReadRest\n");
     assert(ftpState->restart_offset > 0);
     if (code == 350) {
+	ftpState->restarted_offset = ftpState->restart_offset;
 	ftpSendRetr(ftpState);
     } else if (code > 0) {
 	debug(9, 3) ("ftpReadRest: REST not supported\n");
 	ftpState->flags.rest_supported = 0;
+	ftpSendRetr(ftpState);
     } else {
 	ftpFail(ftpState);
     }
@@ -2079,7 +2173,6 @@
     ftpState->flags.tried_nlst = 0;
     /* And off we go */
     if (ftpState->flags.isdir) {
-	safe_free(ftpState->filepath);
 	ftpListDir(ftpState);
     } else {
 	ftpGetFile(ftpState);
@@ -2100,6 +2193,9 @@
 static void
 ftpHackShortcut(FtpStateData * ftpState, FTPSM * nextState)
 {
+    /* Clear some unwanted state */
+    ftpState->restarted_offset = 0;
+    ftpState->restart_offset = 0;
     /* Save old error message & some state info */
     if (ftpState->old_request == NULL) {
 	ftpState->old_request = ftpState->ctrl.last_command;
@@ -2122,7 +2218,7 @@
     if (!ftpState->flags.isdir &&	/* Not a directory */
 	!ftpState->flags.try_slash_hack &&	/* Not in slash hack */
 	ftpState->mdtm <= 0 && ftpState->size < 0 &&	/* Not known as a file */
-	!strNCaseCmp(ftpState->request->urlpath, "/%2f", 4)) {	/* No slash encoded */
+	strNCaseCmp(ftpState->request->urlpath, "/%2f", 4) != 0) {	/* No slash encoded */
 	switch (ftpState->state) {
 	case SENT_CWD:
 	case SENT_RETR:
@@ -2147,13 +2243,36 @@
 	    break;
 	}
     }
-    err = errorCon(ERR_FTP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
+    /* Translate FTP errors into HTTP errors */
+    err = NULL;
+    switch (ftpState->state) {
+    case SENT_USER:
+    case SENT_PASS:
+	if (ftpState->ctrl.replycode > 500)
+	    err = errorCon(ERR_FTP_FORBIDDEN, HTTP_FORBIDDEN);
+	else if (ftpState->ctrl.replycode == 421)
+	    err = errorCon(ERR_FTP_UNAVAILABLE, HTTP_SERVICE_UNAVAILABLE);
+	break;
+    case SENT_CWD:
+    case SENT_RETR:
+	if (ftpState->ctrl.replycode == 550)
+	    err = errorCon(ERR_FTP_NOT_FOUND, HTTP_NOT_FOUND);
+	break;
+    default:
+	break;
+    }
+    if (err == NULL)
+	err = errorCon(ERR_FTP_FAILURE, HTTP_BAD_GATEWAY);
     err->request = requestLink(ftpState->request);
     err->ftp_server_msg = ftpState->ctrl.message;
     if (ftpState->old_request)
 	err->ftp.request = ftpState->old_request;
     else
 	err->ftp.request = ftpState->ctrl.last_command;
+    if (err->ftp.request) {
+	if (!strncmp(err->ftp.request, "PASS", 4))
+	    err->ftp.request = "PASS ";
+    }
     if (ftpState->old_reply)
 	err->ftp.reply = ftpState->old_reply;
     else
@@ -2162,12 +2281,34 @@
     comm_close(ftpState->ctrl.fd);
 }
 
+void
+ftpPumpClosedData(int data_fd, void *data)
+{
+    FtpStateData *ftpState = data;
+    assert(data_fd == ftpState->data.fd);
+    /*
+     * Ugly pump module closed our server-side.  Deal with it.
+     * The data FD is already closed, so just set it to -1.
+     */
+    ftpState->data.fd = -1;
+    /*
+     * Currently, thats all we have to do.  Because the upload failed,
+     * storeAbort() will be called on the reply entry.  That will
+     * call fwdAbort, which closes ftpState->ctrl.fd and then
+     * ftpStateFree gets called.
+     */
+}
+
 static void
 ftpPutStart(FtpStateData * ftpState)
 {
     debug(9, 3) ("ftpPutStart\n");
-    pumpStart(ftpState->data.fd, ftpState->entry,
-	ftpState->request, ftpPutTransferDone, ftpState);
+    /*
+     * sigh, we need this gross hack to detect when ugly pump module
+     * aborts and wants to close the server-side.
+     */
+    comm_add_close_handler(ftpState->data.fd, ftpPumpClosedData, ftpState);
+    pumpStart(ftpState->data.fd, ftpState->fwd, ftpPutTransferDone, ftpState);
 }
 
 static void
@@ -2175,6 +2316,7 @@
 {
     FtpStateData *ftpState = data;
     if (ftpState->data.fd >= 0) {
+	comm_remove_close_handler(fd, ftpPumpClosedData, ftpState);
 	comm_close(ftpState->data.fd);
 	ftpState->data.fd = -1;
     }
@@ -2229,6 +2371,7 @@
 	return;
     ftpState->flags.http_header_sent = 1;
     assert(e->mem_obj->inmem_hi == 0);
+    EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT);
     filename = (t = strRChr(urlpath, '/')) ? t + 1 : strBuf(urlpath);
     if (ftpState->flags.isdir) {
 	mime_type = "text/html";
@@ -2250,8 +2393,19 @@
     storeBuffer(e);
     httpReplyReset(reply);
     /* set standard stuff */
-    httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying",
-	mime_type, ftpState->size, ftpState->mdtm, -2);
+    if (ftpState->restarted_offset) {
+	/* Partial reply */
+	HttpHdrRangeSpec range_spec;
+	range_spec.offset = ftpState->restarted_offset;
+	range_spec.length = ftpState->size - ftpState->restarted_offset;
+	httpReplySetHeaders(reply, 1.0, HTTP_PARTIAL_CONTENT, "Gatewaying",
+	    mime_type, ftpState->size - ftpState->restarted_offset, ftpState->mdtm, -2);
+	httpHeaderAddContRange(&reply->header, range_spec, ftpState->size);
+    } else {
+	/* Full reply */
+	httpReplySetHeaders(reply, 1.0, HTTP_OK, "Gatewaying",
+	    mime_type, ftpState->size, ftpState->mdtm, -2);
+    }
     /* additional info */
     if (mime_enc)
 	httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc);
@@ -2268,7 +2422,7 @@
 	if (pe)
 	    storeRelease(pe);
 	storeRelease(e);
-    } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
+    } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) {
 	storeSetPublicKey(e);
     } else {
 	storeRelease(e);
Index: squid/src/globals.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/globals.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/globals.h	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/globals.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: globals.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: globals.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -42,6 +42,7 @@
 extern char tmp_error_buf[ERROR_BUF_SZ];
 extern char *volatile debug_options;	/* NULL */
 extern char ThisCache[SQUIDHOSTNAMELEN << 1];
+extern char ThisCache2[SQUIDHOSTNAMELEN << 1];
 extern char config_input_line[BUFSIZ];
 extern const char *AclMatchedName;	/* NULL */
 extern const char *DefaultConfigFile;	/* DEFAULT_CONFIG_FILE */
@@ -65,13 +66,13 @@
 extern fde *fd_table;		/* NULL */
 extern int Biggest_FD;		/* -1 */
 extern int Number_FD;		/* 0 */
+extern int Opening_FD;		/* 0 */
 extern int HttpSockets[MAXHTTPPORTS];
 extern int NDnsServersAlloc;	/* 0 */
 extern int NHttpSockets;	/* 0 */
 extern int RESERVED_FD;
 extern int Squid_MaxFD;		/* SQUID_MAXFD */
 extern int config_lineno;	/* 0 */
-extern int configured_once;	/* 0 */
 extern int debugLevels[MAX_DEBUG_SECTIONS];
 extern int do_mallinfo;		/* 0 */
 extern int opt_reuseaddr;	/* 1 */
@@ -124,16 +125,17 @@
 extern int store_hash_buckets;	/* 0 */
 extern hash_table *store_table;	/* NULL */
 extern dlink_list store_list;
+extern dlink_list ClientActiveRequests;
 extern const String StringNull;	/* { 0, 0, NULL } */
 extern const MemBuf MemBufNull;	/* MemBufNULL */
 extern int hot_obj_count;	/* 0 */
 extern int _db_level;
 extern const int CacheDigestHashFuncCount;	/* 4 */
 extern CacheDigest *store_digest;	/* NULL */
-extern const char *StoreDigestUrlPath;	/* "store_digest" */
+extern const char *StoreDigestFileName;		/* "store_digest" */
 extern const char *StoreDigestMimeStr;	/* "application/cache-digest" */
 #if USE_CACHE_DIGESTS
-extern const Version CacheDigestVer;	/* { 4, 3 } */
+extern const Version CacheDigestVer;	/* { 5, 3 } */
 #endif
 extern const char *MultipartMsgBoundaryStr;	/* "Unique-Squid-Separator" */
 extern icpUdpData *IcpQueueHead;	/* NULL */
@@ -141,4 +143,4 @@
 extern int refresh_nocache_hack;	/* 0 */
 #endif
 extern request_flags null_request_flags;
-extern int open_disk_fd;	/* 0 */
+extern int store_open_disk_fd;	/* 0 */
Index: squid/src/gopher.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/gopher.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/gopher.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/gopher.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: gopher.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: gopher.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 10    Gopher
  * AUTHOR: Harvest Derived
@@ -87,6 +87,7 @@
     int len;
     char *buf;			/* pts to a 4k page */
     int fd;
+    FwdState *fwdState;
 } GopherStateData;
 
 static PF gopherStateFree;
@@ -117,7 +118,7 @@
     if (gopherState->entry) {
 	storeUnlockObject(gopherState->entry);
     }
-    memFree(MEM_4K_BUF, gopherState->buf);
+    memFree(gopherState->buf, MEM_4K_BUF);
     gopherState->buf = NULL;
     cbdataFree(gopherState);
 }
@@ -186,6 +187,7 @@
 	break;
     }
     memBufPrintf(&mb, "\r\n");
+    EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT);
     storeAppend(gopherState->entry, mb.buf, mb.size);
     memBufClean(&mb);
 }
@@ -573,14 +575,12 @@
 {
     GopherStateData *gopherState = data;
     StoreEntry *entry = gopherState->entry;
-    ErrorState *err;
     debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
-    if (entry->mem_obj->inmem_hi == 0) {
-	err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT);
-	err->url = xstrdup(gopherState->request);
-	errorAppendEntry(entry, err);
-    } else {
-	storeAbort(entry, 0);
+    if (entry->store_status == STORE_PENDING) {
+	if (entry->mem_obj->inmem_hi == 0) {
+	    fwdFail(gopherState->fwdState,
+		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
+	}
     }
     comm_close(fd);
 }
@@ -600,6 +600,10 @@
 #if DELAY_POOLS
     delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	comm_close(fd);
+	return;
+    }
     errno = 0;
     buf = memAllocate(MEM_4K_BUF);
     read_sz = 4096 - 1;		/* leave room for termination */
@@ -637,7 +641,6 @@
 	    errorAppendEntry(entry, err);
 	    comm_close(fd);
 	} else {
-	    storeAbort(entry, 0);
 	    comm_close(fd);
 	}
     } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
@@ -654,7 +657,7 @@
 	    gopherEndHTML(data);
 	storeTimestampsSet(entry);
 	storeBufferFlush(entry);
-	storeComplete(entry);
+	fwdComplete(gopherState->fwdState);
 	comm_close(fd);
     } else {
 	if (gopherState->conversion != NORMAL) {
@@ -667,7 +670,7 @@
 	    gopherReadReply,
 	    data, 0);
     }
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
     return;
 }
 
@@ -695,7 +698,7 @@
 	errorAppendEntry(entry, err);
 	comm_close(fd);
 	if (buf)
-	    memFree(MEM_4K_BUF, buf);	/* Allocated by gopherSendRequest. */
+	    memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
 	return;
     }
     /* 
@@ -730,7 +733,7 @@
     commSetSelect(fd, COMM_SELECT_READ, gopherReadReply, gopherState, 0);
     commSetDefer(fd, fwdCheckDeferRead, entry);
     if (buf)
-	memFree(MEM_4K_BUF, buf);	/* Allocated by gopherSendRequest. */
+	memFree(buf, MEM_4K_BUF);	/* Allocated by gopherSendRequest. */
 }
 
 /* This will be called when connect completes. Write request. */
@@ -763,8 +766,10 @@
 }
 
 void
-gopherStart(StoreEntry * entry, int fd)
+gopherStart(FwdState * fwdState)
 {
+    int fd = fwdState->server_fd;
+    StoreEntry *entry = fwdState->entry;
     GopherStateData *gopherState = CreateGopherStateData();
     storeLockObject(entry);
     gopherState->entry = entry;
@@ -797,11 +802,12 @@
 	    }
 	}
 	gopherToHTML(gopherState, (char *) NULL, 0);
-	storeComplete(entry);
+	fwdComplete(fwdState);
 	comm_close(fd);
 	return;
     }
     gopherState->fd = fd;
+    gopherState->fwdState = fwdState;
     commSetSelect(fd, COMM_SELECT_WRITE, gopherSendRequest, gopherState, 0);
     commSetTimeout(fd, Config.Timeout.read, gopherTimeout, gopherState);
 }
@@ -810,7 +816,7 @@
 CreateGopherStateData(void)
 {
     GopherStateData *gd = xcalloc(1, sizeof(GopherStateData));
-    cbdataAdd(gd, MEM_NONE);
+    cbdataAdd(gd, cbdataXfree, 0);
     gd->buf = memAllocate(MEM_4K_BUF);
     return (gd);
 }
Index: squid/src/helper.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/helper.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/helper.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/helper.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -59,7 +59,7 @@
 	}
 	hlp->n_running++;
 	srv = memAllocate(MEM_HELPER_SERVER);
-	cbdataAdd(srv, MEM_HELPER_SERVER);
+	cbdataAdd(srv, memFree, MEM_HELPER_SERVER);
 	srv->flags.alive = 1;
 	srv->index = k;
 	srv->rfd = rfd;
@@ -114,6 +114,7 @@
 {
     helper_server *srv;
     dlink_node *link;
+    double tt;
     storeAppendPrintf(sentry, "number running: %d of %d\n",
 	hlp->n_running, hlp->n_to_start);
     storeAppendPrintf(sentry, "requests sent: %d\n",
@@ -134,6 +135,7 @@
 	"Offset");
     for (link = hlp->servers.head; link; link = link->next) {
 	srv = link->data;
+	tt = 0.001 * tvSubMsec(srv->dispatch_time, current_time);
 	storeAppendPrintf(sentry, "%7d\t%7d\t%11d\t%c%c%c%c\t%7.3f\t%7d\n",
 	    srv->index + 1,
 	    srv->rfd,
@@ -142,7 +144,7 @@
 	    srv->flags.busy ? 'B' : ' ',
 	    srv->flags.closing ? 'C' : ' ',
 	    srv->flags.shutdown ? 'S' : ' ',
-	    0.001 * tvSubMsec(srv->dispatch_time, current_time),
+	    tt < 0.0 ? 0.0 : tt,
 	    (int) srv->offset);
     }
     storeAppendPrintf(sentry, "\nFlags key:\n\n");
@@ -177,7 +179,7 @@
 	    continue;
 	}
 	srv->flags.closing = 1;
-	comm_close(srv->wfd);
+	comm_close(srv->rfd);
     }
 }
 
@@ -185,7 +187,7 @@
 helperCreate(const char *name)
 {
     helper *hlp = memAllocate(MEM_HELPER);
-    cbdataAdd(hlp, MEM_HELPER);
+    cbdataAdd(hlp, memFree, MEM_HELPER);
     hlp->id_name = name;
     return hlp;
 }
@@ -209,11 +211,18 @@
 {
     helper_server *srv = data;
     helper *hlp = srv->parent;
+    helper_request *r;
     assert(srv->rfd == fd);
     if (srv->buf) {
-	memFree(MEM_8K_BUF, srv->buf);
+	memFree(srv->buf, MEM_8K_BUF);
 	srv->buf = NULL;
     }
+    if ((r = srv->request)) {
+	if (cbdataValid(r->data))
+	    r->callback(r->data, srv->buf);
+	helperRequestFree(r);
+	srv->request = NULL;
+    }
     if (srv->wfd != srv->rfd)
 	comm_close(srv->wfd);
     dlinkDelete(&srv->link, &hlp->servers);
@@ -268,6 +277,7 @@
 	srv->flags.busy = 0;
 	srv->offset = 0;
 	helperRequestFree(r);
+	srv->request = NULL;
 	hlp->stats.replies++;
 	hlp->stats.avg_svc_time =
 	    intAverage(hlp->stats.avg_svc_time,
@@ -310,7 +320,7 @@
     if ((link = hlp->queue.head)) {
 	r = link->data;
 	dlinkDelete(link, &hlp->queue);
-	memFree(MEM_DLINK_NODE, link);
+	memFree(link, MEM_DLINK_NODE);
 	hlp->stats.queue_size--;
     }
     return r;
@@ -377,5 +387,5 @@
 {
     cbdataUnlock(r->data);
     xfree(r->buf);
-    memFree(MEM_HELPER_REQUEST, r);
+    memFree(r, MEM_HELPER_REQUEST);
 }
Index: squid/src/http.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/http.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/http.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/http.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: http.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -42,12 +42,12 @@
 
 static const char *const crlf = "\r\n";
 
-static CNCB httpConnectDone;
 static CWCB httpSendComplete;
 static CWCB httpSendRequestEntry;
+static CWCB httpSendRequestEntryDone;
 
 static PF httpReadReply;
-static PF httpSendRequest;
+static void httpSendRequest(HttpStateData *);
 static PF httpStateFree;
 static PF httpTimeout;
 static void httpCacheNegatively(StoreEntry *);
@@ -57,14 +57,17 @@
 static void httpMaybeRemovePublic(StoreEntry *, http_status);
 
 static void
-httpStateFree(int fdnotused, void *data)
+httpStateFree(int fd, void *data)
 {
     HttpStateData *httpState = data;
+#if DELAY_POOLS
+    delayClearNoDelay(fd);
+#endif
     if (httpState == NULL)
 	return;
     storeUnlockObject(httpState->entry);
     if (httpState->reply_hdr) {
-	memFree(MEM_8K_BUF, httpState->reply_hdr);
+	memFree(httpState->reply_hdr, MEM_8K_BUF);
 	httpState->reply_hdr = NULL;
     }
     requestUnlink(httpState->request);
@@ -90,11 +93,11 @@
     HttpStateData *httpState = data;
     StoreEntry *entry = httpState->entry;
     debug(11, 4) ("httpTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
-    assert(entry->store_status == STORE_PENDING);
-    if (entry->mem_obj->inmem_hi == 0) {
-	fwdFail(httpState->fwdState, ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, 0);
-    } else {
-	storeAbort(entry, 0);
+    if (entry->store_status == STORE_PENDING) {
+	if (entry->mem_obj->inmem_hi == 0) {
+	    fwdFail(httpState->fwd,
+		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
+	}
     }
     comm_close(fd);
 }
@@ -221,6 +224,12 @@
     case HTTP_MULTIPLE_CHOICES:
     case HTTP_MOVED_PERMANENTLY:
     case HTTP_GONE:
+	/*
+	 * Don't cache objects that need to be refreshed on next request,
+	 * unless we know how to refresh it.
+	 */
+	if (!refreshIsCachable(httpState->entry))
+	    return 0;
 	/* don't cache objects from peers w/o LMT, Date, or Expires */
 	/* check that is it enough to check headers @?@ */
 	if (rep->date > -1)
@@ -375,6 +384,15 @@
     /*
      * What does the reply have to say about keep-alive?
      */
+    /*
+     * XXX BUG?
+     * If the origin server (HTTP/1.0) does not send a keep-alive
+     * header, but keeps the connection open anyway, what happens?
+     * We'll return here and http.c waits for an EOF before changing
+     * store_status to STORE_OK.   Combine this with ENTRY_FWD_HDR_WAIT
+     * and an error status code, and we might have to wait until
+     * the server times out the socket.
+     */
     if (!reply->keep_alive)
 	return 0;
     debug(11, 5) ("httpPconnTransferDone: content_length=%d\n",
@@ -430,8 +448,18 @@
     int clen;
     size_t read_sz;
 #if DELAY_POOLS
-    delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
+    delay_id delay_id;
+
+    /* special "if" only for http (for nodelay proxy conns) */
+    if (delayIsNoDelay(fd))
+	delay_id = 0;
+    else
+	delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	comm_close(fd);
+	return;
+    }
     /* check if we want to defer reading */
     errno = 0;
     read_sz = SQUID_TCP_SO_RCVBUF;
@@ -456,7 +484,7 @@
     }
     if (!httpState->reply_hdr && len > 0) {
 	/* Skip whitespace */
-	while (len > 0 && isspace(*buf))
+	while (len > 0 && xisspace(*buf))
 	    xmemmove(buf, buf + 1, len--);
 	if (len == 0) {
 	    /* Continue to read... */
@@ -470,14 +498,19 @@
 	if (ignoreErrno(errno)) {
 	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
 	} else if (entry->mem_obj->inmem_hi == 0) {
-	    fwdFail(httpState->fwdState, ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno);
+	    ErrorState *err;
+	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
+	    err->xerrno = errno;
+	    fwdFail(httpState->fwd, err);
 	    comm_close(fd);
 	} else {
-	    storeAbort(entry, 0);
 	    comm_close(fd);
 	}
     } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
-	fwdFail(httpState->fwdState, ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE, errno);
+	ErrorState *err;
+	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
+	err->xerrno = errno;
+	fwdFail(httpState->fwd, err);
 	httpState->eof = 1;
 	comm_close(fd);
     } else if (len == 0) {
@@ -491,47 +524,43 @@
 	     * we want to process the reply headers.
 	     */
 	    httpProcessReplyHeader(httpState, buf, len);
-#ifdef PPNR_WIP
-	storePPNR(entry);
-#endif /* PPNR_WIP */
-	storeComplete(entry);	/* deallocates mem_obj->request */
+	fwdComplete(httpState->fwd);
 	comm_close(fd);
     } else {
-#ifndef PPNR_WIP
-	if (httpState->reply_hdr_state < 2)
-#else
 	if (httpState->reply_hdr_state < 2) {
-#endif /* PPNR_WIP */
 	    httpProcessReplyHeader(httpState, buf, len);
-#ifdef PPNR_WIP
-	    if (httpState->reply_hdr_state == 2)
-		storePPNR(entry);
+	    if (httpState->reply_hdr_state == 2) {
+		http_status s = entry->mem_obj->reply->sline.status;
+		/*
+		 * If its not a reply that we will re-forward, then
+		 * allow the client to get it.
+		 */
+		if (!fwdReforwardableStatus(s))
+		    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+	    }
 	}
-#endif /* PPNR_WIP */
 	storeAppend(entry, buf, len);
-#ifdef OPTIMISTIC_IO
-	if (entry->store_status == STORE_ABORTED) {
+	if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
 	    /*
 	     * the above storeAppend() call could ABORT this entry,
 	     * in that case, the server FD should already be closed.
 	     * there's nothing for us to do.
 	     */
 	    (void) 0;
-	} else
-#endif
-	if (httpPconnTransferDone(httpState)) {
+	} else if (httpPconnTransferDone(httpState)) {
 	    /* yes we have to clear all these! */
 	    commSetDefer(fd, NULL, NULL);
 	    commSetTimeout(fd, -1, NULL, NULL);
 	    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
+#if DELAY_POOLS
+	    delayClearNoDelay(fd);
+#endif
 	    comm_remove_close_handler(fd, httpStateFree, httpState);
-	    storeComplete(entry);	/* deallocates mem_obj->request */
-	    /* call storeComplete BEFORE fwdUnregister or else fwdUnregister
-	     * will storeAbort */
-	    fwdUnregister(fd, httpState->fwdState);
+	    fwdUnregister(fd, httpState->fwd);
 	    pconnPush(fd, request->host, request->port);
+	    fwdComplete(httpState->fwd);
 	    httpState->fd = -1;
-	    httpStateFree(-1, httpState);
+	    httpStateFree(fd, httpState);
 	} else {
 	    /* Wait for EOF condition */
 	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
@@ -565,10 +594,16 @@
 	return;
     } else {
 	/* Schedule read reply. */
-	commSetSelect(fd,
-	    COMM_SELECT_READ,
-	    httpReadReply,
-	    httpState, 0);
+	commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
+	/*
+	 * Set the read timeout here because it hasn't been set yet.
+	 * We only set the read timeout after the request has been
+	 * fully written to the server-side.  If we start the timeout
+	 * after connection establishment, then we are likely to hit
+	 * the timeout for POST/PUT requests that have very large
+	 * request bodies.
+	 */
+	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
 	commSetDefer(fd, fwdCheckDeferRead, entry);
     }
 }
@@ -605,7 +640,7 @@
      *    - we can actually parse client Range specs
      *    - the specs are expected to be simple enough (e.g. no out-of-order ranges)
      *    - reply will be cachable
-     * (If the reply will be uncachable we have to though it away after 
+     * (If the reply will be uncachable we have to throw it away after 
      *  serving this request, so it is better to forward ranges to 
      *  the server and fetch only the requested content) 
      */
@@ -726,6 +761,8 @@
 	    if (strLen(request->urlpath))
 		assert(strstr(url, strBuf(request->urlpath)));
 	}
+	if (flags.only_if_cached)
+	    EBIT_SET(cc->mask, CC_ONLY_IF_CACHED);
 	httpHeaderPutCc(hdr_out, cc);
 	httpHdrCcDestroy(cc);
     }
@@ -768,12 +805,10 @@
     memBufAppend(mb, crlf, 2);
     return mb->size - offset;
 }
-
 /* This will be called when connect completes. Write request. */
 static void
-httpSendRequest(int fd, void *data)
+httpSendRequest(HttpStateData * httpState)
 {
-    HttpStateData *httpState = data;
     MemBuf mb;
     request_t *req = httpState->request;
     StoreEntry *entry = httpState->entry;
@@ -781,7 +816,7 @@
     peer *p = httpState->peer;
     CWCB *sendHeaderDone;
 
-    debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", fd, httpState);
+    debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState);
 
     if (pumpMethod(req->method))
 	sendHeaderDone = httpSendRequestEntry;
@@ -806,6 +841,9 @@
 	httpState->flags.keepalive = 1;
     else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50)
 	httpState->flags.keepalive = 1;
+    if (httpState->peer)
+	if (neighborType(httpState->peer, httpState->request) == PEER_SIBLING)
+	    httpState->flags.only_if_cached = 1;
     memBufDefInit(&mb);
     httpBuildRequestPrefix(req,
 	httpState->orig_request,
@@ -813,26 +851,27 @@
 	&mb,
 	cfd,
 	httpState->flags);
-    debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", fd, mb.buf);
-    comm_write_mbuf(fd, mb, sendHeaderDone, httpState);
+    debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, mb.buf);
+    comm_write_mbuf(httpState->fd, mb, sendHeaderDone, httpState);
 }
 
 void
-httpStart(FwdState * fwdState, int fd)
+httpStart(FwdState * fwd)
 {
+    int fd = fwd->server_fd;
     HttpStateData *httpState = memAllocate(MEM_HTTP_STATE_DATA);
     request_t *proxy_req;
-    request_t *orig_req = fwdState->request;
+    request_t *orig_req = fwd->request;
     debug(11, 3) ("httpStart: \"%s %s\"\n",
 	RequestMethodStr[orig_req->method],
-	storeUrl(fwdState->entry));
-    cbdataAdd(httpState, MEM_HTTP_STATE_DATA);
-    storeLockObject(fwdState->entry);
-    httpState->fwdState = fwdState;
-    httpState->entry = fwdState->entry;
+	storeUrl(fwd->entry));
+    cbdataAdd(httpState, memFree, MEM_HTTP_STATE_DATA);
+    storeLockObject(fwd->entry);
+    httpState->fwd = fwd;
+    httpState->entry = fwd->entry;
     httpState->fd = fd;
-    if (fwdState->servers)
-	httpState->peer = fwdState->servers->peer;	/* might be NULL */
+    if (fwd->servers)
+	httpState->peer = fwd->servers->peer;	/* might be NULL */
     if (httpState->peer) {
 	proxy_req = requestCreate(orig_req->method,
 	    PROTO_NONE, storeUrl(httpState->entry));
@@ -851,11 +890,9 @@
 	if (httpState->peer->options.proxy_only)
 	    storeReleaseRequest(httpState->entry);
 #if DELAY_POOLS
-	if (httpState->peer->options.no_delay) {
-	    proxy_req->delay_id = 0;
-	} else {
-	    proxy_req->delay_id = orig_req->delay_id;
-	}
+	assert(delayIsNoDelay(fd) == 0);
+	if (httpState->peer->options.no_delay)
+	    delaySetNoDelay(fd);
 #endif
     } else {
 	httpState->request = requestLink(orig_req);
@@ -867,46 +904,52 @@
     comm_add_close_handler(fd, httpStateFree, httpState);
     Counter.server.all.requests++;
     Counter.server.http.requests++;
-    httpConnectDone(fd, COMM_OK, httpState);
+    httpSendRequest(httpState);
+    /*
+     * We used to set the read timeout here, but not any more.
+     * Now its set in httpSendComplete() after the full request,
+     * including request body, has been written to the server.
+     */
 }
 
 static void
-httpConnectDone(int fd, int status, void *data)
+httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data)
 {
     HttpStateData *httpState = data;
-    request_t *request = httpState->request;
     StoreEntry *entry = httpState->entry;
     ErrorState *err;
-    if (status == COMM_ERR_DNS) {
-	debug(11, 4) ("httpConnectDone: Unknown host: %s\n", request->host);
-	err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE);
-	err->dnsserver_msg = xstrdup(dns_error_message);
-	err->request = requestLink(httpState->orig_request);
-	errorAppendEntry(entry, err);
-	comm_close(fd);
-    } else if (status != COMM_OK) {
-	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
+    debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n",
+	fd, size, errflag);
+    if (size > 0) {
+	fd_bytes(fd, size, FD_WRITE);
+	kb_incr(&Counter.server.all.kbytes_out, size);
+	kb_incr(&Counter.server.http.kbytes_out, size);
+    }
+    if (errflag == COMM_ERR_CLOSING)
+	return;
+    if (errflag) {
+	err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
 	err->xerrno = errno;
-	err->host = xstrdup(request->host);
-	err->port = request->port;
 	err->request = requestLink(httpState->orig_request);
 	errorAppendEntry(entry, err);
-	if (httpState->peer)
-	    peerCheckConnectStart(httpState->peer);
 	comm_close(fd);
-    } else {
-	commSetSelect(fd, COMM_SELECT_WRITE, httpSendRequest, httpState, 0);
-	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
+	return;
     }
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	comm_close(fd);
+	return;
+    }
+    pumpStart(fd, httpState->fwd, httpSendRequestEntryDone, httpState);
 }
 
 static void
-httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data)
+httpSendRequestEntryDone(int fd, char *bufnotused, size_t size, int errflag, void *data)
 {
     HttpStateData *httpState = data;
     StoreEntry *entry = httpState->entry;
     ErrorState *err;
-    debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n",
+    aclCheck_t ch;
+    debug(11, 5) ("httpSendRequestEntryDone: FD %d: size %d: errflag %d.\n",
 	fd, size, errflag);
     if (size > 0) {
 	fd_bytes(fd, size, FD_WRITE);
@@ -923,5 +966,16 @@
 	comm_close(fd);
 	return;
     }
-    pumpStart(fd, entry, httpState->orig_request, httpSendComplete, httpState);
+    memset(&ch, '\0', sizeof(ch));
+    ch.request = httpState->request;
+    if (!Config.accessList.brokenPosts) {
+	debug(11, 5) ("httpSendRequestEntryDone: No brokenPosts list\n");
+	httpSendComplete(fd, NULL, 0, 0, data);
+    } else if (!aclCheckFast(Config.accessList.brokenPosts, &ch)) {
+	debug(11, 5) ("httpSendRequestEntryDone: didn't match brokenPosts\n");
+	httpSendComplete(fd, NULL, 0, 0, data);
+    } else {
+	debug(11, 2) ("httpSendRequestEntryDone: matched brokenPosts\n");
+	comm_write(fd, "\r\n", 2, httpSendComplete, data, NULL);
+    }
 }
Index: squid/src/icmp.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/icmp.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/icmp.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/icmp.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: icmp.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: icmp.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 37    ICMP Routines
  * AUTHOR: Duane Wessels
@@ -169,7 +169,7 @@
     strcpy(payload + len, url);
     len += ulen + 1;
     icmpSendEcho(to, S_ICMP_ICP, payload, len);
-    memFree(MEM_8K_BUF, payload);
+    memFree(payload, MEM_8K_BUF);
 #endif
 }
 #endif
Index: squid/src/icp_v2.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/icp_v2.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/icp_v2.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/icp_v2.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: icp_v2.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: icp_v2.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 12    Internet Cache Protocol
  * AUTHOR: Duane Wessels
@@ -218,6 +218,7 @@
 	    break;
 	}
 	checklist.src_addr = from.sin_addr;
+	checklist.my_addr = no_addr;
 	checklist.request = icp_request;
 	allow = aclCheckFast(Config.accessList.icp, &checklist);
 	if (!allow) {
@@ -271,7 +272,9 @@
 	break;
 
     case ICP_HIT:
+#if ALLOW_SOURCE_PING
     case ICP_SECHO:
+#endif
     case ICP_DECHO:
     case ICP_MISS:
     case ICP_DENIED:
@@ -492,6 +495,7 @@
     if (theOutIcpConnection > -1) {
 	debug(12, 1) ("FD %d Closing ICP connection\n", theOutIcpConnection);
 	comm_close(theOutIcpConnection);
+	theOutIcpConnection = -1;
     }
 }
 
Index: squid/src/icp_v3.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/icp_v3.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/icp_v3.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/icp_v3.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: icp_v3.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: icp_v3.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 12    Internet Cache Protocol
  * AUTHOR: Duane Wessels
@@ -72,6 +72,7 @@
 	    break;
 	}
 	checklist.src_addr = from.sin_addr;
+	checklist.my_addr = no_addr;
 	checklist.request = icp_request;
 	allow = aclCheckFast(Config.accessList.icp, &checklist);
 	if (!allow) {
@@ -112,7 +113,9 @@
 	break;
 
     case ICP_HIT:
+#if ALLOW_SOURCE_PING
     case ICP_SECHO:
+#endif
     case ICP_DECHO:
     case ICP_MISS:
     case ICP_DENIED:
Index: squid/src/ident.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ident.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/ident.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/ident.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ident.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: ident.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 30    Ident (RFC 931)
  * AUTHOR: Duane Wessels
@@ -35,113 +35,210 @@
 
 #include "squid.h"
 
+#if USE_IDENT
+
 #define IDENT_PORT 113
+#define IDENT_KEY_SZ 50
+
+typedef struct _IdentClient {
+    IDCB *callback;
+    void *callback_data;
+    struct _IdentClient *next;
+} IdentClient;
+
+typedef struct _IdentStateData {
+    char *key;
+    struct _IdentStateData *next;
+    int fd;			/* IDENT fd */
+    struct sockaddr_in me;
+    struct sockaddr_in peer;
+    IdentClient *clients;
+} IdentStateData;
 
 static PF identReadReply;
 static PF identClose;
 static PF identTimeout;
 static CNCB identConnectDone;
-static void identCallback(ConnStateData * connState);
+static hash_table *ident_hash = NULL;
+static void identClientAdd(IdentStateData *, IDCB *, void *);
+
+/**** PRIVATE FUNCTIONS ****/
+
+static void
+identCallback(IdentStateData * state, char *result)
+{
+    IdentClient *client;
+    if (result && *result == '\0')
+	result = NULL;
+    while ((client = state->clients)) {
+	state->clients = client->next;
+	if (cbdataValid(client->callback_data))
+	    client->callback(result, client->callback_data);
+	cbdataUnlock(client->callback_data);
+	xfree(client);
+    }
+}
 
 static void
 identClose(int fdnotused, void *data)
 {
-    ConnStateData *connState = data;
-    connState->ident.fd = -1;
+    IdentStateData *state = data;
+    identCallback(state, NULL);
+    comm_close(state->fd);
+    hash_remove_link(ident_hash, (hash_link *) state);
+    cbdataFree(state);
 }
 
 static void
 identTimeout(int fd, void *data)
 {
-    ConnStateData *connState = data;
+    IdentStateData *state = data;
     debug(30, 3) ("identTimeout: FD %d, %s\n", fd,
-	inet_ntoa(connState->peer.sin_addr));
+	inet_ntoa(state->peer.sin_addr));
     comm_close(fd);
 }
 
-/* start a TCP connection to the peer host on port 113 */
-void
-identStart(int fd, ConnStateData * connState, IDCB * callback, void *data)
-{
-    connState->ident.callback = callback;
-    connState->ident.callback_data = data;
-    connState->ident.state = IDENT_PENDING;
-    if (fd < 0) {
-	fd = comm_open(SOCK_STREAM,
-	    0,
-	    connState->me.sin_addr,
-	    0,
-	    COMM_NONBLOCKING,
-	    "ident");
-	if (fd == COMM_ERROR) {
-	    identCallback(connState);
-	    return;
-	}
-    }
-    connState->ident.fd = fd;
-    comm_add_close_handler(fd,
-	identClose,
-	connState);
-    commConnectStart(fd,
-	inet_ntoa(connState->peer.sin_addr),
-	IDENT_PORT,
-	identConnectDone,
-	connState);
-}
-
 static void
 identConnectDone(int fd, int status, void *data)
 {
-    ConnStateData *connState = data;
+    IdentStateData *state = data;
+    IdentClient *c;
     MemBuf mb;
     if (status != COMM_OK) {
+	/* Failed to connect */
+	comm_close(fd);
+	return;
+    }
+    /*
+     * see if our clients still care
+     */
+    for (c = state->clients; c; c = c->next) {
+	if (cbdataValid(c->callback_data))
+	    break;
+    }
+    if (c == NULL) {
+	/* no clients care */
 	comm_close(fd);
-	identCallback(connState);
 	return;
     }
     memBufDefInit(&mb);
     memBufPrintf(&mb, "%d, %d\r\n",
-	ntohs(connState->peer.sin_port),
-	ntohs(connState->me.sin_port));
-    comm_write_mbuf(fd, mb, NULL, connState);
-    commSetSelect(fd, COMM_SELECT_READ, identReadReply, connState, 0);
-    commSetTimeout(fd, Config.Timeout.read, identTimeout, connState);
+	ntohs(state->peer.sin_port),
+	ntohs(state->me.sin_port));
+    comm_write_mbuf(fd, mb, NULL, state);
+    commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
+    commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
 }
 
 static void
 identReadReply(int fd, void *data)
 {
-    ConnStateData *connState = data;
+    IdentStateData *state = data;
     LOCAL_ARRAY(char, buf, BUFSIZ);
+    char *ident = NULL;
     char *t = NULL;
     int len = -1;
-
     buf[0] = '\0';
     Counter.syscalls.sock.reads++;
     len = read(fd, buf, BUFSIZ - 1);
     fd_bytes(fd, len, FD_READ);
-    if (len > 0) {
-	buf[len] = '\0';
-	if ((t = strchr(buf, '\r')))
-	    *t = '\0';
-	if ((t = strchr(buf, '\n')))
-	    *t = '\0';
-	debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
-	if (strstr(buf, "USERID")) {
-	    if ((t = strrchr(buf, ':'))) {
-		while (isspace(*++t));
-		xstrncpy(connState->ident.ident, t, USER_IDENT_SZ);
-	    }
+    if (len <= 0) {
+	comm_close(fd);
+	return;
+    }
+    /*
+     * XXX This isn't really very tolerant. It should read until EOL
+     * or EOF and then decode the answer... If the reply is fragmented
+     * then this will fail
+     */
+    buf[len] = '\0';
+    if ((t = strchr(buf, '\r')))
+	*t = '\0';
+    if ((t = strchr(buf, '\n')))
+	*t = '\0';
+    debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
+    if (strstr(buf, "USERID")) {
+	if ((ident = strrchr(buf, ':'))) {
+	    while (xisspace(*++ident));
+	    identCallback(state, ident);
 	}
     }
     comm_close(fd);
-    identCallback(connState);
 }
 
+
 static void
-identCallback(ConnStateData * connState)
+identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
+{
+    IdentClient *c = xcalloc(1, sizeof(*c));
+    IdentClient **C;
+    c->callback = callback;
+    c->callback_data = callback_data;
+    cbdataLock(callback_data);
+    for (C = &state->clients; *C; C = &(*C)->next);
+    *C = c;
+}
+
+/**** PUBLIC FUNCTIONS ****/
+
+/*
+ * start a TCP connection to the peer host on port 113
+ */
+void
+identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *data)
+{
+    IdentStateData *state;
+    int fd;
+    char key1[IDENT_KEY_SZ];
+    char key2[IDENT_KEY_SZ];
+    char key[IDENT_KEY_SZ];
+    snprintf(key1, IDENT_KEY_SZ, "%s:%d",
+	inet_ntoa(me->sin_addr),
+	ntohs(me->sin_port));
+    snprintf(key2, IDENT_KEY_SZ, "%s:%d",
+	inet_ntoa(peer->sin_addr),
+	ntohs(peer->sin_port));
+    snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
+    if ((state = hash_lookup(ident_hash, key)) != NULL) {
+	identClientAdd(state, callback, data);
+	return;
+    }
+    fd = comm_open(SOCK_STREAM,
+	0,
+	me->sin_addr,
+	0,
+	COMM_NONBLOCKING,
+	"ident");
+    if (fd == COMM_ERROR) {
+	/* Failed to get a local socket */
+	callback(NULL, data);
+	return;
+    }
+    state = xcalloc(1, sizeof(IdentStateData));
+    cbdataAdd(state, cbdataXfree, 0);
+    state->key = xstrdup(key);
+    state->fd = fd;
+    state->me = *me;
+    state->peer = *peer;
+    identClientAdd(state, callback, data);
+    hash_join(ident_hash, (hash_link *) state);
+    comm_add_close_handler(fd,
+	identClose,
+	state);
+    commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
+    commConnectStart(fd,
+	inet_ntoa(state->peer.sin_addr),
+	IDENT_PORT,
+	identConnectDone,
+	state);
+}
+
+void
+identInit(void)
 {
-    connState->ident.state = IDENT_DONE;
-    if (connState->ident.callback)
-	connState->ident.callback(connState->ident.callback_data);
+    ident_hash = hash_create((HASHCMP *) strcmp,
+	hashPrime(Squid_MaxFD / 8),
+	hash4);
 }
+
+#endif
Index: squid/src/internal.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/internal.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/internal.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/internal.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: internal.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: internal.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 76    Internal Squid Object handling
  * AUTHOR: Duane, Alex, Henrik
Index: squid/src/ipc.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ipc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/ipc.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/ipc.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ipc.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: ipc.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 54    Interprocess Communication
  * AUTHOR: Duane Wessels
@@ -66,6 +66,7 @@
     int cwfd = -1;
     int pwfd = -1;
     int fd;
+    int t1, t2, t3;
     socklen_t len;
     int tmp_s;
 #if HAVE_PUTENV
@@ -207,9 +208,9 @@
     /* child */
     no_suid();			/* give up extra priviliges */
     /* close shared socket with parent */
-    comm_close(prfd);
+    close(prfd);
     if (pwfd != prfd)
-	comm_close(pwfd);
+	close(pwfd);
     pwfd = prfd = -1;
 
     if (type == IPC_TCP_SOCKET) {
@@ -218,7 +219,7 @@
 	    debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
 	    _exit(1);
 	}
-	debug(54, 3) ("ipcCreate: accepted new FD %d\n", fd);
+	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
 	close(crfd);
 	cwfd = crfd = fd;
     } else if (type == IPC_UDP_SOCKET) {
@@ -244,20 +245,27 @@
     snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
     putenv(env_str);
 #endif
-    dup2(crfd, 0);
-    dup2(cwfd, 1);
-    dup2(fileno(debug_log), 2);
-    fclose(debug_log);
     /*
-     * Solaris pthreads seems to close FD 0 upon fork(), so don't close
-     * this FD if its 0, 1, or 2.
-     * -- Michael O'Reilly 
+     * This double-dup stuff avoids problems when one of 
+     *  crfd, cwfd, or debug_log are in the rage 0-2.
      */
-    if (crfd > 2)
-	close(crfd);
-    if (cwfd != crfd)
-	if (cwfd > 2)
-	    close(cwfd);
+    do {
+	x = open(_PATH_DEVNULL, 0, 0444);
+	commSetCloseOnExec(x);
+    } while (x < 3);
+    t1 = dup(crfd);
+    t2 = dup(cwfd);
+    t3 = dup(fileno(debug_log));
+    assert(t1 > 2 && t2 > 2 && t3 > 2);
+    close(crfd);
+    close(cwfd);
+    close(fileno(debug_log));
+    dup2(t1, 0);
+    dup2(t2, 1);
+    dup2(t3, 2);
+    close(t1);
+    close(t2);
+    close(t3);
 #if HAVE_SETSID
     setsid();
 #endif
Index: squid/src/ipcache.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ipcache.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/ipcache.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/ipcache.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ipcache.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: ipcache.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 14    IP Cache
  * AUTHOR: Harvest Derived
@@ -126,7 +126,7 @@
     }
     safe_free(i->name);
     safe_free(i->error_message);
-    memFree(MEM_IPCACHE_ENTRY, i);
+    memFree(i, MEM_IPCACHE_ENTRY);
     return;
 }
 
@@ -175,7 +175,7 @@
 	ipcache_release(i);
 	removed++;
     }
-    debug(14, 3) ("ipcache_purgelru: removed %d entries\n", removed);
+    debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed);
 }
 
 /* create blank ipcache_entry */
@@ -247,7 +247,7 @@
 	    }
 	    cbdataUnlock(p->handlerData);
 	}
-	memFree(MEM_IPCACHE_PENDING, p);
+	memFree(p, MEM_IPCACHE_PENDING);
     }
     i->pending_head = NULL;	/* nuke list */
     debug(14, 10) ("ipcache_call_pending: Called %d handlers.\n", nhandler);
@@ -270,10 +270,11 @@
     i.status = IP_NEGATIVE_CACHED;
     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);
+    debug(14, 5) ("ipcacheParse: parsing: {%s}\n", buf);
     token = strtok(buf, w_space);
     if (NULL == token) {
 	debug(14, 1) ("ipcacheParse: Got , expecting '$addr'\n");
@@ -416,7 +417,7 @@
     /* for HIT, PENDING, DISPATCHED we've returned.  For MISS we submit */
     c = xcalloc(1, sizeof(*c));
     c->data = i;
-    cbdataAdd(c, MEM_NONE);
+    cbdataAdd(c, cbdataXfree, 0);
     i->status = IP_DISPATCHED;
     ipcacheLockEntry(i);
     dnsSubmit(i->name, ipcacheHandleReply, c);
@@ -722,13 +723,13 @@
     ip_pending *p;
     while ((p = i->pending_head)) {
 	i->pending_head = p->next;
-	memFree(MEM_IPCACHE_PENDING, p);
+	memFree(p, MEM_IPCACHE_PENDING);
     }
     safe_free(i->addrs.in_addrs);
     safe_free(i->addrs.bad_mask);
     safe_free(i->name);
     safe_free(i->error_message);
-    memFree(MEM_IPCACHE_ENTRY, i);
+    memFree(i, MEM_IPCACHE_ENTRY);
 }
 
 void
@@ -825,12 +826,6 @@
     case IP_LOC:
 	*(Answer->val.integer) = IpcacheStats.release_locked;
 	break;
-#if DELETE_ME
-    case IP_LENG:
-	*(Answer->val.integer) = queue_length;
-	Answer->type = SMI_GAUGE32;
-	break;
-#endif
     default:
 	*ErrP = SNMP_ERR_NOSUCHNAME;
 	snmp_var_free(Answer);
Index: squid/src/leakfinder.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/leakfinder.c,v
retrieving revision 1.1
retrieving revision 1.1.1.1
diff -u -r1.1 -r1.1.1.1
--- squid/src/leakfinder.c	26 Jan 2000 03:23:10 -0000	1.1
+++ squid/src/leakfinder.c	26 Jan 2000 03:23:10 -0000	1.1.1.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: leakfinder.c,v 1.1 2000/01/26 03:23:10 hno Exp $
+ * $Id: leakfinder.c,v 1.1.1.1 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 45    Callback Data Registry
  * AUTHOR: Duane Wessels
Index: squid/src/main.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/main.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/main.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/main.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: main.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: main.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -40,8 +40,10 @@
 
 static int opt_send_signal = -1;
 static int opt_no_daemon = 0;
+static int opt_parse_cfg_only = 0;
 static int httpPortNumOverride = 1;
 static int icpPortNumOverride = 1;	/* Want to detect "-u 0" */
+static int configured_once = 0;
 #if MALLOC_DBG
 static int malloc_debug_level = 0;
 #endif
@@ -68,6 +70,7 @@
 extern void log_trace_init(char *);
 #endif
 static EVH SquidShutdown;
+static void mainSetCwd(void);
 
 static void
 usage(void)
@@ -79,8 +82,9 @@
 	"       -f file   Use given config-file instead of\n"
 	"                 %s\n"
 	"       -h        Print help message.\n"
-	"       -k reconfigure|rotate|shutdown|interrupt|kill|debug|check\n"
-	"                 Send signal to running copy and exit.\n"
+	"       -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
+	"                 Parse configuration file, then send signal to \n"
+	"                 running copy (except -k parse) and exit.\n"
 	"       -s        Enable logging to syslog.\n"
 	"       -u port   Specify ICP port number (default: %d), disable with 0.\n"
 	"       -v        Print version.\n"
@@ -152,13 +156,13 @@
 	    if (!strncmp(optarg, "reconfigure", strlen(optarg)))
 		opt_send_signal = SIGHUP;
 	    else if (!strncmp(optarg, "rotate", strlen(optarg)))
-#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO)
+#ifdef _SQUID_LINUX_THREADS_
 		opt_send_signal = SIGQUIT;
 #else
 		opt_send_signal = SIGUSR1;
 #endif
 	    else if (!strncmp(optarg, "debug", strlen(optarg)))
-#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO)
+#ifdef _SQUID_LINUX_THREADS_
 		opt_send_signal = SIGTRAP;
 #else
 		opt_send_signal = SIGUSR2;
@@ -171,6 +175,8 @@
 		opt_send_signal = SIGKILL;
 	    else if (!strncmp(optarg, "check", strlen(optarg)))
 		opt_send_signal = 0;	/* SIGNULL */
+	    else if (!strncmp(optarg, "parse", strlen(optarg)))
+		opt_parse_cfg_only = 1;		/* parse cfg file only */
 	    else
 		usage();
 	    break;
@@ -335,6 +341,7 @@
 	    debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
     }
     storeDirOpenSwapLogs();
+    writePidFile();		/* write PID file */
     debug(1, 1) ("Ready to serve requests.\n");
     reconfiguring = 0;
 }
@@ -355,6 +362,9 @@
 setEffectiveUser(void)
 {
     leave_suid();		/* Run as non privilegied user */
+#ifdef _SQUID_OS2_
+    return;
+#endif
     if (geteuid() == 0) {
 	debug(0, 0) ("Squid is not safe to run as root!  If you must\n");
 	debug(0, 0) ("start Squid as root, then you must configure\n");
@@ -365,6 +375,34 @@
 }
 
 static void
+mainSetCwd(void)
+{
+    if (Config.coredump_dir) {
+	if (!chdir(Config.coredump_dir)) {
+	    debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
+	    return;
+	} else {
+	    debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
+	}
+    }
+    if (!Config.effectiveUser) {
+	char *p = getcwd(NULL, 0);
+	debug(0, 1) ("Current Directory is %s\n", p);
+	xfree(p);
+	return;
+    }
+    /* we were probably started as root, so cd to a swap
+     * directory in case we dump core */
+    if (!chdir(storeSwapDir(0))) {
+	debug(0, 1) ("Set Current Directory to %s\n", storeSwapDir(0));
+	return;
+    } else {
+	debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror());
+	fatal_dump("Cannot cd to swap directory?");
+    }
+}
+
+static void
 mainInitialize(void)
 {
     if (opt_catch_signals) {
@@ -374,14 +412,6 @@
     squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
     squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
 
-    if (!configured_once) {
-	cbdataInit();
-	memInit();		/* memInit must go before config parsing */
-    }
-    if (ConfigFile == NULL)
-	ConfigFile = xstrdup(DefaultConfigFile);
-    parseConfigFile(ConfigFile);
-
     setEffectiveUser();
     assert(Config.Port.http);
     if (httpPortNumOverride != 1)
@@ -409,10 +439,12 @@
     authenticateInit();
     useragentOpenLog();
     httpHeaderInitModule();	/* must go before any header processing (e.g. the one in errorInitialize) */
-    httpAnonInitModule();	/* must go before accepting requests */
     httpReplyInitModule();	/* must go before accepting replies */
     errorInitialize();
     accessLogInit();
+#if USE_IDENT
+    identInit();
+#endif
 #ifdef SQUID_SNMP
     snmpInit();
 #endif
@@ -427,14 +459,7 @@
 	cachemgrInit();
 	statInit();
 	storeInit();
-	if (Config.effectiveUser) {
-	    /* we were probably started as root, so cd to a swap
-	     * directory in case we dump core */
-	    if (chdir(storeSwapDir(0)) < 0) {
-		debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror());
-		fatal_dump("Cannot cd to swap directory?");
-	    }
-	}
+	mainSetCwd();
 	/* after this point we want to see the mallinfo() output */
 	do_mallinfo = 1;
 	mimeInit(Config.mimeTablePathname);
@@ -444,6 +469,7 @@
 #if DELAY_POOLS
 	delayPoolsInit();
 #endif
+	fwdInit();
     }
     serverConnectionsOpen();
     if (theOutIcpConnection >= 0) {
@@ -455,7 +481,7 @@
     if (!configured_once)
 	writePidFile();		/* write PID file */
 
-#if (defined(_SQUID_LINUX_) && USE_ASYNC_IO)
+#ifdef _SQUID_LINUX_THREADS_
     squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
     squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
 #else
@@ -523,17 +549,30 @@
 
     mainParseOptions(argc, argv);
 
+    /* parse configuration file
+     * note: in "normal" case this used to be called from mainInitialize() */
+    {
+	int parse_err;
+	if (!ConfigFile)
+	    ConfigFile = xstrdup(DefaultConfigFile);
+	assert(!configured_once);
+	cbdataInit();
+#if USE_LEAKFINDER
+	leakInit();
+#endif
+	memInit();		/* memInit is required for config parsing */
+	parse_err = parseConfigFile(ConfigFile);
+
+	if (opt_parse_cfg_only)
+	    return parse_err;
+    }
+
     /* send signal to running copy and exit */
     if (opt_send_signal != -1) {
 	sendSignal();
 	/* NOTREACHED */
     }
     if (opt_create_swap_dirs) {
-	if (ConfigFile == NULL)
-	    ConfigFile = xstrdup(DefaultConfigFile);
-	cbdataInit();
-	memInit();		/* memInit is required for config parsing */
-	parseConfigFile(ConfigFile);
 	setEffectiveUser();
 	debug(0, 0) ("Creating Swap Directories\n");
 	storeCreateSwapDirectories();
@@ -547,15 +586,16 @@
 	for (n = Squid_MaxFD; n > 2; n--)
 	    close(n);
 
-    /*init comm module */
+    /* init comm module */
     comm_init();
     comm_select_init();
 
-    /* we have to init fdstat here. */
-    fd_open(0, FD_LOG, "stdin");
-    fd_open(1, FD_LOG, "stdout");
-    fd_open(2, FD_LOG, "stderr");
-
+    if (opt_no_daemon) {
+	/* we have to init fdstat here. */
+	fd_open(0, FD_LOG, "stdin");
+	fd_open(1, FD_LOG, "stdout");
+	fd_open(2, FD_LOG, "stderr");
+    }
     mainInitialize();
 
     /* main loop */
@@ -616,11 +656,6 @@
 {
     pid_t pid;
     debug_log = stderr;
-    if (ConfigFile == NULL)
-	ConfigFile = xstrdup(DefaultConfigFile);
-    cbdataInit();
-    memInit();
-    parseConfigFile(ConfigFile);
     pid = readPidFile();
     if (pid > 1) {
 	if (kill(pid, opt_send_signal) &&
@@ -652,32 +687,64 @@
     int status;
 #endif
     pid_t pid;
+    int i;
     if (*(argv[0]) == '(')
 	return;
+    openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
+    if ((pid = fork()) < 0)
+	syslog(LOG_ALERT, "fork failed: %s", xstrerror());
+    else if (pid > 0)
+	exit(0);
+    if (setsid() < 0)
+	syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
+#ifdef TIOCNOTTY
+    if ((i = open("/dev/tty", O_RDWR)) >= 0) {
+	ioctl(i, TIOCNOTTY, NULL);
+	close(i);
+    }
+#endif
+    for (i = 0; i < Squid_MaxFD; i++)
+	close(i);
+#if NOT_NEEDED
+    umask(0);
+#endif
     for (;;) {
-	if (fork() == 0) {
+	if ((pid = fork()) == 0) {
 	    /* child */
 	    prog = xstrdup(argv[0]);
 	    argv[0] = xstrdup("(squid)");
 	    execvp(prog, argv);
-	    fatal("execvp failed");
+	    syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
 	}
-	/* parent */ time(&start);
-	do {
-	    squid_signal(SIGINT, SIG_IGN, SA_RESTART);
+	/* parent */
+	syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
+	time(&start);
+	squid_signal(SIGINT, SIG_IGN, SA_RESTART);
 #ifdef _SQUID_NEXT_
-	    pid = wait3(&status, 0, NULL);
+	pid = wait3(&status, 0, NULL);
 #else
-	    pid = waitpid(-1, &status, 0);
+	pid = waitpid(-1, &status, 0);
 #endif
-	} while (pid > 0);
 	time(&stop);
+	if (WIFEXITED(status)) {
+	    syslog(LOG_NOTICE,
+		"Squid Parent: child process %d exited with status %d",
+		pid, WEXITSTATUS(status));
+	} else if (WIFSIGNALED(status)) {
+	    syslog(LOG_NOTICE,
+		"Squid Parent: child process %d exited due to signal %d",
+		pid, WTERMSIG(status));
+	} else {
+	    syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
+	}
 	if (stop - start < 10)
 	    failcount++;
 	else
 	    failcount = 0;
-	if (failcount == 5)
+	if (failcount == 5) {
+	    syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
 	    exit(1);
+	}
 	if (WIFEXITED(status))
 	    if (WEXITSTATUS(status) == 0)
 		exit(0);
@@ -706,11 +773,20 @@
     releaseServerSockets();
     commCloseAllSockets();
     unlinkdClose();
+#if USE_ASYNC_IO
+    aioSync();			/* flush pending object writes / unlinks */
+#endif
     storeDirWriteCleanLogs(0);
     PrintRusage();
     dumpMallocStats();
+#if USE_ASYNC_IO
+    aioSync();			/* flush log writes */
+#endif
     storeLogClose();
     accessLogClose();
+#if USE_ASYNC_IO
+    aioSync();			/* flush log close */
+#endif
 #if PURIFY || XMALLOC_TRACE
     configFreeMemory();
     storeFreeMemory();
@@ -722,17 +798,20 @@
     clientdbFreeMemory();
     httpHeaderCleanModule();
     statFreeMemory();
+    eventFreeMemory();
     mimeFreeMemory();
     errorClean();
 #endif
-    memClean();
 #if !XMALLOC_TRACE
-    file_close(0);
-    file_close(1);
-    file_close(2);
+    if (opt_no_daemon) {
+	file_close(0);
+	file_close(1);
+	file_close(2);
+    }
 #endif
     fdDumpOpen();
     fdFreeMemory();
+    memClean();
 #if XMALLOC_TRACE
     xmalloc_find_leaks();
     debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
Index: squid/src/mem.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mem.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/mem.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/mem.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: mem.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -127,9 +127,9 @@
     return memPoolAlloc(MemPools[type]);
 }
 
-/* find appropriate pool and use it */
+/* give memory back to the pool */
 void
-memFree(mem_type type, void *p)
+memFree(void *p, int type)
 {
     memPoolFree(MemPools[type], p);
 }
@@ -216,6 +216,9 @@
     memDataInit(MEM_COMMWRITESTATEDATA, "CommWriteStateData",
 	sizeof(CommWriteStateData), 0);
     memDataInit(MEM_CONNSTATEDATA, "ConnStateData", sizeof(ConnStateData), 0);
+#if USE_CACHE_DIGESTS
+    memDataInit(MEM_DIGEST_FETCH_STATE, "DigestFetchState", sizeof(DigestFetchState), 0);
+#endif
     memDataInit(MEM_DISK_BUF, "Disk I/O Buffer", DISK_PAGE_SIZE, 200);
     memDataInit(MEM_DLINK_LIST, "dlink_list", sizeof(dlink_list), 10);
     memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10);
@@ -257,10 +260,11 @@
     memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0);
     memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0);
     memDataInit(MEM_NET_DB_PEER, "net_db_peer", sizeof(net_db_peer), 0);
+    memDataInit(MEM_PEER, "peer", sizeof(peer), 0);
 #if USE_CACHE_DIGESTS
+    memDataInit(MEM_PEER_DIGEST, "PeerDigest", sizeof(PeerDigest), 0);
     memDataInit(MEM_DIGEST_FETCH_STATE, "DigestFetchState", sizeof(DigestFetchState), 0);
 #endif
-    memDataInit(MEM_PEER, "peer", sizeof(peer), 0);
     memDataInit(MEM_PINGERECHODATA, "pingerEchoData",
 	sizeof(pingerEchoData), 0);
     memDataInit(MEM_PINGERREPLYDATA, "pingerReplyData",
@@ -274,7 +278,7 @@
     memDataInit(MEM_SQUIDCONFIG2, "SquidConfig2", sizeof(SquidConfig2), 0);
     memDataInit(MEM_STATCOUNTERS, "StatCounters", sizeof(StatCounters), 0);
     memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE,
-	Config.Mem.maxSize / SM_PAGE_SIZE);
+	Config.memMaxSize / SM_PAGE_SIZE);
     memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0);
     memDataInit(MEM_STORE_CLIENT, "store_client", sizeof(store_client), 0);
     memDataInit(MEM_SWAPDIR, "SwapDir", sizeof(SwapDir), 0);
@@ -293,7 +297,7 @@
 	    continue;
 	/*
 	 * If you hit this assertion, then you forgot to add a
-	 * memDataInit() line for type 't' above.
+	 * memDataInit() line for type 't'.
 	 */
 	assert(MemPools[t]);
     }
@@ -323,23 +327,23 @@
 void
 memFree2K(void *p)
 {
-    memFree(MEM_2K_BUF, p);
+    memFree(p, MEM_2K_BUF);
 }
 
 void
 memFree4K(void *p)
 {
-    memFree(MEM_4K_BUF, p);
+    memFree(p, MEM_4K_BUF);
 }
 
 void
 memFree8K(void *p)
 {
-    memFree(MEM_8K_BUF, p);
+    memFree(p, MEM_8K_BUF);
 }
 
 void
 memFreeDISK(void *p)
 {
-    memFree(MEM_DISK_BUF, p);
+    memFree(p, MEM_DISK_BUF);
 }
Index: squid/src/mib.txt
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mib.txt,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/mib.txt	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/mib.txt	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 SQUID-MIB  DEFINITIONS ::= BEGIN
 --
--- $Id: mib.txt,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+-- $Id: mib.txt,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
 --
 
 IMPORTS
@@ -36,24 +36,12 @@
     REVISION      "9809220000Z"
     DESCRIPTION
 		"Move to SMIv2. Prepare to split into proxy/squid."
+    REVISION      "9901010000Z"
+    DESCRIPTION
+		"Added objects and corrected asn.1 syntax and 
+		descriptions."
     ::= { nlanr 1 }
 
--- v 1.16 1998/09/22 glenn@ircache.net
-
---
---     This is a hack to get around a problem with the current
---     version of the SNMP library. Remove the following seven lines
---     before using with SNMP tools.
---
-
-org            OBJECT IDENTIFIER ::= { iso 1 }
-dod            OBJECT IDENTIFIER ::= { org 6 }
-internet       OBJECT IDENTIFIER ::= { dod 1 }
-private        OBJECT IDENTIFIER ::= { internet 4 }
-enterprises    OBJECT IDENTIFIER ::= { private 1 }
-nlanr          OBJECT IDENTIFIER ::= { enterprises 3495 }
-squid          OBJECT IDENTIFIER ::= { nlanr 1 }
-
 --
 -- OID Assignments
 --
@@ -74,7 +62,7 @@
 		MAX-ACCESS read-only
 		STATUS current
 		DESCRIPTION
-			" Virtual Memory size in KB"
+			" Storage Mem size in KB"
 	::= { cacheSystem 1 }
 
 	cacheSysStorage OBJECT-TYPE
@@ -82,7 +70,7 @@
 		MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Diskspace in KB"
+                        " Storage Swap size in KB"
         ::= { cacheSystem 2 }
 
 	cacheUptime  OBJECT-TYPE
@@ -90,7 +78,7 @@
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Number of timeticks since cache started "
+                        " The Uptime of the cache in timeticks"
 	::= { cacheSystem 3 }
 
 --
@@ -142,48 +130,32 @@
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Cache Memory Maximum Size "
+                        " The value of the cache_mem parameter in MB"
         ::= { cacheStorageConfig 1 }
 
-	cacheMemHighWM OBJECT-TYPE
-                SYNTAX Integer32
-                MAX-ACCESS read-only
-                STATUS current
-                DESCRIPTION
-                        " Cache Memory High Water Mark "
-        ::= { cacheStorageConfig 2 }
-
-        cacheMemLowWM OBJECT-TYPE
-                SYNTAX Integer32
-                MAX-ACCESS read-only
-                STATUS current
-                DESCRIPTION
-                        " Cache Memory Low Water Mark "
-        ::= { cacheStorageConfig 3 }
-
         cacheSwapMaxSize OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Cache Swap Maximum Size "
-        ::= { cacheStorageConfig 4 }
+                        " The total of the cache_dir space allocated in MB"
+        ::= { cacheStorageConfig 2 }
 
         cacheSwapHighWM OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Cache Swap High Water Mark "
-        ::= { cacheStorageConfig 5 }
+                        " Cache Swap High Water Mark"
+        ::= { cacheStorageConfig 3 }
 
         cacheSwapLowWM OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Cache Swap Low Water Mark "
-        ::= { cacheStorageConfig 6 }
+                        " Cache Swap Low Water Mark"
+        ::= { cacheStorageConfig 4 }
 
 -- end of  cacheStorageConfig group
 
@@ -203,7 +175,7 @@
                 MAX-ACCESS read-only
                 STATUS current
                 DESCRIPTION
-                        " Number of system page faults "
+                        " Page faults with physical i/o"
         ::= { cacheSysPerf 1 }
 
         cacheSysNumReads OBJECT-TYPE
@@ -211,39 +183,39 @@
                 MAX-ACCESS not-accessible
                 STATUS current 
                 DESCRIPTION
-                        " Number of Reads " 
+                        " HTTP I/O number of reads" 
        	::= { cacheSysPerf 2 }
 
-        cacheSysDefReads OBJECT-TYPE
-                SYNTAX Counter32
-                MAX-ACCESS not-accessible
-                STATUS current
-		DESCRIPTION
-			" see cachemgr "
-       	::= { cacheSysPerf 3 }
-
 	cacheMemUsage OBJECT-TYPE
 		SYNTAX Integer32
 		MAX-ACCESS read-only
 		STATUS 	current
 		DESCRIPTION
-			" Amount of system memory allocated by the cache"
-	::= { cacheSysPerf 4 } 
+			" Total memory accounted for KB"
+	::= { cacheSysPerf 3 } 
 
-	cacheCpuUsage OBJECT-TYPE
+	cacheCpuTime OBJECT-TYPE
 		SYNTAX Integer32
 		MAX-ACCESS read-only
                 STATUS  current
                 DESCRIPTION
                         " Amount of cpu seconds consumed"
-	::= { cacheSysPerf 5 }
+	::= { cacheSysPerf 4 }
+
+	cacheCpuUsage OBJECT-TYPE
+                SYNTAX Integer32
+                MAX-ACCESS read-only
+                STATUS  current
+                DESCRIPTION
+                        " The percentage use of the CPU"
+        ::= { cacheSysPerf 5 }
 
 	cacheMaxResSize OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS  current
                 DESCRIPTION
-                        " Maximum Resident Size"
+                        " Maximum Resident Size in KB"
         ::= { cacheSysPerf 6 }
 
 	cacheNumObjCount OBJECT-TYPE
@@ -251,31 +223,39 @@
 		MAX-ACCESS read-only
                 STATUS  current
                 DESCRIPTION
-                        " Number of objects "
+                        " Number of objects stored by the cache"
         ::= { cacheSysPerf 7 }
 
         cacheCurrentLRUExpiration OBJECT-TYPE
                 SYNTAX TimeTicks
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Storage LRU Expiration Age"
         ::= { cacheSysPerf 8 }
 
         cacheCurrentUnlinkRequests OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Requests given to unlinkd"
         ::= { cacheSysPerf 9 }
 
         cacheCurrentUnusedFileDescrCount OBJECT-TYPE
                 SYNTAX Gauge32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Available number of file descriptors"
         ::= { cacheSysPerf 10 }
 
 	cacheCurrentReservedFileDescrCount  OBJECT-TYPE
                 SYNTAX Gauge32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Reserved number of file descriptors"
         ::= { cacheSysPerf 11 }
 
 	--
@@ -292,86 +272,121 @@
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Number of HTTP requests received"
         ::= { cacheProtoAggregateStats 1 }
 
         cacheHttpHits OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Number of HTTP Hits"
         ::= { cacheProtoAggregateStats 2 }
 
         cacheHttpErrors OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Number of HTTP Errors"
         ::= { cacheProtoAggregateStats 3 }
 
         cacheHttpInKb OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+			" Number of HTTP KB's recieved"
         ::= { cacheProtoAggregateStats 4 }
 
         cacheHttpOutKb OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Number of HTTP KB's transmitted"
         ::= { cacheProtoAggregateStats 5 }
 
 	cacheIcpPktsSent OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Number of ICP messages sent"
         ::= { cacheProtoAggregateStats 6 }
 
 	cacheIcpPktsRecv OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Number of ICP messages received"
         ::= { cacheProtoAggregateStats 7 }
 
         cacheIcpKbSent OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Number of ICP KB's transmitted"
         ::= { cacheProtoAggregateStats 8 }
 
         cacheIcpKbRecv OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Number of ICP KB's recieved"
         ::= { cacheProtoAggregateStats 9 }
 
         cacheServerRequests OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " All requests from the client for the cache server"
         ::= { cacheProtoAggregateStats 10 }
 
         cacheServerErrors OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " All errors for the cache server from client requests"
         ::= { cacheProtoAggregateStats 11 }
 
 	cacheServerInKb OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " KB's of traffic recieved from servers"
         ::= { cacheProtoAggregateStats 12 }
 
         cacheServerOutKb OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " KB's of traffic sent to servers"
         ::= { cacheProtoAggregateStats 13 }
 
 	cacheCurrentSwapSize OBJECT-TYPE
                 SYNTAX Counter32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " Storage Swap size"
         ::= { cacheProtoAggregateStats 14 }
 
+       cacheClients OBJECT-TYPE
+                SYNTAX Counter32
+                MAX-ACCESS read-only
+                STATUS current
+		DESCRIPTION
+                        " Number of clients accessing cache"
+        ::= { cacheProtoAggregateStats 15 }
 
 	--
 	-- cacheProtoMedianSvcStats group
@@ -402,57 +417,91 @@
 		cacheHttpHitSvcTime 	Integer32,
 		cacheIcpQuerySvcTime 	Integer32,
 		cacheIcpReplySvcTime 	Integer32,
-		cacheDnsSvcTime		Integer32
+		cacheDnsSvcTime		Integer32,
+		cacheRequestHitRatio	Integer32,
+		cacheRequestByteRatio	Integer32
 	}
 
 	cacheMedianTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " The value used to index the table 1/5/60"
         ::= { cacheMedianSvcEntry 1 }
 
 	cacheHttpAllSvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " HTTP all service time" 
         ::= { cacheMedianSvcEntry 2 } 
 
 	cacheHttpMissSvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " HTTP miss service time"
         ::= { cacheMedianSvcEntry 3 } 
 
 	cacheHttpNmSvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " HTTP near miss service time"
         ::= { cacheMedianSvcEntry 4 } 
 
 	cacheHttpHitSvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " HTTP hit service time"
         ::= { cacheMedianSvcEntry 5 } 
 
 	cacheIcpQuerySvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " ICP query service time"
         ::= { cacheMedianSvcEntry 6 } 
 
 	cacheIcpReplySvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " ICP reply service time"
         ::= { cacheMedianSvcEntry 7 } 
 
 	cacheDnsSvcTime OBJECT-TYPE
                 SYNTAX Integer32
                 MAX-ACCESS read-only
                 STATUS current
+		DESCRIPTION
+                        " DNS service time"
         ::= { cacheMedianSvcEntry 8 } 
 
+        cacheRequestHitRatio OBJECT-TYPE
+                SYNTAX Integer32
+                MAX-ACCESS read-only
+                STATUS current
+		DESCRIPTION
+                        " Request Hit Ratios"
+        ::= { cacheMedianSvcEntry 9 }
+
+        cacheRequestByteRatio OBJECT-TYPE
+                SYNTAX Integer32
+                MAX-ACCESS read-only
+                STATUS current
+		DESCRIPTION
+                        " Byte Hit Ratios"
+        ::= { cacheMedianSvcEntry 10 }
+
 --
 -- cacheNetwork group
 --
@@ -516,11 +565,6 @@
                 STATUS current
         ::= { cacheIpCache 8 } 
 
-	cacheQueueLength OBJECT-TYPE
-                SYNTAX Gauge32
-                MAX-ACCESS read-only
-                STATUS current
-        ::= { cacheIpCache 9 } 
 --
 -- cacheFqdnCache
 --
@@ -567,12 +611,6 @@
                 STATUS current
         ::= { cacheFqdnCache 7 } 
 
-	cacheQueueLength OBJECT-TYPE
-                SYNTAX Gauge32
-                MAX-ACCESS read-only
-                STATUS current
-        ::= { cacheFqdnCache 8 } 
-
 --
 --	cacheDNS 
 --
Index: squid/src/mime.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/mime.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/mime.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/mime.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mime.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: mime.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 25    MIME Parsing
  * AUTHOR: Harvest Derived
@@ -84,11 +84,11 @@
     for (p = mime; *p; p += strcspn(p, "\n\r")) {
 	if (strcmp(p, "\r\n\r\n") == 0 || strcmp(p, "\n\n") == 0)
 	    return NULL;
-	while (isspace(*p))
+	while (xisspace(*p))
 	    p++;
 	if (strncasecmp(p, name, namelen))
 	    continue;
-	if (!isspace(p[namelen]) && p[namelen] != ':')
+	if (!xisspace(p[namelen]) && p[namelen] != ':')
 	    continue;
 	l = strcspn(p, "\n\r") + 1;
 	if (l > GET_HDR_SZ)
@@ -99,12 +99,12 @@
 	q += namelen;
 	if (*q == ':')
 	    q++, got = 1;
-	while (isspace(*q))
+	while (xisspace(*q))
 	    q++, got = 1;
 	if (got && prefix) {
 	    /* we could process list entries here if we had strcasestr(). */
 	    /* make sure we did not match a part of another field-value */
-	    got = !strncasecmp(q, prefix, preflen) && !isalpha(q[preflen]);
+	    got = !strncasecmp(q, prefix, preflen) && !xisalpha(q[preflen]);
 	}
 	if (got) {
 	    debug(25, 5) ("mime_get_header: returning '%s'\n", q);
@@ -393,6 +393,7 @@
     LOCAL_ARRAY(char, url, MAX_URL);
     char *buf;
     const char *type = mimeGetContentType(icon);
+    HttpReply *reply;
     if (type == NULL)
 	fatal("Unknown icon format while reading mime.conf\n");
     buf = internalLocalUri("/squid-internal-static/icons/", icon);
@@ -416,21 +417,24 @@
 	flags,
 	METHOD_GET);
     assert(e != NULL);
+    storeSetPublicKey(e);
     e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
-    httpReplyReset(e->mem_obj->reply);
-    httpReplySetHeaders(e->mem_obj->reply, 1.0, HTTP_OK, NULL,
-	type, (int) sb.st_size, sb.st_mtime, squid_curtime + 86400);
-    httpReplySwapOut(e->mem_obj->reply, e);
+    httpReplyReset(reply = e->mem_obj->reply);
+    httpReplySetHeaders(reply, 1.0, HTTP_OK, NULL,
+	type, (int) sb.st_size, sb.st_mtime, -1);
+    reply->cache_control = httpHdrCcCreate();
+    httpHdrCcSetMaxAge(reply->cache_control, 86400);
+    httpHeaderPutCc(&reply->header, reply->cache_control);
+    httpReplySwapOut(reply, e);
     /* read the file into the buffer and append it to store */
     buf = memAllocate(MEM_4K_BUF);
     while ((n = read(fd, buf, 4096)) > 0)
 	storeAppend(e, buf, n);
     file_close(fd);
-    storeSetPublicKey(e);
     storeComplete(e);
     storeTimestampsSet(e);
     EBIT_SET(e->flags, ENTRY_SPECIAL);
     debug(25, 3) ("Loaded icon %s\n", url);
     storeUnlockObject(e);
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
 }
Index: squid/src/mime.conf
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Attic/mime.conf,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/mime.conf	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/mime.conf	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -116,6 +116,8 @@
 \.mwrt$		application/macwriteii		anthony-unknown.gif		-		image
 \.msw$		application/msword		anthony-unknown.gif		-		image
 \.doc$		application/msword		anthony-unknown.gif	-	image	+view
+\.xls$		application/msexcel		anthony-unknown.gif	-	image
+\.wk[s1234]$	application/vnd.lotus-1-2-3	anthony-unknown.gif	-	image
 \.mif$		application/x-mif		anthony-unknown.gif		-		image
 \.sit$		application/stuffit		anthony-unknown.gif		-		image
 \.pict$		application/pict		anthony-image.gif		-		image
@@ -127,5 +129,6 @@
 README		text/plain			anthony-text.gif	-	ascii	+download
 ^core$		application/octet-stream	anthony-bomb.gif		-		image
 \.core$		application/octet-stream	anthony-bomb.gif		-		image
+\.png$		image/png			anthony-image.gif		-		image
 # the default
 .		text/plain			anthony-unknown.gif	-	image	+view +download
Index: squid/src/neighbors.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/neighbors.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/neighbors.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/neighbors.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: neighbors.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -132,21 +132,22 @@
 	if (request->flags.need_validation)
 	    return 0;
     }
-    if (p->pinglist == NULL && p->access == NULL)
+    if (p->peer_domain == NULL && p->access == NULL)
 	return do_ping;
     do_ping = 0;
-    for (d = p->pinglist; d; d = d->next) {
+    for (d = p->peer_domain; d; d = d->next) {
 	if (matchDomainName(d->domain, request->host)) {
 	    do_ping = d->do_ping;
 	    break;
 	}
 	do_ping = !d->do_ping;
     }
-    if (p->pinglist && 0 == do_ping)
+    if (p->peer_domain && 0 == do_ping)
 	return do_ping;
     if (p->access == NULL)
 	return do_ping;
     checklist.src_addr = request->client_addr;
+    checklist.my_addr = request->my_addr;
     checklist.request = request;
     return aclCheckFast(p->access, &checklist);
 }
@@ -317,7 +318,7 @@
     }
     if (p) {
 	*P = p->next;
-	peerDestroy(p);
+	cbdataFree(p);
 	Config.npeers--;
     }
     first_ping = Config.peers;
@@ -438,6 +439,18 @@
 	     * last query
 	     */
 	    p->stats.last_reply = squid_curtime;
+	    /*
+	     * We used to not expect a reply in this case; we assumed
+	     * the peer was DEAD if we hadn't queried it in a long
+	     * time.  However, the number of people whining to
+	     * squid-users that ICP is broken became unbearable.  They
+	     * tried a single request which, to their amazement, was
+	     * forwarded directly to the origin server, even thought
+	     * they KNEW it was in a neighbor cache.  Ok, I give up, you
+	     * win!
+	     */
+	    (*exprep)++;
+	    (*timeout) += 1000;
 	} else if (neighborUp(p)) {
 	    /* its alive, expect a reply from it */
 	    (*exprep)++;
@@ -510,31 +523,28 @@
     assert(request);
     debug(15, 5) ("peerDigestLookup: peer %s\n", p->host);
     /* does the peeer have a valid digest? */
-    if (p->digest.flags.disabled) {
-	debug(15, 5) ("peerDigestLookup: Disabled!\n");
+    if (!p->digest) {
+	debug(15, 5) ("peerDigestLookup: gone!\n");
 	return LOOKUP_NONE;
     } else if (!peerHTTPOkay(p, request)) {
-	debug(15, 5) ("peerDigestLookup: !peerHTTPOkay()\n");
+	debug(15, 5) ("peerDigestLookup: !peerHTTPOkay\n");
 	return LOOKUP_NONE;
-    } else if (p->digest.flags.usable) {
-	debug(15, 5) ("peerDigestLookup: Usable!\n");
+    } else if (p->digest->flags.usable) {
+	debug(15, 5) ("peerDigestLookup: usable\n");
 	/* fall through; put here to have common case on top */ ;
-    } else if (!p->digest.flags.inited) {
-	debug(15, 5) ("peerDigestLookup: !initialized\n");
-	if (!p->digest.flags.init_pending) {
-	    p->digest.flags.init_pending = 1;
-	    cbdataLock(p);
-	    eventAdd("peerDigestInit", peerDigestInit, p, 0.0, 1);
-	}
+    } else if (!p->digest->flags.needed) {
+	debug(15, 5) ("peerDigestLookup: note need\n");
+	peerDigestNeeded(p->digest);
 	return LOOKUP_NONE;
     } else {
-	debug(15, 5) ("peerDigestLookup: Whatever!\n");
+	debug(15, 5) ("peerDigestLookup: !ready && %srequested\n",
+	    p->digest->flags.requested ? "" : "!");
 	return LOOKUP_NONE;
     }
     debug(15, 5) ("peerDigestLookup: OK to lookup peer %s\n", p->host);
-    assert(p->digest.cd);
+    assert(p->digest->cd);
     /* does digest predict a hit? */
-    if (!cacheDigestTest(p->digest.cd, key))
+    if (!cacheDigestTest(p->digest->cd, key))
 	return LOOKUP_MISS;
     debug(15, 5) ("peerDigestLookup: peer %s says HIT!\n", p->host);
     return LOOKUP_HIT;
@@ -555,7 +565,8 @@
     peer *p;
     int p_rtt;
     int i;
-
+    if (!request->flags.hierarchical)
+	return NULL;
     key = storeKeyPublic(storeUrl(entry), request->method);
     for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
 	lookup_t lookup;
@@ -844,6 +855,20 @@
     return p;
 }
 
+peer *
+peerFindByNameAndPort(const char *name, unsigned short port)
+{
+    peer *p = NULL;
+    for (p = Config.peers; p; p = p->next) {
+	if (strcasecmp(name, p->host))
+	    continue;
+	if (port != p->http_port)
+	    continue;
+	break;
+    }
+    return p;
+}
+
 int
 neighborUp(const peer * p)
 {
@@ -857,19 +882,39 @@
 }
 
 void
-peerDestroy(peer * p)
+peerDestroy(void *data, int unused)
 {
+    peer *p = data;
     struct _domain_ping *l = NULL;
     struct _domain_ping *nl = NULL;
     if (p == NULL)
 	return;
-    for (l = p->pinglist; l; l = nl) {
+    for (l = p->peer_domain; l; l = nl) {
 	nl = l->next;
 	safe_free(l->domain);
 	safe_free(l);
     }
     safe_free(p->host);
-    cbdataFree(p);
+#if USE_CACHE_DIGESTS
+    if (p->digest) {
+	PeerDigest *pd = p->digest;
+	p->digest = NULL;
+	cbdataUnlock(pd);
+    }
+#endif
+    xfree(p);
+}
+
+void
+peerNoteDigestGone(peer * p)
+{
+#if USE_CACHE_DIGESTS
+    if (p->digest) {
+	PeerDigest *pd = p->digest;
+	p->digest = NULL;
+	cbdataUnlock(pd);
+    }
+#endif
 }
 
 static void
@@ -915,7 +960,7 @@
 {
     peer *p = NULL;
     if (eventFind(peerRefreshDNS, NULL))
-	return;
+	eventDelete(peerRefreshDNS, NULL);
     if (!data && 0 == stat5minClientRequests()) {
 	/* no recent client traffic, wait a bit */
 	eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
@@ -1012,10 +1057,9 @@
     psstate->request = requestLink(urlParse(METHOD_GET, url));
     psstate->entry = fake;
     psstate->callback = NULL;
-    psstate->fail_callback = NULL;
     psstate->callback_data = p;
     psstate->ping.start = current_time;
-    cbdataAdd(psstate, MEM_NONE);
+    cbdataAdd(psstate, cbdataXfree, 0);
     mem = fake->mem_obj;
     mem->request = requestLink(psstate->request);
     mem->start_ping = current_time;
@@ -1056,7 +1100,7 @@
 	p->mcast.avg_n_members,
 	p->stats.rtt);
     p->mcast.n_replies_expected = (int) p->mcast.avg_n_members;
-    fake->store_status = STORE_ABORTED;
+    EBIT_SET(fake->flags, ENTRY_ABORTED);
     requestUnlink(fake->mem_obj->request);
     fake->mem_obj->request = NULL;
     storeReleaseRequest(fake);
@@ -1190,9 +1234,9 @@
 	    storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
 		mkhttpdlogtime(&(e->last_fail_time)));
 	}
-	if (e->pinglist != NULL) {
+	if (e->peer_domain != NULL) {
 	    storeAppendPrintf(sentry, "DOMAIN LIST: ");
-	    for (d = e->pinglist; d; d = d->next) {
+	    for (d = e->peer_domain; d; d = d->next) {
 		storeAppendPrintf(sentry, "%s%s ",
 		    d->do_ping ? null_string : "!", d->domain);
 	    }
Index: squid/src/net_db.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/net_db.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/net_db.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/net_db.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: net_db.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: net_db.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 38    Network Measurement Database
  * AUTHOR: Duane Wessels
@@ -126,7 +126,7 @@
     }
     hash_remove_link(host_table, (hash_link *) x);
     xfree(x->name);
-    memFree(MEM_NET_DB_NAME, (void *) x);
+    memFree((void *) x, MEM_NET_DB_NAME);
 }
 
 static netdbEntry *
@@ -152,7 +152,7 @@
     n->n_peers_alloc = 0;
     if (n->link_count == 0) {
 	netdbHashDelete(n->network);
-	memFree(MEM_NETDBENTRY, n);
+	memFree(n, MEM_NETDBENTRY);
     }
 }
 
@@ -460,7 +460,7 @@
 	}
 	count++;
     }
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
     fclose(fp);
     getCurrentTime();
     debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n",
@@ -484,7 +484,7 @@
 {
     netdbEntry *n = data;
     safe_free(n->peers);
-    memFree(MEM_NETDBENTRY, n);
+    memFree(n, MEM_NETDBENTRY);
 }
 
 static void
@@ -492,7 +492,7 @@
 {
     net_db_name *x = data;
     xfree(x->name);
-    memFree(MEM_NET_DB_NAME, x);
+    memFree(x, MEM_NET_DB_NAME);
 }
 
 static void
@@ -587,8 +587,8 @@
     debug(38, 3) ("netdbExchangeHandleReply: used %d entries, (x %d bytes) == %d bytes total\n",
 	nused, rec_sz, nused * rec_sz);
     debug(38, 3) ("netdbExchangeHandleReply: seen %d, used %d\n", ex->seen, ex->used);
-    if (ex->e->store_status == STORE_ABORTED) {
-	debug(38, 3) ("netdbExchangeHandleReply: STORE_ABORTED\n");
+    if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) {
+	debug(38, 3) ("netdbExchangeHandleReply: ENTRY_ABORTED\n");
 	netdbExchangeDone(ex);
     } else if (ex->e->store_status == STORE_PENDING) {
 	debug(38, 3) ("netdbExchangeHandleReply: STORE_PENDING\n");
@@ -609,7 +609,7 @@
 {
     netdbExchangeState *ex = data;
     debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex->e));
-    memFree(MEM_4K_BUF, ex->buf);
+    memFree(ex->buf, MEM_4K_BUF);
     requestUnlink(ex->r);
     storeUnregister(ex->e, ex);
     storeUnlockObject(ex->e);
@@ -650,7 +650,7 @@
 	if (n->next_ping_time > squid_curtime)
 	    return;
     h = xstrdup(hostname);
-    cbdataAdd(h, MEM_NONE);
+    cbdataAdd(h, cbdataXfree, 0);
     cbdataLock(h);
     ipcache_nbgethostbyname(hostname, netdbSendPing, h);
 #endif
@@ -668,6 +668,8 @@
     N = ++n->pings_recv;
     if (N > 5)
 	N = 5;
+    if (rtt < 1.0)
+	rtt = 1.0;
     n->hops = ((n->hops * (N - 1)) + hops) / N;
     n->rtt = ((n->rtt * (N - 1)) + rtt) / N;
     debug(38, 3) ("netdbHandlePingReply: %s; rtt=%5.1f  hops=%4.1f\n",
@@ -932,7 +934,7 @@
     }
     assert(0 == i);
     storeBufferFlush(s);
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
 #else
     httpReplyReset(reply);
     httpReplySetHeaders(reply, 1.0, HTTP_BAD_REQUEST, "Bad Request",
@@ -949,7 +951,7 @@
     peer *p = data;
     char *uri;
     netdbExchangeState *ex = xcalloc(1, sizeof(*ex));
-    cbdataAdd(ex, MEM_NONE);
+    cbdataAdd(ex, cbdataXfree, 0);
     cbdataLock(p);
     ex->p = p;
     uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb");
@@ -971,7 +973,7 @@
     storeClientCopy(ex->e, ex->seen, ex->used, ex->buf_sz,
 	ex->buf, netdbExchangeHandleReply, ex);
     ex->r->flags.loopdetect = 1;	/* cheat! -- force direct */
-    fwdStart(-1, ex->e, ex->r, no_addr);
+    fwdStart(-1, ex->e, ex->r, no_addr, no_addr);
 #endif
 }
 
Index: squid/src/pconn.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/pconn.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/pconn.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/pconn.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: pconn.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: pconn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 48    Persistent Connections
  * AUTHOR: Duane Wessels
@@ -181,7 +181,7 @@
     int *old;
     LOCAL_ARRAY(char, key, SQUIDHOSTNAMELEN + 10);
     LOCAL_ARRAY(char, desc, FD_DESC_SZ);
-    if (fdNFree() < (RESERVED_FD << 2)) {
+    if (fdNFree() < (RESERVED_FD << 1)) {
 	debug(48, 3) ("pconnPush: Not many unused FDs\n");
 	comm_close(fd);
 	return;
Index: squid/src/peer_digest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_digest.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/peer_digest.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/peer_digest.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_digest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: peer_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 72    Peer Digest Routines
  * AUTHOR: Alex Rousskov
@@ -40,235 +40,264 @@
 /* local types */
 
 /* local prototypes */
-static void peerDigestClean(peer * p);
-static time_t peerDigestNextDisDelay(const peer * p);
-static time_t peerDigestExpiresDelay(const peer * p, const StoreEntry * e);
-static void peerDigestDisable(peer * p);
-static void peerDigestDelay(peer * p, int disable, time_t delay);
-static EVH peerDigestValidate;
-static void peerDigestRequest(peer * p);
+static time_t peerDigestIncDelay(const PeerDigest * pd);
+static time_t peerDigestNewDelay(const StoreEntry * e);
+static void peerDigestSetCheck(PeerDigest * pd, time_t delay);
+static void peerDigestClean(PeerDigest *);
+static EVH peerDigestCheck;
+static void peerDigestRequest(PeerDigest * pd);
 static STCB peerDigestFetchReply;
-static void peerDigestRequest(peer * p);
 static STCB peerDigestSwapInHeaders;
 static STCB peerDigestSwapInCBlock;
 static STCB peerDigestSwapInMask;
 static int peerDigestFetchedEnough(DigestFetchState * fetch, char *buf, ssize_t size, const char *step_name);
-static void peerDigestFetchFinish(DigestFetchState * fetch, char *buf, const char *err_msg);
-static int peerDigestSetCBlock(peer * p, const char *buf);
-static int peerDigestUseful(const peer * peer);
-#define max_delay(t1,t2) ((t1) >= (t2) ? (t1) : (t2))
+static void peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason);
+static void peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason);
+static void peerDigestReqFinish(DigestFetchState * fetch, char *buf, int, int, int, const char *reason, int err);
+static void peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err);
+static void peerDigestFetchFinish(DigestFetchState * fetch, int err);
+static void peerDigestFetchSetStats(DigestFetchState * fetch);
+static int peerDigestSetCBlock(PeerDigest * pd, const char *buf);
+static int peerDigestUseful(const PeerDigest * pd);
 
 
 /* local constants */
 
 #define StoreDigestCBlockSize sizeof(StoreDigestCBlock)
 
-/* min interval for requesting digests from the same peer */
-static const time_t PeerDigestRequestMinGap = 5 * 60;	/* seconds */
-/* min interval for requesting digests at start */
-static const time_t GlobalDigestRequestMinGap = 1 * 60;		/* seconds */
+/* min interval for requesting digests from a given peer */
+static const time_t PeerDigestReqMinGap = 5 * 60;	/* seconds */
+/* min interval for requesting digests (cumulative request stream) */
+static const time_t GlobDigestReqMinGap = 1 * 60;	/* seconds */
 
 /* local vars */
 
-static time_t global_last_req_timestamp = 0;
+static time_t pd_last_req_time = 0;	/* last call to Check */
 
-/* always call cbdataLock() before calling this! */
-void
-peerDigestInit(void *data)
+/* initialize peer digest */
+static void
+peerDigestInit(PeerDigest * pd, peer * p)
 {
-    peer *p = data;
-    assert(p);
-    if (!cbdataValid(p)) {	/* peer disappeared */
-	cbdataUnlock(p);
-	return;
-    }
-    assert(p->digest.flags.init_pending);
-    assert(!p->digest.flags.inited);
-    assert(!p->digest.cd);
-    assert(SM_PAGE_SIZE == 4096);	/* we use MEM_4K_BUF */
-    if (p->options.no_digest) {
-	peerDigestClean(p);
-    } else {
-	peerDigestValidate(p);
-    }
-    p->digest.flags.inited = 1;
-    p->digest.flags.init_pending = 0;
+    assert(pd && p);
+
+    memset(pd, 0, sizeof(*pd));
+    pd->peer = p;
+    /* if peer disappears, we will know it's name */
+    stringInit(&pd->host, p->host);
+
+    pd->times.initialized = squid_curtime;
 }
 
-/* no pending events or requests should exist when you call this */
 static void
-peerDigestClean(peer * p)
+peerDigestClean(PeerDigest * pd)
 {
-    if (cbdataValid(p)) {
-	assert(!p->digest.flags.requested);
-	peerDigestDisable(p);
-    }
-    cbdataUnlock(p);
+    assert(pd);
+    if (pd->cd)
+	cacheDigestDestroy(pd->cd);
+    stringClean(&pd->host);
 }
 
+/* allocate new peer digest, call Init, and lock everything */
+PeerDigest *
+peerDigestCreate(peer * p)
+{
+    PeerDigest *pd;
+    assert(p);
+
+    pd = memAllocate(MEM_PEER_DIGEST);
+    cbdataAdd(pd, memFree, MEM_PEER_DIGEST);
+    peerDigestInit(pd, p);
+    cbdataLock(pd->peer);	/* we will use the peer */
+
+    return pd;
+}
+
+/* call Clean and free/unlock everything */
+void
+peerDigestDestroy(PeerDigest * pd)
+{
+    peer *p;
+    assert(pd);
+
+    p = pd->peer;
+    pd->peer = NULL;
+    /* inform peer (if any) that we are gone */
+    if (cbdataValid(p))
+	peerNoteDigestGone(p);
+    cbdataUnlock(p);		/* must unlock, valid or not */
+
+    peerDigestClean(pd);
+    cbdataFree(pd);
+}
+
+/* called by peer to indicate that somebody actually needs this digest */
+void
+peerDigestNeeded(PeerDigest * pd)
+{
+    assert(pd);
+    assert(!pd->flags.needed);
+    assert(!pd->cd);
+
+    pd->flags.needed = 1;
+    pd->times.needed = squid_curtime;
+    peerDigestSetCheck(pd, 0);	/* check asap */
+}
+
+/* currently we do not have a reason to disable without destroying */
+#if FUTURE_CODE
 /* disables peer for good */
 static void
-peerDigestDisable(peer * p)
+peerDigestDisable(PeerDigest * pd)
 {
-    peerDigestDelay(p, 1, -1);
+    debug(72, 2) ("peerDigestDisable: peer %s disabled for good\n",
+	strBuf(pd->host));
+    pd->times.disabled = squid_curtime;
+    pd->times.next_check = -1;	/* never */
+    pd->flags.usable = 0;
+
+    if (pd->cd) {
+	cacheDigestDestroy(pd->cd);
+	pd->cd = NULL;
+    }
+    /* we do not destroy the pd itself to preserve its "history" and stats */
 }
+#endif
 
-/* next delay for a disabled entry */
+/* increment retry delay [after an unsuccessful attempt] */
 static time_t
-peerDigestNextDisDelay(const peer * p)
+peerDigestIncDelay(const PeerDigest * pd)
 {
-    assert(p);
-    return p->digest.last_dis_delay ?
-	2 * p->digest.last_dis_delay :	/* exponential backoff */
-	PeerDigestRequestMinGap;	/* minimal delay */
+    assert(pd);
+    return pd->times.retry_delay > 0 ?
+	2 * pd->times.retry_delay :	/* exponential backoff */
+	PeerDigestReqMinGap;	/* minimal delay */
 }
 
-/* artificially increases expires to avoid race conditions */
+/* artificially increases Expires: setting to avoid race conditions 
+ * returns the delay till that [increased] expiration time */
 static time_t
-peerDigestExpiresDelay(const peer * p, const StoreEntry * e)
+peerDigestNewDelay(const StoreEntry * e)
 {
-    assert(p);
-    if (!e)
-	return 0;
+    assert(e);
     if (e->expires > 0)
-	return e->expires + PeerDigestRequestMinGap - squid_curtime;
-    return PeerDigestRequestMinGap;
+	return e->expires + PeerDigestReqMinGap - squid_curtime;
+    return PeerDigestReqMinGap;
 }
 
-
-/* delays/disables digest for a psecified delay (disables forever if negative delay) */
+/* registers next digest verification */
 static void
-peerDigestDelay(peer * p, int disable, time_t delay)
+peerDigestSetCheck(PeerDigest * pd, time_t delay)
 {
-    assert(p);
-    if (disable) {
-	p->digest.flags.disabled = 1;
-	p->digest.last_dis_delay = delay;
-    }
-    if (delay >= 0) {
-	assert(delay || !disable);
-	debug(72, 2) ("peerDigestDelay: %s: peer %s for %d secs till %s\n",
-	    disable ? "disabling" : "delaying",
-	    p->host ? p->host : "",
-	    delay, mkrfc1123(squid_curtime + delay));
-	eventAdd("peerDigestValidate", peerDigestValidate, p, (double) delay, 1);
+    eventAdd("peerDigestCheck", peerDigestCheck, pd, (double) delay, 1);
+    pd->times.next_check = squid_curtime + delay;
+    debug(72, 3) ("peerDigestSetCheck: will check peer %s in %d secs\n",
+	strBuf(pd->host), delay);
+}
+
+/*
+ * called when peer is about to disappear or have already disappeared
+ */
+void
+peerDigestNotePeerGone(PeerDigest * pd)
+{
+    if (pd->flags.requested) {
+	debug(72, 2) ("peerDigest: peer %s gone, will destroy after fetch.\n",
+	    strBuf(pd->host));
+	/* do nothing now, the fetching chain will notice and take action */
     } else {
-	assert(disable);
-	debug(72, 2) ("peerDigestDisable: disabling peer %s for good\n",
-	    p->host ? p->host : "");
-	/* just in case, will not need it anymore */
-	p->digest.flags.usable = 0;
+	debug(72, 2) ("peerDigest: peer %s is gone, destroying now.\n",
+	    strBuf(pd->host));
+	peerDigestDestroy(pd);
     }
 }
 
-/* request new digest if our copy is too old; schedule next validation */
+/* callback for eventAdd() (with peer digest locked)
+ * request new digest if our copy is too old or if we lack one; 
+ * schedule next check otherwise */
 static void
-peerDigestValidate(void *data)
+peerDigestCheck(void *data)
 {
-    peer *p = data;
-    StoreEntry *e = NULL;
-    int do_request;
-    time_t req_time = squid_curtime;
-    assert(p);
-    if (!cbdataValid(p)) {
-	peerDigestClean(p);
+    PeerDigest *pd = data;
+    time_t req_time;
+
+    /*
+     * you can't assert(cbdataValid(pd)) -- if its not valid this
+     * function never gets called
+     */
+    assert(!pd->flags.requested);
+
+    pd->times.next_check = 0;	/* unknown */
+
+    if (!cbdataValid(pd->peer)) {
+	peerDigestNotePeerGone(pd);
 	return;
     }
-    debug(72, 3) ("peerDigestValidate: digest %s\n", p->host);
-    debug(72, 3) ("current GMT time: %s\n", mkrfc1123(squid_curtime));
-    assert(!p->digest.flags.requested);
-    debug(72, 3) ("peerDigestValidate: %s was %s disabled\n",
-	p->host, p->digest.last_dis_delay ? "" : "not");
-    if (1 /* p->digest.cd */ ) {
-	const cache_key *key;
-	const char *u = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestUrlPath);
-	key = storeKeyPublic(u, METHOD_GET);
-	e = storeGet(key);
-	debug(72, 3) ("peerDigestValidate: %s store entry, key: %s, exp: %s\n",
-	    e ? "has" : "no", storeKeyText(key), mkrfc1123(e ? e->expires : 0));
-    }
-    /* currently we rely on entry->expire information */
-    {
-	const int loaded = p->digest.cd != NULL;
-	const time_t exp_delay = loaded ? peerDigestExpiresDelay(p, e) : 0;
-	do_request = exp_delay <= 0;
-	req_time = squid_curtime + exp_delay;
-	if (req_time < squid_curtime)
-	    req_time = squid_curtime;
-    }
-    /* do not request too often from one peer */
-    if (req_time - p->digest.last_req_timestamp < PeerDigestRequestMinGap) {
-	if (do_request) {
-	    debug(72, 2) ("peerDigestValidate: %s, avoiding too close peer requests (%d secs).\n",
-		p->host, req_time - p->digest.last_req_timestamp);
-	    do_request = 0;
-	}
-	req_time = p->digest.last_req_timestamp + PeerDigestRequestMinGap;
-    }
-    /* at start, do not request too often from all peers */
-    if (!p->digest.flags.inited &&
-	req_time - global_last_req_timestamp < GlobalDigestRequestMinGap) {
-	if (do_request) {
-	    debug(72, 2) ("peerDigestValidate: %s, avoiding too close requests (%d secs).\n",
-		p->host, req_time - global_last_req_timestamp);
-	    do_request = 0;
-	}
-	req_time = global_last_req_timestamp + GlobalDigestRequestMinGap;
-	/* otherwise we have all but one peer returning at the same moment @?@ */
-	debug(72, 5) ("peerDigestValidate: inc req_time (%+d) in anticipation of more reqs\n",
-	    (int) (req_time - global_last_req_timestamp));
-	global_last_req_timestamp = req_time;
-    }
-    /* start request if needed */
-    if (do_request) {
-	static int nest_level = 0;
-	nest_level++;
-	assert(nest_level == 1);
-	debug(72, 2) ("peerDigestValidate: %s requesting; old entry expires: %s\n",
-	    p->host, e ? mkrfc1123(e->expires) : "no entry");
-	/* will eventually disable digests or call peerDigest Delay */
-	peerDigestRequest(p);
-	nest_level--;
-    } else {
-	/* schedule next re-validation */
-	assert(req_time > squid_curtime);
-	peerDigestDelay(p, !p->digest.cd, req_time - squid_curtime);
-    }
+    debug(72, 3) ("peerDigestCheck: peer %s:%d\n", pd->peer->host, pd->peer->http_port);
+    debug(72, 3) ("peerDigestCheck: time: %d, last received: %d (%+d)\n",
+	squid_curtime, pd->times.received, (squid_curtime - pd->times.received));
+
+    /* decide when we should send the request:
+     * request now unless too close to other requests */
+    req_time = squid_curtime;
+
+    /* per-peer limit */
+    if (req_time - pd->times.received < PeerDigestReqMinGap) {
+	debug(72, 2) ("peerDigestCheck: %s, avoiding close peer requests (%d < %d secs).\n",
+	    strBuf(pd->host), req_time - pd->times.received,
+	    PeerDigestReqMinGap);
+	req_time = pd->times.received + PeerDigestReqMinGap;
+    }
+    /* global limit */
+    if (req_time - pd_last_req_time < GlobDigestReqMinGap) {
+	debug(72, 2) ("peerDigestCheck: %s, avoiding close requests (%d < %d secs).\n",
+	    strBuf(pd->host), req_time - pd_last_req_time,
+	    GlobDigestReqMinGap);
+	req_time = pd_last_req_time + GlobDigestReqMinGap;
+    }
+    if (req_time <= squid_curtime)
+	peerDigestRequest(pd);	/* will set pd->flags.requested */
+    else
+	peerDigestSetCheck(pd, req_time - squid_curtime);
 }
 
-/* ask peer cache for a fresh digest */
+/* ask store for a digest */
 static void
-peerDigestRequest(peer * p)
+peerDigestRequest(PeerDigest * pd)
 {
+    peer *p = pd->peer;
     StoreEntry *e, *old_e;
     char *url;
     const cache_key *key;
     request_t *req;
     DigestFetchState *fetch = NULL;
-    assert(p);
-    p->digest.flags.requested = 1;
+
+    pd->req_result = NULL;
+    pd->flags.requested = 1;
+
     /* compute future request components */
-    url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestUrlPath);
+    url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestFileName);
     key = storeKeyPublic(url, METHOD_GET);
     debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
     req = urlParse(METHOD_GET, url);
-    if (NULL == req) {
-	debug(72, 1) ("peerDigestRequest: Bad URI: %s\n", url);
-	return;			/* @?@ */
-    }
+    assert(req);
+
     /* add custom headers */
     assert(!req->header.len);
     httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr);
     httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html");
+
     /* create fetch state structure */
     fetch = memAllocate(MEM_DIGEST_FETCH_STATE);
-    cbdataAdd(fetch, MEM_DIGEST_FETCH_STATE);
-    cbdataLock(fetch);
+    cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE);
     fetch->request = requestLink(req);
-    fetch->peer = p;
+    fetch->pd = pd;
+    fetch->offset = 0;
+
+    /* update timestamps */
     fetch->start_time = squid_curtime;
-    p->digest.last_req_timestamp = squid_curtime;
-    global_last_req_timestamp = squid_curtime;
+    pd->times.requested = squid_curtime;
+    pd_last_req_time = squid_curtime;
+
     req->flags.cachable = 1;
     /* the rest is based on clientProcessExpired() */
     req->flags.refresh = 1;
@@ -280,38 +309,43 @@
 	storeClientListAdd(old_e, fetch);
     }
     e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method);
-    debug(72, 5) ("peerDigestRequest: new entry is private: %d\n",
-	(int) EBIT_TEST(e->flags, KEY_PRIVATE));
+    assert(EBIT_TEST(e->flags, KEY_PRIVATE));
     storeClientListAdd(e, fetch);
     /* set lastmod to trigger IMS request if possible */
     if (old_e)
 	e->lastmod = old_e->lastmod;
-    fetch->offset = 0;
-    debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
+
     /* push towards peer cache */
-    fwdStart(-1, e, req, no_addr);
-    storeClientCopy(e, 0, 0, SM_PAGE_SIZE, memAllocate(MEM_4K_BUF),
+    debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n");
+    fwdStart(-1, e, req, no_addr, no_addr);
+    cbdataLock(fetch);
+    cbdataLock(fetch->pd);
+    storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF),
 	peerDigestFetchReply, fetch);
 }
 
-/* waits for full http headers to be received and parses them */
+/* wait for full http headers to be received then parse them */
 static void
 peerDigestFetchReply(void *data, char *buf, ssize_t size)
 {
     DigestFetchState *fetch = data;
-    peer *peer = fetch->peer;
-    assert(peer && buf);
+    PeerDigest *pd = fetch->pd;
+    assert(pd && buf);
     assert(!fetch->offset);
+
     if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply"))
 	return;
+
     if (headersEnd(buf, size)) {
 	http_status status;
 	HttpReply *reply = fetch->entry->mem_obj->reply;
 	assert(reply);
 	httpReplyParse(reply, buf);
 	status = reply->sline.status;
-	debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %s\n",
-	    peer->host, status, mkrfc1123(reply->expires));
+	debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %d (%+d)\n",
+	    strBuf(pd->host), status,
+	    reply->expires, reply->expires - squid_curtime);
+
 	/* this "if" is based on clientHandleIMSReply() */
 	if (status == HTTP_NOT_MODIFIED) {
 	    request_t *r = NULL;
@@ -325,25 +359,16 @@
 	    storeTimestampsSet(fetch->old_entry);
 	    /* get rid of 304 reply */
 	    storeUnregister(fetch->entry, fetch);
-	    /* paranoid assert: storeUnregister should not call us recursively */
-	    assert(fetch->entry);
 	    storeUnlockObject(fetch->entry);
 	    fetch->entry = fetch->old_entry;
 	    fetch->old_entry = NULL;
 	    /* preserve request -- we need its size to update counters */
 	    /* requestUnlink(r); */
 	    /* fetch->entry->mem_obj->request = NULL; */
-	    assert(fetch->entry->mem_obj);
-	    /* kludge to make peerDigestFetchFinish think that we
-	     * fetched the whole thing while we are reusing old digest */
-	     if (fetch->peer->digest.cd) {
-		assert(!fetch->mask_offset);
-		fetch->mask_offset = peer->digest.cd->mask_size;
-	     }
 	} else if (status == HTTP_OK) {
 	    /* get rid of old entry if any */
 	    if (fetch->old_entry) {
-		debug(72, 3) ("peerDigestFetchReply: got new digest, requesting release of old digest\n");
+		debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n");
 		storeUnregister(fetch->old_entry, fetch);
 		storeReleaseRequest(fetch->old_entry);
 		storeUnlockObject(fetch->old_entry);
@@ -351,21 +376,20 @@
 	    }
 	} else {
 	    /* some kind of a bug */
-	    peerDigestFetchFinish(fetch, buf, httpStatusLineReason(&reply->sline));
+	    peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline));
 	    return;
 	}
 	/* must have a ready-to-use store entry if we got here */
-	/* can we stay with the old digest? */
-	if (status == HTTP_NOT_MODIFIED && fetch->peer->digest.cd)
-	    peerDigestFetchFinish(fetch, buf, NULL);
+	/* can we stay with the old in-memory digest? */
+	if (status == HTTP_NOT_MODIFIED && fetch->pd->cd)
+	    peerDigestFetchStop(fetch, buf, "Not modified");
 	else
 	    storeClientCopy(fetch->entry,	/* have to swap in */
 		0, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch);
-	return;
     } else {
 	/* need more data, do we have space? */
 	if (size >= SM_PAGE_SIZE)
-	    peerDigestFetchFinish(fetch, buf, "too big header");
+	    peerDigestFetchAbort(fetch, buf, "reply header too big");
 	else
 	    storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf,
 		peerDigestFetchReply, fetch);
@@ -377,12 +401,11 @@
 peerDigestSwapInHeaders(void *data, char *buf, ssize_t size)
 {
     DigestFetchState *fetch = data;
-    peer *peer;
     size_t hdr_size;
+
     if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInHeaders"))
 	return;
-    peer = fetch->peer;
-    assert(peer && buf);
+
     assert(!fetch->offset);
     if ((hdr_size = headersEnd(buf, size))) {
 	assert(fetch->entry->mem_obj->reply);
@@ -390,8 +413,8 @@
 	    httpReplyParse(fetch->entry->mem_obj->reply, buf);
 	if (fetch->entry->mem_obj->reply->sline.status != HTTP_OK) {
 	    debug(72, 1) ("peerDigestSwapInHeaders: %s status %d got cached!\n",
-		peer->host, fetch->entry->mem_obj->reply->sline.status);
-	    peerDigestFetchFinish(fetch, buf, "internal status error");
+		strBuf(fetch->pd->host), fetch->entry->mem_obj->reply->sline.status);
+	    peerDigestFetchAbort(fetch, buf, "internal status error");
 	    return;
 	}
 	fetch->offset += hdr_size;
@@ -401,7 +424,7 @@
     } else {
 	/* need more data, do we have space? */
 	if (size >= SM_PAGE_SIZE)
-	    peerDigestFetchFinish(fetch, buf, "too big stored header");
+	    peerDigestFetchAbort(fetch, buf, "stored header too big");
 	else
 	    storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf,
 		peerDigestSwapInHeaders, fetch);
@@ -412,33 +435,36 @@
 peerDigestSwapInCBlock(void *data, char *buf, ssize_t size)
 {
     DigestFetchState *fetch = data;
+
     if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestSwapInCBlock"))
 	return;
+
     if (size >= StoreDigestCBlockSize) {
-	peer *peer = fetch->peer;
+	PeerDigest *pd = fetch->pd;
 	HttpReply *rep = fetch->entry->mem_obj->reply;
 	const int seen = fetch->offset + size;
 
-	assert(peer && rep);
-	if (peerDigestSetCBlock(peer, buf)) {
+	assert(pd && rep);
+	if (peerDigestSetCBlock(pd, buf)) {
+	    /* XXX: soon we will have variable header size */
 	    fetch->offset += StoreDigestCBlockSize;
-	    /* switch to CD buffer */
-	    memFree(MEM_4K_BUF, buf);
+	    /* switch to CD buffer and fetch digest guts */
+	    memFree(buf, MEM_4K_BUF);
 	    buf = NULL;
-	    assert(peer->digest.cd->mask);
+	    assert(pd->cd->mask);
 	    storeClientCopy(fetch->entry,
 		seen,
 		fetch->offset,
-		peer->digest.cd->mask_size,
-		peer->digest.cd->mask,
+		pd->cd->mask_size,
+		pd->cd->mask,
 		peerDigestSwapInMask, fetch);
 	} else {
-	    peerDigestFetchFinish(fetch, buf, "invalid digest cblock");
+	    peerDigestFetchAbort(fetch, buf, "invalid digest cblock");
 	}
     } else {
 	/* need more data, do we have space? */
 	if (size >= SM_PAGE_SIZE)
-	    peerDigestFetchFinish(fetch, buf, "too big cblock");
+	    peerDigestFetchAbort(fetch, buf, "digest cblock too big");
 	else
 	    storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf,
 		peerDigestSwapInCBlock, fetch);
@@ -449,107 +475,206 @@
 peerDigestSwapInMask(void *data, char *buf, ssize_t size)
 {
     DigestFetchState *fetch = data;
-    peer *peer;
-    HttpReply *rep;
-    size_t buf_sz;
-    /*
-     * NOTE! buf points to the middle of peer->digest.cd->mask!
-     */
+    PeerDigest *pd;
+
+    /* NOTE! buf points to the middle of pd->cd->mask! */
     if (peerDigestFetchedEnough(fetch, NULL, size, "peerDigestSwapInMask"))
 	return;
 
-    peer = fetch->peer;
-    rep = fetch->entry->mem_obj->reply;
-    assert(peer && rep);
-    assert(peer->digest.cd && peer->digest.cd->mask);
+    pd = fetch->pd;
+    assert(pd->cd && pd->cd->mask);
 
     fetch->offset += size;
     fetch->mask_offset += size;
-    if (fetch->mask_offset >= peer->digest.cd->mask_size) {
+    if (fetch->mask_offset >= pd->cd->mask_size) {
 	debug(72, 2) ("peerDigestSwapInMask: Done! Got %d, expected %d\n",
-	    fetch->mask_offset, peer->digest.cd->mask_size);
-	assert(fetch->mask_offset == peer->digest.cd->mask_size);
-	peerDigestFetchFinish(fetch, NULL, NULL);
-	return;
+	    fetch->mask_offset, pd->cd->mask_size);
+	assert(fetch->mask_offset == pd->cd->mask_size);
+	assert(peerDigestFetchedEnough(fetch, NULL, 0, "peerDigestSwapInMask"));
+    } else {
+	const size_t buf_sz = pd->cd->mask_size - fetch->mask_offset;
+	assert(buf_sz > 0);
+	storeClientCopy(fetch->entry,
+	    fetch->offset,
+	    fetch->offset,
+	    buf_sz,
+	    pd->cd->mask + fetch->mask_offset,
+	    peerDigestSwapInMask, fetch);
     }
-    buf_sz = peer->digest.cd->mask_size - fetch->mask_offset;
-    assert(buf_sz > 0);
-    storeClientCopy(fetch->entry,
-	fetch->offset,
-	fetch->offset,
-	buf_sz,
-	peer->digest.cd->mask + fetch->mask_offset,
-	peerDigestSwapInMask, fetch);
 }
 
 static int
 peerDigestFetchedEnough(DigestFetchState * fetch, char *buf, ssize_t size, const char *step_name)
 {
-    const char *reason = NULL;
-    const char *no_bug = NULL;
+    PeerDigest *pd = NULL;
+    const char *host = "";	/* peer host */
+    const char *reason = NULL;	/* reason for completion */
+    const char *no_bug = NULL;	/* successful completion if set */
     const int fcb_valid = cbdataValid(fetch);
-    const int pcb_valid = fcb_valid && cbdataValid(fetch->peer);
+    const int pdcb_valid = fcb_valid && cbdataValid(fetch->pd);
+    const int pcb_valid = pdcb_valid && cbdataValid(fetch->pd->peer);
 
-    if (pcb_valid)
-	debug(72, 6) ("%s: %s offset: %d size: %d.\n",
-	    step_name, fetch->peer->host, fetch->offset, size);
-
-
-    /* test exiting conditions */
-    if (!fcb_valid)
-	reason = "fetch aborted?";
-    else if (!pcb_valid)
-	reason = "peer disappeared";
-    else if (size < 0)
-	reason = "swap failure";
-    else if (!size)
-	reason = no_bug = "eof";
-    else if (!fetch->entry)
-	reason = "swap abort(?)";
-    else if (fetch->entry->store_status == STORE_ABORTED)
-	reason = "swap abort";
+    /* test possible exiting conditions (the same for most steps!)
+     * cases marked with '?!' should not happen */
 
-    /* report exit reason */
+    if (!reason) {
+	if (!fcb_valid)
+	    reason = "fetch aborted?!";
+	else if (!(pd = fetch->pd))
+	    reason = "peer digest disappeared?!";
+#if DONT
+	else if (!cbdataValid(pd))
+	    reason = "invalidated peer digest?!";
+#endif
+	else
+	    host = strBuf(pd->host);
+    }
+    debug(72, 6) ("%s: peer %s, offset: %d size: %d.\n",
+	step_name, host, fcb_valid ? fetch->offset : -1, size);
+
+    /* continue checking (with pd and host known and valid) */
+    if (!reason) {
+	if (!cbdataValid(pd->peer))
+	    reason = "peer disappeared";
+	else if (size < 0)
+	    reason = "swap failure";
+	else if (!fetch->entry)
+	    reason = "swap aborted?!";
+	else if (EBIT_TEST(fetch->entry->flags, ENTRY_ABORTED))
+	    reason = "swap aborted";
+    }
+    /* continue checking (maybe-successful eof case) */
+    if (!reason && !size) {
+	if (!pd->cd)
+	    reason = "null digest?!";
+	else if (fetch->mask_offset != pd->cd->mask_size)
+	    reason = "premature end of digest?!";
+	else if (!peerDigestUseful(pd))
+	    reason = "useless digest";
+	else
+	    reason = no_bug = "success";
+    }
+    /* finish if we have a reason */
     if (reason) {
-	debug(72, pcb_valid ? 3 : 1) ("%s: exiting on %s\n", step_name, reason);
-	if (pcb_valid) {
-	    peerDigestFetchFinish(fetch, buf, no_bug ? NULL : reason);
+	const int level = strstr(reason, "?!") ? 1 : 3;
+	debug(72, level) ("%s: peer %s, exiting after '%s'\n",
+	    step_name, host, reason);
+	peerDigestReqFinish(fetch, buf,
+	    fcb_valid, pdcb_valid, pcb_valid, reason, !no_bug);
+    } else {
+	/* paranoid check */
+	assert(fcb_valid && pdcb_valid && pcb_valid);
+    }
+    return reason != NULL;
+}
+
+/* call this when all callback data is valid and fetch must be stopped but
+ * no error has occurred (e.g. we received 304 reply and reuse old digest) */
+static void
+peerDigestFetchStop(DigestFetchState * fetch, char *buf, const char *reason)
+{
+    assert(reason);
+    debug(72, 2) ("peerDigestFetchStop: peer %s, reason: %s\n",
+	strBuf(fetch->pd->host), reason);
+    peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 0);
+}
+
+/* call this when all callback data is valid but something bad happened */
+static void
+peerDigestFetchAbort(DigestFetchState * fetch, char *buf, const char *reason)
+{
+    assert(reason);
+    debug(72, 2) ("peerDigestFetchAbort: peer %s, reason: %s\n",
+	strBuf(fetch->pd->host), reason);
+    peerDigestReqFinish(fetch, buf, 1, 1, 1, reason, 1);
+}
+
+/* complete the digest transfer, update stats, unlock/release everything */
+static void
+peerDigestReqFinish(DigestFetchState * fetch, char *buf,
+    int fcb_valid, int pdcb_valid, int pcb_valid,
+    const char *reason, int err)
+{
+    assert(reason);
+
+    /* must go before peerDigestPDFinish */
+    if (pdcb_valid) {
+	fetch->pd->flags.requested = 0;
+	fetch->pd->req_result = reason;
+    }
+    /* schedule next check if peer is still out there */
+    if (pcb_valid) {
+	PeerDigest *pd = fetch->pd;
+	if (err) {
+	    pd->times.retry_delay = peerDigestIncDelay(pd);
+	    peerDigestSetCheck(pd, pd->times.retry_delay);
 	} else {
-	    /* XXX: this is probably wrong, but 
-	     * !fcb_valid implies !pcb_valid so we cannot access peer cbdata */
-	    if (fcb_valid) {
-		cbdataUnlock(fetch);
-		cbdataFree(fetch);
-	    } else {
-		cbdataUnlock(fetch);
-	    }
+	    pd->times.retry_delay = 0;
+	    peerDigestSetCheck(pd, peerDigestNewDelay(fetch->entry));
 	}
     }
-    return reason != NULL;
+    /* note: order is significant */
+    if (fcb_valid)
+	peerDigestFetchSetStats(fetch);
+    if (pdcb_valid)
+	peerDigestPDFinish(fetch, pcb_valid, err);
+    if (fcb_valid)
+	peerDigestFetchFinish(fetch, err);
+    if (buf)
+	memFree(buf, MEM_4K_BUF);
 }
 
-/* free state structures, disables digest on error
- * must be called only when peer and fetch cbdata's are valid */
+
+/* destroys digest if peer disappeared
+ * must be called only when fetch and pd cbdata are valid */
 static void
-peerDigestFetchFinish(DigestFetchState * fetch, char *buf, const char *err_msg)
+peerDigestPDFinish(DigestFetchState * fetch, int pcb_valid, int err)
 {
-    peer *peer = fetch->peer;
-    MemObject *mem = fetch->entry->mem_obj;
-    const time_t expires = fetch->entry->expires;
-    const time_t fetch_resp_time = squid_curtime - fetch->start_time;
-    const int b_read = (fetch->entry->store_status == STORE_PENDING) ?
-    mem->inmem_hi : mem->object_sz;
-    const int req_len = fetch->request ? httpRequestPrefixLen(fetch->request) : 0;
-    assert(fetch->request);
-    /* final checks */
-    if (!err_msg) {
-	if (!peer->digest.cd)
-	    err_msg = "null digest (internal bug?)";
-	else if (fetch->mask_offset != peer->digest.cd->mask_size)
-	    err_msg = "premature eof";
-	else if (!peerDigestUseful(peer))
-	    err_msg = "useless digest";
+    PeerDigest *pd = fetch->pd;
+    const char *host = strBuf(pd->host);
+
+    pd->times.received = squid_curtime;
+    pd->times.req_delay = fetch->resp_time;
+    kb_incr(&pd->stats.sent.kbytes, (size_t) fetch->sent.bytes);
+    kb_incr(&pd->stats.recv.kbytes, (size_t) fetch->recv.bytes);
+    pd->stats.sent.msgs += fetch->sent.msg;
+    pd->stats.recv.msgs += fetch->recv.msg;
+
+    if (err) {
+	debug(72, 1) ("%sdisabling (%s) digest from %s\n",
+	    pcb_valid ? "temporary " : "",
+	    pd->req_result, host);
+
+	if (pd->cd) {
+	    cacheDigestDestroy(pd->cd);
+	    pd->cd = NULL;
+	}
+	pd->flags.usable = 0;
+
+	if (!pcb_valid)
+	    peerDigestNotePeerGone(pd);
+    } else {
+	assert(pcb_valid);
+
+	pd->flags.usable = 1;
+
+	/* XXX: ugly condition, but how? */
+	if (fetch->entry->store_status == STORE_OK)
+	    debug(72, 2) ("re-used old digest from %s\n", host);
+	else
+	    debug(72, 2) ("received valid digest from %s\n", host);
     }
+    fetch->pd = NULL;
+    cbdataUnlock(pd);
+}
+
+/* free fetch state structures
+ * must be called only when fetch cbdata is valid */
+static void
+peerDigestFetchFinish(DigestFetchState * fetch, int err)
+{
+    assert(fetch->entry && fetch->request);
+
     if (fetch->old_entry) {
 	debug(72, 2) ("peerDigestFetchFinish: deleting old entry\n");
 	storeUnregister(fetch->old_entry, fetch);
@@ -557,74 +682,57 @@
 	storeUnlockObject(fetch->old_entry);
 	fetch->old_entry = NULL;
     }
-    assert(fetch->entry);
-    debug(72, 3) ("peerDigestFetchFinish: %s, read %d b, expires: %s lmt: %s\n",
-	peer->host, b_read,
-	mkrfc1123(fetch->entry->expires), mkrfc1123(fetch->entry->lastmod));
-    if (err_msg) {
-	debug(72, 1) ("disabling corrupted (%s) digest from %s\n",
-	    err_msg, peer->host);
-	if (peer->digest.cd) {
-	    cacheDigestDestroy(peer->digest.cd);
-	    peer->digest.cd = NULL;
-	}
-	/* disable for a while */
-	peer->digest.flags.usable = 0;
-	peerDigestDelay(peer, 1,
-	    max_delay(
-		peerDigestExpiresDelay(peer, fetch->entry),
-		peerDigestNextDisDelay(peer)));
-	/* release buggy entry */
-	storeReleaseRequest(fetch->entry);
-    } else {
-	/* ugly condition, but how? */
-	if (fetch->entry->store_status == STORE_OK) {
-	    debug(72, 2) ("re-used old digest from %s\n", peer->host);
-	} else {
-	    debug(72, 2) ("received valid digest from %s\n", peer->host);
-	}
-	peer->digest.flags.usable = 1;
-	peer->digest.flags.disabled = 0;
-	peer->digest.last_dis_delay = 0;
-	peerDigestDelay(peer, 0,
-	    max_delay(peerDigestExpiresDelay(peer, fetch->entry), 0));
-    }
     /* update global stats */
-    /* note: outgoing numbers are not precise! @?@ */
-    kb_incr(&Counter.cd.kbytes_sent, req_len);
-    kb_incr(&Counter.cd.kbytes_recv, (size_t) b_read);
-    Counter.cd.msgs_sent++;
-    Counter.cd.msgs_recv++;
-    /* update peer stats */
-    kb_incr(&peer->digest.stats.kbytes_sent, req_len);
-    kb_incr(&peer->digest.stats.kbytes_recv, (size_t) b_read);
-    peer->digest.stats.msgs_sent++;
-    peer->digest.stats.msgs_recv++;
+    kb_incr(&Counter.cd.kbytes_sent, (size_t) fetch->sent.bytes);
+    kb_incr(&Counter.cd.kbytes_recv, (size_t) fetch->recv.bytes);
+    Counter.cd.msgs_sent += fetch->sent.msg;
+    Counter.cd.msgs_recv += fetch->recv.msg;
+
     /* unlock everything */
     storeUnregister(fetch->entry, fetch);
     storeUnlockObject(fetch->entry);
     requestUnlink(fetch->request);
     fetch->entry = NULL;
     fetch->request = NULL;
+    assert(fetch->pd == NULL);
     cbdataUnlock(fetch);
     cbdataFree(fetch);
-    fetch = NULL;
-    if (buf)
-	memFree(MEM_4K_BUF, buf);
-    buf = NULL;
-    /* set it here and in peerDigestRequest to protect against long downloads */
-    peer->digest.last_req_timestamp = squid_curtime;
-    peer->digest.last_fetch_resp_time = fetch_resp_time;
-    peer->digest.flags.requested = 0;
-    debug(72, 2) ("peerDigestFetchFinish: %s done; took: %d secs; expires: %s\n",
-	peer->host, fetch_resp_time, mkrfc1123(expires));
 }
 
+/* calculate fetch stats after completion */
+static void
+peerDigestFetchSetStats(DigestFetchState * fetch)
+{
+    MemObject *mem;
+    assert(fetch->entry && fetch->request);
+
+    mem = fetch->entry->mem_obj;
+    assert(mem);
+
+    /* XXX: outgoing numbers are not precise */
+    /* XXX: we must distinguish between 304 hits and misses here */
+    fetch->sent.bytes = httpRequestPrefixLen(fetch->request);
+    fetch->recv.bytes = fetch->entry->store_status == STORE_PENDING ?
+	mem->inmem_hi : mem->object_sz;
+    fetch->sent.msg = fetch->recv.msg = 1;
+    fetch->expires = fetch->entry->expires;
+    fetch->resp_time = squid_curtime - fetch->start_time;
+
+    debug(72, 3) ("peerDigestFetchFinish: recv %d bytes in %d secs\n",
+	fetch->recv.bytes, fetch->resp_time);
+    debug(72, 3) ("peerDigestFetchFinish: expires: %d (%+d), lmt: %d (%+d)\n",
+	fetch->expires, fetch->expires - squid_curtime,
+	fetch->entry->lastmod, fetch->entry->lastmod - squid_curtime);
+}
+
+
 static int
-peerDigestSetCBlock(peer * peer, const char *buf)
+peerDigestSetCBlock(PeerDigest * pd, const char *buf)
 {
     StoreDigestCBlock cblock;
     int freed_size = 0;
+    const char *host = strBuf(pd->host);
+
     xmemcpy(&cblock, buf, sizeof(cblock));
     /* network -> host conversions */
     cblock.ver.current = ntohs(cblock.ver.current);
@@ -634,76 +742,128 @@
     cblock.del_count = ntohl(cblock.del_count);
     cblock.mask_size = ntohl(cblock.mask_size);
     debug(72, 2) ("got digest cblock from %s; ver: %d (req: %d)\n",
-	peer->host, (int) cblock.ver.current, (int) cblock.ver.required);
+	host, (int) cblock.ver.current, (int) cblock.ver.required);
     debug(72, 2) ("\t size: %d bytes, e-cnt: %d, e-util: %d%%\n",
 	cblock.mask_size, cblock.count,
 	xpercentInt(cblock.count, cblock.capacity));
     /* check version requirements (both ways) */
     if (cblock.ver.required > CacheDigestVer.current) {
 	debug(72, 1) ("%s digest requires version %d; have: %d\n",
-	    peer->host, cblock.ver.required, CacheDigestVer.current);
+	    host, cblock.ver.required, CacheDigestVer.current);
 	return 0;
     }
     if (cblock.ver.current < CacheDigestVer.required) {
 	debug(72, 1) ("%s digest is version %d; we require: %d\n",
-	    peer->host, cblock.ver.current, CacheDigestVer.required);
+	    host, cblock.ver.current, CacheDigestVer.required);
 	return 0;
     }
     /* check consistency */
     if (cblock.ver.required > cblock.ver.current ||
 	cblock.mask_size <= 0 || cblock.capacity <= 0 ||
 	cblock.bits_per_entry <= 0 || cblock.hash_func_count <= 0) {
-	debug(72, 0) ("%s digest cblock is corrupted.\n", peer->host);
+	debug(72, 0) ("%s digest cblock is corrupted.\n", host);
 	return 0;
     }
     /* check consistency further */
     if (cblock.mask_size != cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry)) {
 	debug(72, 0) ("%s digest cblock is corrupted (mask size mismatch: %d ? %d).\n",
-	    peer->host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry));
+	    host, cblock.mask_size, cacheDigestCalcMaskSize(cblock.capacity, cblock.bits_per_entry));
 	return 0;
     }
     /* there are some things we cannot do yet */
     if (cblock.hash_func_count != CacheDigestHashFuncCount) {
 	debug(72, 0) ("%s digest: unsupported #hash functions: %d ? %d.\n",
-	    peer->host, cblock.hash_func_count, CacheDigestHashFuncCount);
+	    host, cblock.hash_func_count, CacheDigestHashFuncCount);
 	return 0;
     }
     /*
      * no cblock bugs below this point
      */
     /* check size changes */
-    if (peer->digest.cd && cblock.mask_size != peer->digest.cd->mask_size) {
+    if (pd->cd && cblock.mask_size != pd->cd->mask_size) {
 	debug(72, 2) ("%s digest changed size: %d -> %d\n",
-	    peer->host, cblock.mask_size, peer->digest.cd->mask_size);
-	freed_size = peer->digest.cd->mask_size;
-	cacheDigestDestroy(peer->digest.cd);
-	peer->digest.cd = NULL;
+	    host, cblock.mask_size, pd->cd->mask_size);
+	freed_size = pd->cd->mask_size;
+	cacheDigestDestroy(pd->cd);
+	pd->cd = NULL;
     }
-    if (!peer->digest.cd) {
+    if (!pd->cd) {
 	debug(72, 2) ("creating %s digest; size: %d (%+d) bytes\n",
-	    peer->host, cblock.mask_size, (int) (cblock.mask_size - freed_size));
-	peer->digest.cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
+	    host, cblock.mask_size, (int) (cblock.mask_size - freed_size));
+	pd->cd = cacheDigestCreate(cblock.capacity, cblock.bits_per_entry);
 	if (cblock.mask_size >= freed_size)
 	    kb_incr(&Counter.cd.memory, cblock.mask_size - freed_size);
     }
-    assert(peer->digest.cd);
+    assert(pd->cd);
     /* these assignments leave us in an inconsistent state until we finish reading the digest */
-    peer->digest.cd->count = cblock.count;
-    peer->digest.cd->del_count = cblock.del_count;
+    pd->cd->count = cblock.count;
+    pd->cd->del_count = cblock.del_count;
     return 1;
 }
 
 static int
-peerDigestUseful(const peer * peer)
+peerDigestUseful(const PeerDigest * pd)
 {
     /* TODO: we should calculate the prob of a false hit instead of bit util */
-    const int bit_util = cacheDigestBitUtil(peer->digest.cd);
-    if (bit_util > 75) {
+    const int bit_util = cacheDigestBitUtil(pd->cd);
+    if (bit_util > 65) {
 	debug(72, 0) ("Warning: %s peer digest has too many bits on (%d%%).\n",
-	    peer->host, bit_util);
+	    strBuf(pd->host), bit_util);
 	return 0;
     }
     return 1;
 }
 
+static int
+saneDiff(time_t diff)
+{
+    return abs(diff) > squid_curtime / 2 ? 0 : diff;
+}
+
+void
+peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e)
+{
+#define f2s(flag) (pd->flags.flag ? "yes" : "no")
+#define appendTime(tm) storeAppendPrintf(e, "%s\t %10d\t %+d\t %+d\n", \
+    ""#tm, pd->times.tm, \
+    saneDiff(pd->times.tm - squid_curtime), \
+    saneDiff(pd->times.tm - pd->times.initialized))
+
+    const char *host = pd ? strBuf(pd->host) : NULL;
+    assert(pd);
+
+    storeAppendPrintf(e, "\npeer digest from %s\n", host);
+
+    cacheDigestGuessStatsReport(&pd->stats.guess, e, host);
+
+    storeAppendPrintf(e, "\nevent\t timestamp\t secs from now\t secs from init\n");
+    appendTime(initialized);
+    appendTime(needed);
+    appendTime(requested);
+    appendTime(received);
+    appendTime(next_check);
+
+    storeAppendPrintf(e, "peer digest state:\n");
+    storeAppendPrintf(e, "\tneeded: %3s, usable: %3s, requested: %3s\n",
+	f2s(needed), f2s(usable), f2s(requested));
+    storeAppendPrintf(e, "\n\tlast retry delay: %d secs\n",
+	pd->times.retry_delay);
+    storeAppendPrintf(e, "\tlast request response time: %d secs\n",
+	pd->times.req_delay);
+    storeAppendPrintf(e, "\tlast request result: %s\n",
+	pd->req_result ? pd->req_result : "(none)");
+
+    storeAppendPrintf(e, "\npeer digest traffic:\n");
+    storeAppendPrintf(e, "\trequests sent: %d, volume: %d KB\n",
+	pd->stats.sent.msgs, (int) pd->stats.sent.kbytes.kb);
+    storeAppendPrintf(e, "\treplies recv:  %d, volume: %d KB\n",
+	pd->stats.recv.msgs, (int) pd->stats.recv.kbytes.kb);
+
+    storeAppendPrintf(e, "\npeer digest structure:\n");
+    if (pd->cd)
+	cacheDigestReport(pd->cd, host, e);
+    else
+	storeAppendPrintf(e, "\tno in-memory copy\n");
+}
+
 #endif
Index: squid/src/peer_select.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_select.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/peer_select.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/peer_select.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_select.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: peer_select.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 44    Peer Selection Algorithm
  * AUTHOR: Duane Wessels
@@ -44,7 +44,6 @@
     "DEFAULT_PARENT",
     "SINGLE_PARENT",
     "FIRST_UP_PARENT",
-    "NO_PARENT_DIRECT",
     "FIRST_PARENT_MISS",
     "CLOSEST_PARENT_MISS",
     "CLOSEST_PARENT",
@@ -54,7 +53,6 @@
     "ROUNDROBIN_PARENT",
 #if USE_CACHE_DIGESTS
     "CACHE_DIGEST_HIT",
-    "NO_CACHE_DIGEST_DIRECT",
 #endif
 #if USE_CARP
     "CARP",
@@ -69,6 +67,7 @@
 
 static char *DirectStr[] =
 {
+    "DIRECT_UNKNOWN",
     "DIRECT_NO",
     "DIRECT_MAYBE",
     "DIRECT_YES"
@@ -76,7 +75,7 @@
 
 static void peerSelectFoo(ps_state *);
 static void peerPingTimeout(void *data);
-static void peerSelectCallbackFail(ps_state * psstate);
+static void peerSelectCallback(ps_state * psstate);
 static IRCB peerHandlePingReply;
 static void peerSelectStateFree(ps_state * psstate);
 static void peerIcpParentMiss(peer *, icp_common_t *, ps_state *);
@@ -85,6 +84,11 @@
 static void peerHandleHtcpReply(peer *, peer_t, htcpReplyData *, void *);
 #endif
 static int peerCheckNetdbDirect(ps_state * psstate);
+static void peerGetSomeNeighbor(ps_state *);
+static void peerGetSomeNeighborReplies(ps_state *);
+static void peerGetSomeDirect(ps_state *);
+static void peerGetSomeParent(ps_state *);
+static void peerAddFwdServer(FwdServer **, peer *, hier_code);
 
 static void
 peerSelectStateFree(ps_state * psstate)
@@ -107,12 +111,10 @@
 peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry)
 {
     int n;
-    if (entry == NULL)
-	return 0;
-    debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry));
-    if (entry->ping_status != PING_NONE)
-	return 0;
+    assert(entry);
+    assert(entry->ping_status == PING_NONE);
     assert(direct != DIRECT_YES);
+    debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry));
     if (!request->flags.hierarchical && direct != DIRECT_NO)
 	return 0;
     if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys)
@@ -124,37 +126,10 @@
 }
 
 
-peer *
-peerGetSomeParent(request_t * request, hier_code * code)
-{
-    peer *p;
-    debug(44, 3) ("peerGetSomeParent: %s %s\n",
-	RequestMethodStr[request->method],
-	request->host);
-    if ((p = getDefaultParent(request))) {
-	*code = DEFAULT_PARENT;
-	return p;
-    }
-    if ((p = getRoundRobinParent(request))) {
-	*code = ROUNDROBIN_PARENT;
-	return p;
-    }
-    if ((p = getFirstUpParent(request))) {
-	*code = FIRSTUP_PARENT;
-	return p;
-    }
-    if ((p = getAnyParent(request))) {
-	*code = ANY_OLD_PARENT;
-	return p;
-    }
-    return NULL;
-}
-
 void
 peerSelect(request_t * request,
     StoreEntry * entry,
     PSC * callback,
-    PSC * fail_callback,
     void *callback_data)
 {
     ps_state *psstate = xcalloc(1, sizeof(ps_state));
@@ -162,12 +137,12 @@
 	debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
     else
 	debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]);
-    cbdataAdd(psstate, MEM_NONE);
+    cbdataAdd(psstate, cbdataXfree, 0);
     psstate->request = requestLink(request);
     psstate->entry = entry;
     psstate->callback = callback;
-    psstate->fail_callback = fail_callback;
     psstate->callback_data = callback_data;
+    psstate->direct = DIRECT_UNKNOWN;
 #if USE_CACHE_DIGESTS
     request->hier.peer_select_start = current_time;
 #endif
@@ -198,9 +173,10 @@
 }
 
 static void
-peerSelectCallback(ps_state * psstate, peer * p)
+peerSelectCallback(ps_state * psstate)
 {
     StoreEntry *entry = psstate->entry;
+    FwdServer *fs = psstate->servers;
     void *data = psstate->callback_data;
     if (entry) {
 	debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry));
@@ -208,27 +184,18 @@
 	    eventDelete(peerPingTimeout, psstate);
 	entry->ping_status = PING_DONE;
     }
+    if (fs == NULL) {
+	debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry));
+	debug(44, 1) ("  always_direct = %d\n", psstate->always_direct);
+	debug(44, 1) ("   never_direct = %d\n", psstate->never_direct);
+	debug(44, 1) ("       timedout = %d\n", psstate->ping.timedout);
+    }
     psstate->ping.stop = current_time;
-    if (cbdataValid(data))
-	psstate->callback(p, data);
-    cbdataUnlock(data);
-    peerSelectStateFree(psstate);
-}
-
-static void
-peerSelectCallbackFail(ps_state * psstate)
-{
-    request_t *request = psstate->request;
-    void *data = psstate->callback_data;
-    const char *url = psstate->entry ? storeUrl(psstate->entry) : urlCanonical(request);
-    if (psstate->entry)
-	psstate->entry->ping_status = PING_DONE;
-    debug(44, 1) ("Failed to select source for '%s'\n", url);
-    debug(44, 1) ("  always_direct = %d\n", psstate->always_direct);
-    debug(44, 1) ("   never_direct = %d\n", psstate->never_direct);
-    debug(44, 1) ("       timedout = %d\n", psstate->ping.timedout);
-    if (cbdataValid(data))
-	psstate->fail_callback(NULL, data);
+    psstate->request->hier.ping = psstate->ping;
+    if (cbdataValid(data)) {
+	psstate->servers = NULL;
+	psstate->callback(fs, data);
+    }
     cbdataUnlock(data);
     peerSelectStateFree(psstate);
 }
@@ -257,146 +224,216 @@
 }
 
 static void
-peerSelectFoo(ps_state * psstate)
+peerSelectFoo(ps_state * ps)
 {
-    peer *p;
-    hier_code code;
-    StoreEntry *entry = psstate->entry;
-    request_t *request = psstate->request;
-    int direct;
+    StoreEntry *entry = ps->entry;
+    request_t *request = ps->request;
     debug(44, 3) ("peerSelectFoo: '%s %s'\n",
 	RequestMethodStr[request->method],
 	request->host);
-    if (psstate->always_direct == 0 && Config.accessList.AlwaysDirect) {
-	psstate->acl_checklist = aclChecklistCreate(
-	    Config.accessList.AlwaysDirect,
-	    request,
-	    request->client_addr,
-	    NULL,		/* user agent */
-	    NULL);		/* ident */
-	aclNBCheck(psstate->acl_checklist,
-	    peerCheckAlwaysDirectDone,
-	    psstate);
-	return;
-    } else if (psstate->always_direct > 0) {
-	direct = DIRECT_YES;
-    } else if (psstate->never_direct == 0 && Config.accessList.NeverDirect) {
-	psstate->acl_checklist = aclChecklistCreate(
-	    Config.accessList.NeverDirect,
-	    request,
-	    request->client_addr,
-	    NULL,		/* user agent */
-	    NULL);		/* ident */
-	aclNBCheck(psstate->acl_checklist,
-	    peerCheckNeverDirectDone,
-	    psstate);
-	return;
-    } else if (psstate->never_direct > 0) {
-	direct = DIRECT_NO;
-    } else if (request->flags.loopdetect) {
-	direct = DIRECT_YES;
-    } else {
-	direct = DIRECT_MAYBE;
-    }
-    debug(44, 3) ("peerSelectFoo: direct = %s\n", DirectStr[direct]);
-    if (direct == DIRECT_YES) {
-	debug(44, 3) ("peerSelectFoo: DIRECT\n");
-	hierarchyNote(&request->hier, DIRECT, &psstate->ping, request->host);
-	peerSelectCallback(psstate, NULL);
-	return;
-    }
-    if ((p = getSingleParent(request))) {
-	code = SINGLE_PARENT;
-	debug(44, 3) ("peerSelectFoo: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-	return;
-    }
-    if (!request->flags.hierarchical && direct != DIRECT_NO) {
-	debug(44, 3) ("peerSelectFoo: DIRECT for non-hierarchical request\n");
-	hierarchyNote(&request->hier, DIRECT, &psstate->ping, request->host);
-	peerSelectCallback(psstate, NULL);
+    if (ps->direct == DIRECT_UNKNOWN) {
+	if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) {
+	    ps->acl_checklist = aclChecklistCreate(
+		Config.accessList.AlwaysDirect,
+		request,
+		request->client_addr,
+		request->my_addr,
+		NULL,		/* user agent */
+		NULL);		/* ident */
+	    aclNBCheck(ps->acl_checklist,
+		peerCheckAlwaysDirectDone,
+		ps);
+	    return;
+	} else if (ps->always_direct > 0) {
+	    ps->direct = DIRECT_YES;
+	} else if (ps->never_direct == 0 && Config.accessList.NeverDirect) {
+	    ps->acl_checklist = aclChecklistCreate(
+		Config.accessList.NeverDirect,
+		request,
+		request->client_addr,
+		request->my_addr,
+		NULL,		/* user agent */
+		NULL);		/* ident */
+	    aclNBCheck(ps->acl_checklist,
+		peerCheckNeverDirectDone,
+		ps);
+	    return;
+	} else if (ps->never_direct > 0) {
+	    ps->direct = DIRECT_NO;
+	} else if (request->flags.loopdetect) {
+	    ps->direct = DIRECT_YES;
+	} else {
+	    ps->direct = DIRECT_MAYBE;
+	}
+	debug(44, 3) ("peerSelectFoo: direct = %s\n",
+	    DirectStr[ps->direct]);
+    }
+    if (entry == NULL) {
+	(void) 0;
+    } else if (entry->ping_status == PING_NONE) {
+	peerGetSomeNeighbor(ps);
+	if (entry->ping_status == PING_WAITING)
+	    return;
+    } else if (entry->ping_status == PING_WAITING) {
+	peerGetSomeNeighborReplies(ps);
+	entry->ping_status = PING_DONE;
+    }
+    if (Config.onoff.prefer_direct)
+	peerGetSomeDirect(ps);
+    peerGetSomeParent(ps);
+    if (!Config.onoff.prefer_direct)
+	peerGetSomeDirect(ps);
+    peerSelectCallback(ps);
+}
+
+/*
+ * peerGetSomeNeighbor
+ * 
+ * Selects a neighbor (parent or sibling) based on one of the
+ * following methods:
+ *      Cache Digests
+ *      CARP
+ *      Netdb RTT estimates
+ *      ICP/HTCP queries
+ */
+static void
+peerGetSomeNeighbor(ps_state * ps)
+{
+    StoreEntry *entry = ps->entry;
+    request_t *request = ps->request;
+    peer *p;
+    hier_code code = HIER_NONE;
+    assert(entry->ping_status == PING_NONE);
+    if (ps->direct == DIRECT_YES) {
+	entry->ping_status = PING_DONE;
 	return;
     }
 #if USE_CACHE_DIGESTS
-    else if ((p = neighborsDigestSelect(request, entry))) {
-	debug(44, 2) ("peerSelect: Using Cache Digest\n");
-	request->hier.alg = PEER_SA_DIGEST;
+    if ((p = neighborsDigestSelect(request, entry))) {
 	code = CACHE_DIGEST_HIT;
-	debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-	return;
-    }
+    } else
 #endif
 #if USE_CARP
-    else if ((p = carpSelectParent(request))) {
-	hierarchyNote(&request->hier, CARP, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-	return;
-    }
+    if ((p = carpSelectParent(request))) {
+	code = CARP;
+    } else
 #endif
-    else if ((p = netdbClosestParent(request))) {
-	request->hier.alg = PEER_SA_NETDB;
+    if ((p = netdbClosestParent(request))) {
 	code = CLOSEST_PARENT;
-	debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-	return;
-    } else if (peerSelectIcpPing(request, direct, entry)) {
-	assert(entry->ping_status == PING_NONE);
-	request->hier.alg = PEER_SA_ICP;
+    } else if (peerSelectIcpPing(request, ps->direct, entry)) {
 	debug(44, 3) ("peerSelect: Doing ICP pings\n");
-	psstate->ping.start = current_time;
-	psstate->ping.n_sent = neighborsUdpPing(request,
+	ps->ping.start = current_time;
+	ps->ping.n_sent = neighborsUdpPing(request,
 	    entry,
 	    peerHandlePingReply,
-	    psstate,
-	    &psstate->ping.n_replies_expected,
-	    &psstate->ping.timeout);
-	if (psstate->ping.n_sent == 0)
+	    ps,
+	    &ps->ping.n_replies_expected,
+	    &ps->ping.timeout);
+	if (ps->ping.n_sent == 0)
 	    debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n");
-	debug(44, 3) ("peerSelectFoo: %d ICP replies expected, RTT %d msec\n",
-	    psstate->ping.n_replies_expected, psstate->ping.timeout);
-	if (psstate->ping.n_replies_expected > 0) {
+	debug(44, 3) ("peerSelect: %d ICP replies expected, RTT %d msec\n",
+	    ps->ping.n_replies_expected, ps->ping.timeout);
+	if (ps->ping.n_replies_expected > 0) {
 	    entry->ping_status = PING_WAITING;
 	    eventAdd("peerPingTimeout",
 		peerPingTimeout,
-		psstate,
-		0.001 * psstate->ping.timeout,
+		ps,
+		0.001 * ps->ping.timeout,
 		0);
 	    return;
 	}
     }
-    debug(44, 3) ("peerSelectFoo: After peerSelectIcpPing.\n");
-    if (peerCheckNetdbDirect(psstate)) {
+    if (code != HIER_NONE) {
+	assert(p);
+	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
+	peerAddFwdServer(&ps->servers, p, code);
+    }
+    entry->ping_status = PING_DONE;
+}
+
+/*
+ * peerGetSomeNeighborReplies
+ * 
+ * Selects a neighbor (parent or sibling) based on ICP/HTCP replies.
+ */
+static void
+peerGetSomeNeighborReplies(ps_state * ps)
+{
+    StoreEntry *entry = ps->entry;
+    request_t *request = ps->request;
+    peer *p = NULL;
+    hier_code code = HIER_NONE;
+    assert(entry->ping_status == PING_WAITING);
+    assert(ps->direct != DIRECT_YES);
+    if (peerCheckNetdbDirect(ps)) {
 	code = CLOSEST_DIRECT;
 	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, request->host);
-	peerSelectCallback(psstate, NULL);
-    } else if ((p = whichPeer(&psstate->closest_parent_miss))) {
+	peerAddFwdServer(&ps->servers, NULL, code);
+	return;
+    }
+    if ((p = ps->hit)) {
+	code = ps->hit_type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT;
+    } else
+#if ALLOW_SOURCE_PING
+    if ((p = ps->secho)) {
+	code = SOURCE_FASTEST;
+    } else
+#endif
+    if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
+	p = whichPeer(&ps->closest_parent_miss);
 	code = CLOSEST_PARENT_MISS;
-	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-    } else if ((p = whichPeer(&psstate->first_parent_miss))) {
+    } else if (ps->first_parent_miss.sin_addr.s_addr != any_addr.s_addr) {
+	p = whichPeer(&ps->first_parent_miss);
 	code = FIRST_PARENT_MISS;
+    }
+    if (p && code != HIER_NONE) {
 	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-    } else if (direct != DIRECT_NO) {
-	code = DIRECT;
-	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, request->host);
-	peerSelectCallback(psstate, NULL);
-    } else if ((p = peerGetSomeParent(request, &code))) {
+	peerAddFwdServer(&ps->servers, p, code);
+    }
+}
+
+
+/*
+ * peerGetSomeDirect
+ * 
+ * Simply adds a 'direct' entry to the FwdServers list if this
+ * request can be forwarded directly to the origin server
+ */
+static void
+peerGetSomeDirect(ps_state * ps)
+{
+    if (ps->direct == DIRECT_NO)
+	return;
+    if (ps->request->protocol == PROTO_WAIS)
+	/* Its not really DIRECT, now is it? */
+	peerAddFwdServer(&ps->servers, Config.Wais.peer, DIRECT);
+    else
+	peerAddFwdServer(&ps->servers, NULL, DIRECT);
+}
+
+static void
+peerGetSomeParent(ps_state * ps)
+{
+    peer *p;
+    request_t *request = ps->request;
+    hier_code code = HIER_NONE;
+    debug(44, 3) ("peerGetSomeParent: %s %s\n",
+	RequestMethodStr[request->method],
+	request->host);
+    if (ps->direct == DIRECT_YES)
+	return;
+    if ((p = getDefaultParent(request))) {
+	code = DEFAULT_PARENT;
+    } else if ((p = getRoundRobinParent(request))) {
+	code = ROUNDROBIN_PARENT;
+    } else if ((p = getFirstUpParent(request))) {
+	code = FIRSTUP_PARENT;
+    } else if ((p = getAnyParent(request))) {
+	code = ANY_OLD_PARENT;
+    }
+    if (code != HIER_NONE) {
 	debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
-	hierarchyNote(&request->hier, code, &psstate->ping, p->host);
-	peerSelectCallback(psstate, p);
-    } else {
-	code = NO_DIRECT_FAIL;
-	hierarchyNote(&request->hier, code, &psstate->ping, NULL);
-	peerSelectCallbackFail(psstate);
+	peerAddFwdServer(&ps->servers, p, code);
     }
 }
 
@@ -407,9 +444,9 @@
     StoreEntry *entry = psstate->entry;
     if (entry)
 	debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry));
-    entry->ping_status = PING_TIMEOUT;
     if (!cbdataValid(psstate->callback_data)) {
 	/* request aborted */
+	entry->ping_status = PING_DONE;
 	cbdataUnlock(psstate->callback_data);
 	peerSelectStateFree(psstate);
 	return;
@@ -461,7 +498,6 @@
 {
     ps_state *psstate = data;
     icp_opcode op = header->opcode;
-    request_t *request = psstate->request;
     debug(44, 3) ("peerHandleIcpReply: %s %s\n",
 	icp_opcode_str[op],
 	storeUrl(psstate->entry));
@@ -476,20 +512,18 @@
 	if (type == PEER_PARENT)
 	    peerIcpParentMiss(p, header, psstate);
     } else if (op == ICP_HIT) {
-	hierarchyNote(&request->hier,
-	    type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT,
-	    &psstate->ping,
-	    p->host);
-	peerSelectCallback(psstate, p);
-	return;
-    } else if (op == ICP_SECHO) {
-	hierarchyNote(&request->hier,
-	    SOURCE_FASTEST,
-	    &psstate->ping,
-	    request->host);
-	peerSelectCallback(psstate, NULL);
+	psstate->hit = p;
+	psstate->hit_type = type;
+	peerSelectFoo(psstate);
+	return;
+    }
+#if ALLOW_SOURCE_PING
+    else if (op == ICP_SECHO) {
+	psstate->secho = p;
+	peerSelectFoo(psstate);
 	return;
     }
+#endif
     if (psstate->ping.n_recv < psstate->ping.n_replies_expected)
 	return;
     peerSelectFoo(psstate);
@@ -506,11 +540,9 @@
 	storeUrl(psstate->entry));
     psstate->ping.n_recv++;
     if (htcp->hit) {
-	hierarchyNote(&request->hier,
-	    type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT,
-	    &psstate->ping,
-	    p->host);
-	peerSelectCallback(psstate, p);
+	psstate->hit = p;
+	psstate->hit_type = type;
+	peerSelectFoo(psstate);
 	return;
     }
     if (type == PEER_PARENT)
@@ -562,3 +594,18 @@
     else
 	debug(44, 1) ("peerHandlePingReply: unknown protocol_t %d\n", (int) proto);
 }
+
+static void
+peerAddFwdServer(FwdServer ** FS, peer * p, hier_code code)
+{
+    FwdServer *fs = memAllocate(MEM_FWD_SERVER);
+    debug(44, 5) ("peerAddFwdServer: adding %s %s\n",
+	p ? p->host : "DIRECT",
+	hier_strings[code]);
+    fs->peer = p;
+    fs->code = code;
+    cbdataLock(fs->peer);
+    while (*FS)
+	FS = &(*FS)->next;
+    *FS = fs;
+}
Index: squid/src/pinger.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/pinger.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/pinger.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/pinger.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: pinger.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: pinger.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 42    ICMP Pinger program
  * AUTHOR: Duane Wessels
@@ -152,6 +152,14 @@
     struct sockaddr_in S;
     memset(pkt, '\0', MAX_PKT_SZ);
     icmp = (struct icmphdr *) (void *) pkt;
+
+    /*
+     * cevans - beware signed/unsigned issues in untrusted data from
+     * the network!!
+     */
+    if (len < 0) {
+	len = 0;
+    }
     icmp->icmp_type = ICMP_ECHO;
     icmp->icmp_code = 0;
     icmp->icmp_cksum = 0;
@@ -169,6 +177,9 @@
     }
     icmp->icmp_cksum = in_cksum((u_short *) icmp, icmp_pktsize);
     S.sin_family = AF_INET;
+    /*
+     * cevans: alert: trusting to-host, was supplied in network packet
+     */
     S.sin_addr = to;
     S.sin_port = 0;
     assert(icmp_pktsize <= MAX_PKT_SZ);
@@ -294,9 +305,12 @@
     if (n < 0)
 	return n;
     guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ);
-    if (guess_size != pecho.psize)
+    if (guess_size != pecho.psize) {
 	fprintf(stderr, "size mismatch, guess=%d psize=%d\n",
 	    guess_size, pecho.psize);
+	errno = 0;
+	return -1;
+    }
     pingerSendEcho(pecho.to,
 	pecho.opcode,
 	pecho.payload,
@@ -336,12 +350,19 @@
     char *t;
     time_t last_check_time = 0;
 
+/*
+ * cevans - do this first. It grabs a raw socket. After this we can
+ * drop privs
+ */
+    pingerOpen();
+    setgid(getgid());
+    setuid(getuid());
+
     if ((t = getenv("SQUID_DEBUG")))
 	debug_args = xstrdup(t);
     getCurrentTime();
     _db_init(NULL, debug_args);
 
-    pingerOpen();
     for (;;) {
 	tv.tv_sec = 10;
 	tv.tv_usec = 0;
Index: squid/src/protos.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/protos.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/protos.h	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/protos.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: protos.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -36,7 +36,7 @@
 extern void accessLogClose(void);
 extern void accessLogInit(void);
 extern const char *accessLogTime(time_t);
-extern void hierarchyNote(HierarchyLogEntry *, hier_code, ping_data *, const char *);
+extern void hierarchyNote(HierarchyLogEntry *, hier_code, const char *);
 #if FORW_VIA_DB
 extern void fvdbCountVia(const char *key);
 extern void fvdbCountForw(const char *key);
@@ -45,6 +45,7 @@
 extern aclCheck_t *aclChecklistCreate(const struct _acl_access *,
     request_t *,
     struct in_addr src,
+    struct in_addr me,
     const char *user_agent,
     const char *ident);
 extern void aclNBCheck(aclCheck_t *, PF *, void *);
@@ -55,7 +56,7 @@
 extern void aclDestroyAcls(acl **);
 extern void aclParseAccessLine(struct _acl_access **);
 extern void aclParseAclLine(acl **);
-extern struct _acl *aclFindByName(const char *name);
+extern int aclIsProxyAuth(const char *name);
 extern int aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name);
 extern void aclParseDenyInfoLine(struct _acl_deny_info_list **);
 extern void aclDestroyDenyInfoList(struct _acl_deny_info_list **);
@@ -75,6 +76,7 @@
 extern int aio_unlink(const char *, aio_result_t *);
 extern int aio_opendir(const char *, aio_result_t *);
 extern aio_result_t *aio_poll_done(void);
+extern int aio_operations_pending(void);
 
 extern void aioCancel(int, void *);
 extern void aioOpen(const char *, int, mode_t, AIOCB *, void *, void *);
@@ -84,27 +86,29 @@
 extern void aioStat(char *, struct stat *, AIOCB *, void *, void *);
 extern void aioUnlink(const char *, AIOCB *, void *);
 extern void aioCheckCallbacks(void);
+extern void aioSync(void);
 #endif
 
 extern int parseConfigFile(const char *file_name);
 extern void intlistDestroy(intlist **);
 extern int intlistFind(intlist * list, int i);
 extern wordlist *wordlistAdd(wordlist **, const char *);
+extern wordlist *wordlistDup(const wordlist *);
 extern void wordlistDestroy(wordlist **);
 extern void configFreeMemory(void);
 extern void wordlistCat(const wordlist *, MemBuf * mb);
 
 extern void cbdataInit(void);
 #if CBDATA_DEBUG
-extern void cbdataAddDbg(const void *p, mem_type, const char *, int);
+extern void cbdataAddDbg(const void *p, CBDUNL *, int, const char *, int);
 #else
-extern void cbdataAdd(const void *p, mem_type);
+extern void cbdataAdd(const void *p, CBDUNL *, int);
 #endif
 extern void cbdataFree(void *p);
 extern void cbdataLock(const void *p);
 extern void cbdataUnlock(const void *p);
 extern int cbdataValid(const void *p);
-extern void cbdataDump(StoreEntry *);
+extern CBDUNL cbdataXfree;
 
 extern void clientdbInit(void);
 extern void clientdbUpdate(struct in_addr, log_type, protocol_t, size_t);
@@ -171,7 +175,7 @@
 extern void packerToMemInit(Packer * p, MemBuf * mb);
 extern void packerClean(Packer * p);
 extern void packerAppend(Packer * p, const char *buf, int size);
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void packerPrintf(Packer * p, const char *fmt,...);
 #else
 extern void packerPrintf();
@@ -185,11 +189,12 @@
 extern void _db_init(const char *logfile, const char *options);
 extern void _db_rotate_log(void);
 
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void _db_print(const char *,...);
 #else
 extern void _db_print();
 #endif
+extern void xassert(const char *, const char *, int);
 
 /* packs, then prints an object using debug() */
 extern void debugObj(int section, int level, const char *label, void *obj, ObjPackMethod pm);
@@ -213,9 +218,13 @@
 extern time_t eventNextTime(void);
 extern void eventDelete(EVH * func, void *arg);
 extern void eventInit(void);
+extern void eventFreeMemory(void);
 extern int eventFind(EVH *, void *);
 
 extern void fd_close(int fd);
+#if USE_ASYNC_IO
+extern void fd_was_closed(int fd);
+#endif
 extern void fd_open(int fd, unsigned int type, const char *);
 extern void fd_note(int fd, const char *);
 extern void fd_bytes(int fd, int len, unsigned int type);
@@ -245,17 +254,17 @@
 extern void fqdncache_restart(void);
 extern EVH fqdncache_purgelru;
 
-extern void ftpStart(request_t * req, StoreEntry * entry, int);
+extern void ftpStart(FwdState *);
 extern char *ftpUrlWith2f(const request_t *);
 
-extern void gopherStart(StoreEntry *, int fd);
+extern void gopherStart(FwdState *);
 extern int gopherCachable(const char *);
 
 
-extern void whoisStart(FwdState *, int fd);
+extern void whoisStart(FwdState *);
 
 extern int httpCachable(method_t);
-extern void httpStart(FwdState *, int fd);
+extern void httpStart(FwdState *);
 extern void httpParseReplyHeaders(const char *, http_reply *);
 extern void httpProcessReplyHeader(HttpStateData *, const char *, int);
 extern size_t httpBuildRequestPrefix(request_t * request,
@@ -330,6 +339,7 @@
 extern int httpHdrRangeIsComplex(const HttpHdrRange * range);
 extern int httpHdrRangeWillBeComplex(const HttpHdrRange * range);
 extern size_t httpHdrRangeFirstOffset(const HttpHdrRange * range);
+extern size_t httpHdrRangeLowestOffset(const HttpHdrRange * range, size_t size);
 
 
 /* Http Content Range Header Field */
@@ -347,7 +357,8 @@
 extern HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count);
 extern void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count);
 extern int httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * attrs, int end);
-extern void httpHeaderMaskInit(HttpHeaderMask * mask);
+extern int httpHeaderIdByNameDef(const char *name, int name_len);
+extern void httpHeaderMaskInit(HttpHeaderMask * mask, int value);
 extern void httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, int count);
 extern int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive);
 extern void httpHeaderAddContRange(HttpHeader * hdr, HttpHdrRangeSpec spec, size_t ent_len);
@@ -359,7 +370,7 @@
 extern int httpHeaderParseInt(const char *start, int *val);
 extern int httpHeaderParseSize(const char *start, size_t * sz);
 extern int httpHeaderReset(HttpHeader * hdr);
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void httpHeaderPutStrf(HttpHeader * hdr, http_hdr_type id, const char *fmt,...);
 #else
 extern void
@@ -480,15 +491,24 @@
 #ifdef SQUID_SNMP
 extern PF snmpHandleUdp;
 extern void snmpInit(void);
-extern int snmpInitConfig(void);
 extern void snmpConnectionOpen(void);
 extern void snmpConnectionShutdown(void);
 extern void snmpConnectionClose(void);
-extern int snmpCreateView(char **);
-extern int snmpCreateUser(char **);
-extern int snmpCreateCommunity(char **);
-extern void snmpTokenize(char *, char **, int);
-extern int snmpCompare(oid * name1, int len1, oid * name2, int len2);
+extern void snmpDebugOid(int lvl, oid * Name, snint Len);
+extern void addr2oid(struct in_addr addr, oid * Dest);
+extern struct in_addr *oid2addr(oid * id);
+extern struct in_addr *client_entry(struct in_addr *current);
+extern variable_list *snmp_basicFn(variable_list *, snint *);
+extern variable_list *snmp_confFn(variable_list *, snint *);
+extern variable_list *snmp_sysFn(variable_list *, snint *);
+extern variable_list *snmp_prfSysFn(variable_list *, snint *);
+extern variable_list *snmp_prfProtoFn(variable_list *, snint *);
+extern variable_list *snmp_prfPeerFn(variable_list *, snint *);
+extern variable_list *snmp_netIpFn(variable_list *, snint *);
+extern variable_list *snmp_netFqdnFn(variable_list *, snint *);
+extern variable_list *snmp_netDnsFn(variable_list *, snint *);
+extern variable_list *snmp_meshPtblFn(variable_list *, snint *);
+extern variable_list *snmp_meshCtblFn(variable_list *, snint *);
 #endif /* SQUID_SNMP */
 
 extern void icpHandleIcpV3(int, struct sockaddr_in, char *, int);
@@ -531,7 +551,7 @@
 /* calls memcpy, appends exactly size bytes, extends buffer if needed */
 extern void memBufAppend(MemBuf * mb, const char *buf, mb_size_t size);
 /* calls snprintf, extends buffer if needed */
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void memBufPrintf(MemBuf * mb, const char *fmt,...);
 #else
 extern void memBufPrintf();
@@ -581,14 +601,16 @@
 extern void neighborAdd(const char *, const char *, int, int, int, int, int);
 extern void neighbors_open(int);
 extern peer *peerFindByName(const char *);
+extern peer *peerFindByNameAndPort(const char *, unsigned short);
 extern peer *getDefaultParent(request_t * request);
 extern peer *getRoundRobinParent(request_t * request);
 extern peer *getAnyParent(request_t * request);
 extern lookup_t peerDigestLookup(peer * p, request_t * request, StoreEntry * entry);
 extern peer *neighborsDigestSelect(request_t * request, StoreEntry * entry);
 extern void peerNoteDigestLookup(request_t * request, peer * p, lookup_t lookup);
+extern void peerNoteDigestGone(peer * p);
 extern int neighborUp(const peer * e);
-extern void peerDestroy(peer * e);
+extern CBDUNL peerDestroy;
 extern char *neighborTypeStr(const peer * e);
 extern peer_t neighborType(const peer *, const request_t *);
 extern void peerCheckConnectStart(peer *);
@@ -622,19 +644,24 @@
 extern void cachemgrRegister(const char *, const char *, OBJH *, int, int);
 extern void cachemgrInit(void);
 
-extern void peerSelect(request_t *, StoreEntry *, PSC *, PSC *, void *data);
-extern peer *peerGetSomeParent(request_t *, hier_code *);
+extern void peerSelect(request_t *, StoreEntry *, PSC *, void *data);
 extern void peerSelectInit(void);
 
 /* peer_digest.c */
-extern EVH peerDigestInit;
+extern PeerDigest *peerDigestCreate(peer * p);
+extern void peerDigestNeeded(PeerDigest * pd);
+extern void peerDigestNotePeerGone(PeerDigest * pd);
+extern void peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e);
 
 /* forward.c */
-extern void fwdStart(int, StoreEntry *, request_t *, struct in_addr);
+extern void fwdStart(int, StoreEntry *, request_t *, struct in_addr, struct in_addr);
 extern DEFER fwdCheckDeferRead;
-extern void fwdFail(FwdState *, int, http_status, int);
-extern STABH fwdAbort;
+extern void fwdFail(FwdState *, ErrorState *);
 extern void fwdUnregister(int fd, FwdState *);
+extern void fwdComplete(FwdState * fwdState);
+extern void fwdInit(void);
+extern int fwdReforwardableStatus(http_status s);
+extern void fwdServersFree(FwdServer ** FS);
 
 extern void urnStart(request_t *, StoreEntry *);
 
@@ -647,6 +674,7 @@
 extern void authenticateShutdown(void);
 
 extern void refreshAddToList(const char *, int, time_t, int, time_t);
+extern int refreshIsCachable(const StoreEntry *);
 extern int refreshCheckHTTP(const StoreEntry *, request_t *);
 extern int refreshCheckICP(const StoreEntry *, request_t *);
 extern int refreshCheckDigest(const StoreEntry *, time_t delta);
@@ -659,9 +687,13 @@
 
 extern void start_announce(void *unused);
 extern void sslStart(int fd, const char *, request_t *, size_t * sz);
-extern void waisStart(request_t *, StoreEntry *, int fd);
-extern void passStart(int, const char *, request_t *, size_t *);
-extern void identStart(int, ConnStateData *, IDCB * callback, void *);
+extern void waisStart(FwdState *);
+
+/* ident.c */
+#if USE_IDENT
+extern void identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *cbdata);
+extern void identInit(void);
+#endif
 
 extern void statInit(void);
 extern void statFreeMemory(void);
@@ -670,6 +702,9 @@
 extern int stat5minClientRequests(void);
 extern double stat5minCPUUsage(void);
 extern const char *storeEntryFlags(const StoreEntry *);
+extern double statRequestHitRatio(int minutes);
+extern double statByteHitRatio(int minutes);
+
 
 
 /* StatHist */
@@ -702,7 +737,7 @@
 extern void memConfigure();
 extern void *memAllocate(mem_type);
 extern void *memAllocBuf(size_t net_size, size_t * gross_size);
-extern void memFree(mem_type, void *);
+extern CBDUNL memFree;
 extern void memFreeBuf(size_t size, void *);
 extern void memFree2K(void *);
 extern void memFree4K(void *);
@@ -742,12 +777,9 @@
 extern StoreEntry *storeCreateEntry(const char *, const char *, request_flags, method_t);
 extern void storeSetPublicKey(StoreEntry *);
 extern void storeComplete(StoreEntry *);
-#ifdef PPNR_WIP
-extern void storePPNR(StoreEntry *);
-#endif /* PPNR_WIP */
 extern void storeInit(void);
 extern int storeClientWaiting(const StoreEntry *);
-extern void storeAbort(StoreEntry *, int);
+extern void storeAbort(StoreEntry *);
 extern void storeAppend(StoreEntry *, const char *, int);
 extern void storeLockObject(StoreEntry *);
 extern void storeSwapInStart(StoreEntry *, SIH *, void *data);
@@ -786,7 +818,7 @@
 extern void storeBufferFlush(StoreEntry *);
 extern void storeHashInsert(StoreEntry * e, const cache_key *);
 extern void storeSetMemStatus(StoreEntry * e, int);
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void storeAppendPrintf(StoreEntry *, const char *,...);
 #else
 extern void storeAppendPrintf();
@@ -799,6 +831,7 @@
 extern int contentLen(const StoreEntry * e);
 extern HttpReply *storeEntryReply(StoreEntry *);
 extern int storeTooManyDiskFilesOpen(void);
+extern void storeEntryReset(StoreEntry *);
 
 /*
  * store_log.c
@@ -818,7 +851,6 @@
 extern const cache_key *storeKeyScan(const char *);
 extern const char *storeKeyText(const cache_key *);
 extern const cache_key *storeKeyPublic(const char *, const method_t);
-extern const cache_key *storeKeyPublicOld(const char *, const method_t);
 extern const cache_key *storeKeyPrivate(const char *, method_t, int);
 extern int storeKeyHashBuckets(int);
 extern int storeKeyNull(const cache_key *);
@@ -895,8 +927,6 @@
 /*
  * store_swapout.c
  */
-extern void storeSwapOutStart(StoreEntry * e);
-extern void storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data);
 extern void storeCheckSwapOut(StoreEntry * e);
 extern void storeSwapOutFileClose(StoreEntry * e);
 extern int storeSwapOutWriteQueued(MemObject * mem);
@@ -920,7 +950,7 @@
 extern void safeunlink(const char *path, int quiet);
 extern void death(int sig);
 extern void fatal(const char *message);
-#ifdef __STDC__
+#if STDC_HEADERS
 extern void fatalf(const char *fmt,...);
 #else
 extern void fatalf();
@@ -954,7 +984,7 @@
 extern void dumpMallocStats(void);
 
 extern void pumpInit(int fd, request_t * r, char *uri);
-extern void pumpStart(int, StoreEntry *, request_t *, CWCB * callback, void *);
+extern void pumpStart(int, FwdState *, CWCB * callback, void *);
 extern int pumpMethod(method_t method);
 extern int pumpRestart(request_t *);
 
@@ -1076,14 +1106,25 @@
 #endif
 
 #if DELAY_POOLS
-extern int delayClient(clientHttpRequest *);
 extern void delayPoolsInit(void);
+extern void delayInitDelayData(unsigned short pools);
+extern void delayFreeDelayData();
+extern void delayCreateDelayPool(unsigned short pool, u_char class);
+extern void delayInitDelayPool(unsigned short pool, u_char class, delaySpecSet * rates);
+extern void delayFreeDelayPool(unsigned short pool);
+extern void delayPoolsReconfigure();
+extern void delaySetNoDelay(int fd);
+extern void delayClearNoDelay(int fd);
+extern int delayIsNoDelay(int fd);
+extern delay_id delayClient(request_t *);
 extern EVH delayPoolsUpdate;
-extern int delayMostBytesWanted(const MemObject * mem, int max);
-extern int delayMostBytesAllowed(const MemObject * mem);
+extern int delayBytesWanted(delay_id d, int min, int max);
 extern void delayBytesIn(delay_id, int qty);
+extern int delayMostBytesWanted(const MemObject * mem, int max);
+extern delay_id delayMostBytesAllowed(const MemObject * mem);
 extern void delaySetStoreClient(StoreEntry * e, void *data, delay_id delay_id);
-extern int delayBytesWanted(delay_id d, int min, int max);
+void delayRegisterDelayIdPtr(delay_id * loc);
+void delayUnregisterDelayIdPtr(delay_id * loc);
 #endif
 
 /* helper.c */
@@ -1094,6 +1135,13 @@
 extern helper *helperCreate(const char *);
 extern void helperFree(helper *);
 
+#if USE_LEAKFINDER
+extern void leakInit(void);
+extern void *leakAddFL(void *, const char *, int);
+extern void *leakTouchFL(void *, const char *, int);
+extern void *leakFree(void *);
+#endif
+
 /*
  * prototypes for system functions missing from system includes
  */
Index: squid/src/pump.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Attic/pump.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/pump.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/pump.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,5 +1,5 @@
 /*
- * $Id: pump.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: pump.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 61    PUMP handler
  * AUTHOR: Kostas Anagnostakis
@@ -37,6 +37,7 @@
 #define PUMP_MAXBUFFER 2*SQUID_UDP_SO_SNDBUF
 
 struct _PumpStateData {
+    FwdState *fwd;
     request_t *req;
     int c_fd;			/* client fd */
     int s_fd;			/* server end */
@@ -93,7 +94,7 @@
     p->request_entry = storeCreateEntry(new_key, new_key, flags, r->method);
     storeClientListAdd(p->request_entry, p);
 #if DELAY_POOLS
-    delaySetStoreClient(p->request_entry, p, r->delay_id);
+    delaySetStoreClient(p->request_entry, p, delayClient(r));
 #endif
     /*
      * initialize data structure
@@ -106,19 +107,20 @@
     p->cbdata = NULL;
     p->next = pump_head;
     pump_head = p;
-    cbdataAdd(p, MEM_NONE);
+    cbdataAdd(p, cbdataXfree, 0);
     comm_add_close_handler(p->c_fd, pumpFree, p);
     commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
     debug(61, 4) ("pumpInit: FD %d, Created %p\n", fd, p);
 }
 
 void
-pumpStart(int s_fd, StoreEntry * reply_entry, request_t * r, CWCB * callback, void *cbdata)
+pumpStart(int s_fd, FwdState * fwd, CWCB * callback, void *cbdata)
 {
     PumpStateData *p = NULL;
+    request_t *r = fwd->request;
     size_t copy_sz;
     debug(61, 3) ("pumpStart: FD %d, key %s\n",
-	s_fd, storeKeyText(reply_entry->key));
+	s_fd, storeKeyText(fwd->entry->key));
     /*
      * find state data generated by pumpInit in linked list
      */
@@ -126,11 +128,13 @@
     assert(p != NULL);
     assert(p->request_entry);
     assert(p->c_fd > -1);
+    assert(r == p->req);
     /*
      * fill in the rest of data needed by the pump
      */
+    p->fwd = fwd;
     p->s_fd = s_fd;
-    p->reply_entry = reply_entry;
+    p->reply_entry = fwd->entry;
     p->callback = callback;
     p->cbdata = cbdata;
     cbdataLock(p->cbdata);
@@ -142,12 +146,8 @@
     if (p->rcvd < p->cont_len && r->body_sz > 0) {
 	assert(p->request_entry->store_status == STORE_PENDING);
 	assert(r->body != NULL);
-	if (r->flags.proxy_keepalive) {
-	    assert(r->body_sz <= p->cont_len);
-	    copy_sz = XMIN(r->body_sz, p->cont_len);
-	} else {
-	    copy_sz = r->body_sz;
-	}
+	assert(r->body_sz <= p->cont_len);
+	copy_sz = XMIN(r->body_sz, p->cont_len);
 	debug(61, 3) ("pumpStart: Appending %d bytes from r->body\n", copy_sz);
 	storeAppend(p->request_entry, r->body, copy_sz);
 	p->rcvd = copy_sz;
@@ -162,7 +162,7 @@
 	commSetDefer(p->c_fd, pumpReadDefer, p);
     }
     p->sent = 0;
-    if (r->flags.proxy_keepalive && p->sent == p->cont_len) {
+    if (p->sent == p->cont_len) {
 	pumpServerCopyComplete(p->s_fd, NULL, 0, DISK_OK, p);
     } else {
 	storeClientCopy(p->request_entry, p->sent, p->sent, 4096,
@@ -178,13 +178,13 @@
     debug(61, 5) ("pumpServerCopy: called with size=%d\n", size);
     if (size < 0) {
 	debug(61, 5) ("pumpServerCopy: freeing and returning\n");
-	memFree(MEM_4K_BUF, buf);
+	memFree(buf, MEM_4K_BUF);
 	return;
     }
     if (size == 0) {
 	debug(61, 5) ("pumpServerCopy: done, finishing\n", size);
 	pumpServerCopyComplete(p->s_fd, NULL, 0, DISK_OK, p);
-	memFree(MEM_4K_BUF, buf);
+	memFree(buf, MEM_4K_BUF);
 	return;
     }
     debug(61, 5) ("pumpServerCopy: to FD %d, %d bytes\n", p->s_fd, size);
@@ -205,14 +205,13 @@
 	pumpClose(p);
 	return;
     }
-    if (p->request_entry->store_status == STORE_ABORTED) {
-	debug(61, 5) ("pumpServerCopyComplete: STORE_ABORTED\n");
+    if (EBIT_TEST(p->request_entry->flags, ENTRY_ABORTED)) {
+	debug(61, 5) ("pumpServerCopyComplete: ENTRY_ABORTED\n");
 	pumpClose(p);
 	return;
     }
     p->sent += size;
-    if (p->req->flags.proxy_keepalive)
-	assert(p->sent <= p->cont_len);
+    assert(p->sent <= p->cont_len);
     if (p->sent < p->cont_len) {
 	storeClientCopy(p->request_entry, p->sent, p->sent, 4096,
 	    memAllocate(MEM_4K_BUF),
@@ -240,11 +239,9 @@
     PumpStateData *p = data;
     StoreEntry *req = p->request_entry;
     LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF);
-    int bytes_to_read = SQUID_TCP_SO_RCVBUF;
+    int bytes_to_read = XMIN(p->cont_len - p->rcvd, SQUID_TCP_SO_RCVBUF);
     int len = 0;
     errno = 0;
-    if (p->cont_len - p->rcvd < bytes_to_read)
-	bytes_to_read = p->cont_len - p->rcvd;
     Counter.syscalls.sock.reads++;
     len = read(fd, buf, bytes_to_read);
     fd_bytes(fd, len, FD_READ);
@@ -278,7 +275,7 @@
     }
     if (len > 0) {
 	int delta = p->rcvd + len - p->cont_len;
-	if (delta > 0) {
+	if (delta > 0 && p->req->flags.proxy_keepalive) {
 	    debug(61, delta == 2 ? 3 : 1) ("pumpReadFromClient: Warning: read %d bytes past content-length, truncating\n", delta);
 	    len = p->cont_len - p->rcvd;
 	}
@@ -292,10 +289,12 @@
 	return;
     }
     /* all done! */
-    assert(p->rcvd == p->cont_len);
+    if (p->req->flags.proxy_keepalive)
+	assert(p->rcvd == p->cont_len);
     debug(61, 2) ("pumpReadFromClient: finished!\n");
     storeComplete(req);
     commSetDefer(p->c_fd, NULL, NULL);
+    commSetTimeout(p->c_fd, -1, NULL, NULL);
 }
 
 static int
@@ -324,15 +323,10 @@
     p->flags.closing = 1;
     if (req != NULL && req->store_status == STORE_PENDING) {
 	storeUnregister(req, p);
-	storeAbort(req, 0);
     }
     if (rep != NULL && rep->store_status == STORE_PENDING) {
-	/*
-	 * Set the storeAbort() 'cbflag' so that the server-side
-	 * abort handler (httpAbort) gets called and the server-side
-	 * FD gets closed.
-	 */
-	storeAbort(rep, 1);
+	ErrorState *err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
+	fwdFail(p->fwd, err);
     }
     if (p->s_fd > -1) {
 	comm_close(p->s_fd);
@@ -369,25 +363,17 @@
     rep = p->reply_entry;
     if (req != NULL) {
 	storeUnregister(req, p);
-	if (req->store_status == STORE_PENDING)
-	    storeAbort(req, 0);
 	storeUnlockObject(req);
 	p->request_entry = NULL;
     }
     if (rep != NULL) {
-	/*
-	 * Set the storeAbort() 'cbflag' so that the server-side
-	 * abort handler (httpAbort) gets called and the server-side
-	 * FD gets closed.
-	 */
-	if (rep->store_status == STORE_PENDING)
-	    storeAbort(rep, 1);
+	debug(61, 3) ("pumpFree: did the server-side FD (%d) get closed?\n", p->s_fd);
 	storeUnlockObject(rep);
 	p->reply_entry = NULL;
     }
     requestUnlink(p->req);
     if (p->s_fd > -1) {
-	assert(0 == fd_table[p->s_fd].open);
+	assert(!fd_table[p->s_fd].flags.open);
 	p->s_fd = -1;
     }
     cbdataFree(p);
Index: squid/src/redirect.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/redirect.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/redirect.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/redirect.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: redirect.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: redirect.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 29    Redirector
  * AUTHOR: Duane Wessels
@@ -100,13 +100,13 @@
 	return;
     }
     r = xcalloc(1, sizeof(redirectStateData));
-    cbdataAdd(r, MEM_NONE);
+    cbdataAdd(r, cbdataXfree, 0);
     r->orig_url = xstrdup(http->uri);
     r->client_addr = conn->log_addr;
-    if (conn->ident.ident == NULL || *conn->ident.ident == '\0') {
+    if (conn->ident == NULL || *conn->ident == '\0') {
 	r->client_ident = dash_str;
     } else {
-	r->client_ident = conn->ident.ident;
+	r->client_ident = conn->ident;
     }
     r->method_s = RequestMethodStr[http->request->method];
     r->handler = handler;
Index: squid/src/refresh.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/refresh.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/refresh.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/refresh.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: refresh.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: refresh.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 22    Refresh Calculation
  * AUTHOR: Harvest Derived
@@ -41,7 +41,7 @@
 #include "squid.h"
 
 typedef enum {
-    rcHTTP, rcICP, rcCDigest, rcCount
+    rcHTTP, rcICP, rcCDigest, rcStore, rcCount
 } refreshCountsEnum;
 
 static struct RefreshCounts {
@@ -187,8 +187,8 @@
 	    rc->negative_age_stale++;
 	    return 1;
 	}
-	if (request->max_age > -1) {
-	    if (age > request->max_age) {
+	if (request->cache_control && request->cache_control->max_age > -1) {
+	    if (age > request->cache_control->max_age) {
 		debug(22, 3) ("refreshCheck: YES: age > client-max-age\n");
 		rc->request_max_age_stale++;
 		return 1;
@@ -255,6 +255,34 @@
     return 1;
 }
 
+int
+refreshIsCachable(const StoreEntry * entry)
+{
+    /*
+     * Don't look at the request to avoid no-cache and other nuisances.
+     * the object should have a mem_obj so the URL will be found there.
+     * 60 seconds delta, to avoid objects which expire almost
+     * immediately, and which can't be refreshed.
+     */
+    if (!refreshCheck(entry, NULL, 60, &refreshCounts[rcStore]))
+	/* Does not need refresh. This is certainly cachable */
+	return 1;
+    if (entry->lastmod < 0)
+	/* Last modified is needed to do a refresh */
+	return 0;
+    if (entry->mem_obj == NULL)
+	/* no mem_obj? */
+	return 1;
+    if (entry->mem_obj->reply)
+	/* no reply? */
+	return 1;
+    if (entry->mem_obj->reply->content_length == 0)
+	/* No use refreshing (caching?) 0 byte objects */
+	return 0;
+    /* This seems to be refreshable. Cache it */
+    return 1;
+}
+
 /* refreshCheck... functions below are protocol-specific wrappers around
  * refreshCheck() function above */
 
@@ -357,6 +385,7 @@
     memset(refreshCounts, 0, sizeof(refreshCounts));
     refreshCounts[rcHTTP].proto = "HTTP";
     refreshCounts[rcICP].proto = "ICP";
+    refreshCounts[rcStore].proto = "On Store";
     refreshCounts[rcCDigest].proto = "Cache Digests";
 
     cachemgrRegister("refresh",
Index: squid/src/send-announce.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/send-announce.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/send-announce.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/send-announce.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: send-announce.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: send-announce.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 27    Cache Announcer
  * AUTHOR: Duane Wessels
@@ -45,7 +45,7 @@
 	return;
     if (theOutIcpConnection < 0)
 	return;
-    cbdataAdd(junk = xmalloc(1), MEM_NONE);
+    cbdataAdd(junk = xmalloc(1), cbdataXfree, 0);
     ipcache_nbgethostbyname(Config.Announce.host, send_announce, junk);
     eventAdd("send_announce", start_announce, NULL, (double) Config.Announce.period, 1);
 }
Index: squid/src/snmp_agent.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/snmp_agent.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/snmp_agent.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/snmp_agent.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: snmp_agent.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: snmp_agent.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 49     SNMP Interface
  * AUTHOR: Kostas Anagnostakis
@@ -35,18 +35,10 @@
 
 
 #include "squid.h"
-
-#include "snmp.h"
-#include "snmp_impl.h"
-#include "asn1.h"
-#include "snmp_api.h"
-#include "snmp_vars.h"
-#include "snmp_oidlist.h"
 #include "cache_snmp.h"
 
 extern StatCounters *snmpStatGet(int);
 
-
 /************************************************************************
 
  SQUID MIB Implementation
@@ -69,7 +61,7 @@
 	Answer->val_len = sizeof(snint);
 	Answer->val.integer = xmalloc(Answer->val_len);
 	Answer->type = ASN_INTEGER;
-	*(Answer->val.integer) = store_mem_size;
+	*(Answer->val.integer) = store_mem_size >> 10;
 	break;
     case SYSSTOR:
 	Answer->val_len = sizeof(snint);
@@ -125,25 +117,13 @@
 	    Answer->val_len = sizeof(snint);
 	    Answer->val.integer = xmalloc(Answer->val_len);
 	    Answer->type = ASN_INTEGER;
-	    *(Answer->val.integer) = (snint) Config.Mem.maxSize;
-	    break;
-	case CONF_ST_MHIWM:
-	    Answer->val_len = sizeof(snint);
-	    Answer->val.integer = xmalloc(Answer->val_len);
-	    Answer->type = ASN_INTEGER;
-	    *(Answer->val.integer) = (snint) Config.Mem.highWaterMark;
-	    break;
-	case CONF_ST_MLOWM:
-	    Answer->val_len = sizeof(snint);
-	    Answer->val.integer = xmalloc(Answer->val_len);
-	    Answer->type = ASN_INTEGER;
-	    *(Answer->val.integer) = (snint) Config.Mem.lowWaterMark;
+	    *(Answer->val.integer) = (snint) Config.memMaxSize >> 20;
 	    break;
 	case CONF_ST_SWMAXSZ:
 	    Answer->val_len = sizeof(snint);
 	    Answer->val.integer = xmalloc(Answer->val_len);
 	    Answer->type = ASN_INTEGER;
-	    *(Answer->val.integer) = (snint) Config.Swap.maxSize;
+	    *(Answer->val.integer) = (snint) Config.Swap.maxSize >> 10;
 	    break;
 	case CONF_ST_SWHIWM:
 	    Answer->val_len = sizeof(snint);
@@ -197,13 +177,6 @@
 	if (p->in_addr.sin_addr.s_addr == laddr->s_addr)
 	    break;
 
-#if SNMP_OLD_INDEX
-    p = Config.peers;
-    cnt = Var->name[LEN_SQ_MESH + 3];
-    debug(49, 5) ("snmp_meshPtblFn: we want .x.%d\n", Var->name[10]);
-    while (--cnt)
-	if (!(p = p->next));
-#endif
     if (p == NULL) {
 	*ErrP = SNMP_ERR_NOSUCHNAME;
 	snmp_var_free(Answer);
@@ -321,17 +294,18 @@
 	*(Answer->val.integer) = IOStats.Http.reads;
 	Answer->type = SMI_COUNTER32;
 	break;
-    case PERF_SYS_DEFR:	/* XXX unused, remove me */
-	Answer->type = SMI_COUNTER32;
-	*(Answer->val.integer) = 0;
-	break;
     case PERF_SYS_MEMUSAGE:
 	*(Answer->val.integer) = (snint) memTotalAllocated() >> 10;
 	break;
-    case PERF_SYS_CPUUSAGE:
+    case PERF_SYS_CPUTIME:
 	squid_getrusage(&rusage);
 	*(Answer->val.integer) = (snint) rusage_cputime(&rusage);
 	break;
+    case PERF_SYS_CPUUSAGE:
+	squid_getrusage(&rusage);
+	*(Answer->val.integer) = (snint)
+	    dpercent(rusage_cputime(&rusage), tvSubDsec(squid_start, current_time));
+	break;
     case PERF_SYS_MAXRESSZ:
 	squid_getrusage(&rusage);
 	*(Answer->val.integer) = (snint) rusage_maxrss(&rusage);
@@ -428,6 +402,9 @@
 	case PERF_PROTOSTAT_AGGR_CURSWAP:
 	    *(Answer->val.integer) = (snint) store_swap_size;
 	    break;
+	case PERF_PROTOSTAT_AGGR_CLIENTS:
+	    *(Answer->val.integer) = (snint) Counter.client_http.clients;
+	    break;
 	default:
 	    *ErrP = SNMP_ERR_NOSUCHNAME;
 	    snmp_var_free(Answer);
@@ -436,7 +413,12 @@
 	return Answer;
     case PERF_PROTOSTAT_MEDIAN:
 
-	minutes = Var->name[LEN_SQ_PRF + 4];
+	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);
@@ -477,6 +459,12 @@
 	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;
 	    snmp_var_free(Answer);
@@ -489,26 +477,3 @@
     snmp_var_free(Answer);
     return (NULL);
 }
-
-void
-addr2oid(struct in_addr addr, oid * Dest)
-{
-    u_char *cp;
-    cp = (u_char *) & (addr.s_addr);
-    Dest[0] = *cp++;
-    Dest[1] = *cp++;
-    Dest[2] = *cp++;
-    Dest[3] = *cp++;
-}
-
-struct in_addr *
-oid2addr(oid * id)
-{
-    static struct in_addr laddr;
-    u_char *cp = (u_char *) & (laddr.s_addr);
-    cp[0] = id[0];
-    cp[1] = id[1];
-    cp[2] = id[2];
-    cp[3] = id[3];
-    return &laddr;
-}
Index: squid/src/snmp_core.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/snmp_core.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/snmp_core.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/snmp_core.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,8 +1,9 @@
+
 /*
- * $Id: snmp_core.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: snmp_core.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 49    SNMP support
- * AUTHOR: Kostas Anagnostakis
+ * AUTHOR: Glenn Chisholm
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  * ----------------------------------------------------------
@@ -20,300 +21,329 @@
  *  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.
  *
  */
-
-/**********************************************************************
- *
- *           Copyright 1996 by Carnegie Mellon University
- * 
- *                       All Rights Reserved
- * 
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of CMU not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- * 
- * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHAL
- * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * 
- * Author: Ryan Troll 
- * 
- **********************************************************************/
-
-
 #include "squid.h"
-
 #include "cache_snmp.h"
-#include "squid_mib.h"
 
 #define SNMP_REQUEST_SIZE 4096
 #define MAX_PROTOSTAT 5
 
-int snmp_dump_packet;
-void *users, *communities;
-
-static struct sockaddr_in local_snmpd;
-static int snmp_init_config = 0;
-struct snmp_session *Session;
-struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
-
-void snmpFwd_insertPending(struct sockaddr_in *, long);
-int snmpFwd_removePending(struct sockaddr_in *, long);
+typedef struct _mib_tree_entry mib_tree_entry;
+typedef oid *(instance_Fn) (oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
 
-extern void (*snmplib_debug_hook) (int, char *);
-static void snmpSnmplibDebug(int lvl, char *buf);
-
-struct snmpUdpData {
-    struct sockaddr_in address;
-    void *msg;
+struct _mib_tree_entry {
+    oid *name;
     int len;
-    struct snmpUdpData *next;
+    oid_ParseFn *parsefunction;
+    instance_Fn *instancefunction;
+    int children;
+    struct _mib_tree_entry **leaves;
+    struct _mib_tree_entry *parent;
 };
 
-typedef struct snmpUdpData snmpUdpData;
-
-struct snmpFwdQueue {
-    struct sockaddr_in addr;
-    long req_id;
-    time_t req_time;
-    struct snmpFwdQueue *next;
-};
+mib_tree_entry *mib_tree_head;
+mib_tree_entry *mib_tree_last;
 
-struct snmpFwdQueue *snmpHead = NULL;
-
-struct snmpUdpData *snmpUdpHead = NULL;
-struct snmpUdpData *snmpUdpTail = NULL;
-
-void snmpUdpReply(int, void *);
-void snmpAppendUdp(snmpUdpData *);
-void snmpUdpSend(int, const struct sockaddr_in *, void *, int);
-
-/* now include mib location definitions
- * and magic numbers */
-
-#include "cache_snmp.h"
+#if STDC_HEADERS
+static mib_tree_entry *snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...);
+static oid *snmpCreateOid(int length,...);
+#else
+static mib_tree_entry *snmpAddNode();
+static oid *snmpCreateOid();
+#endif
+extern void (*snmplib_debug_hook) (int, char *);
+static oid *static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+static oid *time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+static oid *peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+static oid *client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn);
+static void snmpDecodePacket(snmp_request_t * rq);
+static void snmpConstructReponse(snmp_request_t * rq);
+static struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
+static oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen);
+static oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen);
+static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * current);
+static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current);
+static oid *snmpOidDup(oid * A, snint ALen);
+static void snmpSnmplibDebug(int lvl, char *buf);
 
 
-static void
-snmpSnmplibDebug(int lvl, char *buf)
-{
-    debug(49, lvl) ("%s", buf);
-}
+/*
+ * The functions used during startup:
+ * snmpInit
+ * snmpConnectionOpen
+ * snmpConnectionShutdown
+ * snmpConnectionClose
+ */
 
+/*
+ * Turns the MIB into a Tree structure. Called during the startup process.
+ */
 void
-snmpHandleUdp(int sock, void *not_used)
+snmpInit(void)
 {
-    struct sockaddr_in from;
-    socklen_t from_len;
-    LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
-    LOCAL_ARRAY(char, deb_line, 4096);
-    int len;
-    snmp_request_t *snmp_rq;
-
-    debug(49, 5) ("snmpHandleUdp: Called.\n");
-    commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
-    from_len = sizeof(struct sockaddr_in);
-    memset(&from, '\0', from_len);
-    Counter.syscalls.sock.recvfroms++;
-    len = recvfrom(sock,
-	buf,
-	SNMP_REQUEST_SIZE,
-	0,
-	(struct sockaddr *) &from,
-	&from_len);
-    if (len < 0) {
-#ifdef _SQUID_LINUX_
-	/* Some Linux systems seem to set the FD for reading and then
-	 * return ECONNREFUSED when sendto() fails and generates an ICMP
-	 * port unreachable message. */
-	/* or maybe an EHOSTUNREACH "No route to host" message */
-	if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
-#endif
-	    debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n",
-		sock, xstrerror());
-	return;
-    }
-    if (snmp_dump_packet) {
-	int count;
-	debug(49, 6) ("received %d bytes from %s:\n", (int) len,
-	    inet_ntoa(from.sin_addr));
-	for (count = 0; count < len; count++) {
-	    snprintf(deb_line, 4096, "%s %02X ", deb_line, (u_char) buf[count]);
-	    if ((count % 16) == 15 || count == (len - 1)) {
-		debug(49, 8) ("snmp in: %s\n", deb_line);
-		deb_line[0] = '\0';
-	    }
-	}
-    }
-    buf[len] = '\0';
-    debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
-	sock,
-	len,
-	inet_ntoa(from.sin_addr));
-
-    snmp_rq = xcalloc(1, sizeof(snmp_request_t));
-    snmp_rq->buf = (u_char *) buf;
-    snmp_rq->len = len;
-    snmp_rq->sock = sock;
-    snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
-    memcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
-    snmpAgentParse(snmp_rq);
-}
+    debug(49, 5) ("snmpInit: Called.\n");
 
-void
-snmpAgentParseDone(int errstat, void *data)
-{
-    snmp_request_t *snmp_rq = (snmp_request_t *) data;
-    LOCAL_ARRAY(char, deb_line, 4096);
-    int sock = snmp_rq->sock;
-    long this_reqid = snmp_rq->reqid;
-    debug(49, 2) ("snmpAgentParseDone: errstat=%d, reqid=%d _t=%x\n",
-	errstat, this_reqid, snmp_rq);
-
-    if (memcmp(&snmp_rq->from, &local_snmpd, sizeof(struct sockaddr_in)) == 0) {
-	/* look it up */
-	if (snmpFwd_removePending(&snmp_rq->from, this_reqid)) {	/* failed */
-	    debug(49, 2) ("snmp: bogus response from %s.\n",
-		inet_ntoa(snmp_rq->from.sin_addr));
-	    if (snmp_rq->community)
-		xfree(snmp_rq->community);
-	    xfree(snmp_rq->outbuf);
-	    xfree(snmp_rq);
-	    return;
-	}
-    }
-    switch (errstat) {
-    case 2:			/* we might have to forward */
-	if (Config.Snmp.localPort != 0) {
-	    snmpFwd_insertPending(&snmp_rq->from, this_reqid);
-	    snmpUdpSend(sock, &local_snmpd, snmp_rq->outbuf, snmp_rq->outlen);
-	    break;
-	}
-	debug(49, 4) ("snmp: can't forward.\n");
-	break;
-    case 1:			/* everything is ok */
-	debug(49, 5) ("snmp: parsed.\n");
-	if (snmp_dump_packet) {
-	    int count = 0;
-	    debug(49, 5) ("snmp: sent %d bytes to %s\n", (int) snmp_rq->outlen,
-		inet_ntoa(snmp_rq->from.sin_addr));
-	    for (count = 0; count < snmp_rq->outlen; count++) {
-		snprintf(deb_line, 4096, "%s %02X ", deb_line,
-		    (u_char) snmp_rq->outbuf[count]);
-		if ((count % 16) == 15 || count == (snmp_rq->len - 1)) {
-		    debug(49, 7) ("snmp out: %s\n", deb_line);
-		    deb_line[0] = '\0';
-		}
-	    }
-	}
-	snmpUdpSend(snmp_rq->sock, &snmp_rq->from, snmp_rq->outbuf, snmp_rq->outlen);
-	break;
-    case 0:
-	debug(49, 5) ("snmpagentparsedone failed\n");
-	if (snmp_rq->outbuf)
-	    xfree(snmp_rq->outbuf);
-	break;
-    }
-    if (snmp_rq->community)
-	xfree(snmp_rq->community);
-    cbdataFree(snmp_rq);
-    return;
-}
+    debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
 
-void
-snmpInit(void)
-{
-    assert(NULL != Config.Snmp.mibPath);
-    if (!snmpInitConfig())
-	debug(49, 0) ("snmpInit: snmpInitConfig() failed.\n");
     snmplib_debug_hook = snmpSnmplibDebug;
 
-}
-int
-snmpInitConfig()
-{
-    wordlist *w;
-    char *buf;
-    char *tokens[10];
-
-    if (snmp_init_config)
-	return 1;
-
-    snmp_init_config = 1;
-    assert(NULL != Config.Snmp.mibPath);
-    if (Mib == NULL) {
-	debug(49, 3) ("init_mib: calling with %s\n", Config.Snmp.mibPath);
-	init_mib(Config.Snmp.mibPath);
-    }
-    if (Mib == NULL) {
-	debug(49, 0) ("WARNING: Failed to open MIB '%s'\n",
-	    Config.Snmp.mibPath);
-	return 0;
-    }
-    /*
-     * Process 'snmp_agent_conf' lines
-     */
-    for (w = Config.Snmp.snmpconf; w != NULL; w = w->next) {
-	buf = xstrdup(w->key);
-	snmpTokenize(buf, tokens, 10);
-	if (0 == strcmp("view", tokens[0])) {
-	    if (snmpCreateView(tokens) < 0) {
-		debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-		safe_free(buf);
-		return 0;
-	    }
-	} else if (0 == strcmp("user", tokens[0])) {
-	    if (snmpCreateUser(tokens) < 0) {
-		debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-		safe_free(buf);
-		return 0;
-	    }
-	} else if (0 == strcmp("community", tokens[0])) {
-	    if (snmpCreateCommunity(tokens) < 0)
-		debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-	} else {
-	    debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-	    safe_free(buf);
-	    return 0;
-	}
-	safe_free(buf);
-    }
-    if (!Config.Snmp.communities) {
-	debug(49, 2) ("snmpInit: WARNING: communities not defined.\n");
-    } else
-	debug(49, 5) ("snmpInit: communities defined.\n");
-    snmpInitAgentAuth();
-    assert(0 <= snmpDefaultAuth());
-    return 1;
+    mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
+	1, NULL, NULL, 1,
+	snmpAddNode(snmpCreateOid(2, 1, 3),
+	    2, NULL, NULL, 1,
+	    snmpAddNode(snmpCreateOid(3, 1, 3, 6),
+		3, NULL, NULL, 1,
+		snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
+		    4, NULL, NULL, 1,
+		    snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
+			5, NULL, NULL, 1,
+			snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
+			    6, NULL, NULL, 1,
+			    snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
+				7, NULL, NULL, 1,
+				snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
+				    8, NULL, NULL, 5,
+				    snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
+					LEN_SQ_SYS, NULL, NULL, 3,
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSVMSIZ),
+					    LEN_SYS, snmp_sysFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYSSTOR),
+					    LEN_SYS, snmp_sysFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_SYS, SYS_UPTIME),
+					    LEN_SYS, snmp_sysFn, static_Inst, 0)),
+				    snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
+					LEN_SQ_CONF, NULL, NULL, 5,
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_ADMIN),
+					    LEN_SYS, snmp_confFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION),
+					    LEN_SYS, snmp_confFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_VERSION_ID),
+					    LEN_SYS, snmp_confFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_LOG_FAC),
+					    LEN_SYS, snmp_confFn, static_Inst, 0),
+					snmpAddNode(snmpCreateOid(LEN_SYS, SQ_CONF, CONF_STORAGE),
+					    LEN_SYS, NULL, NULL, 4,
+					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_MMAXSZ),
+						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWMAXSZ),
+						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWHIWM),
+						LEN_CONF_ST, snmp_confFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_CONF_ST, SQ_CONF, CONF_STORAGE, CONF_ST_SWLOWM),
+						LEN_CONF_ST, snmp_confFn, static_Inst, 0))),
+				    snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
+					LEN_SQ_PRF, NULL, NULL, 2,
+					snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS),
+					    LEN_SQ_PRF + 1, NULL, NULL, 11,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11),
+						LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0)),
+					snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_PROTO),
+					    LEN_SQ_PRF + 1, NULL, NULL, 2,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 1),
+						LEN_SQ_PRF + 2, NULL, NULL, 15,
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15),
+						    LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0)),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, 2),
+						LEN_SQ_PRF + 2, NULL, NULL, 1,
+						snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 2, 1),
+						    LEN_SQ_PRF + 3, NULL, NULL, 10,
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0),
+						    snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10),
+							LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))),
+				    snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
+					LEN_SQ_NET, NULL, NULL, 3,
+					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_IP_CACHE),
+					    LEN_SQ_NET + 1, NULL, NULL, 8,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_ENT),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_REQ),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_HITS),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_PENDHIT),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_NEGHIT),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_MISS),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_GHBN),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_IP_CACHE, IP_LOC),
+						LEN_SQ_NET + 2, snmp_netIpFn, static_Inst, 0)),
+					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_FQDN_CACHE),
+					    LEN_SQ_NET + 1, NULL, NULL, 7,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_ENT),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_REQ),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_HITS),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_PENDHIT),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_NEGHIT),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_MISS),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_FQDN_CACHE, FQDN_GHBN),
+						LEN_SQ_NET + 2, snmp_netFqdnFn, static_Inst, 0)),
+					snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, NET_DNS_CACHE),
+					    LEN_SQ_NET + 1, NULL, NULL, 3,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REQ),
+						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_REP),
+						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0),
+					    snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, NET_DNS_CACHE, DNS_SERVERS),
+						LEN_SQ_NET + 2, snmp_netDnsFn, static_Inst, 0))),
+				    snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
+					LEN_SQ_MESH, NULL, NULL, 2,
+					snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
+					    LEN_SQ_MESH + 1, NULL, NULL, 1,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
+						LEN_SQ_MESH + 2, NULL, NULL, 13,
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
+						    LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))),
+					snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
+					    LEN_SQ_MESH + 1, NULL, NULL, 1,
+					    snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
+						LEN_SQ_MESH + 2, NULL, NULL, 9,
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
+						    LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0),
+						(mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
+							LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0)))))
+				)
+			    )
+			)
+		    )
+		)
+	    )
+	)
+	);
+
+    debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
 }
 
 void
 snmpConnectionOpen(void)
 {
     u_short port;
-    struct in_addr addr;
     struct sockaddr_in xaddr;
     socklen_t len;
     int x;
 
+    debug(49, 5) ("snmpConnectionOpen: Called\n");
     if ((port = Config.Port.snmp) > (u_short) 0) {
 	enter_suid();
 	theInSnmpConnection = comm_open(SOCK_DGRAM,
@@ -328,11 +358,11 @@
 	commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
 	debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
 	    (int) port, theInSnmpConnection);
-	if ((addr = Config.Addrs.snmp_outgoing).s_addr != no_addr.s_addr) {
+	if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
 	    enter_suid();
 	    theOutSnmpConnection = comm_open(SOCK_DGRAM,
 		0,
-		addr,
+		Config.Addrs.snmp_outgoing,
 		port,
 		COMM_NONBLOCKING,
 		"SNMP Port");
@@ -358,118 +388,12 @@
 	if (x < 0)
 	    debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
 		theOutSnmpConnection, xstrerror());
-	else {
+	else
 	    theOutSNMPAddr = xaddr.sin_addr;
-	    if (Config.Snmp.localPort != 0) {
-		local_snmpd.sin_addr = xaddr.sin_addr;
-		local_snmpd.sin_port = Config.Snmp.localPort;
-	    }
-	}
     }
 }
 
 void
-snmpFwd_insertPending(struct sockaddr_in *ad, long reqid)
-{
-    struct snmpFwdQueue *new;
-
-    new = (struct snmpFwdQueue *) xcalloc(1, sizeof(struct snmpFwdQueue));
-    xmemcpy(&new->addr, ad, sizeof(struct sockaddr_in));
-    new->req_id = reqid;
-    new->req_time = squid_curtime;
-    if (snmpHead == NULL) {
-	new->next = NULL;
-	snmpHead = new;
-    }
-    new->next = snmpHead;
-    snmpHead = new;
-}
-
-int
-snmpFwd_removePending(struct sockaddr_in *fr, long reqid)
-{
-    struct snmpFwdQueue *p, *prev = NULL;
-    for (p = snmpHead; p != NULL; p = p->next, prev = p)
-	if (reqid == p->req_id) {
-	    xmemcpy(fr, &p->addr, sizeof(struct sockaddr_in));
-	    if (p == snmpHead)
-		snmpHead = p->next;
-	    else if (p->next == NULL)
-		prev->next = NULL;
-	    debug(49, 3) ("snmpFwd_removePending: freeing %p\n", p);
-	    xfree(p);
-	    return 0;
-	}
-    return 1;
-}
-
-void
-snmpUdpSend(int fd,
-    const struct sockaddr_in *to,
-    void *msg, int len)
-{
-    snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData));
-    debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
-	inet_ntoa(to->sin_addr));
-    data->address = *to;
-    data->msg = msg;
-    data->len = len;
-    snmpAppendUdp(data);
-    commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
-
-}
-void
-snmpUdpReply(int fd, void *data)
-{
-    snmpUdpData *queue = data;
-    int x;
-    /* Disable handler, in case of errors. */
-    commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
-    while ((queue = snmpUdpHead) != NULL) {
-	debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n",
-	    fd,
-	    queue->len,
-	    inet_ntoa(queue->address.sin_addr),
-	    ntohs(queue->address.sin_port));
-	x = comm_udp_sendto(fd,
-	    &queue->address,
-	    sizeof(struct sockaddr_in),
-	    queue->msg,
-	    queue->len);
-	if (x < 0) {
-	    if (ignoreErrno(errno))
-		break;		/* don't de-queue */
-	}
-	snmpUdpHead = queue->next;
-	debug(49, 3) ("snmpUdpReply: freeing %p\n", queue->msg);
-	safe_free(queue->msg);
-	debug(49, 3) ("snmpUdpReply: freeing %p\n", queue);
-	safe_free(queue);
-    }
-    /* Reinstate handler if needed */
-    if (snmpUdpHead) {
-	commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
-    }
-}
-
-void
-snmpAppendUdp(snmpUdpData * item)
-{
-    item->next = NULL;
-    if (snmpUdpHead == NULL) {
-	snmpUdpHead = item;
-	snmpUdpTail = item;
-    } else if (snmpUdpTail == snmpUdpHead) {
-	snmpUdpTail = item;
-	snmpUdpHead->next = item;
-    } else {
-	snmpUdpTail->next = item;
-	snmpUdpTail = item;
-    }
-
-}
-
-void
 snmpConnectionShutdown(void)
 {
     if (theInSnmpConnection < 0)
@@ -484,7 +408,7 @@
      * function from executing repeatedly.  When we are really ready to
      * exit or restart, main will comm_close the 'out' descriptor.
      */ theInSnmpConnection = -1;
-    /* 
+    /*
      * Normally we only write to the outgoing SNMP socket, but we
      * also have a read handler there to catch messages sent to that
      * specific interface.  During shutdown, we must disable reading
@@ -504,346 +428,632 @@
     }
 }
 
-/* returns: 
- * 2: no such object in this mib
- * 1: ok
- * 0: failed */
+/*
+ * Functions for handling the requests.
+ */
 
+/*
+ * Accept the UDP packet
+ */
 void
-snmpAgentParse(void *data)
+snmpHandleUdp(int sock, void *not_used)
 {
-    snmp_request_t *rq = (snmp_request_t *) data;
-    u_char *buf = rq->buf;
-    int len = rq->len;
+    LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
+    struct sockaddr_in from;
+    socklen_t from_len;
+    snmp_request_t *snmp_rq;
+    int len;
+
+    debug(49, 5) ("snmpHandleUdp: Called.\n");
+
+    commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
+    from_len = sizeof(struct sockaddr_in);
+    memset(&from, '\0', from_len);
+    memset(buf, '\0', SNMP_REQUEST_SIZE);
+
+    Counter.syscalls.sock.recvfroms++;
+
+    len = recvfrom(sock,
+	buf,
+	SNMP_REQUEST_SIZE,
+	0,
+	(struct sockaddr *) &from,
+	&from_len);
 
+    if (len > 0) {
+	buf[len] = '\0';
+	debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
+	    sock,
+	    len,
+	    inet_ntoa(from.sin_addr));
+
+	snmp_rq = xcalloc(1, sizeof(snmp_request_t));
+	snmp_rq->buf = (u_char *) buf;
+	snmp_rq->len = len;
+	snmp_rq->sock = sock;
+	snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
+	xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
+	snmpDecodePacket(snmp_rq);
+	xfree(snmp_rq);
+    } else {
+	debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
+    }
+}
+
+/*
+ * Turn SNMP packet into a PDU, check available ACL's
+ */
+void
+snmpDecodePacket(snmp_request_t * rq)
+{
     struct snmp_pdu *PDU;
+    struct snmp_session Session;
+    aclCheck_t checklist;
     u_char *Community;
+    u_char *buf = rq->buf;
+    int len = rq->len;
+    int allow = 0;
 
+    debug(49, 5) ("snmpDecodePacket: Called.\n");
     /* Now that we have the data, turn it into a PDU */
-    cbdataAdd(rq, MEM_NONE);
     PDU = snmp_pdu_create(0);
-    Community = snmp_parse(Session, PDU, buf, len);
+    Session.Version = SNMP_VERSION_1;
+    Community = snmp_parse(&Session, PDU, buf, len);
+
+    checklist.src_addr = rq->from.sin_addr;
+    checklist.snmp_community = (char *) Community;
 
-    if (!snmp_coexist_V2toV1(PDU)) {	/* incompatibility */
-	debug(49, 3) ("snmpAgentParse: Incompatible V2 packet.\n");
+    allow = aclCheckFast(Config.accessList.snmp, &checklist);
+    if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
+	rq->community = Community;
+	rq->PDU = PDU;
+	debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
+	snmpConstructReponse(rq);
+    } else {
+	debug(49, 1) ("Failed SNMP agent query from : %s.\n",
+	    inet_ntoa(rq->from.sin_addr));
 	snmp_free_pdu(PDU);
-	snmpAgentParseDone(0, rq);
-	return;
     }
-    rq->community = Community;
-    rq->PDU = PDU;
-    debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
+}
 
-    if (!Community) {
-	debug(49, 2) ("snmpAgentParse: WARNING: Could not parse community\n");
+/*
+ * Packet OK, ACL Check OK, Create reponse.
+ */
+void
+snmpConstructReponse(snmp_request_t * rq)
+{
+    struct snmp_session Session;
+    struct snmp_pdu *RespPDU;
+    int ret;
 
-	snmp_free_pdu(PDU);
-	snmpAgentParseDone(0, rq);
-	return;
+    debug(49, 5) ("snmpConstructReponse: Called.\n");
+    RespPDU = snmpAgentResponse(rq->PDU);
+    snmp_free_pdu(rq->PDU);
+    if (RespPDU != NULL) {
+	Session.Version = SNMP_VERSION_1;
+	Session.community = rq->community;
+	Session.community_len = strlen((char *) rq->community);
+	ret = snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen);
+	sendto(rq->sock, rq->outbuf, rq->outlen, 0, (struct sockaddr *) &rq->from, sizeof(rq->from));
+	snmp_free_pdu(RespPDU);
+	xfree(rq->outbuf);
     }
-    snmpAclCheckStart(rq);
 }
 
+/*
+ * Decide how to respond to the request, construct a response and
+ * return the response to the requester.
+ * 
+ * If configured forward any reponses which are not for this agent.
+ */
 struct snmp_pdu *
 snmpAgentResponse(struct snmp_pdu *PDU)
 {
     struct snmp_pdu *Answer = NULL;
-    variable_list *VarPtr, *VarNew = NULL;
-    variable_list **VarPtrP, **RespVars;
-    int index = 0;
-    oid_ParseFn *ParseFn;
+    oid_ParseFn *ParseFn = NULL;
 
-    debug(49, 9) ("snmpAgentResponse: Received a %d PDU\n", PDU->command);
+    variable_list *VarPtr, *VarNew = NULL, **VarPtrP;
+    int index = 0;
 
-    /* Create a response */
-    Answer = snmp_pdu_create(SNMP_PDU_RESPONSE);
-    if (Answer == NULL)
-	return (NULL);
-    Answer->reqid = PDU->reqid;
-    Answer->errindex = 0;
-
-    if (PDU->command == SNMP_PDU_GET) {
-
-	RespVars = &(Answer->variables);
-	/* Loop through all variables */
-	for (VarPtrP = &(PDU->variables);
-	    *VarPtrP;
-	    VarPtrP = &((*VarPtrP)->next_variable)) {
-	    VarPtr = *VarPtrP;
+    debug(49, 5) ("snmpAgentResponse: Called.\n");
 
-	    index++;
+    if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
+	Answer->reqid = PDU->reqid;
+	Answer->errindex = 0;
+	if (PDU->command == SNMP_PDU_GET) {
+	    variable_list **RespVars;
+
+	    RespVars = &(Answer->variables);
+	    /* Loop through all variables */
+	    for (VarPtrP = &(PDU->variables);
+		*VarPtrP;
+		VarPtrP = &((*VarPtrP)->next_variable)) {
+		VarPtr = *VarPtrP;
+
+		index++;
+
+		/* Find the parsing function for this variable */
+		ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length);
+
+		if (ParseFn == NULL) {
+		    Answer->errstat = SNMP_ERR_NOSUCHNAME;
+		    debug(49, 5) ("snmpAgentResponse: No such oid. ");
+		} else
+		    VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
+
+		/* Was there an error? */
+		if ((Answer->errstat != SNMP_ERR_NOERROR) ||
+		    (VarNew == NULL)) {
+		    Answer->errindex = index;
+		    debug(49, 5) ("snmpAgentParse: successful.\n");
+		    /* Just copy the rest of the variables.  Quickly. */
+		    *RespVars = VarPtr;
+		    *VarPtrP = NULL;
+		    return (Answer);
+		}
+		/* No error.  Insert this var at the end, and move on to the next.
+		 */
+		*RespVars = VarNew;
+		RespVars = &(VarNew->next_variable);
+	    }
+	    return (Answer);
+	} else if (PDU->command == SNMP_PDU_GETNEXT) {
+	    oid *NextOidName = NULL;
+	    int NextOidNameLen = 0;
 
-	    /* Find the parsing function for this variable */
-	    ParseFn = oidlist_Find(VarPtr->name, VarPtr->name_length);
+	    ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
+		&(NextOidName), (snint *) & NextOidNameLen);
 
 	    if (ParseFn == NULL) {
 		Answer->errstat = SNMP_ERR_NOSUCHNAME;
-		debug(49, 5) ("snmpAgentResponse: No such oid. ");
-	    } else
-		VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
+		debug(49, 5) ("snmpAgentResponse: No such oid: ");
+		snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
+	    } else {
+		xfree(PDU->variables->name);
+		PDU->variables->name = NextOidName;
+		PDU->variables->name_length = NextOidNameLen;
+		VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat);
+	    }
 
 	    /* Was there an error? */
-	    if ((Answer->errstat != SNMP_ERR_NOERROR) ||
-		(VarNew == NULL)) {
-		Answer->errindex = index;
-		debug(49, 5) ("snmpAgentParse: successful.\n");
-		/* Just copy the rest of the variables.  Quickly. */
-		*RespVars = VarPtr;
-		*VarPtrP = NULL;
-		return (Answer);
+	    if (Answer->errstat != SNMP_ERR_NOERROR) {
+		Answer->errindex = 1;
+		Answer->variables = PDU->variables;
+		PDU->variables = NULL;
+	    } else {
+		Answer->variables = VarNew;
 	    }
-	    /* No error.  Insert this var at the end, and move on to the next.
-	     */
-	    *RespVars = VarNew;
-	    RespVars = &(VarNew->next_variable);
-	}
-	return (Answer);
-    } else if (PDU->command == SNMP_PDU_GETNEXT) {
-	oid *TmpOidName;
-	int TmpOidNameLen = 0;
-
-	/* Find the next OID. */
-	VarPtr = PDU->variables;
-
-	ParseFn = oidlist_Next(VarPtr->name, VarPtr->name_length,
-	    &(TmpOidName), (snint *) & (TmpOidNameLen));
-
-	if (ParseFn == NULL) {
-	    Answer->errstat = SNMP_ERR_NOSUCHNAME;
-	    debug(49, 5) ("snmpAgentResponse: No such oid: ");
-	    snmpDebugOid(5, VarPtr->name, VarPtr->name_length);
-	} else {
-	    xfree(VarPtr->name);
-	    VarPtr->name = TmpOidName;
-	    VarPtr->name_length = TmpOidNameLen;
-	    VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
-	}
 
-	/* Was there an error? */
-	if (Answer->errstat != SNMP_ERR_NOERROR) {
-	    Answer->errindex = 1;
-
-	    /* Just copy this variable */
-	    Answer->variables = VarPtr;
-	    PDU->variables = NULL;
 	} else {
-	    Answer->variables = VarNew;
+	    snmp_free_pdu(Answer);
+	    Answer = NULL;
 	}
-
-	/* Done.  Return this PDU */
-	return (Answer);
-    }				/* end SNMP_PDU_GETNEXT */
-    debug(49, 5) ("snmpAgentResponse: Ignoring PDU %d unknown command\n", PDU->command);
-    snmp_free_pdu(Answer);
-    return (NULL);
+    }
+    return (Answer);
 }
 
-void
-snmpDebugOid(int lvl, oid * Name, snint Len)
+oid_ParseFn *
+snmpTreeGet(oid * Current, snint CurrentLen)
 {
-    char mbuf[16], objid[1024];
-    int x;
-    objid[0] = '\0';
+    oid_ParseFn *Fn = NULL;
+    mib_tree_entry *mibTreeEntry = NULL, *lastEntry = NULL;
+    int count = 0;
 
-    for (x = 0; x < Len; x++) {
-	snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
-	strncat(objid, mbuf, sizeof(objid));
-    }
+    debug(49, 5) ("snmpTreeGet: Called\n");
 
-    debug(49, lvl) ("   oid = %s\n", objid);
-}
+    debug(49, 6) ("snmpTreeGet: Current : \n");
+    snmpDebugOid(6, Current, CurrentLen);
 
-int
-oidcmp(oid * A, snint ALen, oid * B, snint BLen)
-{
-    oid *aptr = A;
-    oid *bptr = B;
-    snint m = MIN(ALen, BLen);
-
-    /* Compare the first M bytes. */
-    while (m) {
-	if (*aptr < *bptr)
-	    return (-1);
-	if (*aptr++ > *bptr++)
-	    return (1);
-	m--;
+    mibTreeEntry = mib_tree_head;
+    if (Current[count] == mibTreeEntry->name[count]) {
+	count++;
+	while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
+	    lastEntry = mibTreeEntry;
+	    mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
+	    count++;
+	}
     }
+    if (mibTreeEntry && mibTreeEntry->parsefunction)
+	Fn = mibTreeEntry->parsefunction;
+    debug(49, 5) ("snmpTreeGet: return\n");
+    return (Fn);
+}
 
-    /* The first M bytes were identical.  So, they share the same
-     * root.  The shorter one must come first.
-     */
-    if (ALen < BLen)
-	return (-1);
+oid_ParseFn *
+snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
+{
+    oid_ParseFn *Fn = NULL;
+    mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL;
+    int count = 0;
 
-    if (ALen > BLen)
-	return (1);
+    debug(49, 5) ("snmpTreeNext: Called\n");
 
-    /* Same length, all bytes identical.  Must be the same OID. */
-    return (0);
-}
+    debug(49, 6) ("snmpTreeNext: Current : \n");
+    snmpDebugOid(6, Current, CurrentLen);
 
-int
-oidncmp(oid * A, snint ALen, oid * B, snint BLen, snint CompLen)
-{
-    oid *aptr = A;
-    oid *bptr = B;
-    snint m = MIN(MIN(ALen, BLen), CompLen);
-    snint count = 0;
-
-    /* Compare the first M bytes. */
-    while (count != m) {
-	if (*aptr < *bptr)
-	    return (-1);
-	if (*aptr++ > *bptr++)
-	    return (1);
+    mibTreeEntry = mib_tree_head;
+    if (Current[count] == mibTreeEntry->name[count]) {
 	count++;
+	while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) {
+	    mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry);
+	    count++;
+	}
+	debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n");
+    } else {
+	return NULL;
     }
+    if (mibTreeEntry == mib_tree_last)
+	return (Fn);
+    if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
+	*NextLen = CurrentLen;
+	*Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn);
+	if (*Next)
+	    return (Fn);
+    }
+    if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) {
+	count--;
+	nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent);
+	if (nextoid) {
+	    debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n");
+	    mibTreeEntry = nextoid;
+	    count++;
+	} else {
+	    debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n");
+	    while (!nextoid) {
+		count--;
+		if (mibTreeEntry->parent->parent) {
+		    nextoid = mibTreeEntry->parent;
+		    mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent);
+		    if (!mibTreeEntry) {
+			mibTreeEntry = nextoid;
+			nextoid = NULL;
+		    }
+		} else {
+		    nextoid = mibTreeEntry;
+		    mibTreeEntry = NULL;
+		}
+	    }
+	}
+    }
+    while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
+	mibTreeEntry = mibTreeEntry->leaves[0];
+    }
+    if (mibTreeEntry) {
+	*NextLen = mibTreeEntry->len;
+	*Next = (*mibTreeEntry->instancefunction) (mibTreeEntry->name, NextLen, mibTreeEntry, &Fn);
+    }
+    return (Fn);
+}
 
-    if (m == CompLen)
-	return (0);
-
-
-    if (ALen < BLen)
-	return (-1);
+oid *
+static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
+{
+    oid *instance = NULL;
 
-    if (ALen > BLen)
-	return (1);
+    if (*len <= current->len) {
+	instance = xmalloc(sizeof(name) * (*len + 1));
+	xmemcpy(instance, name, (sizeof(name) * *len));
+	instance[*len] = 0;
+	*len += 1;
+    }
+    *Fn = current->parsefunction;
+    return (instance);
+}
 
-    /* Same length, all bytes identical.  Must be the same OID. */
-    return (0);
+oid *
+time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
+{
+    oid *instance = NULL;
+    int identifier = 0, loop = 0;
+    int index[TIME_INDEX_LEN] =
+    {TIME_INDEX};
+
+    if (*len <= current->len) {
+	instance = xmalloc(sizeof(name) * (*len + 1));
+	xmemcpy(instance, name, (sizeof(name) * *len));
+	instance[*len] = *index;
+	*len += 1;
+    } else {
+	identifier = name[*len - 1];
+	while ((identifier != index[loop]) && (loop < TIME_INDEX_LEN))
+	    loop++;
+	if (loop < TIME_INDEX_LEN - 1) {
+	    instance = xmalloc(sizeof(name) * (*len));
+	    xmemcpy(instance, name, (sizeof(name) * *len));
+	    instance[*len - 1] = index[++loop];
+	}
+    }
+    *Fn = current->parsefunction;
+    return (instance);
 }
 
-/* Allocate space for, and copy, an OID.  Returns new oid, or NULL.
- */
 oid *
-oiddup(oid * A, snint ALen)
+peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
 {
-    oid *Ans;
+    oid *instance = NULL;
+    u_char *cp = NULL;
+    peer *peers = Config.peers;
+    struct in_addr *laddr = NULL;
+    char *host_addr = NULL, *current_addr = NULL, *last_addr = NULL;
+
+    if (peers == NULL) {
+	current = current->parent->parent->parent->leaves[1];
+	while ((current) && (!current->parsefunction))
+	    current = current->leaves[0];
+	instance = client_Inst(current->name, len, current, Fn);
+    } else if (*len <= current->len) {
+	instance = xmalloc(sizeof(name) * (*len + 4));
+	xmemcpy(instance, name, (sizeof(name) * *len));
+	cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
+	instance[*len] = *cp++;
+	instance[*len + 1] = *cp++;
+	instance[*len + 2] = *cp++;
+	instance[*len + 3] = *cp++;
+	*len += 4;
+    } else {
+	laddr = oid2addr(&name[*len - 4]);
+	host_addr = inet_ntoa(*laddr);
+	last_addr = xmalloc(strlen(host_addr));
+	strncpy(last_addr, host_addr, strlen(host_addr));
+	current_addr = inet_ntoa(peers->in_addr.sin_addr);
+	while ((peers) && (strncmp(last_addr, current_addr, strlen(current_addr)))) {
+	    if (peers->next) {
+		peers = peers->next;
+		current_addr = inet_ntoa(peers->in_addr.sin_addr);
+	    } else {
+		peers = NULL;
+	    }
+	}
+	xfree(last_addr);
+	if (peers) {
+	    if (peers->next) {
+		peers = peers->next;
+		instance = xmalloc(sizeof(name) * (*len));
+		xmemcpy(instance, name, (sizeof(name) * *len));
+		cp = (u_char *) & (peers->in_addr.sin_addr.s_addr);
+		instance[*len - 4] = *cp++;
+		instance[*len - 3] = *cp++;
+		instance[*len - 2] = *cp++;
+		instance[*len - 1] = *cp++;
+	    } else {
+		return (instance);
+	    }
+	} else {
+	    return (instance);
+	}
+    }
+    *Fn = current->parsefunction;
+    return (instance);
+}
 
-    Ans = (oid *) xmalloc(sizeof(oid) * ALen);
-    if (Ans)
-	memcpy(Ans, A, (sizeof(oid) * ALen));
-    return (Ans);
+oid *
+client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn)
+{
+    oid *instance = NULL;
+    u_char *cp = NULL;
+    struct in_addr *laddr = NULL;
+
+    if (*len <= current->len) {
+	instance = xmalloc(sizeof(name) * (*len + 4));
+	xmemcpy(instance, name, (sizeof(name) * *len));
+	laddr = client_entry(NULL);
+	if (laddr) {
+	    cp = (u_char *) & (laddr->s_addr);
+	    instance[*len] = *cp++;
+	    instance[*len + 1] = *cp++;
+	    instance[*len + 2] = *cp++;
+	    instance[*len + 3] = *cp++;
+	    *len += 4;
+	}
+    } else {
+	laddr = oid2addr(&name[*len - 4]);
+	laddr = client_entry(laddr);
+	if (laddr) {
+	    instance = xmalloc(sizeof(name) * (*len));
+	    xmemcpy(instance, name, (sizeof(name) * *len));
+	    cp = (u_char *) & (laddr->s_addr);
+	    instance[*len - 4] = *cp++;
+	    instance[*len - 3] = *cp++;
+	    instance[*len - 2] = *cp++;
+	    instance[*len - 1] = *cp++;
+	}
+    }
+    *Fn = current->parsefunction;
+    return (instance);
 }
 
 
-/**********************************************************************
- * OIDLIST FUNCTIONS
- *
- * Find the parsing function for OIDs registered in this agent.
- **********************************************************************/
+/*
+ * Utility functions
+ */
 
-oid_ParseFn *
-oidlist_Find(oid * Src, snint SrcLen)
+/*
+ * Tree utility functions. 
+ */
+
+/* 
+ * Returns a the sibling object in the tree
+ */
+mib_tree_entry *
+snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current)
 {
-    struct MIBListEntry *Ptr;
-    int ret;
+    mib_tree_entry *next = NULL;
+    int count = 0;
 
-    debug(49, 7) ("oidlist_Find:  Called.\n ");
-    snmpDebugOid(7, Src, SrcLen);
+    while ((!next) && (count < current->children)) {
+	if (current->leaves[count]->name[len] == entry) {
+	    next = current->leaves[count];
+	}
+	count++;
+    }
+    if (count < current->children) {
+	next = current->leaves[count];
+    } else {
+	next = NULL;
+    }
+    return (next);
+}
 
-    for (Ptr = squidMIBList; Ptr->GetFn; Ptr++) {
+/* 
+ * Returns the requested child object or NULL if it does not exist
+ */
+mib_tree_entry *
+snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
+{
+    mib_tree_entry *next = NULL;
+    int count = 0;
 
-	ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen);
+    while ((!next) && (count < current->children)) {
+	if (current->leaves[count]->name[len] == entry) {
+	    next = current->leaves[count];
+	}
+	count++;
+    }
+    return (next);
+}
 
-	if (!ret) {
+/*
+ * Adds a node to the MIB tree structure and adds the appropriate children
+ */
+mib_tree_entry *
+#if STDC_HEADERS
+snmpAddNode(oid * name, int len, oid_ParseFn * parsefunction, instance_Fn * instancefunction, int children,...)
+#else
+snmpAddNode(va_alist)
+     va_dcl
+#endif
+{
+#if STDC_HEADERS
+    va_list args;
+    int loop;
+    mib_tree_entry *entry = NULL;
+    va_start(args, children);
+#else
+    va_list args;
+    oid *name = NULL;
+    int len = 0, children = 0, loop;
+    oid_ParseFn *parsefunction = NULL;
+    instance_Fn *instancefunction = NULL;
+    mib_tree_entry *entry = NULL;
+    va_start(args);
+    name = va_arg(args, oid *);
+    len = va_arg(args, int);
+    parsefunction = va_arg(args, oid_ParseFn *);
+    instancefunction = va_arg(args, instance_Fn *);
+    children = va_arg(args, int);
+#endif
 
-	    /* Cool.  We found the mib it's in.  Let it find the function.
-	     */
-	    debug(49, 7) ("oidlist_Find:  found, returning GetFn Ptr! \n");
+    debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
+    snmpDebugOid(6, name, len);
 
-	    return ((*Ptr->GetFn) (Src, SrcLen));
-	}
-	if (ret < 0) {
-	    debug(49, 7) ("oidlist_Find:  We just passed it, so it doesn't exist.\n ");
-	    /* We just passed it, so it doesn't exist. */
-	    return (NULL);
+    va_start(args, children);
+    entry = xmalloc(sizeof(mib_tree_entry));
+    entry->name = snmpOidDup(name, len);
+    entry->len = len;
+    entry->parsefunction = parsefunction;
+    entry->instancefunction = instancefunction;
+    entry->children = children;
+
+    if (children > 0) {
+	entry->leaves = xmalloc(sizeof(mib_tree_entry *) * children);
+	for (loop = 0; loop < children; loop++) {
+	    entry->leaves[loop] = va_arg(args, mib_tree_entry *);
+	    entry->leaves[loop]->parent = entry;
 	}
     }
-
-    debug(49, 5) ("oidlist_Find:  the request was past the end.  It doesn't exist.\n");
-    /* We get here if the request was past the end.  It doesn't exist. */
-    return (NULL);
+    return (entry);
 }
-/* Find the next item.  For SNMP_PDU_GETNEXT requests. 
- *
- * Returns a pointer to the parser function, and copies the oid to dest.
- * 
- * This is just plain ugly and needs a total rewrite, these changes are
- * to make it work, nothing else!
- *
+/* End of tree utility functions */
+
+/* 
+ * Returns the list of parameters in an oid
  */
-oid_ParseFn *
-oidlist_Next(oid * Src, snint SrcLen, oid ** DestP, snint * DestLenP)
+oid *
+#if STDC_HEADERS
+snmpCreateOid(int length,...)
+#else
+snmpCreateOid(va_alist)
+     va_dcl
+#endif
 {
-    struct MIBListEntry *Ptr;
-    int ret;
-    oid_ParseFn *Fn = NULL;
+#if STDC_HEADERS
+    va_list args;
+    oid *new_oid;
+    int loop;
+    va_start(args, length);
+#else
+    va_list args;
+    int length = 0, loop;
+    oid *new_oid;
+    va_start(args);
+    length va_arg(args, int);
+#endif
 
-    debug(49, 7) ("oidlist_Next: Looking for next of:\n");
-    snmpDebugOid(7, Src, SrcLen);
+    new_oid = xmalloc(sizeof(oid) * length);
 
-    for (Ptr = squidMIBList; Ptr->GetNextFn; Ptr++) {
+    if (length > 0) {
+	for (loop = 0; loop < length; loop++) {
+	    new_oid[loop] = va_arg(args, int);
+	}
+    }
+    return (new_oid);
+}
 
-	/* Only look at as much as we have stored */
-	ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen);
+/*
+ * Allocate space for, and copy, an OID.  Returns new oid.
+ */
+oid *
+snmpOidDup(oid * A, snint ALen)
+{
+    oid *Ans = xmalloc(sizeof(oid) * ALen);
+    xmemcpy(Ans, A, (sizeof(oid) * ALen));
+    return Ans;
+}
 
-	if (!ret) {
-	    debug(49, 6) ("oidlist_Next: Checking MIB\n");
-
-	    /* Cool.  We found the mib it's in.  Ask it.
-	     */
-	    while (Ptr != NULL && Ptr->GetNextFn) {
-		Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP));
-		if (Fn == NULL) {
-		    /* If this returned NULL, we're looking for the first
-		     * in the next MIB.
-		     */
-		    debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n");
-		    Ptr++;
-		    continue;
-		}
-		return Fn;
-	    }
-	    /* Return what we found.  NULL if it wasn't in the MIB, and there
-	     * were no more MIBs. 
-	     */
-	    debug(49, 3) ("oidlist_Next: No next mib.\n");
-	    return NULL;
-	}
-	if (ret < 0) {
-	    /* We just passed the mib it would be in.  Return 
-	     * the next in this MIB.
-	     */
-	    debug(49, 3) ("oidlist_Next: Passed mib.  Checking this one.\n");
-	    while (Ptr != NULL && Ptr->GetNextFn) {
-		Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP));
-		if (Fn == NULL && oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen) < 0) {
-		    debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n");
-		    Ptr++;
-		    continue;
-		} else {
-		    return Fn;
-		}
-	    }
-	    debug(49, 3) ("oidlist_Next: No next mib.\n");
-	    return NULL;
-	}
+/*
+ * Debug calls, prints out the OID for debugging purposes.
+ */
+void
+snmpDebugOid(int lvl, oid * Name, snint Len)
+{
+    char mbuf[16], objid[1024];
+    int x;
+    objid[0] = '\0';
+
+    for (x = 0; x < Len; x++) {
+	snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
+	strncat(objid, mbuf, sizeof(objid));
     }
 
-    /* We get here if the request was past the end.  It doesn't exist. */
-    debug(49, 7) ("oidlist_Next: Found nothing.\n");
-    return (NULL);
+    debug(49, lvl) ("   oid = %s\n", objid);
 }
 
-struct in_addr *
-gen_getMax()
+static void
+snmpSnmplibDebug(int lvl, char *buf)
 {
-    static struct in_addr maddr;
-#if USE_ICMP
-    safe_inet_addr("255.255.255.255", &maddr);
-#else
-    safe_inet_addr("0.0.0.0", &maddr);
-#endif
-    return &maddr;
+    debug(49, lvl) ("%s", buf);
+}
+
+void
+addr2oid(struct in_addr addr, oid * Dest)
+{
+    u_char *cp;
+    cp = (u_char *) & (addr.s_addr);
+    Dest[0] = *cp++;
+    Dest[1] = *cp++;
+    Dest[2] = *cp++;
+    Dest[3] = *cp++;
+}
+
+struct in_addr
+       *
+oid2addr(oid * id)
+{
+    static struct in_addr laddr;
+    u_char *cp = (u_char *) & (laddr.s_addr);
+    cp[0] = id[0];
+    cp[1] = id[1];
+    cp[2] = id[2];
+    cp[3] = id[3];
+    return &laddr;
 }
Index: squid/src/squid.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/squid.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/squid.h	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/squid.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: squid.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: squid.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * AUTHOR: Duane Wessels
  *
@@ -69,8 +69,11 @@
 #endif
 
 #if PURIFY
-/* disable assert() under purify */
-#define NODEBUG
+#define assert(EX) ((void)0)
+#elif STDC_HEADERS
+#define assert(EX)  ((EX)?((void)0):xassert( # EX , __FILE__, __LINE__))
+#else
+#define assert(EX)  ((EX)?((void)0):xassert("EX", __FILE__, __LINE__))
 #endif
 
 #if HAVE_UNISTD_H
@@ -172,11 +175,6 @@
 #if HAVE_GETOPT_H
 #include 
 #endif
-#if HAVE_ASSERT_H
-#include 
-#else
-#define assert(X) ((void)0)
-#endif
 
 #if HAVE_DIRENT_H
 #include 
@@ -214,7 +212,7 @@
 #endif /* HAVE_POLL_H */
 #endif /* HAVE_POLL */
 
-#ifdef __STDC__
+#if STDC_HEADERS
 #include 
 #else
 #include 
@@ -300,7 +298,16 @@
 #endif
 
 #if CBDATA_DEBUG
-#define cbdataAdd(a,b)	cbdataAddDbg(a,b,__FILE__,__LINE__)
+#define cbdataAdd(a,b,c)	cbdataAddDbg(a,b,c,__FILE__,__LINE__)
+#endif
+
+#if USE_LEAKFINDER
+#define leakAdd(p) leakAddFL(p,__FILE__,__LINE__)
+#define leakTouch(p) leakTouchFL(p,__FILE__,__LINE__)
+#else
+#define leakAdd(p) p
+#define leakTouch(p) p
+#define leakFree(p) p
 #endif
 
 #if defined(_SQUID_NEXT_) && !defined(S_ISDIR)
@@ -362,11 +369,21 @@
 /*
  * Squid source files should not call these functions directly
  */
+#ifndef malloc
 #define malloc +
+#endif
+#ifndef free
 #define free +
+#endif
+#ifndef calloc
 #define calloc +
+#endif
+#ifndef sprintf
 #define sprintf +
+#endif
+#ifndef strdup
 #define strdup +
+#endif
 
 #if SQUID_SNMP
 extern struct snmp_mib_tree *Mib;
Index: squid/src/ssl.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ssl.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/ssl.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/ssl.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ssl.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: ssl.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 26    Secure Sockets Layer Proxy
  * AUTHOR: Duane Wessels
@@ -40,13 +40,16 @@
     char *host;			/* either request->host or proxy host */
     u_short port;
     request_t *request;
+    FwdServer *servers;
     struct {
 	int fd;
 	int len;
 	char *buf;
     } client, server;
     size_t *size_ptr;		/* pointer to size in an ConnStateData for logging */
-    int proxying;
+#if DELAY_POOLS
+    delay_id delay_id;
+#endif
 } SslStateData;
 
 static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
@@ -61,7 +64,6 @@
 static PF sslWriteClient;
 static PF sslWriteServer;
 static PSC sslPeerSelectComplete;
-static PSC sslPeerSelectFail;
 static void sslStateFree(SslStateData * sslState);
 static void sslConnected(int fd, void *);
 static void sslProxyConnected(int fd, void *);
@@ -102,9 +104,13 @@
     safe_free(sslState->server.buf);
     safe_free(sslState->client.buf);
     safe_free(sslState->url);
+    fwdServersFree(&sslState->servers);
     sslState->host = NULL;
     requestUnlink(sslState->request);
     sslState->request = NULL;
+#if DELAY_POOLS
+    delayUnregisterDelayIdPtr(&sslState->delay_id);
+#endif
     cbdataFree(sslState);
 }
 
@@ -112,8 +118,8 @@
 static int
 sslDeferServerRead(int fdnotused, void *data)
 {
-    request_t *r = data;
-    return delayBytesWanted(r->delay_id, 0, 1) == 0;
+    SslStateData *s = data;
+    return delayBytesWanted(s->delay_id, 0, 1) == 0;
 }
 #endif
 
@@ -155,7 +161,7 @@
 	 * no data flowing in the other direction.  Hence the argument of
 	 * 1 as min.
 	 */
-	read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+	read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
 	if (sslState->server.len < read_sz) {
 	    /* Have room to read more */
@@ -184,7 +190,7 @@
 	fd, read_sz, sslState->server.len);
     errno = 0;
 #if DELAY_POOLS
-    read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz);
+    read_sz = delayBytesWanted(sslState->delay_id, 1, read_sz);
 #endif
     Counter.syscalls.sock.reads++;
     len = read(fd, sslState->server.buf + sslState->server.len, read_sz);
@@ -192,7 +198,7 @@
     if (len > 0) {
 	fd_bytes(fd, len, FD_READ);
 #if DELAY_POOLS
-	delayBytesIn(sslState->request->delay_id, len);
+	delayBytesIn(sslState->delay_id, len);
 #endif
 	kb_incr(&Counter.server.all.kbytes_in, len);
 	kb_incr(&Counter.server.other.kbytes_in, len);
@@ -383,7 +389,7 @@
 	err->callback_data = sslState;
 	errorSend(sslState->client.fd, err);
     } else {
-	if (sslState->proxying)
+	if (sslState->servers->peer)
 	    sslProxyConnected(sslState->server.fd, sslState);
 	else
 	    sslConnected(sslState->server.fd, sslState);
@@ -392,7 +398,7 @@
 	    sslTimeout,
 	    sslState);
 #if DELAY_POOLS
-	commSetDefer(sslState->server.fd, sslDeferServerRead, sslState->request);
+	commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
 #endif
     }
 }
@@ -424,7 +430,11 @@
 	return;
     }
     sslState = xcalloc(1, sizeof(SslStateData));
-    cbdataAdd(sslState, MEM_NONE);
+    cbdataAdd(sslState, cbdataXfree, 0);
+#if DELAY_POOLS
+    sslState->delay_id = delayClient(request);
+    delayRegisterDelayIdPtr(&sslState->delay_id);
+#endif
     sslState->url = xstrdup(url);
     sslState->request = requestLink(request);
     sslState->size_ptr = size_ptr;
@@ -449,7 +459,6 @@
     peerSelect(request,
 	NULL,
 	sslPeerSelectComplete,
-	sslPeerSelectFail,
 	sslState);
     /*
      * Disable the client read handler until peer selection is complete
@@ -493,38 +502,44 @@
 }
 
 static void
-sslPeerSelectComplete(peer * p, void *data)
+sslPeerSelectComplete(FwdServer * fs, void *data)
 {
     SslStateData *sslState = data;
     request_t *request = sslState->request;
     peer *g = NULL;
-    sslState->proxying = p ? 1 : 0;
-    sslState->host = p ? p->host : request->host;
-    if (p == NULL) {
+    if (fs == NULL) {
+	ErrorState *err;
+	err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
+	err->request = requestLink(sslState->request);
+	err->callback = sslErrorComplete;
+	err->callback_data = sslState;
+	errorSend(sslState->client.fd, err);
+	return;
+    }
+    sslState->servers = fs;
+    sslState->host = fs->peer ? fs->peer->host : request->host;
+    if (fs->peer == NULL) {
 	sslState->port = request->port;
-    } else if (p->http_port != 0) {
-	sslState->port = p->http_port;
-    } else if ((g = peerFindByName(p->host))) {
+    } else if (fs->peer->http_port != 0) {
+	sslState->port = fs->peer->http_port;
+    } else if ((g = peerFindByName(fs->peer->host))) {
 	sslState->port = g->http_port;
     } else {
 	sslState->port = CACHE_HTTP_PORT;
     }
+#if DELAY_POOLS
+    /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
+    if (g && g->options.no_delay && sslState->delay_id) {
+	delayUnregisterDelayIdPtr(&sslState->delay_id);
+	sslState->delay_id = 0;
+    }
+#endif
+    hierarchyNote(&sslState->request->hier,
+	fs->peer ? fs->code : DIRECT,
+	sslState->host);
     commConnectStart(sslState->server.fd,
 	sslState->host,
 	sslState->port,
 	sslConnectDone,
 	sslState);
 }
-
-static void
-sslPeerSelectFail(peer * peernotused, void *data)
-{
-    SslStateData *sslState = data;
-    ErrorState *err;
-    err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
-    err->request = requestLink(sslState->request);
-    err->callback = sslErrorComplete;
-    err->callback_data = sslState;
-    errorSend(sslState->client.fd, err);
-
-}
Index: squid/src/stat.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/stat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/stat.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/stat.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: stat.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: stat.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 18    Cache Manager Statistics
  * AUTHOR: Harvest Derived
@@ -76,8 +76,7 @@
 static OBJH statAvg60min;
 static OBJH statUtilization;
 static OBJH statCountersHistograms;
-static double statRequestHitRatio(int minutes);
-static double statByteHitRatio(int minutes);
+static OBJH statClientRequests;
 
 #ifdef XMALLOC_STATISTICS
 static void info_get_mallstat(int, int, StoreEntry *);
@@ -221,12 +220,16 @@
 	strcat(buf, "DISPATCHED,");
     if (EBIT_TEST(flags, KEY_PRIVATE))
 	strcat(buf, "PRIVATE,");
+    if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT))
+	strcat(buf, "FWD_HDR_WAIT,");
     if (EBIT_TEST(flags, ENTRY_NEGCACHED))
 	strcat(buf, "NEGCACHED,");
     if (EBIT_TEST(flags, ENTRY_VALIDATED))
 	strcat(buf, "VALIDATED,");
     if (EBIT_TEST(flags, ENTRY_BAD_LENGTH))
 	strcat(buf, "BAD_LENGTH,");
+    if (EBIT_TEST(flags, ENTRY_ABORTED))
+	strcat(buf, "ABORTED,");
     if ((t = strrchr(buf, ',')))
 	*t = '\0';
     return buf;
@@ -273,7 +276,7 @@
 	for (i = 0, sc = &mem->clients[i]; sc != NULL; sc = sc->next, i++) {
 	    if (sc->callback_data == NULL)
 		continue;
-	    storeAppendPrintf(s, "\tClient #%d\n", i);
+	    storeAppendPrintf(s, "\tClient #%d, %p\n", i, sc->callback_data);
 	    storeAppendPrintf(s, "\t\tcopy_offset: %d\n",
 		(int) sc->copy_offset);
 	    storeAppendPrintf(s, "\t\tseen_offset: %d\n",
@@ -308,7 +311,7 @@
 	storeUnlockObject(state->sentry);
 	cbdataFree(state);
 	return;
-    } else if (state->sentry->store_status == STORE_ABORTED) {
+    } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
 	storeUnlockObject(state->sentry);
 	cbdataFree(state);
 	return;
@@ -338,7 +341,7 @@
     state->sentry = sentry;
     state->filter = filter;
     storeLockObject(sentry);
-    cbdataAdd(state, MEM_NONE);
+    cbdataAdd(state, cbdataXfree, 0);
     eventAdd("statObjects", statObjects, state, 0.0, 1);
 }
 
@@ -404,7 +407,7 @@
     int i;
     fde *f;
     storeAppendPrintf(sentry, "Active file descriptors:\n");
-    storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s %-7s %-21s %s\n",
+    storeAppendPrintf(sentry, "%-4s %-6s %-4s %-7s* %-7s* %-21s %s\n",
 	"File",
 	"Type",
 	"Tout",
@@ -412,17 +415,19 @@
 	"Nwrite",
 	"Remote Address",
 	"Description");
-    storeAppendPrintf(sentry, "---- ------ ---- ------- ------- --------------------- ------------------------------\n");
+    storeAppendPrintf(sentry, "---- ------ ---- -------- -------- --------------------- ------------------------------\n");
     for (i = 0; i < Squid_MaxFD; i++) {
 	f = &fd_table[i];
-	if (!f->open)
+	if (!f->flags.open)
 	    continue;
-	storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d %7d %-21s %s\n",
+	storeAppendPrintf(sentry, "%4d %-6.6s %4d %7d%c %7d%c %-21s %s\n",
 	    i,
 	    fdTypeStr[f->type],
 	    f->timeout_handler ? (int) (f->timeout - squid_curtime) / 60 : 0,
 	    f->bytes_read,
+	    f->read_handler ? '*' : ' ',
 	    f->bytes_written,
+	    f->write_handler ? '*' : ' ',
 	    fdRemoteAddr(f),
 	    f->desc);
     }
@@ -436,7 +441,7 @@
     double runtime;
 #if HAVE_MSTATS && HAVE_GNUMALLOC_H
     struct mstats ms;
-#elif HAVE_MALLINFO
+#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
     struct mallinfo mp;
     int t;
 #endif
@@ -538,7 +543,7 @@
 	ms.bytes_total >> 10);
     storeAppendPrintf(sentry, "\tTotal free:            %6d KB %d%%\n",
 	ms.bytes_free >> 10, percent(ms.bytes_free, ms.bytes_total));
-#elif HAVE_MALLINFO
+#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
     mp = mallinfo();
     storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",
 	appname);
@@ -584,12 +589,14 @@
 	Biggest_FD);
     storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n",
 	Number_FD);
+    storeAppendPrintf(sentry, "\tFiles queued for open:                %4d\n",
+	Opening_FD);
     storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n",
-	Squid_MaxFD - Number_FD);
+	fdNFree());
     storeAppendPrintf(sentry, "\tReserved number of file descriptors:  %4d\n",
 	RESERVED_FD);
-    storeAppendPrintf(sentry, "\tDisk files open:                      %4d\n",
-	open_disk_fd);
+    storeAppendPrintf(sentry, "\tStore Disk files open:                %4d\n",
+	store_open_disk_fd);
 
     storeAppendPrintf(sentry, "Internal Data Structures:\n");
     storeAppendPrintf(sentry, "\t%6d StoreEntries\n",
@@ -857,6 +864,11 @@
     cachemgrRegister("histograms",
 	"Full Histogram Counts",
 	statCountersHistograms, 0, 1);
+    ClientActiveRequests.head = NULL;
+    ClientActiveRequests.tail = NULL;
+    cachemgrRegister("active_requests",
+	"Client-side Active Requests",
+	statClientRequests, 0, 1);
 }
 
 static void
@@ -866,7 +878,7 @@
     StatCounters *p = &CountHist[1];
     StatCounters *c = &Counter;
     struct rusage rusage;
-    eventAdd("statAvgTick", statAvgTick, NULL, COUNT_INTERVAL, 1);
+    eventAdd("statAvgTick", statAvgTick, NULL, (double) COUNT_INTERVAL, 1);
     squid_getrusage(&rusage);
     c->page_faults = rusage_pagefaults(&rusage);
     c->cputime = rusage_cputime(&rusage);
@@ -1143,27 +1155,10 @@
     /* per-peer */
     storeAppendPrintf(sentry, "\nPer-peer statistics:\n");
     for (peer = getFirstPeer(); peer; peer = getNextPeer(peer)) {
-	cacheDigestGuessStatsReport(&peer->digest.stats.guess, sentry, peer->host);
-	storeAppendPrintf(sentry, "peer.msgs_sent = %d\n",
-	    peer->digest.stats.msgs_sent);
-	storeAppendPrintf(sentry, "peer.msgs_recv = %d\n",
-	    peer->digest.stats.msgs_recv);
-	storeAppendPrintf(sentry, "peer.kbytes_sent = %d\n",
-	    (int) peer->digest.stats.kbytes_sent.kb);
-	storeAppendPrintf(sentry, "peer.kbytes_recv = %d\n",
-	    (int) peer->digest.stats.kbytes_recv.kb);
-	storeAppendPrintf(sentry, "peer.local_memory = %d\n",
-	    peer->digest.cd ? peer->digest.cd->mask_size / 1024 : 0);
-	storeAppendPrintf(sentry, "digest state: inited: %d, disabled: %d usable: %d requested: %d\n",
-	    0 < peer->digest.flags.inited,
-	    0 < peer->digest.flags.disabled,
-	    0 < peer->digest.flags.usable,
-	    0 < peer->digest.flags.requested
-	    );
-	if (peer->digest.cd)
-	    cacheDigestReport(peer->digest.cd, peer->host, sentry);
+	if (peer->digest)
+	    peerDigestStatsReport(peer->digest, sentry);
 	else
-	    storeAppendPrintf(sentry, "no cache digest from peer %s\n", peer->host);
+	    storeAppendPrintf(sentry, "\nNo peer digest from %s\n", peer->host);
 	storeAppendPrintf(sentry, "\n");
     }
 
@@ -1278,7 +1273,7 @@
 	tvSubDsec(CountHist[minutes].timestamp, CountHist[0].timestamp));
 }
 
-static double
+extern double
 statRequestHitRatio(int minutes)
 {
     assert(minutes < N_COUNT_HIST);
@@ -1288,7 +1283,7 @@
 	CountHist[minutes].client_http.requests);
 }
 
-static double
+extern double
 statByteHitRatio(int minutes)
 {
     size_t s;
@@ -1303,6 +1298,54 @@
 	return (-1.0 * dpercent(s - c, c));
 }
 
+static void
+statClientRequests(StoreEntry * s)
+{
+    dlink_node *i;
+    clientHttpRequest *http;
+    ConnStateData *conn;
+    StoreEntry *e;
+    int fd;
+    for (i = ClientActiveRequests.head; i; i = i->next) {
+	http = i->data;
+	assert(http);
+	conn = http->conn;
+	storeAppendPrintf(s, "Connection: %p\n", conn);
+	if (conn) {
+	    fd = conn->fd;
+	    storeAppendPrintf(s, "\tFD %d, read %d, wrote %d\n", fd,
+		fd_table[fd].bytes_read, fd_table[fd].bytes_written);
+	    storeAppendPrintf(s, "\tFD desc: %s\n", fd_table[fd].desc);
+	    storeAppendPrintf(s, "\tin: buf %p, offset %d, size %d\n",
+		conn->in.buf, conn->in.offset, conn->in.size);
+	    storeAppendPrintf(s, "\tpeer: %s:%d\n",
+		inet_ntoa(conn->peer.sin_addr),
+		ntohs(conn->peer.sin_port));
+	    storeAppendPrintf(s, "\tme: %s:%d\n",
+		inet_ntoa(conn->me.sin_addr),
+		ntohs(conn->me.sin_port));
+	    storeAppendPrintf(s, "\tnrequests: %d\n",
+		conn->nrequests);
+	    storeAppendPrintf(s, "\tpersistent: %d\n",
+		conn->persistent);
+	    storeAppendPrintf(s, "\tdefer: n %d, until %d\n",
+		conn->defer.n, conn->defer.until);
+	}
+	storeAppendPrintf(s, "uri %s\n", http->uri);
+	storeAppendPrintf(s, "out.offset %d, out.size %d\n",
+	    http->out.offset, http->out.size);
+	storeAppendPrintf(s, "req_sz %d\n", http->req_sz);
+	e = http->entry;
+	storeAppendPrintf(s, "entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A");
+	e = http->old_entry;
+	storeAppendPrintf(s, "old_entry %p/%s\n", e, e ? storeKeyText(e->key) : "N/A");
+	storeAppendPrintf(s, "start %d.%06d (%f seconds ago)\n", http->start.tv_sec,
+	    http->start.tv_usec,
+	    tvSubDsec(http->start, current_time));
+	storeAppendPrintf(s, "\n");
+    }
+}
+
 #if STAT_GRAPHS
 /*
  * urgh, i don't like these, but they do cut the amount of code down immensely
Index: squid/src/stmem.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/stmem.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/stmem.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/stmem.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: stmem.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: stmem.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 19    Store Memory Primitives
  * AUTHOR: Harvest Derived
@@ -41,7 +41,7 @@
     mem_node *p;
     while ((p = mem->head)) {
 	mem->head = p->next;
-	memFree(MEM_STMEM_BUF, p->data);
+	memFree(p->data, MEM_STMEM_BUF);
 	store_mem_size -= SM_PAGE_SIZE;
 	safe_free(p);
     }
@@ -65,7 +65,7 @@
 	    lastp = p;
 	    p = p->next;
 	    current_offset += lastp->len;
-	    memFree(MEM_STMEM_BUF, lastp->data);
+	    memFree(lastp->data, MEM_STMEM_BUF);
 	    store_mem_size -= SM_PAGE_SIZE;
 	    safe_free(lastp);
 	}
Index: squid/src/store.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Storage Manager
  * AUTHOR: Harvest Derived
@@ -49,15 +49,13 @@
 {
     "PING_NONE",
     "PING_WAITING",
-    "PING_TIMEOUT",
     "PING_DONE"
 };
 
 const char *storeStatusStr[] =
 {
     "STORE_OK",
-    "STORE_PENDING",
-    "STORE_ABORTED"
+    "STORE_PENDING"
 };
 
 const char *swapStatusStr[] =
@@ -95,8 +93,7 @@
  * local variables
  */
 static dlink_list inmem_list;
-static int store_pages_high = 0;
-static int store_pages_low = 0;
+static int store_pages_max = 0;
 static int store_swap_high = 0;
 static int store_swap_low = 0;
 static int store_swap_mid = 0;
@@ -157,7 +154,7 @@
     ctx_exit(ctx);		/* must exit before we free mem->url */
     safe_free(mem->url);
     safe_free(mem->log_url);
-    memFree(MEM_MEMOBJECT, mem);
+    memFree(mem, MEM_MEMOBJECT);
 }
 
 static void
@@ -170,7 +167,7 @@
 	destroy_MemObject(e);
     storeHashDelete(e);
     assert(e->key == NULL);
-    memFree(MEM_STOREENTRY, e);
+    memFree(e, MEM_STOREENTRY);
 }
 
 /* ----- INTERFACE BETWEEN STORAGE MANAGER AND HASH TABLE FUNCTIONS --------- */
@@ -250,10 +247,8 @@
 	storeKeyText(e->key), e->lock_count);
     if (e->lock_count)
 	return (int) e->lock_count;
-    if (e->store_status == STORE_PENDING) {
-	assert(!EBIT_TEST(e->flags, ENTRY_DISPATCHED));
+    if (e->store_status == STORE_PENDING)
 	EBIT_SET(e->flags, RELEASE_REQUEST);
-    }
     assert(storePendingNClients(e) == 0);
     if (EBIT_TEST(e->flags, RELEASE_REQUEST))
 	storeRelease(e);
@@ -283,10 +278,7 @@
 StoreEntry *
 storeGetPublic(const char *uri, const method_t method)
 {
-    StoreEntry *e = storeGet(storeKeyPublic(uri, method));
-    if (e == NULL && squid_curtime < 920000000)
-	e = storeGet(storeKeyPublicOld(uri, method));
-    return e;
+    return storeGet(storeKeyPublic(uri, method));
 }
 
 static int
@@ -387,9 +379,6 @@
     e->timestamp = 0;		/* set in storeTimestampsSet() */
     e->ping_status = PING_NONE;
     EBIT_SET(e->flags, ENTRY_VALIDATED);
-#ifdef PPNR_WIP
-    EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT);
-#endif /* PPNR_WIP */
     return e;
 }
 
@@ -408,6 +397,7 @@
     MemObject *mem = e->mem_obj;
     assert(mem != NULL);
     assert(len >= 0);
+    assert(e->store_status == STORE_PENDING);
     if (len) {
 	debug(20, 5) ("storeAppend: appending %d bytes for '%s'\n",
 	    len,
@@ -428,17 +418,18 @@
 #endif
 }
 
-#ifdef __STDC__
 void
+#if STDC_HEADERS
 storeAppendPrintf(StoreEntry * e, const char *fmt,...)
-{
-    va_list args;
-    va_start(args, fmt);
 #else
-void
 storeAppendPrintf(va_alist)
      va_dcl
+#endif
 {
+#if STDC_HEADERS
+    va_list args;
+    va_start(args, fmt);
+#else
     va_list args;
     StoreEntry *e = NULL;
     const char *fmt = NULL;
@@ -470,6 +461,7 @@
 	int too_big;
 	int private_key;
 	int too_many_open_files;
+	int too_many_open_fds;
 	int lru_age_too_low;
     } no;
     struct {
@@ -482,7 +474,7 @@
 {
     if (Config.max_open_disk_fds == 0)
 	return 0;
-    if (open_disk_fd > Config.max_open_disk_fds)
+    if (store_open_disk_fd > Config.max_open_disk_fds)
 	return 1;
     return 0;
 }
@@ -515,9 +507,19 @@
     } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
 	debug(20, 3) ("storeCheckCachable: NO: private key\n");
 	store_check_cachable_hist.no.private_key++;
+    } else if (e->swap_status != SWAPOUT_NONE) {
+	/*
+	 * here we checked the swap_status because the remaining
+	 * cases are only relevant only if we haven't started swapping
+	 * out the object yet.
+	 */
+	return 1;
     } else if (storeTooManyDiskFilesOpen()) {
 	debug(20, 2) ("storeCheckCachable: NO: too many disk files open\n");
 	store_check_cachable_hist.no.too_many_open_files++;
+    } else if (fdNFree() < RESERVED_FD) {
+	debug(20, 2) ("storeCheckCachable: NO: too many FD's open\n");
+	store_check_cachable_hist.no.too_many_open_fds++;
     } else if (storeExpiredReferenceAge() < 300) {
 	debug(20, 2) ("storeCheckCachable: NO: LRU Age = %d\n",
 	    storeExpiredReferenceAge());
@@ -534,6 +536,8 @@
 static void
 storeCheckCachableStats(StoreEntry * sentry)
 {
+    storeAppendPrintf(sentry, "Category\t Count\n");
+
     storeAppendPrintf(sentry, "no.non_get\t%d\n",
 	store_check_cachable_hist.no.non_get);
     storeAppendPrintf(sentry, "no.not_entry_cachable\t%d\n",
@@ -550,6 +554,8 @@
 	store_check_cachable_hist.no.private_key);
     storeAppendPrintf(sentry, "no.too_many_open_files\t%d\n",
 	store_check_cachable_hist.no.too_many_open_files);
+    storeAppendPrintf(sentry, "no.too_many_open_fds\t%d\n",
+	store_check_cachable_hist.no.too_many_open_fds);
     storeAppendPrintf(sentry, "no.lru_age_too_low\t%d\n",
 	store_check_cachable_hist.no.lru_age_too_low);
     storeAppendPrintf(sentry, "yes.default\t%d\n",
@@ -561,7 +567,15 @@
 storeComplete(StoreEntry * e)
 {
     debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->key));
-    assert(e->store_status == STORE_PENDING);
+    if (e->store_status != STORE_PENDING) {
+	/*
+	 * if we're not STORE_PENDING, then probably we got aborted
+	 * and there should be NO clients on this entry
+	 */
+	assert(EBIT_TEST(e->flags, ENTRY_ABORTED));
+	assert(e->mem_obj->nclients == 0);
+	return;
+    }
     e->mem_obj->object_sz = e->mem_obj->inmem_hi;
     e->store_status = STORE_OK;
     assert(e->mem_status == NOT_IN_MEMORY);
@@ -577,49 +591,40 @@
     storeCheckSwapOut(e);
 }
 
-#ifdef PPNR_WIP
-void
-storePPNR(StoreEntry * e)
-{
-    assert(EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT));
-    EBIT_CLR(e->flags, ENTRY_FWD_HDR_WAIT);
-}
-
-#endif /* PPNR_WIP */
-
 /*
  * Someone wants to abort this transfer.  Set the reason in the
  * request structure, call the server-side callback and mark the
  * entry for releasing 
  */
 void
-storeAbort(StoreEntry * e, int cbflag)
+storeAbort(StoreEntry * e)
 {
     MemObject *mem = e->mem_obj;
-    STABH *callback;
-    void *data;
     assert(e->store_status == STORE_PENDING);
     assert(mem != NULL);
     debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->key));
     storeLockObject(e);		/* lock while aborting */
     storeNegativeCache(e);
     storeReleaseRequest(e);
-    e->store_status = STORE_ABORTED;
+    EBIT_SET(e->flags, ENTRY_ABORTED);
     storeSetMemStatus(e, NOT_IN_MEMORY);
     /* No DISK swap for negative cached object */
     e->swap_status = SWAPOUT_NONE;
+    e->store_status = STORE_OK;
     /*
      * We assign an object length here.  The only other place we assign
      * the object length is in storeComplete()
      */
     mem->object_sz = mem->inmem_hi;
     /* Notify the server side */
-    if (cbflag && mem->abort.callback) {
-	callback = mem->abort.callback;
-	data = mem->abort.data;
+    if (mem->abort.callback) {
+	eventAdd("mem->abort.callback",
+	    mem->abort.callback,
+	    mem->abort.data,
+	    0.0,
+	    0);
 	mem->abort.callback = NULL;
 	mem->abort.data = NULL;
-	callback(data);
     }
     /* Notify the client side */
     InvokeHandlers(e);
@@ -657,7 +662,7 @@
 	return;
     last_check = squid_curtime;
     pages_needed = (size / SM_PAGE_SIZE) + 1;
-    if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_high)
+    if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
 	return;
     if (store_rebuilding)
 	return;
@@ -675,7 +680,7 @@
 	}
 	released++;
 	storePurgeMem(e);
-	if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_high)
+	if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max)
 	    break;
     }
     debug(20, 3) ("storeGetMemSpace stats:\n");
@@ -705,25 +710,21 @@
     int expired = 0;
     int max_scan;
     int max_remove;
+    double f;
     static time_t last_warn_time = 0;
     /* We can't delete objects while rebuilding swap */
     if (store_rebuilding) {
 	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1);
 	return;
-    } else if (store_swap_size < store_swap_mid) {
-	max_scan = 100;
-	max_remove = 8;
-	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1);
-    } else if (store_swap_size < store_swap_high) {
-	max_scan = 200;
-	max_remove = 8;
-	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 0.1, 1);
     } else {
-	max_scan = 500;
-	max_remove = 32;
-	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 0.0, 1);
+	f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low);
+	f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f;
+	max_scan = (int) (f * 400.0 + 100.0);
+	max_remove = (int) (f * 70.0 + 10.0);
+	eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1);
     }
-    debug(20, 3) ("storeMaintainSwapSpace\n");
+    debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n",
+	f, max_scan, max_remove);
     for (m = store_list.tail; m; m = prev) {
 	prev = m->prev;
 	e = m->data;
@@ -919,7 +920,7 @@
 	store_hash_buckets,
 	store_maintain_rate,
 	store_maintain_rate == 1 ? null_string : "s");
-    debug(20, 1) ("Max Mem  size: %d KB\n", Config.Mem.maxSize >> 10);
+    debug(20, 1) ("Max Mem  size: %d KB\n", Config.memMaxSize >> 10);
     debug(20, 1) ("Max Swap size: %d KB\n", Config.Swap.maxSize);
 }
 
@@ -957,21 +958,12 @@
 void
 storeConfigure(void)
 {
-    int store_mem_high = 0;
-    int store_mem_low = 0;
-    store_mem_high = (long) (Config.Mem.maxSize / 100) *
-	Config.Mem.highWaterMark;
-    store_mem_low = (long) (Config.Mem.maxSize / 100) *
-	Config.Mem.lowWaterMark;
-
     store_swap_high = (long) (((float) Config.Swap.maxSize *
 	    (float) Config.Swap.highWaterMark) / (float) 100);
     store_swap_low = (long) (((float) Config.Swap.maxSize *
 	    (float) Config.Swap.lowWaterMark) / (float) 100);
     store_swap_mid = (store_swap_high >> 1) + (store_swap_low >> 1);
-
-    store_pages_high = store_mem_high / SM_PAGE_SIZE;
-    store_pages_low = store_mem_low / SM_PAGE_SIZE;
+    store_pages_max = Config.memMaxSize / SM_PAGE_SIZE;
 }
 
 static int
@@ -1063,7 +1055,7 @@
     if (EBIT_TEST(e->flags, ENTRY_NEGCACHED))
 	if (e->expires <= squid_curtime)
 	    return 0;
-    if (e->store_status == STORE_ABORTED)
+    if (EBIT_TEST(e->flags, ENTRY_ABORTED))
 	return 0;
     return 1;
 }
@@ -1240,3 +1232,15 @@
 	return NULL;
     return e->mem_obj->reply;
 }
+
+void
+storeEntryReset(StoreEntry * e)
+{
+    MemObject *mem = e->mem_obj;
+    debug(20, 3) ("storeEntryReset: %s\n", storeUrl(e));
+    assert(mem->swapout.fd == -1);
+    stmemFree(&mem->data_hdr);
+    mem->inmem_hi = mem->inmem_lo = 0;
+    httpReplyDestroy(mem->reply);
+    mem->reply = httpReplyCreate();
+}
Index: squid/src/store_clean.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Attic/store_clean.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_clean.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_clean.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: store_clean.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_clean.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 36    Cache Directory Cleanup
  * AUTHOR: Duane Wessels
@@ -54,6 +54,9 @@
     struct dirent *de = NULL;
     LOCAL_ARRAY(char, p1, MAXPATHLEN + 1);
     LOCAL_ARRAY(char, p2, MAXPATHLEN + 1);
+#if USE_TRUNCATE_NOT_UNLINK
+    struct stat sb;
+#endif
     int files[20];
     int swapfileno;
     int fn;			/* same as swapfileno, but with dirn bits set */
@@ -93,6 +96,11 @@
 	    if (storeDirMapBitTest(fn))
 		if (storeFilenoBelongsHere(fn, D0, D1, D2))
 		    continue;
+#if USE_TRUNCATE_NOT_UNLINK
+	if (!stat(de->d_name, &sb))
+	    if (sb.st_size == 0)
+		continue;
+#endif
 	files[k++] = swapfileno;
     }
     closedir(dp);
@@ -105,7 +113,11 @@
     for (n = 0; n < k; n++) {
 	debug(36, 3) ("storeDirClean: Cleaning file %08X\n", files[n]);
 	snprintf(p2, MAXPATHLEN + 1, "%s/%08X", p1, files[n]);
+#if USE_TRUNCATE_NOT_UNLINK
+	truncate(p2, 0);
+#else
 	safeunlink(p2, 0);
+#endif
 	Counter.swap_files_cleaned++;
     }
     debug(36, 3) ("Cleaned %d unused files from %s\n", k, p1);
Index: squid/src/store_client.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_client.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_client.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_client.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_client.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Client-Side Interface
  * AUTHOR: Duane Wessels
@@ -47,6 +47,8 @@
 static void storeClientFileRead(store_client * sc);
 static EVH storeClientCopyEvent;
 static store_client_t storeClientType(StoreEntry *);
+static int CheckQuickAbort2(StoreEntry * entry);
+static void CheckQuickAbort(StoreEntry * entry);
 
 /* check if there is any client waiting for this object at all */
 /* return 1 if there is at least one client */
@@ -79,9 +81,9 @@
     MemObject *mem = e->mem_obj;
     if (mem->inmem_lo)
 	return STORE_DISK_CLIENT;
-    if (e->store_status == STORE_ABORTED) {
+    if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
 	/* I don't think we should be adding clients to aborted entries */
-	debug(20, 1) ("storeClientType: adding to STORE_ABORTED entry\n");
+	debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n");
 	return STORE_MEM_CLIENT;
     }
     if (e->store_status == STORE_OK) {
@@ -116,7 +118,7 @@
 	return;
     mem->nclients++;
     sc = memAllocate(MEM_STORE_CLIENT);
-    cbdataAdd(sc, MEM_STORE_CLIENT);	/* sc is callback_data for file_read */
+    cbdataAdd(sc, memFree, MEM_STORE_CLIENT);	/* sc is callback_data for file_read */
     sc->callback_data = data;
     sc->seen_offset = 0;
     sc->copy_offset = 0;
@@ -130,6 +132,9 @@
 	assert(e->swap_file_number > -1 || storeSwapOutAble(e));
     for (T = &mem->clients; *T; T = &(*T)->next);
     *T = sc;
+#if DELAY_POOLS
+    sc->delay_id = 0;
+#endif
 }
 
 static void
@@ -154,7 +159,7 @@
     void *data)
 {
     store_client *sc;
-    assert(e->store_status != STORE_ABORTED);
+    assert(!EBIT_TEST(e->flags, ENTRY_ABORTED));
     debug(20, 3) ("storeClientCopy: %s, seen %d, want %d, size %d, cb %p, cbdata %p\n",
 	storeKeyText(e->key),
 	(int) seen_offset,
@@ -177,7 +182,7 @@
 /*
  * This function is used below to decide if we have any more data to
  * send to the client.  If the store_status is STORE_PENDING, then we
- * do have more data to send.  If its STORE_OK or STORE_ABORTED, then
+ * do have more data to send.  If its STORE_OK, then
  * we continue checking.  If the object length is negative, then we
  * don't know the real length and must open the swap file to find out.
  * If the length is >= 0, then we compare it to the requested copy
@@ -204,10 +209,10 @@
     size_t sz;
     if (sc->flags.copy_event_pending)
 	return;
-#ifdef PPNR_WIP
-    if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT))
+    if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
+	debug(20, 5) ("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n");
 	return;
-#endif /* PPNR_WIP */
+    }
     if (sc->flags.store_copying) {
 	sc->flags.copy_event_pending = 1;
 	debug(20, 3) ("storeClientCopy2: Queueing storeClientCopyEvent()\n");
@@ -219,7 +224,7 @@
     debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->key));
     assert(callback != NULL);
     /*
-     * We used to check for STORE_ABORTED here.  But there were some
+     * We used to check for ENTRY_ABORTED here.  But there were some
      * problems.  For example, we might have a slow client (or two) and
      * the server-side is reading far ahead and swapping to disk.  Even
      * if the server-side aborts, we want to give the client(s)
@@ -260,8 +265,11 @@
 	debug(20, 3) ("storeClientCopy2: Need to open swap in file\n");
 	assert(sc->type == STORE_DISK_CLIENT);
 	/* gotta open the swapin file */
-	/* assert(sc->copy_offset == 0); */
-	if (!sc->flags.disk_io_pending) {
+	if (storeTooManyDiskFilesOpen()) {
+	    /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */
+	    sc->callback = NULL;
+	    callback(sc->callback_data, sc->copy_buf, -1);
+	} else if (!sc->flags.disk_io_pending) {
 	    sc->flags.disk_io_pending = 1;
 	    storeSwapInStart(e, storeClientFileOpened, sc);
 	} else {
@@ -445,9 +453,8 @@
     if (e->store_status == STORE_OK && e->swap_status != SWAPOUT_DONE)
 	storeCheckSwapOut(e);
     if (sc->swapin_fd > -1) {
-	commSetSelect(sc->swapin_fd, COMM_SELECT_READ, NULL, NULL, 0);
 	file_close(sc->swapin_fd);
-	/* XXX this probably leaks file_read handler structures */
+	store_open_disk_fd--;
     }
 #if USE_ASYNC_IO
     else
@@ -460,7 +467,13 @@
 	sc->callback = NULL;
 	callback(sc->callback_data, sc->copy_buf, -1);
     }
+#if DELAY_POOLS
+    delayUnregisterDelayIdPtr(&sc->delay_id);
+#endif
     cbdataFree(sc);
+    assert(e->lock_count > 0);
+    if (mem->nclients == 0)
+	CheckQuickAbort(e);
     return 1;
 }
 
@@ -513,3 +526,69 @@
     debug(20, 3) ("storePendingNClients: returning %d\n", npend);
     return npend;
 }
+
+/* return 1 if the request should be aborted */
+static int
+CheckQuickAbort2(StoreEntry * entry)
+{
+    int curlen;
+    int minlen;
+    int expectlen;
+    MemObject *mem = entry->mem_obj;
+    assert(mem);
+    debug(20, 3) ("CheckQuickAbort2: entry=%p, mem=%p\n", entry, mem);
+    if (mem->request && !mem->request->flags.cachable) {
+	debug(20, 3) ("CheckQuickAbort2: YES !mem->request->flags.cachable\n");
+	return 1;
+    }
+    if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
+	debug(20, 3) ("CheckQuickAbort2: YES KEY_PRIVATE\n");
+	return 1;
+    }
+    expectlen = mem->reply->content_length + mem->reply->hdr_sz;
+    curlen = (int) mem->inmem_hi;
+    minlen = (int) Config.quickAbort.min << 10;
+    if (minlen < 0) {
+	debug(20, 3) ("CheckQuickAbort2: NO disabled\n");
+	return 0;
+    }
+    if (curlen > expectlen) {
+	debug(20, 3) ("CheckQuickAbort2: YES bad content length\n");
+	return 1;
+    }
+    if ((expectlen - curlen) < minlen) {
+	debug(20, 3) ("CheckQuickAbort2: NO only little more left\n");
+	return 0;
+    }
+    if ((expectlen - curlen) > (Config.quickAbort.max << 10)) {
+	debug(20, 3) ("CheckQuickAbort2: YES too much left to go\n");
+	return 1;
+    }
+    if (expectlen < 100) {
+	debug(20, 3) ("CheckQuickAbort2: NO avoid FPE\n");
+	return 0;
+    }
+    if ((curlen / (expectlen / 100)) > Config.quickAbort.pct) {
+	debug(20, 3) ("CheckQuickAbort2: NO past point of no return\n");
+	return 0;
+    }
+    debug(20, 3) ("CheckQuickAbort2: YES default, returning 1\n");
+    return 1;
+}
+
+static void
+CheckQuickAbort(StoreEntry * entry)
+{
+    if (entry == NULL)
+	return;
+    if (storePendingNClients(entry) > 0)
+	return;
+    if (entry->store_status != STORE_PENDING)
+	return;
+    if (EBIT_TEST(entry->flags, ENTRY_SPECIAL))
+	return;
+    if (CheckQuickAbort2(entry) == 0)
+	return;
+    Counter.aborted_requests++;
+    storeAbort(entry);
+}
Index: squid/src/store_digest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_digest.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_digest.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_digest.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,5 +1,5 @@
 /*
- * $Id: store_digest.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_digest.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 71    Store Digest Manager
  * AUTHOR: Alex Rousskov
@@ -335,12 +335,12 @@
     }
     debug(71, 2) ("storeDigestRewrite: start rewrite #%d\n", sd_state.rewrite_count + 1);
     /* make new store entry */
-    url = internalLocalUri("/squid-internal-periodic/", StoreDigestUrlPath);
+    url = internalLocalUri("/squid-internal-periodic/", StoreDigestFileName);
     flags = null_request_flags;
     flags.cachable = 1;
     sd_state.rewrite_lock = e = storeCreateEntry(url, url, flags, METHOD_GET);
     assert(sd_state.rewrite_lock);
-    cbdataAdd(sd_state.rewrite_lock, MEM_DONTFREE);
+    cbdataAdd(sd_state.rewrite_lock, NULL, 0);
     debug(71, 3) ("storeDigestRewrite: url: %s key: %s\n", url, storeKeyText(e->key));
     e->mem_obj->request = requestLink(urlParse(METHOD_GET, url));
     /* wait for rebuild (if any) to finish */
@@ -367,7 +367,8 @@
     httpReplySetHeaders(e->mem_obj->reply, 1.0, 200, "Cache Digest OK",
 	"application/cache-digest", store_digest->mask_size + sizeof(sd_state.cblock),
 	squid_curtime, squid_curtime + StoreDigestRewritePeriod);
-    debug(71, 3) ("storeDigestRewrite: entry expires on %s\n", mkrfc1123(e->mem_obj->reply->expires));
+    debug(71, 3) ("storeDigestRewrite: entry expires on %d (%+d)\n",
+	e->mem_obj->reply->expires, e->mem_obj->reply->expires - squid_curtime);
     storeBuffer(e);
     httpReplySwapOut(e->mem_obj->reply, e);
     storeDigestCBlockSwapOut(e);
@@ -382,8 +383,8 @@
     assert(e == sd_state.rewrite_lock);
     storeComplete(e);
     storeTimestampsSet(e);
-    debug(71, 2) ("storeDigestRewriteFinish: digest expires on %s (%d)\n",
-	mkrfc1123(e->expires), e->expires);
+    debug(71, 2) ("storeDigestRewriteFinish: digest expires at %d (%+d)\n",
+	e->expires, e->expires - squid_curtime);
     /* is this the write order? @?@ */
     requestUnlink(e->mem_obj->request);
     e->mem_obj->request = NULL;
Index: squid/src/store_dir.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_dir.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_dir.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_dir.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_dir.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_dir.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 47    Store Directory Routines
  * AUTHOR: Duane Wessels
@@ -283,7 +283,7 @@
 	diru[i] = 1.1;
 	SD = &Config.cacheSwap.swapDirs[i];
 	SD->flags.selected = 0;
-	if (SD->read_only)
+	if (SD->flags.read_only)
 	    continue;
 	u = (double) SD->cur_size / SD->max_size;
 	if (u > high)
@@ -545,6 +545,12 @@
     SwapDir *SD = &Config.cacheSwap.swapDirs[dirn];
     int fd;
     file_close(SD->swaplog_fd);
+#ifdef _SQUID_OS2_
+    if (unlink(swaplog_path) < 0) {
+	debug(50, 0) ("%s: %s\n", swaplog_path, xstrerror());
+	fatal("storeDirCloseTmpSwapLog: unlink failed");
+    }
+#endif
     if (rename(new_path, swaplog_path) < 0) {
 	debug(50, 0) ("%s,%s: %s\n", new_path, swaplog_path, xstrerror());
 	fatal("storeDirCloseTmpSwapLog: rename failed");
@@ -621,6 +627,8 @@
 	storeAppendPrintf(sentry, "Flags:");
 	if (SD->flags.selected)
 	    storeAppendPrintf(sentry, " SELECTED");
+	if (SD->flags.read_only)
+	    storeAppendPrintf(sentry, " READ-ONLY");
 	storeAppendPrintf(sentry, "\n");
     }
 }
@@ -767,25 +775,27 @@
     }
     safe_free(outbuf);
     safe_free(outbufoffset);
-#ifdef _SQUID_MSWIN_
     /*
      * You can't rename open files on Microsoft "operating systems"
-     * so we close before renaming.
+     * so we have to close before renaming.
      */
     storeDirCloseSwapLogs();
-#endif
     /* rename */
     for (dirn = 0; dirn < N; dirn++) {
 	if (fd[dirn] < 0)
 	    continue;
+#ifdef _SQUID_OS2_
+	file_close(fd[dirn]);
+	fd[dirn] = -1;
+	if (unlink(cur[dirn]) < 0)
+	    debug(50, 0) ("storeDirWriteCleanLogs: unlinkd failed: %s, %s\n",
+		xstrerror(), cur[dirn]);
+#endif
 	if (rename(new[dirn], cur[dirn]) < 0) {
 	    debug(50, 0) ("storeDirWriteCleanLogs: rename failed: %s, %s -> %s\n",
 		xstrerror(), new[dirn], cur[dirn]);
 	}
     }
-#ifndef _SQUID_MSWIN_
-    storeDirCloseSwapLogs();
-#endif
     if (reopen)
 	storeDirOpenSwapLogs();
     stop = squid_curtime;
Index: squid/src/store_key_md5.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_key_md5.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_key_md5.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_key_md5.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_key_md5.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_key_md5.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Storage Manager MD5 Cache Keys
  * AUTHOR: Duane Wessels
@@ -107,21 +107,6 @@
     return digest;
 }
 
-/*
- * Compatibility transition period.  Remove this after Feb 25, 1998
- */
-const cache_key *
-storeKeyPublicOld(const char *url, const method_t method)
-{
-    static cache_key digest[MD5_DIGEST_CHARS];
-    MD5_CTX M;
-    MD5Init(&M);
-    MD5Update(&M, (unsigned char *) &method, sizeof(method));
-    MD5Update(&M, (unsigned char *) url, strlen(url));
-    MD5Final(digest, &M);
-    return digest;
-}
-
 const cache_key *
 storeKeyPublic(const char *url, const method_t method)
 {
@@ -153,7 +138,7 @@
 void
 storeKeyFree(const cache_key * key)
 {
-    memFree(MEM_MD5_DIGEST, (void *) key);
+    memFree((void *) key, MEM_MD5_DIGEST);
 }
 
 int
Index: squid/src/store_rebuild.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_rebuild.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_rebuild.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_rebuild.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_rebuild.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_rebuild.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Store Rebuild Routines
  * AUTHOR: Duane Wessels
@@ -137,6 +137,7 @@
 	    debug(20, 1) ("storeRebuildFromDirectory: fstat(FD %d): %s\n",
 		fd, xstrerror());
 	    file_close(fd);
+	    store_open_disk_fd--;
 	    fd = -1;
 	    continue;
 	}
@@ -149,12 +150,18 @@
 	    debug(20, 1) ("storeRebuildFromDirectory: read(FD %d): %s\n",
 		fd, xstrerror());
 	    file_close(fd);
+	    store_open_disk_fd--;
 	    fd = -1;
 	    continue;
 	}
 	file_close(fd);
+	store_open_disk_fd--;
 	fd = -1;
 	swap_hdr_len = 0;
+#if USE_TRUNCATE_NOT_UNLINK
+	if (sb.st_size == 0)
+	    continue;
+#endif
 	tlv_list = storeSwapMetaUnpack(hdr_buf, &swap_hdr_len);
 	if (tlv_list == NULL) {
 	    debug(20, 1) ("storeRebuildFromDirectory: failed to get meta data\n");
@@ -485,13 +492,13 @@
 	    if (d->td == NULL) {
 		debug(50, 1) ("storeGetNextFile: opendir: %s: %s\n",
 		    d->fullpath, xstrerror());
-		break;
+	    } else {
+		d->entry = readdir(d->td);	/* skip . and .. */
+		d->entry = readdir(d->td);
+		if (d->entry == NULL && errno == ENOENT)
+		    debug(20, 1) ("storeGetNextFile: directory does not exist!.\n");
+		debug(20, 3) ("storeGetNextFile: Directory %s\n", d->fullpath);
 	    }
-	    d->entry = readdir(d->td);	/* skip . and .. */
-	    d->entry = readdir(d->td);
-	    if (d->entry == NULL && errno == ENOENT)
-		debug(20, 1) ("storeGetNextFile: directory does not exist!.\n");
-	    debug(20, 3) ("storeGetNextFile: Directory %s\n", d->fullpath);
 	}
 	if (d->td != NULL && (d->entry = readdir(d->td)) != NULL) {
 	    d->in_dir++;
@@ -518,6 +525,7 @@
 	    if (fd < 0)
 		debug(50, 1) ("storeGetNextFile: %s: %s\n", d->fullfilename, xstrerror());
 	    continue;
+	    store_open_disk_fd++;
 	}
 	d->in_dir = 0;
 	if (++d->curlvl2 < Config.cacheSwap.swapDirs[d->dirn].l2)
Index: squid/src/store_swapin.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapin.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_swapin.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_swapin.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapin.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_swapin.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapin Functions
  * AUTHOR: Duane Wessels
@@ -89,6 +89,7 @@
     }
     ctrlp->path = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));
     debug(20, 3) ("storeSwapInValidateComplete: Opening %s\n", ctrlp->path);
+    store_open_disk_fd++;
     file_open(ctrlp->path,
 	O_RDONLY,
 	storeSwapInFileOpened,
@@ -106,6 +107,7 @@
     if (fd == -2 && errcode == -2) {
 	xfree(ctrlp->path);
 	xfree(ctrlp);
+	store_open_disk_fd--;
 	return;
     }
     assert(mem != NULL);
@@ -116,15 +118,18 @@
 	    "\tFile:\t'%s'\n\t URL:\t'%s'\n",
 	    ctrlp->path, storeUrl(e));
 	storeEntryDump(e, 3);
+	store_open_disk_fd--;
     } else if (e->swap_status != SWAPOUT_DONE) {
 	(void) 0;
     } else if (fstat(fd, &sb) < 0) {
 	debug(20, 1) ("storeSwapInFileOpened: fstat() FD %d: %s\n", fd, xstrerror());
 	file_close(fd);
+	store_open_disk_fd--;
 	fd = -1;
     } else if (sb.st_size == 0 || sb.st_size != e->swap_file_sz) {
 	debug(20, 1) ("storeSwapInFileOpened: %s: Size mismatch: %d(fstat) != %d(object)\n", ctrlp->path, (int) sb.st_size, e->swap_file_sz);
 	file_close(fd);
+	store_open_disk_fd--;
 	fd = -1;
     }
     if (fd < 0) {
Index: squid/src/store_swapout.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapout.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/store_swapout.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/store_swapout.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapout.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: store_swapout.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapout Functions
  * AUTHOR: Duane Wessels
@@ -43,14 +43,16 @@
 
 static FOCB storeSwapOutFileOpened;
 static off_t storeSwapOutObjectBytesOnDisk(const MemObject *);
+static void storeSwapOutStart(StoreEntry * e);
+static DWCB storeSwapOutHandle;
 
 /* start swapping object to disk */
-void
+static void
 storeSwapOutStart(StoreEntry * e)
 {
     swapout_ctrl_t *ctrlp = xmalloc(sizeof(swapout_ctrl_t));
     assert(e->mem_obj);
-    cbdataAdd(ctrlp, MEM_NONE);
+    cbdataAdd(ctrlp, cbdataXfree, 0);
     storeLockObject(e);
     e->swap_file_number = storeDirMapAllocate();
     ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));
@@ -58,6 +60,7 @@
     ctrlp->oldswapstatus = e->swap_status;
     e->swap_status = SWAPOUT_OPENING;
     e->mem_obj->swapout.ctrl = ctrlp;
+    store_open_disk_fd++;
     file_open(ctrlp->swapfilename,
 	O_WRONLY | O_CREAT | O_TRUNC,
 	storeSwapOutFileOpened,
@@ -65,7 +68,7 @@
 	e);
 }
 
-void
+static void
 storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data)
 {
     swapout_ctrl_t *ctrlp = data;
@@ -133,27 +136,28 @@
     char *swap_buf;
     ssize_t swap_buf_len;
     int hdr_len = 0;
-    assert(mem != NULL);
+    if (mem == NULL)
+	return;
     /* should we swap something out to disk? */
-    debug(20, 3) ("storeCheckSwapOut: %s\n", storeUrl(e));
-    debug(20, 3) ("storeCheckSwapOut: store_status = %s\n",
+    debug(20, 7) ("storeCheckSwapOut: %s\n", storeUrl(e));
+    debug(20, 7) ("storeCheckSwapOut: store_status = %s\n",
 	storeStatusStr[e->store_status]);
-    if (e->store_status == STORE_ABORTED) {
+    if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
 	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));
 	storeSwapOutFileClose(e);
 	return;
     }
-    debug(20, 3) ("storeCheckSwapOut: mem->inmem_lo = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: mem->inmem_lo = %d\n",
 	(int) mem->inmem_lo);
-    debug(20, 3) ("storeCheckSwapOut: mem->inmem_hi = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: mem->inmem_hi = %d\n",
 	(int) mem->inmem_hi);
-    debug(20, 3) ("storeCheckSwapOut: swapout.queue_offset = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: swapout.queue_offset = %d\n",
 	(int) mem->swapout.queue_offset);
-    debug(20, 3) ("storeCheckSwapOut: swapout.done_offset = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: swapout.done_offset = %d\n",
 	(int) mem->swapout.done_offset);
 #if USE_ASYNC_IO
     if (mem->inmem_hi < mem->swapout.queue_offset) {
-	storeAbort(e, 0);
+	storeAbort(e);
 	assert(EBIT_TEST(e->flags, RELEASE_REQUEST));
 	storeSwapOutFileClose(e);
 	return;
@@ -162,7 +166,7 @@
     assert(mem->inmem_hi >= mem->swapout.queue_offset);
 #endif
     lowest_offset = storeLowestMemReaderOffset(e);
-    debug(20, 3) ("storeCheckSwapOut: lowest_offset = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: lowest_offset = %d\n",
 	(int) lowest_offset);
     new_mem_lo = lowest_offset;
     assert(new_mem_lo >= mem->inmem_lo);
@@ -182,11 +186,11 @@
     if (!storeSwapOutAble(e))
 	return;
     swapout_size = (size_t) (mem->inmem_hi - mem->swapout.queue_offset);
-    debug(20, 3) ("storeCheckSwapOut: swapout_size = %d\n",
+    debug(20, 7) ("storeCheckSwapOut: swapout_size = %d\n",
 	(int) swapout_size);
     if (swapout_size == 0) {
 	if (e->store_status == STORE_OK && !storeSwapOutWriteQueued(mem)) {
-	    debug(20, 3) ("storeCheckSwapOut: nothing to write for STORE_OK\n");
+	    debug(20, 7) ("storeCheckSwapOut: nothing to write for STORE_OK\n");
 	    if (e->swap_file_number > -1) {
 		storeUnlinkFileno(e->swap_file_number);
 		storeDirMapBitReset(e->swap_file_number);
@@ -235,7 +239,7 @@
 	storeDirMapBitReset(e->swap_file_number);
 	e->swap_file_number = -1;
 	e->swap_status = SWAPOUT_NONE;
-	memFree(MEM_DISK_BUF, swap_buf);
+	memFree(swap_buf, MEM_DISK_BUF);
 	storeReleaseRequest(e);
 	storeSwapOutFileClose(e);
 	return;
@@ -269,6 +273,7 @@
     }
     ctrlp = mem->swapout.ctrl;
     file_close(mem->swapout.fd);
+    store_open_disk_fd--;
     mem->swapout.fd = -1;
     xfree(ctrlp->swapfilename);
     cbdataFree(ctrlp);
@@ -289,18 +294,25 @@
 	xfree(ctrlp->swapfilename);
 	cbdataFree(ctrlp);
 	mem->swapout.ctrl = NULL;
+	store_open_disk_fd--;
 	return;
     }
     assert(e->swap_status == SWAPOUT_OPENING);
     if (fd < 0) {
 	debug(20, 0) ("storeSwapOutFileOpened: Unable to open swapfile: %s\n\t%s\n",
 	    ctrlp->swapfilename, xstrerror());
-	storeDirMapBitReset(e->swap_file_number);
+	/*
+	 * yuck.  don't clear the filemap bit for some errors so that
+	 * we don't try re-using it over and over
+	 */
+	if (errno != EPERM)
+	    storeDirMapBitReset(e->swap_file_number);
 	e->swap_file_number = -1;
 	e->swap_status = ctrlp->oldswapstatus;
 	xfree(ctrlp->swapfilename);
 	cbdataFree(ctrlp);
 	mem->swapout.ctrl = NULL;
+	store_open_disk_fd--;
 	return;
     }
     mem->swapout.fd = (short) fd;
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/structs.h	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/structs.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,9 +1,6 @@
 
-
-
-
 /*
- * $Id: structs.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: structs.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -34,6 +31,17 @@
  *
  */
 
+struct _dlink_node {
+    void *data;
+    dlink_node *prev;
+    dlink_node *next;
+};
+
+struct _dlink_list {
+    dlink_node *head;
+    dlink_node *tail;
+};
+
 struct _acl_ip_data {
     struct in_addr addr1;	/* if addr2 non-zero then its a range */
     struct in_addr addr2;
@@ -106,36 +114,6 @@
     u_char *community;
 };
 
-struct _viewEntry {
-    char viewName[32];
-    int viewIndex;
-    int viewType;
-    int viewSubtreeLen;
-    oid viewSubtree[32];
-    struct _viewEntry *next;
-};
-
-struct _communityEntry {
-    char name[64];
-    int readView;
-    int writeView;
-    acl_access *acls;
-    communityEntry *next;
-};
-
-struct _usecEntry {
-    u_char userName[32];
-    int userLen;
-    int qoS;
-    u_char authKey[16];
-    u_char privKey[16];
-    int noauthReadView;
-    int noauthWriteView;
-    int authReadView;
-    int authWriteView;
-    usecEntry *next;
-};
-
 #endif
 
 struct _acl {
@@ -163,11 +141,18 @@
     const acl_access *access_list;
     struct in_addr src_addr;
     struct in_addr dst_addr;
+    struct in_addr my_addr;
     request_t *request;
+#if USE_IDENT
+    ConnStateData *conn;	/* hack for ident */
     char ident[USER_IDENT_SZ];
+#endif
     char browser[BROWSERNAMELEN];
     acl_proxy_auth_user *auth_user;
     acl_lookup_state state[ACL_ENUM_MAX];
+#if SQUID_SNMP
+    char *snmp_community;
+#endif
     PF *callback;
     void *callback_data;
 };
@@ -205,11 +190,28 @@
 };
 
 #if DELAY_POOLS
-struct _delay_spec {
+struct _delaySpec {
     int restore_bps;
     int max_bytes;
 };
 
+/* malloc()'d only as far as used (class * sizeof(delaySpec)!
+ * order of elements very important!
+ */
+struct _delaySpecSet {
+    delaySpec aggregate;
+    delaySpec individual;
+    delaySpec network;
+};
+
+struct _delayConfig {
+    unsigned short pools;
+    unsigned short initial;
+    unsigned char *class;
+    delaySpecSet **rates;
+    acl_access **access;
+};
+
 #endif
 
 struct _SquidConfig {
@@ -217,10 +219,12 @@
 	size_t maxSize;
 	int highWaterMark;
 	int lowWaterMark;
-    } Mem , Swap;
+    } Swap;
+    size_t memMaxSize;
     struct {
 	char *relayHost;
 	u_short relayPort;
+	peer *peer;
     } Wais;
     struct {
 	size_t min;
@@ -242,6 +246,9 @@
 	time_t deadPeer;
 	int icp_query;		/* msec */
 	int mcast_icp_query;	/* msec */
+#if USE_IDENT
+	time_t ident;
+#endif
     } Timeout;
     size_t maxRequestSize;
     struct {
@@ -258,16 +265,7 @@
     struct {
 	char *configFile;
 	char *agentInfo;
-	char *mibPath;
-	char *trap_community;
-	char *trap_sink;
 	u_short localPort;
-	int do_queueing;
-	int conf_authtraps;
-	wordlist *snmpconf;
-	viewEntry *views;
-	usecEntry *users;
-	communityEntry *communities;
     } Snmp;
 #endif
     char *as_whois_server;
@@ -364,7 +362,6 @@
 #endif
 	int common_log;
 	int log_mime_hdrs;
-	int ident_lookup;
 	int log_fqdn;
 	int announce;
 	int accel_with_proxy;
@@ -377,6 +374,8 @@
 	int offline;
 	int redir_rewrites_host;
 	int persistent_client_posts;
+	int prefer_direct;
+	int strip_query_terms;
     } onoff;
     acl *aclList;
     struct {
@@ -387,6 +386,13 @@
 	acl_access *AlwaysDirect;
 	acl_access *ASlists;
 	acl_access *noCache;
+#if SQUID_SNMP
+	acl_access *snmp;
+#endif
+	acl_access *brokenPosts;
+#if USE_IDENT
+	acl_access *identLookup;
+#endif
     } accessList;
     acl_deny_info_list *denyInfoList;
     char *proxyAuthRealm;
@@ -414,23 +420,7 @@
 	size_t limit;
     } MemPools;
 #if DELAY_POOLS
-    struct {
-	struct {
-	    struct _delay_spec aggregate;
-	    acl_access *access;
-	} class1;
-	struct {
-	    struct _delay_spec aggregate;
-	    struct _delay_spec individual;
-	    acl_access *access;
-	} class2;
-	struct {
-	    struct _delay_spec aggregate;
-	    struct _delay_spec individual;
-	    struct _delay_spec network;
-	    acl_access *access;
-	} class3;
-    } Delay;
+    delayConfig Delay;
 #endif
     struct {
 	int icp_average;
@@ -441,6 +431,15 @@
     int max_open_disk_fds;
     int uri_whitespace;
     size_t rangeOffsetLimit;
+#if MULTICAST_MISS_STREAM
+    struct {
+	struct in_addr addr;
+	unsigned short port;
+	char *encode_key;
+    } mcast_miss;
+#endif
+    HttpHeaderMask anonymize_headers;
+    char *coredump_dir;
 };
 
 struct _SquidConfig2 {
@@ -505,12 +504,12 @@
 
 struct _fde {
     unsigned int type;
-    unsigned int open;
     u_short local_port;
     u_short remote_port;
     char ipaddr[16];		/* dotted decimal address of peer */
     char desc[FD_DESC_SZ];
     struct {
+	unsigned int open:1;
 	unsigned int close_request:1;
 	unsigned int write_daemon:1;
 	unsigned int closing:1;
@@ -705,6 +704,7 @@
 struct _http_state_flags {
     unsigned int proxying:1;
     unsigned int keepalive:1;
+    unsigned int only_if_cached:1;
 };
 
 struct _HttpStateData {
@@ -717,7 +717,7 @@
     request_t *orig_request;
     int fd;
     http_state_flags flags;
-    FwdState *fwdState;
+    FwdState *fwd;
 };
 
 struct _icpUdpData {
@@ -818,6 +818,7 @@
 	http_status status;
 	char *location;
     } redirect;
+    dlink_node active;
 };
 
 struct _ConnStateData {
@@ -831,13 +832,7 @@
     struct sockaddr_in peer;
     struct sockaddr_in me;
     struct in_addr log_addr;
-    struct {
-	int fd;
-	char ident[USER_IDENT_SZ];
-	IDCB *callback;
-	int state;
-	void *callback_data;
-    } ident;
+    char ident[USER_IDENT_SZ];
     int nrequests;
     int persistent;
     struct {
@@ -846,17 +841,6 @@
     } defer;
 };
 
-struct _dlink_node {
-    void *data;
-    dlink_node *prev;
-    dlink_node *next;
-};
-
-struct _dlink_list {
-    dlink_node *head;
-    dlink_node *tail;
-};
-
 struct _ipcache_addrs {
     struct in_addr *in_addrs;
     unsigned char *bad_mask;
@@ -940,13 +924,19 @@
 };
 
 struct _DigestFetchState {
-    peer *peer;
+    PeerDigest *pd;
     StoreEntry *entry;
     StoreEntry *old_entry;
+    request_t *request;
     int offset;
     int mask_offset;
     time_t start_time;
-    request_t *request;
+    time_t resp_time;
+    time_t expires;
+    struct {
+	int msg;
+	int bytes;
+    } sent, recv;
 };
 
 /* statistics for cache digests and other hit "predictors" */
@@ -960,24 +950,33 @@
 };
 
 struct _PeerDigest {
-    CacheDigest *cd;
+    peer *peer;			/* pointer back to peer structure, argh */
+    CacheDigest *cd;		/* actual digest structure */
+    String host;		/* copy of peer->host */
+    const char *req_result;	/* text status of the last request */
     struct {
-	unsigned int inited:1;	/* initialized */
-	unsigned int usable:1;	/* ready to use */
+	unsigned int needed:1;	/* there were requests for this digest */
+	unsigned int usable:1;	/* can be used for lookups */
 	unsigned int requested:1;	/* in process of receiving [fresh] digest */
-	unsigned int disabled:1;	/* do not use/validate the digest */
-	unsigned int init_pending:1;
     } flags;
-    time_t last_fetch_resp_time;
-    time_t last_req_timestamp;
-    time_t last_dis_delay;	/* last disability delay */
+    struct {
+	/* all times are absolute unless augmented with _delay */
+	time_t initialized;	/* creation */
+	time_t needed;		/* first lookup/use by a peer */
+	time_t next_check;	/* next scheduled check/refresh event */
+	time_t retry_delay;	/* delay before re-checking _invalid_ digest */
+	time_t requested;	/* requested a fresh copy of a digest */
+	time_t req_delay;	/* last request response time */
+	time_t received;	/* received the current copy of a digest */
+	time_t disabled;	/* disabled for good */
+    } times;
     struct {
 	cd_guess_stats guess;
 	int used_count;
-	int msgs_sent;
-	int msgs_recv;
-	kb_t kbytes_sent;
-	kb_t kbytes_recv;
+	struct {
+	    int msgs;
+	    kb_t kbytes;
+	} sent, recv;
     } stats;
 };
 
@@ -1012,7 +1011,7 @@
     } htcp;
 #endif
     u_short http_port;
-    domain_ping *pinglist;
+    domain_ping *peer_domain;
     domain_type *typelist;
     acl_access *access;
     struct {
@@ -1044,7 +1043,7 @@
 	} flags;
     } mcast;
 #if USE_CACHE_DIGESTS
-    PeerDigest digest;
+    PeerDigest *digest;
 #endif
     int tcp_up;			/* 0 if a connect() fails */
     time_t last_fail_time;
@@ -1100,9 +1099,10 @@
     StoreEntry *entry;
     int always_direct;
     int never_direct;
+    int direct;
     PSC *callback;
-    PSC *fail_callback;
     void *callback_data;
+    FwdServer *servers;
     /*
      * Why are these struct sockaddr_in instead of peer *?  Because a
      * peer structure can become invalid during the peer selection
@@ -1112,6 +1112,15 @@
      */
     struct sockaddr_in first_parent_miss;
     struct sockaddr_in closest_parent_miss;
+    /*
+     * ->hit and ->secho can be peer* because they should only be
+     * accessed during the thread when they are set
+     */
+    peer *hit;
+    peer_t hit_type;
+#if ALLOW_SOURCE_PING
+    peer *secho;
+#endif
     ping_data ping;
     aclCheck_t *acl_checklist;
 };
@@ -1246,12 +1255,12 @@
     int l2;
     int cur_size;
     int max_size;
-    int read_only;
     int suggest;
     fileMap *map;
     int swaplog_fd;
     struct {
 	unsigned int selected:1;
+	unsigned int read_only:1;
     } flags;
 };
 
@@ -1289,20 +1298,17 @@
     request_flags flags;
     HttpHdrCc *cache_control;
     HttpHdrRange *range;
-    time_t max_age;
     float http_ver;
     time_t ims;
     int imslen;
     int max_forwards;
     struct in_addr client_addr;
+    struct in_addr my_addr;
     HttpHeader header;
     char *body;
     size_t body_sz;
     HierarchyLogEntry hier;
     err_type err_type;
-#if DELAY_POOLS
-    delay_id delay_id;
-#endif
     char *peer_login;		/* Configured peer login:password */
 };
 
@@ -1537,6 +1543,7 @@
     MemMeter inuse;
     MemMeter idle;
     gb_t saved;
+    gb_t total;
 };
 
 /* a pool is a [growing] space for objects of the same size */
@@ -1576,26 +1583,24 @@
     int del_count;		/* number of deletions performed so far */
 };
 
+struct _FwdServer {
+    peer *peer;			/* NULL --> origin server */
+    hier_code code;
+    FwdServer *next;
+};
+
 struct _FwdState {
     int client_fd;
     StoreEntry *entry;
     request_t *request;
     FwdServer *servers;
     int server_fd;
-    struct {
-	int err_code;
-	http_status http_code;
-	int xerrno;
-    } fail;
+    ErrorState *err;
     time_t start;
     int n_tries;
-};
-
-struct _FwdServer {
-    char *host;
-    u_short port;
-    peer *peer;
-    struct _FwdServer *next;
+    struct {
+	unsigned int dont_retry:1;
+    } flags;
 };
 
 #if USE_HTCP
Index: squid/src/tools.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/tools.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/tools.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/tools.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: tools.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: tools.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 21    Misc Functions
  * AUTHOR: Harvest Derived
@@ -108,7 +108,7 @@
     fprintf(debug_log, "\tTotal free:            %6d KB %d%%\n",
 	(int) (ms.bytes_free >> 10),
 	percent(ms.bytes_free, ms.bytes_total));
-#elif HAVE_MALLINFO
+#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO
     struct mallinfo mp;
     int t;
     if (!do_mallinfo)
@@ -175,6 +175,11 @@
 	(double) r->ru_utime.tv_usec / 1000000.0;
 }
 
+/* Hack for some HP-UX preprocessors */
+#ifndef HAVE_GETPAGESIZE
+#define HAVE_GETPAGESIZE 0
+#endif
+
 int
 rusage_maxrss(struct rusage *r)
 {
@@ -298,8 +303,7 @@
 fatal_common(const char *message)
 {
 #if HAVE_SYSLOG
-    if (opt_syslog_enable)
-	syslog(LOG_ALERT, "%s", message);
+    syslog(LOG_ALERT, "%s", message);
 #endif
     fprintf(debug_log, "FATAL: %s\n", message);
     if (opt_debug_stderr && debug_log != stderr)
@@ -322,11 +326,11 @@
     if (!store_rebuilding)
 	storeDirWriteCleanLogs(0);
     fatal_common(message);
-    exit(1);
+    exit(shutting_down ? 0 : 1);
 }
 
 /* printf-style interface for fatal */
-#ifdef __STDC__
+#if STDC_HEADERS
 void
 fatalf(const char *fmt,...)
 {
@@ -807,6 +811,8 @@
     static int call_id = 0;
     double value = gb_to_double(g);
     char *buf = bufs[call_id++];
+    if (call_id >= max_cc_calls)
+	call_id = 0;
     /* select format */
     if (value < 1e9)
 	snprintf(buf, sizeof(GbBuf), "%.2f MB", value / 1e6);
Index: squid/src/typedefs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/typedefs.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/typedefs.h	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/typedefs.h	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: typedefs.h,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -163,10 +163,14 @@
 typedef struct _generic_cbdata generic_cbdata;
 
 #if SQUID_SNMP
+typedef variable_list *(oid_ParseFn) (variable_list *, snint *);
 typedef struct _snmp_request_t snmp_request_t;
-typedef struct _viewEntry viewEntry;
-typedef struct _communityEntry communityEntry;
-typedef struct _usecEntry usecEntry;
+#endif
+
+#if DELAY_POOLS
+typedef struct _delayConfig delayConfig;
+typedef struct _delaySpecSet delaySpecSet;
+typedef struct _delaySpec delaySpec;
 #endif
 
 /* define AIOCB even without USE_ASYNC_IO */
@@ -175,16 +179,17 @@
 typedef void CNCB(int fd, int status, void *);
 
 typedef void FREE(void *);
+typedef void CBDUNL(void *, int);
 typedef void FOCB(void *, int fd, int errcode);
 typedef void EVH(void *);
 typedef void PF(int, void *);
 typedef void DRCB(int fd, const char *buf, int size, int errflag, void *data);
 typedef void DWCB(int, int, size_t, void *);
 typedef void FQDNH(const char *, void *);
-typedef void IDCB(void *);
+typedef void IDCB(const char *ident, void *data);
 typedef void IPH(const ipcache_addrs *, void *);
 typedef void IRCB(peer *, peer_t, protocol_t, void *, void *data);
-typedef void PSC(peer *, void *);
+typedef void PSC(FwdServer *, void *);
 typedef void RH(void *data, char *);
 typedef void UH(void *data, wordlist *);
 typedef int DEFER(int fd, void *data);
@@ -205,7 +210,7 @@
 
 /* append/vprintf's for Packer */
 typedef void (*append_f) (void *, const char *buf, int size);
-#ifdef __STDC__
+#if STDC_HEADERS
 typedef void (*vprintf_f) (void *, const char *fmt, va_list args);
 #else
 typedef void (*vprintf_f) ();
@@ -233,7 +238,7 @@
 typedef void (*ObjPackMethod) (void *obj, Packer * p);
 
 #if DELAY_POOLS
-typedef int delay_id;
+typedef unsigned int delay_id;
 #endif
 
 #if USE_HTCP
Index: squid/src/unlinkd.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/unlinkd.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/unlinkd.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/unlinkd.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,5 +1,5 @@
 /*
- * $Id: unlinkd.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: unlinkd.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 12    Unlink Daemon
  * AUTHOR: Duane Wessels
@@ -32,30 +32,12 @@
  *
  */
 
+#include "squid.h"
+
 #ifdef UNLINK_DAEMON
 
 /* This is the external unlinkd process */
 
-#include "config.h"
-
-#if HAVE_LIBC_H
-#include 
-#endif
-#if HAVE_UNISTD_H
-#include 
-#endif
-#if HAVE_STDLIB_H
-#include 
-#endif
-#if HAVE_STDIO_H
-#include 
-#endif
-#ifdef HAVE_STRING_H
-#include 
-#endif
-#ifdef HAVE_STRINGS_H
-#include 
-#endif
 #define UNLINK_BUF_LEN 1024
 
 int
@@ -63,11 +45,21 @@
 {
     char buf[UNLINK_BUF_LEN];
     char *t;
+    int x;
     setbuf(stdin, NULL);
+    setbuf(stdout, NULL);
     while (fgets(buf, UNLINK_BUF_LEN, stdin)) {
 	if ((t = strchr(buf, '\n')))
 	    *t = '\0';
-	unlink(buf);
+#if USE_TRUNCATE_NOT_UNLINK
+	x = truncate(buf, 0);
+#else
+	x = unlink(buf);
+#endif
+	if (x < 0)
+	    printf("ERR\n");
+	else
+	    printf("OK\n");
     }
     exit(0);
 }
@@ -76,36 +68,79 @@
 
 /* This code gets linked to Squid */
 
-#include "squid.h"
-
 #if USE_UNLINKD
 static int unlinkd_wfd = -1;
 static int unlinkd_rfd = -1;
 #endif
 
+#define UNLINKD_QUEUE_LIMIT 20
+
 void
 unlinkdUnlink(const char *path)
 {
 #if USE_UNLINKD
-    char *buf;
+    char buf[MAXPATHLEN];
     int l;
+    int x;
+    static int queuelen = 0;
     if (unlinkd_wfd < 0) {
 	debug_trap("unlinkdUnlink: unlinkd_wfd < 0");
 	safeunlink(path, 0);
 	return;
     }
-    l = strlen(path) + 1;
-    buf = xcalloc(1, l + 1);
-    strcpy(buf, path);
-    strcat(buf, "\n");
-    file_write(unlinkd_wfd,
-	-1,
-	buf,
-	l,
-	NULL,			/* Handler */
-	NULL,			/* Handler-data */
-	xfree);
+    /*
+     * If the queue length is greater than our limit, then
+     * we pause for up to 100ms, hoping that unlinkd
+     * has some feedback for us.  Maybe it just needs a slice
+     * of the CPU's time.
+     */
+    if (queuelen >= UNLINKD_QUEUE_LIMIT) {
+	struct timeval to;
+	fd_set R;
+	int x;
+	FD_ZERO(&R);
+	FD_SET(unlinkd_rfd, &R);
+	to.tv_sec = 0;
+	to.tv_usec = 100000;
+	x = select(unlinkd_rfd + 1, &R, NULL, NULL, &to);
+    }
+    /*
+     * If there is at least one outstanding unlink request, then
+     * try to read a response.  If there's nothing to read we'll
+     * get an EWOULDBLOCK or whatever.  If we get a response, then
+     * decrement the queue size by the number of newlines read.
+     */
+    if (queuelen > 0) {
+	int x;
+	int i;
+	char rbuf[512];
+	x = read(unlinkd_rfd, rbuf, 511);
+	if (x > 0) {
+	    rbuf[x] = '\0';
+	    for (i = 0; i < x; i++)
+		if ('\n' == rbuf[i])
+		    queuelen--;
+	    assert(queuelen >= 0);
+	}
+    }
+    l = strlen(path);
+    assert(l < MAXPATHLEN);
+    xstrncpy(buf, path, MAXPATHLEN);
+    buf[l++] = '\n';
+    x = write(unlinkd_wfd, buf, l);
+    if (x < 0) {
+	debug(50, 1) ("unlinkdUnlink: write FD %d failed: %s\n",
+	    unlinkd_wfd, xstrerror());
+	safeunlink(path, 0);
+	return;
+    } else if (x != l) {
+	debug(50, 1) ("unlinkdUnlink: FD %d only wrote %d of %d bytes\n",
+	    unlinkd_wfd, x, l);
+	safeunlink(path, 0);
+	return;
+    }
     Counter.unlink.requests++;
+    queuelen++;
 #endif
 }
 
@@ -152,7 +187,11 @@
     fd_note(unlinkd_rfd, "unlinkd -> squid");
     commSetTimeout(unlinkd_rfd, -1, NULL, NULL);
     commSetTimeout(unlinkd_wfd, -1, NULL, NULL);
-    commSetNonBlocking(unlinkd_wfd);
+    /*
+     * We leave unlinkd_wfd blocking, because we never want to lose an
+     * unlink request, and we don't have code to retry if we get
+     * EWOULDBLOCK.
+     */
     commSetNonBlocking(unlinkd_rfd);
     debug(12, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd);
 #endif
Index: squid/src/url.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/url.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/url.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/url.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: url.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: url.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 23    URL Parsing
  * AUTHOR: Duane Wessels
@@ -233,7 +233,7 @@
 	}
     }
     for (t = host; *t; t++)
-	*t = tolower(*t);
+	*t = xtolower(*t);
     if (strspn(host, valid_hostname_chars) != strlen(host)) {
 	debug(23, 1) ("urlParse: Illegal character in hostname '%s'\n", host);
 	return NULL;
@@ -256,7 +256,7 @@
     }
 #endif
     if (stringHasWhitespace(urlpath)) {
-	debug(23, 1) ("urlParse: URI has whitespace: {%s}\n", url);
+	debug(23, 2) ("urlParse: URI has whitespace: {%s}\n", url);
 	switch (Config.uri_whitespace) {
 	case URI_WHITESPACE_DENY:
 	    return NULL;
@@ -350,8 +350,9 @@
 	    /*
 	     * strip arguments AFTER a question-mark
 	     */
-	    if ((t = strchr(buf, '?')))
-		*(++t) = '\0';
+	    if (Config.onoff.strip_query_terms)
+		if ((t = strchr(buf, '?')))
+		    *(++t) = '\0';
 	    break;
 	}
     }
Index: squid/src/urn.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/urn.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/urn.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/urn.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,7 +1,7 @@
 
 /*
  *
- * $Id: urn.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: urn.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 52    URN Parsing
  * AUTHOR: Kostas Anagnostakis
@@ -109,7 +109,7 @@
     urnState = xcalloc(1, sizeof(UrnState));
     urnState->entry = e;
     urnState->request = requestLink(r);
-    cbdataAdd(urnState, MEM_NONE);
+    cbdataAdd(urnState, cbdataXfree, 0);
     storeLockObject(urnState->entry);
     if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) {
 	char *new_path = xstrdup(strBuf(r->urlpath) + 5);
@@ -138,15 +138,11 @@
     if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) {
 	urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET);
 	storeClientListAdd(urlres_e, urnState);
-	fwdStart(-1, urlres_e, urlres_r, no_addr);
+	fwdStart(-1, urlres_e, urlres_r, no_addr, no_addr);
     } else {
 	storeLockObject(urlres_e);
 	storeClientListAdd(urlres_e, urnState);
     }
-#if DELAY_POOLS
-    urlres_r->delay_id = r->delay_id;
-    delaySetStoreClient(urlres_e, urnState, r->delay_id);
-#endif
     urnState->urlres_e = urlres_e;
     urnState->urlres_r = requestLink(urlres_r);
     storeClientCopy(urlres_e,
@@ -191,15 +187,15 @@
     int urlcnt = 0;
 
     debug(52, 3) ("urnHandleReply: Called with size=%d.\n", size);
-    if (urlres_e->store_status == STORE_ABORTED) {
-	memFree(MEM_4K_BUF, buf);
+    if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) {
+	memFree(buf, MEM_4K_BUF);
 	return;
     }
     if (size == 0) {
-	memFree(MEM_4K_BUF, buf);
+	memFree(buf, MEM_4K_BUF);
 	return;
     } else if (size < 0) {
-	memFree(MEM_4K_BUF, buf);
+	memFree(buf, MEM_4K_BUF);
 	return;
     }
     if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) {
@@ -232,7 +228,7 @@
 	errorAppendEntry(e, err);
 	return;
     }
-    while (isspace(*s))
+    while (xisspace(*s))
 	s++;
     urls = urnParseReply(s, urnState->request->method);
     for (i = 0; NULL != urls[i].url; i++)
@@ -286,7 +282,7 @@
     httpBodySet(&rep->body, &mb);
     httpReplySwapOut(rep, e);
     storeComplete(e);
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
     for (i = 0; i < urlcnt; i++) {
 	safe_free(urls[i].url);
 	safe_free(urls[i].host);
Index: squid/src/useragent.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/useragent.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/useragent.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/useragent.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: useragent.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: useragent.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 40    User-Agent logging
  * AUTHOR: Joe Ramey 
@@ -89,6 +89,11 @@
 	snprintf(to, MAXPATHLEN, "%s.%d", fname, i);
 	rename(from, to);
     }
+    if (cache_useragent_log) {
+	file_close(fileno(cache_useragent_log));
+	fclose(cache_useragent_log);
+	cache_useragent_log = NULL;
+    }
     /* Rotate the current log to .0 */
     if (Config.Log.rotateNumber > 0) {
 	snprintf(to, MAXPATHLEN, "%s.%d", fname, 0);
Index: squid/src/wais.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/wais.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/wais.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/wais.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wais.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: wais.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 24    WAIS Relay
  * AUTHOR: Harvest Derived
@@ -42,6 +42,7 @@
     const HttpHeader *request_hdr;
     char url[MAX_URL];
     request_t *request;
+    FwdState *fwd;
 } WaisStateData;
 
 static PF waisStateFree;
@@ -66,12 +67,14 @@
 waisTimeout(int fd, void *data)
 {
     WaisStateData *waisState = data;
-    ErrorState *err;
     StoreEntry *entry = waisState->entry;
     debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
-    err = errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT);
-    err->request = requestLink(waisState->request);
-    errorAppendEntry(entry, err);
+    if (entry->store_status == STORE_PENDING) {
+	if (entry->mem_obj->inmem_hi == 0) {
+	    fwdFail(waisState->fwd,
+		errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
+	}
+    }
     comm_close(fd);
 }
 
@@ -90,6 +93,10 @@
 #if DELAY_POOLS
     delay_id delay_id = delayMostBytesAllowed(entry->mem_obj);
 #endif
+    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
+	comm_close(fd);
+	return;
+    }
     errno = 0;
     read_sz = 4096;
 #if DELAY_POOLS
@@ -141,7 +148,7 @@
     } else if (len == 0) {
 	/* Connection closed; retrieval done. */
 	entry->expires = squid_curtime;
-	storeComplete(entry);
+	fwdComplete(waisState->fwd);
 	comm_close(fd);
     } else {
 	storeAppend(entry, buf, len);
@@ -206,25 +213,30 @@
     comm_write_mbuf(fd, mb, waisSendComplete, waisState);
     if (EBIT_TEST(waisState->entry->flags, ENTRY_CACHABLE))
 	storeSetPublicKey(waisState->entry);	/* Make it public */
+    EBIT_CLR(waisState->entry->flags, ENTRY_FWD_HDR_WAIT);
 }
 
 void
-waisStart(request_t * request, StoreEntry * entry, int fd)
+waisStart(FwdState * fwd)
 {
     WaisStateData *waisState = NULL;
+    request_t *request = fwd->request;
+    StoreEntry *entry = fwd->entry;
+    int fd = fwd->server_fd;
     const char *url = storeUrl(entry);
     method_t method = request->method;
     debug(24, 3) ("waisStart: \"%s %s\"\n", RequestMethodStr[method], url);
     Counter.server.all.requests++;
     Counter.server.other.requests++;
     waisState = xcalloc(1, sizeof(WaisStateData));
-    cbdataAdd(waisState, MEM_NONE);
+    cbdataAdd(waisState, cbdataXfree, 0);
     waisState->method = method;
     waisState->request_hdr = &request->header;
     waisState->fd = fd;
     waisState->entry = entry;
     xstrncpy(waisState->url, url, MAX_URL);
     waisState->request = requestLink(request);
+    waisState->fwd = fwd;
     comm_add_close_handler(waisState->fd, waisStateFree, waisState);
     storeLockObject(entry);
     commSetSelect(fd, COMM_SELECT_WRITE, waisSendRequest, waisState, 0);
Index: squid/src/whois.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/whois.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/src/whois.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/src/whois.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,5 +1,6 @@
+
 /*
- * $Id: whois.c,v 1.1.1.1 2000/01/26 03:21:47 hno Exp $
+ * $Id: whois.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $
  *
  * DEBUG: section 75    WHOIS protocol
  * AUTHOR: Duane Wessels, Kostas Anagnostakis
@@ -39,7 +40,7 @@
 typedef struct {
     StoreEntry *entry;
     request_t *request;
-    FwdState *fwdState;
+    FwdState *fwd;
 } WhoisState;
 
 static PF whoisClose;
@@ -49,15 +50,16 @@
 /* PUBLIC */
 
 void
-whoisStart(FwdState * fwdState, int fd)
+whoisStart(FwdState * fwd)
 {
     WhoisState *p = xcalloc(1, sizeof(*p));
+    int fd = fwd->server_fd;
     char *buf;
     size_t l;
-    p->request = fwdState->request;
-    p->entry = fwdState->entry;
-    p->fwdState = fwdState;
-    cbdataAdd(p, MEM_NONE);
+    p->request = fwd->request;
+    p->entry = fwd->entry;
+    p->fwd = fwd;
+    cbdataAdd(p, cbdataXfree, 0);
     storeLockObject(p->entry);
     comm_add_close_handler(fd, whoisClose, p);
     l = strLen(p->request->urlpath) + 3;
@@ -102,18 +104,20 @@
 	if (ignoreErrno(errno)) {
 	    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read);
 	} else if (entry->mem_obj->inmem_hi == 0) {
-	    fwdFail(p->fwdState, ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, errno);
+	    ErrorState *err;
+	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
+	    err->xerrno = errno;
+	    fwdFail(p->fwd, err);
 	    comm_close(fd);
 	} else {
-	    storeAbort(entry, 0);
 	    comm_close(fd);
 	}
     } else {
-	storeComplete(entry);
+	fwdComplete(p->fwd);
 	debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry));
 	comm_close(fd);
     }
-    memFree(MEM_4K_BUF, buf);
+    memFree(buf, MEM_4K_BUF);
 }
 
 static void
Index: squid/test-suite/tcp-banger2.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/test-suite/tcp-banger2.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/test-suite/tcp-banger2.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/test-suite/tcp-banger2.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -1,5 +1,7 @@
 #include "config.h"
 
+/* $Id: tcp-banger2.c,v 1.1.1.2 2000/01/26 03:23:10 hno Exp $ */
+
 /*
  * On some systems, FD_SETSIZE is set to something lower than the
  * actual number of files which can be opened.  IRIX is one case,
@@ -82,6 +84,9 @@
 #if HAVE_ASSERT_H
 #include 
 #endif
+#if HAVE_CTYPE_H
+#include 
+#endif
 
 #define PROXY_PORT 3128
 #define PROXY_ADDR "127.0.0.1"
@@ -94,6 +99,7 @@
 static int nrequests;
 static int opt_ims = 0;
 static int opt_range = 0;
+static int opt_accel = 0;
 static int max_connections = 64;
 static time_t lifetime = 60;
 static time_t process_lifetime = 86400;
@@ -121,6 +127,7 @@
     int validsize;
     int bodysize;
     int content_length;
+    int status;
     long validsum;
     long sum;
 };
@@ -133,9 +140,9 @@
 static void
 free_request(struct _request *r)
 {
-	if (r->url)
-	    free(r->url);
-	free(r);
+    if (r->url)
+	free(r->url);
+    free(r);
 }
 
 char *
@@ -216,9 +223,11 @@
 		if (!header)
 		    break;
 		/* Decode header */
-		if (strncasecmp(header, "Content-Length:", 15) == 0)
+		if (strncmp(header, "HTTP", 4) == 0)
+		    r->status = atoi(header + 8);
+		else if (strncasecmp(header, "Content-Length:", 15) == 0)
 		    r->content_length = atoi(header + 15);
-		if (strncasecmp(header, "X-Request-URI:", 14) == 0) {
+		else if (strncasecmp(header, "X-Request-URI:", 14) == 0) {
 		    /* Check URI */
 		    if (strncmp(r->url, header + 15, strcspn(header + 15, "\r\n"))) {
 			char url[8192];
@@ -270,8 +279,12 @@
 		r->url, r->validsum, r->sum);
     }
     if (trace_file) {
-	fprintf(trace_file, "%s %s %s %d 0x%lx\n",
-	    r->method, r->url, r->requestbodyfile, r->bodysize, r->sum);
+	if (opt_checksum)
+	    fprintf(trace_file, "%s %s %d %s %d 0x%lx\n",
+		r->method, r->url, r->status, r->requestbodyfile, r->bodysize, r->sum);
+	else
+	    fprintf(trace_file, "%s %s %d %s %d\n",
+		r->method, r->url, r->status, r->requestbodyfile, r->bodysize);
     }
     free_request(r);
 }
@@ -283,6 +296,7 @@
     char buf[4096];
     char msg[8192];
     char *method, *url, *file, *size, *checksum;
+    char *host;
     char urlbuf[8192];
     int len, len2;
     time_t w;
@@ -334,9 +348,19 @@
     if (checksum && strcmp(checksum, "-") != 0)
 	r->validsum = strtoul(checksum, NULL, 0);
     r->content_length = -1;	/* Unknown */
-    msg[0] = '\0';
-    sprintf(buf, "%s %s HTTP/1.0\r\n", method, url);
-    strcat(msg, buf);
+    if (opt_accel) {
+	host = strchr(url, '/') + 2;
+	url = strchr(host, '/');
+    } else {
+	host = NULL;
+    }
+    sprintf(msg, "%s %s HTTP/1.0\r\n", method, url);
+    if (host) {
+	url[0] = '\0';
+	sprintf(buf, "Host: %s\r\n", host);
+	strcat(msg, buf);
+	url[0] = '/';
+    }
     strcat(msg, "Accept: */*\r\n");
     if (opt_ims && (lrand48() & 0x03) == 0) {
 	w = time(NULL) - (lrand48() & 0x3FFFF);
@@ -441,6 +465,7 @@
     fprintf(stderr, " -c              Check checksum agains trace\n");
     fprintf(stderr, " -i              Send random If-Modified-Since times\n");
     fprintf(stderr, " -l     Connection lifetime timeout (default 60)\n");
+    fprintf(stderr, " -a              Accelerator mode\n");
 }
 
 int
@@ -461,8 +486,11 @@
     progname = strdup(argv[0]);
     gettimeofday(&now, NULL);
     start = last = now;
-    while ((c = getopt(argc, argv, "p:h:n:icrl:L:t:")) != -1) {
+    while ((c = getopt(argc, argv, "ap:h:n:icrl:L:t:")) != -1) {
 	switch (c) {
+	case 'a':
+	    opt_accel = 1;
+	    break;
 	case 'p':
 	    proxy_port = atoi(optarg);
 	    break;
@@ -485,9 +513,9 @@
 	    opt_checksum = 1;
 	    break;
 	case 't':
-	    opt_checksum = 1;	/* Tracing requires checksums */
-	    trace_file = fopen(optarg, "w");
+	    trace_file = fopen(optarg, "a");
 	    assert(trace_file);
+	    setbuf(trace_file, NULL);
 	    break;
 	case 'r':
 	    opt_range = 1;
@@ -550,9 +578,12 @@
 		(int) total_bytes_read / 1024 / 1024,
 		(int) total_bytes_read / 1024 / dt);
 	    reqpersec = 0;
-	    if (dt > process_lifetime)
-		exit(0);
+	    /*
+	     * if (dt > process_lifetime)
+	     *     exit(0);
+	     */
 	}
     }
+    printf("Exiting normally\n");
     return 0;
 }
Index: squid/test-suite/tcp-banger3.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/test-suite/tcp-banger3.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.2
diff -u -r1.1.1.1 -r1.1.1.2
--- squid/test-suite/tcp-banger3.c	26 Jan 2000 03:21:47 -0000	1.1.1.1
+++ squid/test-suite/tcp-banger3.c	26 Jan 2000 03:23:10 -0000	1.1.1.2
@@ -136,8 +136,10 @@
 	*t = '\0';
 	port = (unsigned short) atoi(t + 1);
     }
+#if 0
     if ((int) port != 80)
 	return 0;
+#endif
     t = strchr(url + 7, '/');
     strncpy(path, (t ? t : "/"), URL_BUF_SZ);
     memset(&S, '\0', sizeof(S));