From cc192b5087ebbd5c214fcacdf26f117e4f15241b Mon Sep 17 00:00:00 2001 From: amosjeffries <> Date: Sat, 15 Dec 2007 06:11:41 +0000 Subject: [PATCH] Import IPv6 support from squid3-ipv6 branch to 3-HEAD. This patch fully enables squid to handle IPv6 on internally supported protocols which have IPv6 capability. see 3.1 Release Notes for full details on the IPv6 changes. also see squid.conf generated from this point for configuration changes. TODO: Release-Notes fro 3.1 have yet to be created. The mentioned details documentation will come in a later patch. --- configure.in | 156 ++++- .../squid_kerb_auth/squid_kerb_auth.c | 14 +- helpers/ntlm_auth/SMB/smbval/rfcnb-priv.h | 2 +- include/cache_snmp.h | 301 ++++---- include/config.h | 10 +- include/rfc1035.h | 4 +- include/snmp_vars.h | 46 +- include/squid_mswin.h | 16 +- include/util.h | 14 +- lib/GNUregex.c | 4 +- lib/Makefile.am | 6 +- lib/rfc1035.c | 36 +- lib/safe_inet_addr.c | 65 -- lib/tests/testRFC1035.cc | 110 +++ lib/tests/testRFC1035.h | 29 + src/ACLARP.cc | 78 +-- src/ACLASN.h | 15 +- src/ACLChecklist.cc | 17 +- src/ACLChecklist.h | 10 +- src/ACLDestinationASN.h | 5 +- src/ACLDestinationDomain.cc | 9 +- src/ACLDestinationIP.cc | 6 +- src/ACLIP.cc | 299 +++++--- src/ACLIP.h | 14 +- src/ACLIdent.cc | 2 +- src/ACLMaxUserIP.cc | 4 +- src/ACLMaxUserIP.h | 4 +- src/ACLMyPort.cc | 4 +- src/ACLSourceASN.h | 5 +- src/ACLSourceDomain.cc | 4 +- src/AccessLogEntry.h | 10 +- src/AuthUser.cc | 19 +- src/AuthUser.h | 8 +- src/AuthUserRequest.cc | 12 +- src/AuthUserRequest.h | 10 +- src/CompositePoolNode.h | 5 +- src/ConnectionDetail.h | 8 +- src/Debug.h | 7 +- src/DelayConfig.h | 5 +- src/DelayId.cc | 7 +- src/DiskIO/DiskDaemon/DiskdIOStrategy.cc | 6 +- src/ESI.cc | 8 +- src/HttpRequest.cc | 8 +- src/HttpRequest.h | 36 +- src/ICAP/ICAPModXact.cc | 6 +- src/ICMP.h | 153 +++++ src/ICMPConfig.h | 73 ++ src/ICMPPinger.cc | 237 +++++++ src/ICMPPinger.h | 83 +++ src/ICMPSquid.cc | 303 ++++++++ src/ICMPSquid.h | 69 ++ src/ICMPv4.cc | 247 +++++++ src/ICMPv4.h | 179 +++++ src/ICMPv6.cc | 343 +++++++++ src/ICMPv6.h | 96 +++ src/ICP.h | 21 +- src/IPInterception.cc | 115 ++-- src/IPInterception.h | 7 +- src/Makefile.am | 56 +- src/PeerSelectState.h | 18 +- src/SquidTime.h | 6 +- src/access_log.cc | 39 +- src/asn.cc | 124 ++-- src/auth/digest/auth_digest.cc | 12 +- src/auth/negotiate/auth_negotiate.cc | 4 +- src/auth/ntlm/auth_ntlm.cc | 4 +- src/cache_cf.cc | 207 ++++-- src/cf.data.depend | 2 +- src/cf.data.pre | 73 +- src/client_db.cc | 80 ++- src/client_side.cc | 128 ++-- src/client_side.h | 8 +- src/client_side_reply.cc | 56 +- src/client_side_reply.h | 6 +- src/client_side_request.cc | 22 +- src/comm.cc | 344 +++++++--- src/comm.h | 13 +- src/comm_select.cc | 14 +- src/debug.cc | 4 +- src/defines.h | 4 +- src/delay_pools.cc | 66 +- src/dns_internal.cc | 221 ++++-- src/dnsserver.cc | 330 +++++---- src/errorpage.cc | 11 +- src/errorpage.h | 5 +- src/event.cc | 8 +- src/external_acl.cc | 43 +- src/fd.cc | 6 +- src/fde.h | 17 +- src/forward.cc | 63 +- src/forward.h | 5 +- src/fqdncache.cc | 38 +- src/ftp.cc | 259 ++++--- src/globals.h | 16 +- src/helper.cc | 6 +- src/helper.h | 8 +- src/htcp.cc | 132 ++-- src/htcp.h | 5 +- src/http.cc | 32 +- src/icmp.cc | 304 ++------ src/icp_v2.cc | 134 ++-- src/icp_v3.cc | 26 +- src/ident.cc | 34 +- src/internal.cc | 13 +- src/ipc.cc | 45 +- src/ipc_win32.cc | 89 +-- src/ipcache.cc | 472 +++++++++++-- src/main.cc | 27 +- src/mib.txt | 168 +++-- src/multicast.cc | 18 +- src/neighbors.cc | 157 ++--- src/net_db.cc | 140 ++-- src/pconn.cc | 21 +- src/pconn.h | 6 +- src/peer_digest.cc | 5 +- src/peer_select.cc | 69 +- src/pinger.cc | 649 +++--------------- src/protos.h | 63 +- src/redirect.cc | 21 +- src/send-announce.cc | 14 +- src/snmp_agent.cc | 67 +- src/snmp_core.cc | 479 +++++++------ src/squid.h | 6 +- src/stat.cc | 12 +- src/store_log.cc | 4 +- src/structs.h | 91 +-- src/tests/stub_comm.cc | 4 +- src/tests/testEvent.cc | 38 +- src/tests/testHttpRequest.cc | 64 +- src/tests/testHttpRequest.h | 2 + src/tests/testICMP.cc | 84 +++ src/tests/testICMP.h | 50 ++ src/time.cc | 6 +- src/tools.cc | 105 +-- src/tunnel.cc | 13 +- src/typedefs.h | 8 +- src/unlinkd.cc | 6 +- src/url.cc | 171 ++++- src/urn.cc | 5 +- src/wccp.cc | 77 +-- src/wccp2.cc | 109 +-- src/win32.cc | 61 +- test-suite/hash.h | 5 +- test-suite/pconn-banger.c | 28 +- tools/cachemgr.cc | 40 +- tools/squidclient.cc | 122 ++-- 146 files changed, 6483 insertions(+), 3514 deletions(-) create mode 100644 lib/tests/testRFC1035.cc create mode 100644 lib/tests/testRFC1035.h create mode 100644 src/ICMP.h create mode 100644 src/ICMPConfig.h create mode 100644 src/ICMPPinger.cc create mode 100644 src/ICMPPinger.h create mode 100644 src/ICMPSquid.cc create mode 100644 src/ICMPSquid.h create mode 100644 src/ICMPv4.cc create mode 100644 src/ICMPv4.h create mode 100644 src/ICMPv6.cc create mode 100644 src/ICMPv6.h create mode 100644 src/tests/testICMP.cc create mode 100644 src/tests/testICMP.h diff --git a/configure.in b/configure.in index 5a2f8c18d6..a9c99a656f 100644 --- a/configure.in +++ b/configure.in @@ -1,17 +1,17 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.489 2007/12/14 01:11:53 hno Exp $ +dnl $Id: configure.in,v 1.490 2007/12/14 23:11:41 amosjeffries Exp $ dnl dnl dnl -AC_INIT(Squid Web Proxy, 3.HEAD-CVS, http://www.squid-cache.org/bugs/, squid) +AC_INIT(Squid Web Proxy, 3.HEAD-IPv6-CVS, http://www.squid-cache.org/bugs/, squid) AC_PREREQ(2.52) AM_CONFIG_HEADER(include/autoconf.h) AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.489 $)dnl +AC_REVISION($Revision: 1.490 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -668,14 +668,8 @@ AC_ARG_ENABLE(icmp, [ if test "$enableval" = "yes" ; then echo "ICMP enabled" AC_DEFINE(USE_ICMP,1, - [If you want to use Squid's ICMP features (highly recommended!) then - define this. When USE_ICMP is defined, Squid will send ICMP pings - to origin server sites. This information is used in numerous ways: - - Sent in ICP replies so neighbor caches know how close - you are to the source. - - For finding the closest instance of a URN. - - With the 'test_reachability' option. Squid will return - ICP_OP_MISS_NOFETCH for sites which it cannot ping.]) + [ Defined this to use Squid's ICMP features (highly recommended!) + When USE_ICMP is defined, Squid will send ICMP pings to origin server sites.]) AM_CONDITIONAL(ENABLE_PINGER, true) fi ]) @@ -1733,6 +1727,72 @@ AC_ARG_ENABLE(x_accelerator_vary, fi ]) +dnl Enable IPv6 support +AC_MSG_CHECKING([whether to enable IPv6]) +AC_ARG_ENABLE(ipv6, +[ --enable-ipv6 Enable ipv6 support], +[ AC_MSG_RESULT(yes) + AC_CACHE_CHECK([if PF_INET6 is available], $enableval, + AC_TRY_RUN( + [ /* PF_INET6 available check */ +# include +# include + void main() { + if (socket(PF_INET6, SOCK_STREAM, 0) < 0) + exit(1); + else + exit(0); + } + ], + [ AC_DEFINE(USE_IPV6,1,[Enable support for IPv6 ]) + AC_MSG_RESULT(yes) + ], + [ AC_DEFINE(USE_IPV6,0,[0 == Disable support for IPv6]) + AC_DEFINE(IPV6_SPECIAL_SPLITSTACK,0,[0 == Disable support for Split-Stack IPv6 Implementations]) + AC_DEFINE(IPV6_SPECIAL_LOCALHOST,0,[0 == Keep IPv4 and IPv6 Localhosts seperate.]) + AC_DEFINE(IPV6_SPECIAL_V4MAPPING,0,[0 == Leave all v4-mapping to OS Implementation]) + AC_MSG_RESULT(no) + ]) + ) +], +[ AC_DEFINE(USE_IPV6,0,[Disable support for IPv6]) + AC_DEFINE(IPV6_SPECIAL_SPLITSTACK,0,[ 0 == Disable support for Split-Stack IPv6 Implementations]) + AC_DEFINE(IPV6_SPECIAL_LOCALHOST,0,[ 0 == Keep IPv4 and IPv6 Localhosts seperate.]) + AC_DEFINE(IPV6_SPECIAL_V4MAPPING,0,[ 0 == Leave v4-mapping to OS Implementation]) + AC_MSG_RESULT(no) +]) +if test $ac_cv_enable_ipv6 ; then +dnl Check for Windows XP option +AC_MSG_CHECKING([for IPv6 split-stack requirement]) +AC_ARG_WITH(ipv6-split-stack, + [ --with-ipv6-split-stack Require IPv6 split-stack support (Requires IPv6 Support)], + [AC_DEFINE(IPV6_SPECIAL_SPLITSTACK, 1, [ 1 == Enable support for IPv6 on split-stack implementations]) AC_MSG_RESULT(yes)], + [AC_DEFINE(IPV6_SPECIAL_SPLITSTACK, 0, [ 0 == Disable support for split-stack IPv6 implementations]) AC_MSG_RESULT(no)] +) + +dnl Check for IPv6 Windows Vista option +AC_MSG_CHECKING([for IPv6 v4-mapping requirement]) +AC_ARG_WITH(ipv4-mapped, + [ --with-ipv4-mapped Hybrid-Stack OS require Squid to do any v4-mapping (Requires IPv6 Support)], + [AC_DEFINE(IPV6_SPECIAL_V4MAPPING, 1, [ 1 == Perform v4-mapping internally]) AC_MSG_RESULT(yes)], + [AC_DEFINE(IPV6_SPECIAL_V4MAPPING, 0, [ 0 == Leave all v4-mapping to the OS]) AC_MSG_RESULT(no)] +) + +dnl Check for IPv6-pure option +AC_MSG_CHECKING([for IPv6-Localhost requirement]) +AC_ARG_WITH(localhost-ipv6, + [ --with-localhost-ipv6 Prefer IPv6 localhost address over IPv4 (Requires IPv6 Support). + Treats 127.0.0.1 and ::1 as identical and converts all inputs of to ::1 + This depends on Dual-Stack support in the OS and all applications + squid contacts via localhost being IPv6 enabled. + Default: OFF. Treats these two IP as different, squid.conf must + define both 127.0.0.1 and ::1 for the localhost ACL, etc. ], + [AC_DEFINE(IPV6_SPECIAL_LOCALHOST, 1, [ 1 == Convert IPv4-localhost requests to IPv6.]) AC_MSG_RESULT(yes)], + [AC_DEFINE(IPV6_SPECIAL_LOCALHOST, 0, [ 0 == Keep IPv4 and IPv6 Localhosts seperate.]) AC_MSG_RESULT(no)] +) +# end IPv6-only options +fi + AC_ARG_WITH(filedescriptors, [ --with-filedescriptors=NUMBER Force squid to support NUMBER filedescriptors], @@ -1865,11 +1925,16 @@ AC_CHECK_HEADERS( \ net/pfvar.h \ netdb.h \ netinet/in.h \ + netinet/icmp6.h \ + netinet/in_systm.h \ + netinet/ip.h \ + netinet/ip6.h \ + netinet/ip_icmp.h \ netinet/ip_fil_compat.h \ - netinet/tcp.h \ openssl/err.h \ openssl/md5.h \ openssl/ssl.h \ + netinet/tcp.h \ openssl/engine.h \ paths.h \ poll.h \ @@ -2543,7 +2608,11 @@ AC_CHECK_FUNCS(\ dnl ... and some we provide local replacements for AC_REPLACE_FUNCS(\ drand48 \ + inet_ntop \ + inet_pton \ initgroups \ + getaddrinfo \ + getnameinfo \ strerror \ tempnam \ ) @@ -3174,6 +3243,61 @@ if test "$ac_cv_func_statvfs" = "yes" ; then fi fi +dnl Detect what resolver fields we have available to use... +AC_CACHE_CHECK(for _res_ext.nsaddr_list, ac_cv_have_res_ext_nsaddr_list, +AC_TRY_COMPILE([ +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_ARPA_NAMESER_H +#include +#endif +#if HAVE_RESOLV_H +#include +#endif +], +[_res_ext.nsaddr_list[[0]].s_addr;], +ac_cv_have_res_ext_nsaddr_list="yes", +ac_cv_have_res_ext_nsaddr_list="no")) +if test "$ac_cv_have_res_ext_nsaddr_list" = "yes" ; then + AC_DEFINE(_SQUID_RES_NSADDR6_LARRAY,_res_ext.nsaddr_list,[If _res_ext structure has nsaddr_list member]) + AC_DEFINE(_SQUID_RES_NSADDR6_COUNT,ns6count,[Nameserver Counter for IPv6 _res_ext]) +fi + +if test "$_SQUID_RES_NSADDR6_LIST" == ""; then +AC_CACHE_CHECK(for _res._u._ext.nsaddrs, ac_cv_have_res_ext_nsaddrs, +AC_TRY_COMPILE([ +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_ARPA_NAMESER_H +#include +#endif +#if HAVE_RESOLV_H +#include +#endif +], +[_res._u._ext.nsaddrs[[0]]->sin6_addr;], +ac_cv_have_res_ext_nsaddrs="yes", +ac_cv_have_res_ext_nsaddrs="no")) +if test "$ac_cv_have_res_ext_nsaddrs" = "yes" ; then + AC_DEFINE(_SQUID_RES_NSADDR6_LPTR,_res._u._ext.nsaddrs,[If _res structure has _ext.nsaddrs member]) + AC_DEFINE(_SQUID_RES_NSADDR6_COUNT,_res._u._ext.nscount6,[Nameserver Counter for IPv6 _res]) +fi +fi + AC_CACHE_CHECK(for _res.nsaddr_list, ac_cv_have_res_nsaddr_list, AC_TRY_COMPILE([ #if HAVE_SYS_TYPES_H @@ -3196,10 +3320,11 @@ AC_TRY_COMPILE([ ac_cv_have_res_nsaddr_list="yes", ac_cv_have_res_nsaddr_list="no")) if test $ac_cv_have_res_nsaddr_list = "yes" ; then - AC_DEFINE(HAVE_RES_NSADDR_LIST,1,[If _res structure has nsaddr_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_LIST,_res.nsaddr_list,[If _res structure has nsaddr_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_COUNT,_res.nscount,[Nameserver counter for IPv4 _res]) fi -if test $ac_cv_have_res_nsaddr_list = "no" ; then +if test "$_SQUID_RES_NSADDR_LIST" == ""; then AC_CACHE_CHECK(for _res.ns_list, ac_cv_have_res_ns_list, AC_TRY_COMPILE([ #if HAVE_SYS_TYPES_H @@ -3222,7 +3347,8 @@ AC_TRY_COMPILE([ ac_cv_have_res_ns_list="yes", ac_cv_have_res_ns_list="no")) if test $ac_cv_have_res_ns_list = "yes" ; then - AC_DEFINE(HAVE_RES_NS_LIST,1,[If _res structure has ns_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_LIST,_res.ns_list,[If _res structure has ns_list member]) + AC_DEFINE(_SQUID_RES_NSADDR_COUNT,_res.nscount,[Nameserver counter for IPv4 _res]) fi fi diff --git a/helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c b/helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c index fa4b4836ce..e4e2181e84 100755 --- a/helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c +++ b/helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c @@ -78,6 +78,7 @@ static const char *LogTime() return buf; } +// AYJ: this looks like a duplicate of the lib/gethostname function */ char *gethost_name(void) { char hostname[MAXHOSTNAMELEN]; struct addrinfo *hres=NULL, *hres_list; @@ -89,9 +90,10 @@ char *gethost_name(void) { fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname); return NULL; } - rc = getaddrinfo(hostname,NULL,NULL,&hres); + rc = xgetaddrinfo(hostname,NULL,NULL,&hres); if (rc != 0) { - fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc)); + fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc)); + xfreeaddrinfo(hres); return NULL; } hres_list=hres; @@ -100,14 +102,14 @@ char *gethost_name(void) { count++; hres_list=hres_list->ai_next; } - rc = getnameinfo (hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0); + rc = xgetnameinfo(hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0); if (rc != 0) { - fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, gai_strerror(rc)); - freeaddrinfo(hres); + fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc)); + xfreeaddrinfo(hres); return NULL ; } - freeaddrinfo(hres); + xfreeaddrinfo(hres); hostname[MAXHOSTNAMELEN]='\0'; return(strdup(hostname)); } diff --git a/helpers/ntlm_auth/SMB/smbval/rfcnb-priv.h b/helpers/ntlm_auth/SMB/smbval/rfcnb-priv.h index 40141cd81f..766a66fb92 100644 --- a/helpers/ntlm_auth/SMB/smbval/rfcnb-priv.h +++ b/helpers/ntlm_auth/SMB/smbval/rfcnb-priv.h @@ -59,7 +59,7 @@ typedef struct redirect_addr *redirect_ptr; struct redirect_addr { - struct IN_ADDR ip_addr; + struct in_addr ip_addr; int port; redirect_ptr next; diff --git a/include/cache_snmp.h b/include/cache_snmp.h index 34023c58db..e8cf9eae6b 100644 --- a/include/cache_snmp.h +++ b/include/cache_snmp.h @@ -1,5 +1,5 @@ /* - * $Id: cache_snmp.h,v 1.29 2006/09/22 02:48:51 hno Exp $ + * $Id: cache_snmp.h,v 1.30 2007/12/14 23:11:44 amosjeffries Exp $ */ #ifndef SQUID_CACHE_SNMP_H @@ -42,26 +42,26 @@ /* basic groups under .squid */ -#define SQ_SYS SQUIDMIB, 1 +#define SQ_SYS SQUIDMIB, 1 /* cacheSystem group { squid 1 } */ #define LEN_SQ_SYS LEN_SQUIDMIB+1 -#define SQ_CONF SQUIDMIB, 2 +#define SQ_CONF SQUIDMIB, 2 /* cacheConfig group { squid 2 } */ #define LEN_SQ_CONF LEN_SQUIDMIB+1 -#define SQ_PRF SQUIDMIB, 3 +#define SQ_PRF SQUIDMIB, 3 /* cachePerformance group { squid 3 } */ #define LEN_SQ_PRF LEN_SQUIDMIB+1 -#define SQ_NET SQUIDMIB, 4 +#define SQ_NET SQUIDMIB, 4 /* cacheNetwork group { squid 4 } */ #define LEN_SQ_NET LEN_SQUIDMIB+1 -#define SQ_MESH SQUIDMIB, 5 +#define SQ_MESH SQUIDMIB, 5 /* cacheMesh group { squid 5 } */ #define LEN_SQ_MESH LEN_SQUIDMIB+1 /* - * cacheSystem group + * cacheSystem group { squid 1 } */ enum { SYS_START, - SYSVMSIZ, - SYSSTOR, - SYS_UPTIME, + SYSVMSIZ, /* cacheSysVMsize */ + SYSSTOR, /* cacheSysStorage */ + SYS_UPTIME,/* cacheUptime */ SYS_END }; @@ -69,29 +69,33 @@ enum { #define LEN_SYS_INST LEN_SQ_SYS + 2 /* - * cacheConfig group + * cacheConfig group { squid 2 } */ enum { CONF_START, - CONF_ADMIN, - CONF_VERSION, - CONF_VERSION_ID, - CONF_LOG_FAC, - CONF_STORAGE, - CONF_UNIQNAME, + CONF_ADMIN, /* cacheAdmin */ + CONF_VERSION, /* cacheSoftware */ + CONF_VERSION_ID, /* cacheVersionId */ + CONF_LOG_FAC, /* cacheLoggingFacility */ + CONF_STORAGE, /* cacheStorageConfig group */ + CONF_UNIQNAME, /* cacheUniqName */ CONF_END }; #define LEN_CONF LEN_SQ_CONF + 1 #define LEN_CONF_INST LEN_SQ_CONF + 2 + +/* + * cacheStorageConfig group { cacheConfig 5 } + */ enum { CONF_ST_START, - CONF_ST_MMAXSZ, - CONF_ST_SWMAXSZ, - CONF_ST_SWHIWM, - CONF_ST_SWLOWM, + CONF_ST_MMAXSZ, /* cacheMemMaxSize */ + CONF_ST_SWMAXSZ, /* cacheSwapMaxSize */ + CONF_ST_SWHIWM, /* cacheSwapHighWM */ + CONF_ST_SWLOWM, /* cacheSwapLowWM */ CONF_ST_END }; @@ -99,164 +103,187 @@ enum { #define LEN_CONF_ST_INST LEN_CONF + 2 /* - * cacheMesh group + * Cache Performance Group {squid 3} */ enum { - MESH_START, - MESH_PTBL, - MESH_CTBL, - MESH_END + PERF_START, + PERF_SYS, /* cacheSysPerf */ + PERF_PROTO, /* cacheProtoStats */ + PERF_END }; -enum { /* cachePeerTable */ - MESH_PTBL_START, - MESH_PTBL_NAME, - MESH_PTBL_IP, - MESH_PTBL_HTTP, - MESH_PTBL_ICP, - MESH_PTBL_TYPE, - MESH_PTBL_STATE, - MESH_PTBL_SENT, - MESH_PTBL_PACKED, - MESH_PTBL_FETCHES, - MESH_PTBL_RTT, - MESH_PTBL_IGN, - MESH_PTBL_KEEPAL_S, - MESH_PTBL_KEEPAL_R, - MESH_PTBL_END + +/* cacheSysPerf */ +enum { + PERF_SYS_START, + PERF_SYS_PF, /* cacheSysPageFaults */ + PERF_SYS_NUMR, /* cacheSysNumReads */ + PERF_SYS_MEMUSAGE, /* cacheMemUsage */ + PERF_SYS_CPUTIME, /* cacheCpuTime */ + PERF_SYS_CPUUSAGE, /* cacheCpuUsage */ + PERF_SYS_MAXRESSZ, /* cacheMaxResSize */ + PERF_SYS_NUMOBJCNT, /* cacheNumObjCount */ + PERF_SYS_CURLRUEXP, /* cacheCurrentLRUExpiration */ + PERF_SYS_CURUNLREQ, /* cacheCurrentUnlinkRequests */ + PERF_SYS_CURUNUSED_FD, /* cacheCurrentUnusedFDescrCnt */ + PERF_SYS_CURRESERVED_FD, /* cacheCurrentResFileDescrCnt */ + PERF_SYS_CURUSED_FD, /* cacheCurrentFileDescrCnt */ + PERF_SYS_CURMAX_FD, /* cacheCurrentFileDescrMax */ + PERF_SYS_END }; -enum { /* cacheClientTable */ - MESH_CTBL_START, - MESH_CTBL_ADDR, - MESH_CTBL_HTREQ, - MESH_CTBL_HTBYTES, - MESH_CTBL_HTHITS, - MESH_CTBL_HTHITBYTES, - MESH_CTBL_ICPREQ, - MESH_CTBL_ICPBYTES, - MESH_CTBL_ICPHITS, - MESH_CTBL_ICPHITBYTES, - MESH_CTBL_END +/* cacheProtoStats */ +enum { + PERF_PROTOSTAT_START, + PERF_PROTOSTAT_AGGR, /* cacheProtoAggregateStats */ + PERF_PROTOSTAT_MEDIAN, /* cacheMedianSvcTable */ + PERF_PROTOSTAT_END +}; + +/* cacheProtoAggregateStats */ +enum { + PERF_PROTOSTAT_AGGR_START, + PERF_PROTOSTAT_AGGR_HTTP_REQ, /* cacheProtoClientHttpRequests */ + PERF_PROTOSTAT_AGGR_HTTP_HITS, /* cacheHttpHits */ + PERF_PROTOSTAT_AGGR_HTTP_ERRORS, /* cacheHttpErrors */ + PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN, /* cacheHttpInKb */ + PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT, /* cacheHttpOutKb */ + PERF_PROTOSTAT_AGGR_ICP_S, /* cacheIcpPktsSent */ + PERF_PROTOSTAT_AGGR_ICP_R, /* cacheIcpPktsRecv */ + PERF_PROTOSTAT_AGGR_ICP_SKB, /* cacheIcpKbSent */ + PERF_PROTOSTAT_AGGR_ICP_RKB, /* cacheIcpKbRecv */ + PERF_PROTOSTAT_AGGR_REQ, /* cacheServerRequests */ + PERF_PROTOSTAT_AGGR_ERRORS, /* cacheServerErrors */ + PERF_PROTOSTAT_AGGR_KBYTES_IN, /* cacheServerInKb */ + PERF_PROTOSTAT_AGGR_KBYTES_OUT, /* cacheServerOutKb */ + PERF_PROTOSTAT_AGGR_CURSWAP, /* cacheCurrentSwapSize */ + PERF_PROTOSTAT_AGGR_CLIENTS, /* cacheClients */ + PERF_PROTOSTAT_AGGR_END +}; + + +/* CacheMedianSvcEntry */ +enum { + PERF_MEDIAN_START, + PERF_MEDIAN_TIME, /* cacheMedianTime */ + PERF_MEDIAN_HTTP_ALL, /* cacheHttpAllSvcTime */ + PERF_MEDIAN_HTTP_MISS, /* cacheHttpMissSvcTime */ + PERF_MEDIAN_HTTP_NM, /* cacheHttpNmSvcTime */ + PERF_MEDIAN_HTTP_HIT, /* cacheHttpHitSvcTime */ + PERF_MEDIAN_ICP_QUERY, /* cacheIcpQuerySvcTime */ + PERF_MEDIAN_ICP_REPLY, /* cacheIcpReplySvcTime */ + PERF_MEDIAN_DNS, /* cacheDnsSvcTime */ + PERF_MEDIAN_RHR, /* cacheRequestHitRatio */ + PERF_MEDIAN_BHR, /* cacheRequestByteRatio */ + PERF_MEDIAN_HTTP_NH, /* cacheHttpNhSvcTime */ + PERF_MEDIAN_END }; + + + /* - * cacheNetwork group + * cacheNetwork group { squid 4 } */ enum { NET_START, - NET_IP_CACHE, - NET_FQDN_CACHE, - NET_DNS_CACHE, + NET_IP_CACHE, /* cacheIpCache */ + NET_FQDN_CACHE, /* cacheFqdnCache */ + NET_DNS_CACHE, /* cacheDns */ NET_END }; +/* cacheIpCache */ enum { - IP_START, - IP_ENT, - IP_REQ, - IP_HITS, - IP_PENDHIT, - IP_NEGHIT, - IP_MISS, - IP_GHBN, - IP_LOC, + IP_START, + IP_ENT, /* cacheIpEntrie */ + IP_REQ, /* cacheIpRequests */ + IP_HITS, /* acheIpHits */ + IP_PENDHIT, /* cacheIpPendingHits */ + IP_NEGHIT, /* cacheIpNegativeHit */ + IP_MISS, /* cacheIpMisses */ + IP_GHBN, /* cacheBlockingGetHostByName */ + IP_LOC, /* cacheAttemptReleaseLckEntries */ IP_END }; +/* cacheFqdnCache */ enum { FQDN_START, - FQDN_ENT, - FQDN_REQ, - FQDN_HITS, - FQDN_PENDHIT, - FQDN_NEGHIT, - FQDN_MISS, - FQDN_GHBN, + FQDN_ENT, /* cacheFqdnEntries */ + FQDN_REQ, /* cacheFqdnRequests */ + FQDN_HITS, /* cacheFqdnHits */ + FQDN_PENDHIT, /* cacheFqdnPendingHits */ + FQDN_NEGHIT, /* cacheFqdnNegativeHits */ + FQDN_MISS, /* cacheFqdnMisses */ + FQDN_GHBN, /* cacheBlockingGetHostByAddr */ FQDN_END }; + +/* cacheDNS */ enum { DNS_START, - DNS_REQ, - DNS_REP, - DNS_SERVERS, + DNS_REQ, /* cacheDnsRequests */ + DNS_REP, /* cacheDnsReplies */ + DNS_SERVERS, /* cacheDnsNumberServers */ DNS_END }; + + + /* - * Cache Performance Group + * cacheMesh group { squid 5 } */ enum { - PERF_START, - PERF_SYS, - PERF_PROTO, - PERF_END + MESH_START, + MESH_PTBL, /* cachePeerTable */ + MESH_CTBL, /* cacheClientTable */ + MESH_END }; -enum { - PERF_SYS_START, - PERF_SYS_PF, - PERF_SYS_NUMR, - PERF_SYS_MEMUSAGE, - PERF_SYS_CPUTIME, - PERF_SYS_CPUUSAGE, - PERF_SYS_MAXRESSZ, - PERF_SYS_NUMOBJCNT, - PERF_SYS_CURLRUEXP, - PERF_SYS_CURUNLREQ, - PERF_SYS_CURUNUSED_FD, - PERF_SYS_CURRESERVED_FD, - PERF_SYS_CURUSED_FD, - PERF_SYS_CURMAX_FD, - PERF_SYS_END +/* cachePeerEntry */ +enum { + MESH_PTBL_START, + MESH_PTBL_INDEX, /* cachePeerIndex */ + MESH_PTBL_NAME, /* cachePeerName */ + MESH_PTBL_ADDR_TYPE, /* cachePeerAddressType */ + MESH_PTBL_ADDR, /* cachePeerAddress */ + MESH_PTBL_HTTP, /* cachePortHttp */ + MESH_PTBL_ICP, /* cachePeerPortIcp */ + MESH_PTBL_TYPE, /* cachePeerType */ + MESH_PTBL_STATE, /* cachePeerStat */ + MESH_PTBL_SENT, /* cachePeerPingsSent */ + MESH_PTBL_PACKED, /* cachePeerPingsAcked */ + MESH_PTBL_FETCHES, /* cachePeerFetches */ + MESH_PTBL_RTT, /* cachePeerRtt */ + MESH_PTBL_IGN, /* cachePeerIgnored */ + MESH_PTBL_KEEPAL_S, /* cachePeerKeepAlSent */ + MESH_PTBL_KEEPAL_R, /* cachePeerKeepAlRecv */ + MESH_PTBL_END }; -enum { - PERF_PROTOSTAT_START, - PERF_PROTOSTAT_AGGR, - PERF_PROTOSTAT_MEDIAN, - PERF_PROTOSTAT_END +/* cacheClientEntry */ +enum { + MESH_CTBL_START, + MESH_CTBL_ADDR_TYPE, /* cacheClientAddressType */ + MESH_CTBL_ADDR, /* cacheClientAddress */ + MESH_CTBL_HTREQ, /* cacheClientHttpRequests */ + MESH_CTBL_HTBYTES, /* cacheClientHttpKb */ + MESH_CTBL_HTHITS, /* cacheClientHttpHits */ + MESH_CTBL_HTHITBYTES, /* cacheClientHTTPHitKb */ + MESH_CTBL_ICPREQ, /* cacheClientIcpRequests */ + MESH_CTBL_ICPBYTES, /* cacheClientIcpKb */ + MESH_CTBL_ICPHITS, /* cacheClientIcpHits */ + MESH_CTBL_ICPHITBYTES,/* cacheClientIcpHitKb */ + MESH_CTBL_END }; -enum { - PERF_PROTOSTAT_AGGR_START, - PERF_PROTOSTAT_AGGR_HTTP_REQ, - PERF_PROTOSTAT_AGGR_HTTP_HITS, - PERF_PROTOSTAT_AGGR_HTTP_ERRORS, - PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN, - PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT, - PERF_PROTOSTAT_AGGR_ICP_S, - PERF_PROTOSTAT_AGGR_ICP_R, - PERF_PROTOSTAT_AGGR_ICP_SKB, - PERF_PROTOSTAT_AGGR_ICP_RKB, - PERF_PROTOSTAT_AGGR_REQ, - PERF_PROTOSTAT_AGGR_ERRORS, - PERF_PROTOSTAT_AGGR_KBYTES_IN, - PERF_PROTOSTAT_AGGR_KBYTES_OUT, - PERF_PROTOSTAT_AGGR_CURSWAP, - PERF_PROTOSTAT_AGGR_CLIENTS, - PERF_PROTOSTAT_AGGR_END -}; -enum { - PERF_MEDIAN_START, - PERF_MEDIAN_TIME, - PERF_MEDIAN_HTTP_ALL, - PERF_MEDIAN_HTTP_MISS, - PERF_MEDIAN_HTTP_NM, - PERF_MEDIAN_HTTP_HIT, - PERF_MEDIAN_ICP_QUERY, - PERF_MEDIAN_ICP_REPLY, - PERF_MEDIAN_DNS, - PERF_MEDIAN_RHR, - PERF_MEDIAN_BHR, - PERF_MEDIAN_HTTP_NH, - PERF_MEDIAN_END -}; #endif /* SQUID_SNMP */ diff --git a/include/config.h b/include/config.h index c468320310..7bb9d37556 100644 --- a/include/config.h +++ b/include/config.h @@ -1,5 +1,5 @@ /* - * $Id: config.h,v 1.25 2007/09/20 11:07:53 amosjeffries Exp $ + * $Id: config.h,v 1.26 2007/12/14 23:11:44 amosjeffries Exp $ * * AUTHOR: Duane Wessels * @@ -193,14 +193,6 @@ #define FD_SETSIZE SQUID_MAXFD #endif - - -/* - * This is hack to allow compiling IPv6-IPv4 version, - * not disturbing branches others than squid3-ipv6 - */ -#define IN_ADDR in_addr - /* Typedefs for missing entries on a system */ #include "squid_types.h" diff --git a/include/rfc1035.h b/include/rfc1035.h index 8a9e9c798f..8ef3625c53 100644 --- a/include/rfc1035.h +++ b/include/rfc1035.h @@ -1,5 +1,5 @@ /* - * $Id: rfc1035.h,v 1.18 2007/09/20 11:58:21 amosjeffries Exp $ + * $Id: rfc1035.h,v 1.19 2007/12/14 23:11:44 amosjeffries Exp $ * * AUTHOR: Duane Wessels * @@ -95,7 +95,7 @@ SQUIDCEXTERN int rfc1035MessageUnpack(const char *buf, size_t sz, rfc1035_message ** answer); SQUIDCEXTERN int rfc1035QueryCompare(const rfc1035_query *, const rfc1035_query *); -SQUIDCEXTERN void rfc1035MessageDestroy(rfc1035_message * message); +SQUIDCEXTERN void rfc1035MessageDestroy(rfc1035_message ** message); SQUIDCEXTERN int rfc1035_errno; SQUIDCEXTERN const char *rfc1035_error_message; diff --git a/include/snmp_vars.h b/include/snmp_vars.h index b0ba155498..0868f96294 100644 --- a/include/snmp_vars.h +++ b/include/snmp_vars.h @@ -25,7 +25,7 @@ * * Author: Ryan Troll * - * $Id: snmp_vars.h,v 1.13 2003/01/23 00:36:48 robertc Exp $ + * $Id: snmp_vars.h,v 1.14 2007/12/14 23:11:44 amosjeffries Exp $ * **********************************************************************/ @@ -71,9 +71,47 @@ u_char *snmp_var_DecodeVarBind(u_char *, int *, struct variable_list **, int); #define SMI_TIMETICKS (ASN_APPLICATION | 3) /* INTEGER */ #define SMI_OPAQUE (ASN_APPLICATION | 4) /* OCTET STRING */ #define SMI_COUNTER64 (ASN_APPLICATION | 6) /* INTEGER */ -#define SMI_NOSUCHOBJECT (ASN_CONTEXT | ASN_PRIMITIVE | 0x0) -#define SMI_NOSUCHINSTANCE (ASN_CONTEXT | ASN_PRIMITIVE | 0x1) -#define SMI_ENDOFMIBVIEW (ASN_CONTEXT | ASN_PRIMITIVE | 0x2) + + +/* constants for enums for the MIB nodes + * cachePeerAddressType (InetAddressType / ASN_INTEGER) + * cacheClientAddressType (InetAddressType / ASN_INTEGER) + * Defined Types + */ + +#ifndef INETADDRESSTYPE_ENUMS +#define INETADDRESSTYPE_ENUMS + +#define INETADDRESSTYPE_UNKNOWN 0 +#define INETADDRESSTYPE_IPV4 1 +#define INETADDRESSTYPE_IPV6 2 +#define INETADDRESSTYPE_IPV4Z 3 +#define INETADDRESSTYPE_IPV6Z 4 +#define INETADDRESSTYPE_DNS 16 + +#endif /* INETADDRESSTYPE_ENUMS */ + + +/* + * RFC 1905: Protocol Operations for SNMPv2 + * + * Variable binding. + * + * VarBind ::= + * SEQUENCE { + * name ObjectName + * CHOICE { + * value ObjectSyntax + * unSpecified NULL + * noSuchObject[0] NULL + * noSuchInstance[1] NULL + * endOfMibView[2] NULL + * } + * } + */ +#define SMI_NOSUCHOBJECT (ASN_CONTEXT | ASN_PRIMITIVE | 0x0) /* noSuchObject[0] */ +#define SMI_NOSUCHINSTANCE (ASN_CONTEXT | ASN_PRIMITIVE | 0x1) /* noSuchInstance[1] */ +#define SMI_ENDOFMIBVIEW (ASN_CONTEXT | ASN_PRIMITIVE | 0x2) /* endOfMibView[2] */ typedef struct variable variable; typedef struct variable_list variable_list; diff --git a/include/squid_mswin.h b/include/squid_mswin.h index 345aa436a5..9c398df0b6 100755 --- a/include/squid_mswin.h +++ b/include/squid_mswin.h @@ -1,5 +1,5 @@ /* - * $Id: squid_mswin.h,v 1.6 2007/09/23 15:21:29 serassio Exp $ + * $Id: squid_mswin.h,v 1.7 2007/12/14 23:11:44 amosjeffries Exp $ * * AUTHOR: Andrey Shorin * AUTHOR: Guido Serassio @@ -211,6 +211,7 @@ struct timezone #include #include #include +#include #if defined(_MSC_VER) /* Microsoft C Compiler ONLY */ /* Hack to suppress compiler warnings on FD_SET() & FD_CLR() */ #pragma warning (push) @@ -243,6 +244,7 @@ typedef char * caddr_t; #define ECONNRESET WSAECONNRESET #define ENOTCONN WSAENOTCONN #define ERESTART WSATRY_AGAIN +#define EAFNOSUPPORT WSAEAFNOSUPPORT #undef h_errno #define h_errno errno /* we'll set it ourselves */ @@ -392,10 +394,10 @@ char *index(const char *s, int c) namespace Squid { inline -int accept(int s, struct sockaddr * a, int * l) +int accept(int s, struct sockaddr * a, size_t * l) { SOCKET result; - if ((result = ::accept(_get_osfhandle(s), a, l)) == INVALID_SOCKET) { + if ((result = ::accept(_get_osfhandle(s), a, (int *)l)) == INVALID_SOCKET) { if (WSAEMFILE == (errno = WSAGetLastError())) errno = EMFILE; return -1; @@ -458,9 +460,9 @@ HOSTENT FAR * gethostbyaddr(const char * a, int l, int t) #define gethostbyaddr(a,l,t) Squid::gethostbyaddr(a,l,t) inline -int getsockname(int s, struct sockaddr * n, int * l) +int getsockname(int s, struct sockaddr * n, size_t * l) { - if ((::getsockname(_get_osfhandle(s), n, l)) == SOCKET_ERROR) { + if ((::getsockname(_get_osfhandle(s), n, (int *)l)) == SOCKET_ERROR) { errno = WSAGetLastError(); return -1; } @@ -541,10 +543,10 @@ int recv(int s, void * b, size_t l, int f) } inline -int recvfrom(int s, void * b, size_t l, int f, struct sockaddr * fr, int * fl) +int recvfrom(int s, void * b, size_t l, int f, struct sockaddr * fr, size_t * fl) { int result; - if ((result = ::recvfrom(_get_osfhandle(s), (char *)b, l, f, fr, fl)) == SOCKET_ERROR) { + if ((result = ::recvfrom(_get_osfhandle(s), (char *)b, l, f, fr, (int *)fl)) == SOCKET_ERROR) { errno = WSAGetLastError(); return -1; } diff --git a/include/util.h b/include/util.h index ec46aba06c..fa64e8418d 100644 --- a/include/util.h +++ b/include/util.h @@ -1,5 +1,5 @@ /* - * $Id: util.h,v 1.78 2007/09/20 12:32:50 amosjeffries Exp $ + * $Id: util.h,v 1.79 2007/12/14 23:11:44 amosjeffries Exp $ * * AUTHOR: Harvest Derived * @@ -45,6 +45,9 @@ #if HAVE_SYS_TIME_H #include #endif +#if HAVE_ARPA_INET_H +#include +#endif #if !defined(SQUIDHOSTNAMELEN) #define SQUIDHOSTNAMELEN 256 @@ -125,8 +128,6 @@ extern size_t xmalloc_total; extern void xmalloc_find_leaks(void); #endif -typedef struct IN_ADDR SIA; -SQUIDCEXTERN int safe_inet_addr(const char *, SIA *); SQUIDCEXTERN time_t parse_iso3307_time(const char *buf); SQUIDCEXTERN char *base64_decode(const char *coded); SQUIDCEXTERN const char *base64_encode(const char *decoded); @@ -143,6 +144,13 @@ SQUIDCEXTERN const char *xint64toa(int64_t num); SQUIDCEXTERN double drand48(void); #endif +#ifndef xmax +#define xmax(a,b) ((a) < (b) ? (b) : (a)) +#endif +#ifndef xmin +#define xmin(a,b) ((a) < (b) ? (a) : (b)) +#endif + typedef struct { size_t count; size_t bytes; diff --git a/lib/GNUregex.c b/lib/GNUregex.c index 27a2b2ea1a..34635113cd 100644 --- a/lib/GNUregex.c +++ b/lib/GNUregex.c @@ -1,5 +1,5 @@ /* - * $Id: GNUregex.c,v 1.21 2005/04/30 19:32:01 serassio Exp $ + * $Id: GNUregex.c,v 1.22 2007/12/14 23:11:44 amosjeffries Exp $ */ /* Extended regular expression matching and search library, @@ -247,7 +247,9 @@ char *alloca(); #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#if !defined(__MINGW32__) /* MinGW defines boolean */ typedef char boolean; +#endif #define false 0 #define true 1 diff --git a/lib/Makefile.am b/lib/Makefile.am index c6bb30821b..7ece54d485 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in # -# $Id: Makefile.am,v 1.32 2007/12/14 04:42:24 amosjeffries Exp $ +# $Id: Makefile.am,v 1.33 2007/12/14 23:11:44 amosjeffries Exp $ # DIST_SUBDIRS = libTrie @@ -67,7 +67,6 @@ libmiscutil_a_SOURCES = \ rfc1738.c \ rfc2617.c \ rfc3596.c \ - safe_inet_addr.c \ $(SNPRINTFSOURCE) \ Splay.cc \ $(STRSEPSOURCE) \ @@ -104,6 +103,9 @@ tests_testAll_SOURCES= \ tests/testArray.cc \ tests/testIPAddress.h \ tests/testIPAddress.cc \ + IPAddress.cc \ + tests/testRFC1035.h \ + tests/testRFC1035.cc \ tests/testMain.cc \ $(XPROF_STATS_SOURCE) \ $(WIN32SRC) \ diff --git a/lib/rfc1035.c b/lib/rfc1035.c index 77a4d6ddfe..3faede1aec 100644 --- a/lib/rfc1035.c +++ b/lib/rfc1035.c @@ -1,6 +1,6 @@ /* - * $Id: rfc1035.c,v 1.50 2007/12/06 02:37:15 amosjeffries Exp $ + * $Id: rfc1035.c,v 1.51 2007/12/14 23:11:45 amosjeffries Exp $ * * Low level DNS protocol routines * AUTHOR: Duane Wessels @@ -472,16 +472,17 @@ rfc1035SetErrno(int n) } static void -rfc1035RRDestroy(rfc1035_rr * rr, int n) +rfc1035RRDestroy(rfc1035_rr ** rr, int n) { - if (rr == NULL) + if (*rr == NULL) return; assert(n > 0); while (n--) { - if (rr[n].rdata) - xfree(rr[n].rdata); + if ((*rr)[n].rdata) + xfree((*rr)[n].rdata); } - xfree(rr); + xfree(*rr); + *rr = NULL; } /* @@ -517,15 +518,16 @@ rfc1035QueryUnpack(const char *buf, size_t sz, unsigned int *off, rfc1035_query } void -rfc1035MessageDestroy(rfc1035_message * msg) +rfc1035MessageDestroy(rfc1035_message ** msg) { - if (!msg) + if (!*msg) return; - if (msg->query) - xfree(msg->query); - if (msg->answer) - rfc1035RRDestroy(msg->answer, msg->ancount); - xfree(msg); + if ((*msg)->query) + xfree((*msg)->query); + if ((*msg)->answer) + rfc1035RRDestroy(&(*msg)->answer, (*msg)->ancount); + xfree(*msg); + *msg = NULL; } /* @@ -602,7 +604,7 @@ rfc1035MessageUnpack(const char *buf, if (rfc1035QueryUnpack(buf, sz, &off, &querys[j])) { RFC1035_UNPACK_DEBUG; rfc1035SetErrno(rfc1035_unpack_error); - rfc1035MessageDestroy(msg); + rfc1035MessageDestroy(&msg); return -rfc1035_unpack_error; } } @@ -615,7 +617,7 @@ rfc1035MessageUnpack(const char *buf, if (msg->ancount == 0) return 0; i = (unsigned int) msg->ancount; - recs = msg->answer = xcalloc(i, sizeof(*recs)); + recs = msg->answer = (rfc1035_rr*)xcalloc(i, sizeof(*recs)); for (j = 0; j < i; j++) { if (off >= sz) { /* corrupt packet */ RFC1035_UNPACK_DEBUG; @@ -632,7 +634,7 @@ rfc1035MessageUnpack(const char *buf, * we expected to unpack some answers (ancount != 0), but * didn't actually get any. */ - rfc1035MessageDestroy(msg); + rfc1035MessageDestroy(&msg); *answer = NULL; rfc1035SetErrno(rfc1035_unpack_error); return -rfc1035_unpack_error; @@ -804,7 +806,7 @@ main(int argc, char *argv[]) printf("%d answers\n", n); for (i = 0; i < n; i++) { if (answers[i].type == RFC1035_TYPE_A) { - struct IN_ADDR a; + struct in_addr a; memcpy(&a, answers[i].rdata, 4); printf("A\t%d\t%s\n", answers[i].ttl, inet_ntoa(a)); } else if (answers[i].type == RFC1035_TYPE_PTR) { diff --git a/lib/safe_inet_addr.c b/lib/safe_inet_addr.c index 23f63c5753..e69de29bb2 100644 --- a/lib/safe_inet_addr.c +++ b/lib/safe_inet_addr.c @@ -1,65 +0,0 @@ - -/* - * $Id: safe_inet_addr.c,v 1.15 2007/12/06 18:01:52 rousskov Exp $ - */ - -#include "config.h" -#include "util.h" - -#if HAVE_STDIO_H -#include -#endif -#if HAVE_STDLIB_H -#include -#endif -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_SYS_SOCKET_H -#include -#endif -#if HAVE_NETINET_IN_H -#include -#endif -#if HAVE_ARPA_INET_H -#include -#endif - - -int -safe_inet_addr(const char *buf, struct IN_ADDR *addr) -{ - static char addrbuf[32]; - 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; - if (a2 < 0 || a2 > 255) - return 0; - if (a3 < 0 || a3 > 255) - return 0; - if (a4 < 0 || a4 > 255) - return 0; - snprintf(addrbuf, 32, "%d.%d.%d.%d", a1, a2, a3, a4); - A.s_addr = inet_addr(addrbuf); - if (addr) - addr->s_addr = A.s_addr; - return 1; -} diff --git a/lib/tests/testRFC1035.cc b/lib/tests/testRFC1035.cc new file mode 100644 index 0000000000..642d9589a5 --- /dev/null +++ b/lib/tests/testRFC1035.cc @@ -0,0 +1,110 @@ +#include "config.h" + +#if HAVE_ASSERT_H +#include +#endif + +#include "testRFC1035.h" + +/* Being a C library code it is best bodily included and tested with C++ type-safe techniques. */ +#include "rfc1035.c" + +CPPUNIT_TEST_SUITE_REGISTRATION( testRFC1035 ); + +// TODO Test each function in the Library independently +// Just because we can for global functions. +// It's good for the code too. + +void testRFC1035::testHeaderUnpack() +{ + /* Setup a buffer with the known-content packet */ + const char *buf = "\x76\xb1\x81\x80\x00\x01\x00\x01\x00\x02\x00\x02\x03\x77\x77\x77\x07\x67\x61\x6d\x65\x64\x65\x76\x03\x6e\x65\x74\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\xef\x00\x04\xd8\xb9\x60\xea\xc0\x10\x00\x02\x00\x01\x00\x00\x00\xef\x00\x0f\x03\x6e\x73\x32\x05\x7a\x77\x61\x76\x65\x03\x63\x6f\x6d\x00\xc0\x10\x00\x02\x00\x01\x00\x00\x00\xef\x00\x06\x03\x6e\x73\x31\xc0\x41\xc0\x3d\x00\x01\x00\x01\x00\x00\x29\x6b\x00\x04\xd8\xea\xee\x4a\xc0\x58\x00\x01\x00\x01\x00\x00\x29\x6b\x00\x04\xd8\xea\xee\x4b"; + size_t len = 126; + rfc1035_message *msg = NULL; + int res = 0; + unsigned int off = 0; + + /* Test the HeaderUnpack function */ + msg = new rfc1035_message; + res = rfc1035HeaderUnpack(buf, len, &off, msg); + CPPUNIT_ASSERT(res == 0); + CPPUNIT_ASSERT_EQUAL((short unsigned int)0x76b1, msg->id); + CPPUNIT_ASSERT(msg->qr == 1); + /* flags */ + CPPUNIT_ASSERT_EQUAL((unsigned int)0, msg->opcode); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, msg->aa); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, msg->tc); + CPPUNIT_ASSERT_EQUAL((unsigned int)1, msg->rd); + CPPUNIT_ASSERT_EQUAL((unsigned int)1, msg->ra); + CPPUNIT_ASSERT_EQUAL((unsigned int)0, msg->rcode); + /* RR counts */ + CPPUNIT_ASSERT_EQUAL((unsigned short)1, msg->qdcount); + CPPUNIT_ASSERT_EQUAL((unsigned short)1, msg->ancount); + CPPUNIT_ASSERT_EQUAL((unsigned short)2, msg->nscount); + CPPUNIT_ASSERT_EQUAL((unsigned short)2, msg->arcount); + + /* cleanup */ + delete msg; msg = NULL; +} + +void testRFC1035::testParseAPacket() +{ + /* Setup a buffer with the known-content packet */ + const char *buf = "\x76\xb1\x81\x80\x00\x01\x00\x01\x00\x02\x00\x02\x03\x77\x77\x77\x07\x67\x61\x6d\x65\x64\x65\x76\x03\x6e\x65\x74\x00\x00\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\xef\x00\x04\xd8\xb9\x60\xea\xc0\x10\x00\x02\x00\x01\x00\x00\x00\xef\x00\x0f\x03\x6e\x73\x32\x05\x7a\x77\x61\x76\x65\x03\x63\x6f\x6d\x00\xc0\x10\x00\x02\x00\x01\x00\x00\x00\xef\x00\x06\x03\x6e\x73\x31\xc0\x41\xc0\x3d\x00\x01\x00\x01\x00\x00\x29\x6b\x00\x04\xd8\xea\xee\x4a\xc0\x58\x00\x01\x00\x01\x00\x00\x29\x6b\x00\x04\xd8\xea\xee\x4b"; + size_t len = 126; + rfc1035_message *msg = NULL; + int res = 0; + + /* Test the MessageUnpack function itself */ + res = rfc1035MessageUnpack(buf, len, &msg); + + CPPUNIT_ASSERT_EQUAL(1, res); + CPPUNIT_ASSERT(msg != NULL); + /* cleanup */ + rfc1035MessageDestroy(&msg); + CPPUNIT_ASSERT(msg == NULL); +} + +void testRFC1035::testBugPacketEndingOnCompressionPtr() +{ + /* Setup a buffer with the known-to-fail packet */ + const char *buf = "\xec\x7b\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x05\x62\x75\x72\x73\x74\x02\x74\x65\x06\x74\x61\x63\x6f\x64\x61\x03\x6e\x65\x74\x00\x00\x1c\x00\x01\xc0\x0c\x00\x05\x00\x01\x00\x00\x19\xe5\x00\x0a\x02\x74\x65\x04\x67\x73\x6c\x62\xc0\x15"; + size_t len = 59; + rfc1035_message *msg = NULL; + int res = 0; + unsigned int off = 0; + + + /* Test the HeaderUnpack function results */ + msg = new rfc1035_message; + res = rfc1035HeaderUnpack(buf, len, &off, msg); + CPPUNIT_ASSERT(0 == res); + CPPUNIT_ASSERT(0xec7b == msg->id); + CPPUNIT_ASSERT(1 == msg->qr); + /* flags */ + CPPUNIT_ASSERT(0 == msg->opcode); + CPPUNIT_ASSERT(0 == msg->aa); + CPPUNIT_ASSERT(0 == msg->tc); + CPPUNIT_ASSERT(1 == msg->rd); + CPPUNIT_ASSERT(1 == msg->ra); + CPPUNIT_ASSERT(0 == msg->rcode); + /* RR counts */ + CPPUNIT_ASSERT(1 == msg->qdcount); + CPPUNIT_ASSERT(1 == msg->ancount); + CPPUNIT_ASSERT(0 == msg->nscount); + CPPUNIT_ASSERT(0 == msg->arcount); + CPPUNIT_ASSERT(12 == off); + printf("\n Header : OK"); + /* cleanup */ + delete msg; msg = NULL; + +// TODO explicitly test RR and Name unpack functions for this packet. + + /* Test the MessageUnpack function itself */ + res = rfc1035MessageUnpack(buf, len, &msg); + + CPPUNIT_ASSERT_EQUAL((const char*)NULL, rfc1035_error_message); + CPPUNIT_ASSERT_EQUAL(1, res); + CPPUNIT_ASSERT(msg != NULL); + rfc1035MessageDestroy(&msg); +} diff --git a/lib/tests/testRFC1035.h b/lib/tests/testRFC1035.h new file mode 100644 index 0000000000..b994c9a78b --- /dev/null +++ b/lib/tests/testRFC1035.h @@ -0,0 +1,29 @@ +#ifndef SQUID_SRC_TEST_RFC1035_H +#define SQUID_SRC_TEST_RFC1035_H + +#include + +/* + * test the DNS resolver RFC 1035 Engine + */ + +class testRFC1035 : public CPPUNIT_NS::TestFixture +{ + CPPUNIT_TEST_SUITE( testRFC1035 ); + CPPUNIT_TEST( testHeaderUnpack ); + CPPUNIT_TEST( testParseAPacket ); + + CPPUNIT_TEST( testBugPacketEndingOnCompressionPtr ); + CPPUNIT_TEST_SUITE_END(); + +public: + +protected: + void testHeaderUnpack(); + void testParseAPacket(); + + // bugs. + void testBugPacketEndingOnCompressionPtr(); +}; + +#endif /* SQUID_SRC_TEST_IPADDRESS_H */ diff --git a/src/ACLARP.cc b/src/ACLARP.cc index 1af39c43ad..6eda311e1d 100644 --- a/src/ACLARP.cc +++ b/src/ACLARP.cc @@ -1,5 +1,6 @@ + /* - * $Id: ACLARP.cc,v 1.24 2007/04/28 22:26:37 hno Exp $ + * $Id: ACLARP.cc,v 1.25 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -39,13 +40,14 @@ #include #endif #include "squid.h" +#include "IPAddress.h" #ifdef _SQUID_WIN32_ struct arpreq { - struct sockaddr arp_pa; /* protocol address */ + IPAddress arp_pa; /* protocol address */ struct sockaddr arp_ha; /* hardware address */ int arp_flags; /* flags */ @@ -83,7 +85,7 @@ struct arpreq #endif static void aclParseArpList(SplayNode **curlist); static int decode_eth(const char *asc, char *eth); -static int aclMatchArp(SplayNode **dataptr, struct IN_ADDR c); +static int aclMatchArp(SplayNode **dataptr, IPAddress &c); static SplayNode::SPLAYCMP aclArpCompare; static SplayNode::SPLAYWALKEE aclDumpArpListWalkee; @@ -224,6 +226,13 @@ aclParseArpList(SplayNode **curlist) int ACLARP::match(ACLChecklist *checklist) { + /* IPv6 does not do ARP */ + if(!checklist->src_addr.IsIPv4()) + { + debugs(14, 3, "ACLARP::match: IPv4 Required for ARP Lookups. Skipping " << checklist->src_addr ); + return 0; + } + return aclMatchArp(&data, checklist->src_addr); } @@ -231,13 +240,15 @@ ACLARP::match(ACLChecklist *checklist) /* aclMatchArp */ /***************/ int -aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) +aclMatchArp(SplayNode **dataptr, IPAddress &c) { -#if defined(_SQUID_LINUX_) + char ntoabuf[MAX_IPSTRLEN]; struct arpreq arpReq; - struct sockaddr_in ipAddr; + IPAddress ipAddr = c; + +#if defined(_SQUID_LINUX_) unsigned char ifbuffer[sizeof(struct ifreq) * 64]; @@ -257,15 +268,13 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) * name first. If that does not succeed, the try each interface * in turn */ + /* * Set up structures for ARP lookup with blank interface name */ - ipAddr.sin_family = AF_INET; - ipAddr.sin_port = 0; - ipAddr.sin_addr = c; memset(&arpReq, '\0', sizeof(arpReq)); - xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + ipAddr.GetSockAddr(arpReq.arp_pa); /* Query ARP table */ if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) { @@ -287,7 +296,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) acl_arp_data X; memcpy (X.eth, arpReq.arp_ha.sa_data, 6); *Top = (*Top)->splay(&X, aclArpCompare); - debugs(28, 3, "aclMatchArp: '" << inet_ntoa(c) << "' " << (splayLastResult ? "NOT found" : "found")); + debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found")); return (0 == splayLastResult); } @@ -321,18 +330,13 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) if (NULL != strchr(ifr->ifr_name, ':')) continue; - debugs(28, 4, "Looking up ARP address for " << inet_ntoa(c) << " on " << ifr->ifr_name); + debugs(28, 4, "Looking up ARP address for " << c << " on " << ifr->ifr_name); /* Set up structures for ARP lookup */ - ipAddr.sin_family = AF_INET; - - ipAddr.sin_port = 0; - - ipAddr.sin_addr = c; memset(&arpReq, '\0', sizeof(arpReq)); - xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + ipAddr.GetSockAddr(arpReq.arp_pa); strncpy(arpReq.arp_dev, ifr->ifr_name, sizeof(arpReq.arp_dev) - 1); @@ -377,7 +381,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* Return if match, otherwise continue to other interfaces */ if (0 == splayLastResult) { - debugs(28, 3, "aclMatchArp: " << inet_ntoa(c) << " found on " << ifr->ifr_name); + debugs(28, 3, "aclMatchArp: " << c << " found on " << ifr->ifr_name); return 1; } @@ -389,24 +393,15 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) #elif defined(_SQUID_SOLARIS_) - struct arpreq arpReq; - - struct sockaddr_in ipAddr; - SplayNode **Top = dataptr; /* * Set up structures for ARP lookup with blank interface name */ - ipAddr.sin_family = AF_INET; - - ipAddr.sin_port = 0; - - ipAddr.sin_addr = c; memset(&arpReq, '\0', sizeof(arpReq)); - xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + ipAddr.GetSockAddr(arpReq.arp_pa); /* Query ARP table */ if (ioctl(HttpSockets[0], SIOCGARP, &arpReq) != -1) { @@ -433,17 +428,13 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* Do lookup */ *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare); - debugs(28, 3, "aclMatchArp: '" << inet_ntoa(c) << "' " << (splayLastResult ? "NOT found" : "found")); + debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found")); return (0 == splayLastResult); } #elif defined(_SQUID_FREEBSD_) || defined(_SQUID_NETBSD_) || defined(_SQUID_OPENBSD_) - struct arpreq arpReq; - - struct sockaddr_in ipAddr; - SplayNode **Top = dataptr; int mib[6]; @@ -461,15 +452,10 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* * Set up structures for ARP lookup with blank interface name */ - ipAddr.sin_family = AF_INET; - - ipAddr.sin_port = 0; - - ipAddr.sin_addr = c; memset(&arpReq, '\0', sizeof(arpReq)); - xmemcpy(&arpReq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + ipAddr.GetSockAddr(arpReq.arp_pa); /* Query ARP table */ mib[0] = CTL_NET; @@ -514,7 +500,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) sdl = (struct sockaddr_dl *)((char *) sin + ROUNDUP(sin->sin_len)); - if (c.s_addr == sin->sin_addr.s_addr) { + if (c == sin->sin_addr) { if (sdl->sdl_alen) { arpReq.arp_ha.sa_len = sizeof(struct sockaddr); @@ -542,7 +528,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* Do lookup */ *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare); - debugs(28, 3, "aclMatchArp: '" << inet_ntoa(c) << "' " << (splayLastResult ? "NOT found" : "found")); + debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found")); return (0 == splayLastResult); @@ -558,8 +544,6 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) SplayNode **Top = dataptr; - struct arpreq arpReq; - memset(&arpReq, '\0', sizeof(arpReq)); /* Get size of Windows ARP table */ @@ -583,7 +567,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* Find MAC address from net table */ for (i = 0 ; i < NetTable->dwNumEntries ; i++) { - if ((c.s_addr == NetTable->table[i].dwAddr) && (NetTable->table[i].dwType > 2)) { + if ((c == (struct in_addr)NetTable->table[i].dwAddr) && (NetTable->table[i].dwType > 2)) { arpReq.arp_ha.sa_family = AF_UNSPEC; memcpy(arpReq.arp_ha.sa_data, NetTable->table[i].bPhysAddr, NetTable->table[i].dwPhysAddrLen); } @@ -607,7 +591,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* Do lookup */ *Top = (*Top)->splay((acl_arp_data *)&arpReq.arp_ha.sa_data, aclArpCompare); - debugs(28, 3, "aclMatchArp: '" << inet_ntoa(c) << "' " << (splayLastResult ? "NOT found" : "found")); + debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found")); return (0 == splayLastResult); @@ -619,7 +603,7 @@ aclMatchArp(SplayNode **dataptr, struct IN_ADDR c) /* * Address was not found on any interface */ - debugs(28, 3, "aclMatchArp: " << inet_ntoa(c) << " NOT found"); + debugs(28, 3, "aclMatchArp: " << c << " NOT found"); return 0; } diff --git a/src/ACLASN.h b/src/ACLASN.h index ff1b0b08a3..b1244bc9fc 100644 --- a/src/ACLASN.h +++ b/src/ACLASN.h @@ -1,6 +1,6 @@ /* - * $Id: ACLASN.h,v 1.8 2006/05/29 00:14:59 robertc Exp $ + * $Id: ACLASN.h,v 1.9 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -39,17 +39,18 @@ #include "List.h" #include "ACLStrategised.h" #include "ACLChecklist.h" +#include "IPAddress.h" /* forward decls */ class CacheManager; -SQUIDCEXTERN int asnMatchIp(List *, struct IN_ADDR); +SQUIDCEXTERN int asnMatchIp(List *, IPAddress &); SQUIDCEXTERN void asnInit(void); extern void asnRegisterWithCacheManager(CacheManager & manager); SQUIDCEXTERN void asnFreeMemory(void); -class ACLASN : public ACLData +class ACLASN : public ACLData { public: @@ -57,18 +58,18 @@ public: virtual ~ACLASN(); - virtual bool match(struct IN_ADDR); + virtual bool match(IPAddress); virtual wordlist *dump(); virtual void parse(); bool empty() const; - virtual ACLData *clone() const; + virtual ACLData *clone() const; virtual void prepareForUse(); private: static ACL::Prototype SourceRegistryProtoype; - static ACLStrategised SourceRegistryEntry_; + static ACLStrategised SourceRegistryEntry_; static ACL::Prototype DestinationRegistryProtoype; - static ACLStrategised DestinationRegistryEntry_; + static ACLStrategised DestinationRegistryEntry_; List *data; }; diff --git a/src/ACLChecklist.cc b/src/ACLChecklist.cc index f5d0181949..6db3623669 100644 --- a/src/ACLChecklist.cc +++ b/src/ACLChecklist.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLChecklist.cc,v 1.42 2007/09/01 05:56:37 amosjeffries Exp $ + * $Id: ACLChecklist.cc,v 1.43 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -356,7 +356,9 @@ ACLChecklist::operator delete (void *address) cbdataFree(t); } -ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL), +ACLChecklist::ACLChecklist() : + accessList (NULL), + request (NULL), reply (NULL), auth_user_request (NULL), #if SQUID_SNMP @@ -374,12 +376,9 @@ ACLChecklist::ACLChecklist() : accessList (NULL), my_port (0), request (NULL), sourceDomainChecked_(false), lastACLResult_(false) { - - memset (&src_addr, '\0', sizeof (struct IN_ADDR)); - - memset (&dst_addr, '\0', sizeof (struct IN_ADDR)); - - memset (&my_addr, '\0', sizeof (struct IN_ADDR)); + my_addr.SetEmpty(); + src_addr.SetEmpty(); + dst_addr.SetEmpty(); rfc931[0] = '\0'; } @@ -399,6 +398,7 @@ ACLChecklist::~ACLChecklist() * If this fails, then we'll need a backup UNLOCK call in the * destructor. */ + /* AYJ: It fails in builds without any Authentication configured */ assert(auth_user_request == NULL); conn_ = NULL; @@ -573,7 +573,6 @@ aclChecklistCreate(const acl_access * A, HttpRequest * request, const char *iden checklist->request = HTTPMSGLOCK(request); checklist->src_addr = request->client_addr; checklist->my_addr = request->my_addr; - checklist->my_port = request->my_port; } #if USE_IDENT diff --git a/src/ACLChecklist.h b/src/ACLChecklist.h index 1862bab7e8..8746925b1f 100644 --- a/src/ACLChecklist.h +++ b/src/ACLChecklist.h @@ -1,6 +1,6 @@ /* - * $Id: ACLChecklist.h,v 1.28 2007/09/01 05:56:37 amosjeffries Exp $ + * $Id: ACLChecklist.h,v 1.29 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -115,12 +115,12 @@ class NullState : public AsyncState const acl_access *accessList; - struct IN_ADDR src_addr; + IPAddress src_addr; - struct IN_ADDR dst_addr; + IPAddress dst_addr; + + IPAddress my_addr; - struct IN_ADDR my_addr; - unsigned short my_port; HttpRequest *request; /* for acls that look at reply data */ HttpReply *reply; diff --git a/src/ACLDestinationASN.h b/src/ACLDestinationASN.h index 02e19e843e..9ef42d62b4 100644 --- a/src/ACLDestinationASN.h +++ b/src/ACLDestinationASN.h @@ -1,6 +1,6 @@ /* - * $Id: ACLDestinationASN.h,v 1.2 2005/04/18 21:52:41 hno Exp $ + * $Id: ACLDestinationASN.h,v 1.3 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,8 +37,9 @@ #define SQUID_ACLDESTINATIONASN_H #include "ACLASN.h" #include "ACLStrategy.h" +#include "IPAddress.h" -class ACLDestinationASNStrategy : public ACLStrategy +class ACLDestinationASNStrategy : public ACLStrategy { public: diff --git a/src/ACLDestinationDomain.cc b/src/ACLDestinationDomain.cc index 68739f53bb..51208e5726 100644 --- a/src/ACLDestinationDomain.cc +++ b/src/ACLDestinationDomain.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLDestinationDomain.cc,v 1.15 2007/11/03 04:49:53 wessels Exp $ + * $Id: ACLDestinationDomain.cc,v 1.16 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -79,10 +79,11 @@ ACLDestinationDomainStrategy::match (ACLData * &data, ACLChecklist *c const ipcache_addrs *ia = NULL; const char *fqdn = NULL; - if (data->match(checklist->request->host)) + if (data->match(checklist->request->GetHost())) return 1; - if ((ia = ipcacheCheckNumeric(checklist->request->host)) == NULL) + /* numeric IPA? */ + if ((ia = ipcacheCheckNumeric(checklist->request->GetHost())) == NULL) return 0; checklist->dst_addr = ia->in_addrs[0]; @@ -92,7 +93,7 @@ ACLDestinationDomainStrategy::match (ACLData * &data, ACLChecklist *c return data->match(fqdn); } else if (!checklist->destinationDomainChecked()) { /* FIXME: Using AclMatchedName here is not OO correct. Should find a way to the current acl */ - debugs(28, 3, "aclMatchAcl: Can't yet compare '" << AclMatchedName << "' ACL for '" << checklist->request->host << "'"); + debugs(28, 3, "aclMatchAcl: Can't yet compare '" << AclMatchedName << "' ACL for '" << checklist->request->GetHost() << "'"); checklist->changeState(DestinationDomainLookup::Instance()); return 0; } diff --git a/src/ACLDestinationIP.cc b/src/ACLDestinationIP.cc index e16a70ae2a..4f0042e2fd 100644 --- a/src/ACLDestinationIP.cc +++ b/src/ACLDestinationIP.cc @@ -47,7 +47,7 @@ ACLDestinationIP::typeString() const int ACLDestinationIP::match(ACLChecklist *checklist) { - const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->host, IP_LOOKUP_IF_MISS); + const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->GetHost(), IP_LOOKUP_IF_MISS); if (ia) { /* Entry in cache found */ @@ -60,7 +60,7 @@ ACLDestinationIP::match(ACLChecklist *checklist) return 0; } else if (!checklist->request->flags.destinationIPLookedUp()) { /* No entry in cache, lookup not attempted */ - debugs(28, 3, "aclMatchAcl: Can't yet compare '" << name << "' ACL for '" << checklist->request->host << "'"); + debugs(28, 3, "aclMatchAcl: Can't yet compare '" << name << "' ACL for '" << checklist->request->GetHost() << "'"); checklist->changeState (DestinationIPLookup::Instance()); return 0; } else { @@ -80,7 +80,7 @@ void DestinationIPLookup::checkForAsync(ACLChecklist *checklist)const { checklist->asyncInProgress(true); - ipcache_nbgethostbyname(checklist->request->host, LookupDone, checklist); + ipcache_nbgethostbyname(checklist->request->GetHost(), LookupDone, checklist); } void diff --git a/src/ACLIP.cc b/src/ACLIP.cc index 6bc249221e..1780ba646c 100644 --- a/src/ACLIP.cc +++ b/src/ACLIP.cc @@ -55,16 +55,17 @@ ACLIP::operator delete (void *address) void ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state) { + char tmpbuf[MAX_IPSTRLEN]; MemBuf mb; wordlist **W = static_cast(state); mb.init(); - mb.Printf("%s", inet_ntoa(ip->addr1)); + mb.Printf("%s", ip->addr1.NtoA(tmpbuf,MAX_IPSTRLEN)); - if (ip->addr2.s_addr != any_addr.s_addr) - mb.Printf("-%s", inet_ntoa(ip->addr2)); + if (!ip->addr2.IsAnyAddr()) + mb.Printf("-%s", ip->addr2.NtoA(tmpbuf,MAX_IPSTRLEN)); - if (ip->mask.s_addr != no_addr.s_addr) - mb.Printf("/%s", inet_ntoa(ip->mask)); + if (!ip->mask.IsNoAddr()) + mb.Printf("/%s", ip->mask.NtoA(tmpbuf,MAX_IPSTRLEN)); wordlistAdd(W, mb.buf); @@ -78,22 +79,33 @@ ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state) void acl_ip_data::toStr(char *buf, int len) const { - char b1[20]; - char b2[20]; - char b3[20]; - snprintf(b1, 20, "%s", inet_ntoa(addr1)); + char *b1 = buf; + char *b2 = NULL; + char *b3 = NULL; + int rlen = 0; - if (addr2.s_addr != any_addr.s_addr) - snprintf(b2, 20, "-%s", inet_ntoa(addr2)); + addr1.NtoA(b1, len - rlen ); + rlen = strlen(buf); + b2 = buf + rlen; + + if (!addr2.IsAnyAddr()) + { + b2[0] = '-'; rlen++; + addr2.NtoA(&(b2[1]), len - rlen ); + rlen = strlen(buf); + } else b2[0] = '\0'; - if (mask.s_addr != no_addr.s_addr) - snprintf(b3, 20, "/%s", inet_ntoa(mask)); + b3 = buf + rlen; + + if (!mask.IsNoAddr()) + { + b3[0] = '/'; rlen++; + mask.NtoA(&(b3[1]), len - rlen ); + } else b3[0] = '\0'; - - snprintf(buf, len, "%s%s%s", b1, b2, b3); } /* @@ -106,30 +118,21 @@ acl_ip_data::toStr(char *buf, int len) const int aclIpAddrNetworkCompare(acl_ip_data * const &p, acl_ip_data * const &q) { + IPAddress A = p->addr1; - struct IN_ADDR A = p->addr1; + /* apply netmask */ + A.ApplyMask(q->mask); - const struct IN_ADDR B = q->addr1; + if (q->addr2.IsAnyAddr()) { /* single address check */ - const struct IN_ADDR C = q->addr2; - A.s_addr &= q->mask.s_addr; /* apply netmask */ + return A.matchIPAddr( q->addr1 ); - if (C.s_addr == 0) { /* single address check */ + } else { /* range address check */ - if (ntohl(A.s_addr) > ntohl(B.s_addr)) - return 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - return -1; + if ( (A >= q->addr1) && (A <= q->addr2) ) + return 0; /* valid. inside range. */ else - return 0; - } else { /* range address check */ - - if (ntohl(A.s_addr) > ntohl(C.s_addr)) - return 1; - else if (ntohl(A.s_addr) < ntohl(B.s_addr)) - return -1; - else - return 0; + return A.matchIPAddr( q->addr1 ); /* outside of range, 'less than' */ } } @@ -147,26 +150,27 @@ int acl_ip_data::NetworkCompare(acl_ip_data * const & a, acl_ip_data * const &b) { int ret; + bool bina = true; ret = aclIpAddrNetworkCompare(b, a); if (ret != 0) { + bina = false; ret = aclIpAddrNetworkCompare(a, b); } if (ret == 0) { - char buf_n1[60]; - char buf_n2[60]; - char buf_a[60]; - b->toStr(buf_n1, 60); - a->toStr(buf_n2, 60); - a->toStr(buf_a, 60); - /* TODO: this warning may display the wrong way around */ - debugs(28, 0, "WARNING: '" << buf_n1 << - "' is a subnetwork of '" << buf_n2 << "'"); - debugs(28, 0, "WARNING: because of this '" << buf_a << - "' is ignored to keep splay tree searching predictable"); - debugs(28, 0, "WARNING: You should probably remove '" << buf_n1 << - "' from the ACL named '" << AclMatchedName << "'"); + char buf_n1[3*(MAX_IPSTRLEN+1)]; + char buf_n2[3*(MAX_IPSTRLEN+1)]; + if(bina) { + b->toStr(buf_n1, 3*(MAX_IPSTRLEN+1)); + a->toStr(buf_n2, 3*(MAX_IPSTRLEN+1)); + } else { + a->toStr(buf_n1, 3*(MAX_IPSTRLEN+1)); + b->toStr(buf_n2, 3*(MAX_IPSTRLEN+1)); + } + debugs(28, 0, "WARNING: (" << (bina?'B':'A') << ") '" << buf_n1 << "' is a subnetwork of (" << (bina?'A':'B') << ") '" << buf_n2 << "'"); + debugs(28, 0, "WARNING: because of this '" << (bina?buf_n2:buf_n1) << "' is ignored to keep splay tree searching predictable"); + debugs(28, 0, "WARNING: You should probably remove '" << buf_n1 << "' from the ACL named '" << AclMatchedName << "'"); } return ret; @@ -178,138 +182,221 @@ acl_ip_data::NetworkCompare(acl_ip_data * const & a, acl_ip_data * const &b) * This function should NOT be called if 'asc' is a hostname! */ bool -acl_ip_data::DecodeMask(const char *asc, struct IN_ADDR *mask) +acl_ip_data::DecodeMask(const char *asc, IPAddress &mask, int ctype) { char junk; int a1 = 0; + /* default is a mask that doesn't change any IP */ + mask.SetNoAddr(); + if (!asc || !*asc) { - mask->s_addr = htonl(0xFFFFFFFFul); return true; } - if (sscanf(asc, "%d%c", &a1, &junk) == 1 && a1 >= 0 && a1 < 33) - { /* a significant bits value for a mask */ - mask->s_addr = a1 ? htonl(0xfffffffful << (32 - a1)) : 0; - return true; + /* An int mask 128, 32 */ + if ((sscanf(asc, "%d%c", &a1, &junk)==1) && + (a1 <= 128) && (a1 >= 0) + ) + { + return mask.ApplyMask(a1, ctype); } /* dotted notation */ - if (safe_inet_addr(asc, mask)) + /* assignment returns true if asc contained an IP address as text */ + if ((mask = asc)) return true; return false; } -#define SCAN_ACL1 "%[0123456789.]-%[0123456789.]/%[0123456789.]" -#define SCAN_ACL2 "%[0123456789.]-%[0123456789.]%c" -#define SCAN_ACL3 "%[0123456789.]/%[0123456789.]" -#define SCAN_ACL4 "%[0123456789.]%c" +/* Handle either type of address, IPv6 will be discarded with a warning if disabled */ +#define SCAN_ACL1_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]/%[0123456789]" +#define SCAN_ACL2_6 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]%c" +#define SCAN_ACL3_6 "%[0123456789ABCDEFabcdef:]/%[0123456789]" +#define SCAN_ACL4_6 "%[0123456789ABCDEFabcdef:]/%c" +/* We DO need to know which is which though, for proper CIDR masking. */ +#define SCAN_ACL1_4 "%[0123456789.]-%[0123456789.]/%[0123456789.]" +#define SCAN_ACL2_4 "%[0123456789.]-%[0123456789.]%c" +#define SCAN_ACL3_4 "%[0123456789.]/%[0123456789.]" +#define SCAN_ACL4_4 "%[0123456789.]/%c" acl_ip_data * acl_ip_data::FactoryParse(const char *t) { + LOCAL_ARRAY(char, addr1, 256); LOCAL_ARRAY(char, addr2, 256); LOCAL_ARRAY(char, mask, 256); - acl_ip_data *r; - acl_ip_data **Q; - char **x; + acl_ip_data *r = NULL; + acl_ip_data **Q = NULL; + IPAddress temp; char c; - debugs(28, 5, "aclParseIpData: " << t); + unsigned int changed; acl_ip_data *q = new acl_ip_data; + int iptype = AF_UNSPEC; + + debugs(28, 5, "aclIpParseIpData: " << t); - if (!strcasecmp(t, "all")) { - q->addr1.s_addr = 0; - q->addr2.s_addr = 0; - q->mask.s_addr = 0; + /* Special ACL RHS "all" matches entire Internet */ + if (strcasecmp(t, "all") == 0) { + q->addr1.SetAnyAddr(); + q->addr2.SetEmpty(); + q->mask.SetAnyAddr(); return q; } - LOCAL_ARRAY(char, addr1, 256); +#if USE_IPV6 + /* Special ACL RHS "ipv6" matches IPv6-Unicast Internet */ + if (strcasecmp(t, "ipv6") == 0) { + t = "2000::/3"; + } +#endif - if (sscanf(t, SCAN_ACL1, addr1, addr2, mask) == 3) { - (void) 0; - } else if (sscanf(t, SCAN_ACL2, addr1, addr2, &c) == 2) { +// IPv4 + if (sscanf(t, SCAN_ACL1_4, addr1, addr2, mask) == 3) { + iptype=AF_INET; + } else if (sscanf(t, SCAN_ACL2_4, addr1, addr2, &c) >= 2) { mask[0] = '\0'; - } else if (sscanf(t, SCAN_ACL3, addr1, mask) == 2) { + iptype=AF_INET; + } else if (sscanf(t, SCAN_ACL3_4, addr1, mask) == 2) { addr2[0] = '\0'; - } else if (sscanf(t, SCAN_ACL4, addr1, &c) == 1) { - addr2[0] = '\0'; - mask[0] = '\0'; + iptype=AF_INET; + } else if (sscanf(t, SCAN_ACL4_4, addr1,&c) == 2) { + addr2[0] = '\0'; + mask[0] = '\0'; + iptype=AF_INET; + +// IPv6 + } else if (sscanf(t, SCAN_ACL1_6, addr1, addr2, mask) == 3) { + iptype=AF_INET6; + } else if (sscanf(t, SCAN_ACL2_6, addr1, addr2, &c) >= 2) { + mask[0] = '\0'; + iptype=AF_INET6; + } else if (sscanf(t, SCAN_ACL3_6, addr1, mask) == 2) { + addr2[0] = '\0'; + iptype=AF_INET6; + } else if (sscanf(t, SCAN_ACL4_6, addr1, mask) == 2) { + addr2[0] = '\0'; + iptype=AF_INET6; + +// Neither } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) { addr2[0] = '\0'; } else if (sscanf(t, "%s", addr1) == 1) { - /* - * Note, must use plain gethostbyname() here because at startup + * Note, must use plain xgetaddrinfo() here because at startup * ipcache hasn't been initialized + * TODO: offload this to one of the IPAddress lookups. */ - struct hostent *hp; + debugs(28, 5, "aclIpParseIpData: Lookup Host/IP " << addr1); + struct addrinfo *hp = NULL, *x = NULL; + struct addrinfo hints; + IPAddress *prev_addr = NULL; + + memset(&hints, 0, sizeof(struct addrinfo)); + + if( iptype != AF_UNSPEC ) { + hints.ai_flags |= AI_NUMERICHOST; + } + +#if 0 && USE_IPV6 && !IPV6_SPECIAL_SPLITSTACK + hints.ai_flags |= AI_V4MAPPED | AI_ALL; +#endif - if ((hp = gethostbyname(addr1)) == NULL) { - debugs(28, 0, "aclParseIpData: Bad host/IP: '" << t << "'"); + int errcode = xgetaddrinfo(addr1,NULL,&hints,&hp); + if (hp == NULL) { + debugs(28, 0, "aclIpParseIpData: Bad host/IP: '" << addr1 << + "' in '" << t << "', flags=" << hints.ai_flags << + " : (" << errcode << ") " << xgai_strerror(errcode) ); self_destruct(); + return NULL; } Q = &q; - for (x = hp->h_addr_list; x != NULL && *x != NULL; x++) { + for (x = hp; x != NULL;) { if ((r = *Q) == NULL) r = *Q = new acl_ip_data; - xmemcpy(&r->addr1.s_addr, *x, sizeof(r->addr1.s_addr)); + /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */ + /* BUT sorted fortunately, so we can drop most of them easily */ + r->addr1 = *x; + x = x->ai_next; + if( prev_addr && r->addr1 == *prev_addr) { + debugs(28, 3, "aclIpParseIpData: Duplicate host/IP: '" << r->addr1 << "' dropped."); + delete r; + *Q = NULL; + continue; + } + else + prev_addr = &r->addr1; + + debugs(28, 3, "aclIpParseIpData: Located host/IP: '" << r->addr1 << "'"); - r->addr2.s_addr = 0; - DecodeMask(NULL, &r->mask); + r->addr2.SetAnyAddr(); + r->mask.SetNoAddr(); Q = &r->next; - debugs(28, 3, "" << addr1 << " --> " << inet_ntoa(r->addr1)); + debugs(28, 3, "" << addr1 << " --> " << r->addr1 ); } if (*Q != NULL) { - debugs(28, 0, "aclParseIpData: Bad host/IP: '" << t << "'"); + debugs(28, 0, "aclIpParseIpData: Bad host/IP: '" << t << "'"); self_destruct(); + return NULL; } + xfreeaddrinfo(hp); + return q; } +#if !USE_IPV6 + /* ignore IPv6 addresses when built with IPv4-only */ + if( iptype == AF_INET6 ) { + debugs(28, 0, "aclIpParseIpData: IPv6 has not been enabled. build with '--enable-ipv6'"); + return NULL; + } +#endif + /* Decode addr1 */ - if (!safe_inet_addr(addr1, &q->addr1)) { - debugs(28, 0, "aclParseIpData: unknown first address in '" << t << "'"); + if (!*addr1) { + debugs(28, 0, "aclIpParseIpData: unknown first address in '" << t << "'"); delete q; self_destruct(); return NULL; } + else q->addr1 = addr1; /* Decode addr2 */ - if (*addr2 && !safe_inet_addr(addr2, &q->addr2)) { - debugs(28, 0, "aclParseIpData: unknown second address in '" << t << "'"); + if (*addr2 && !(q->addr2=addr2) ) { + debugs(28, 0, "aclIpParseIpData: unknown second address in '" << t << "'"); delete q; self_destruct(); return NULL; } + else q->addr2 = addr2; /* Decode mask (NULL or empty means a exact host mask) */ - if (!DecodeMask(mask, &q->mask)) { + if (!DecodeMask(mask, q->mask, iptype)) { debugs(28, 0, "aclParseIpData: unknown netmask '" << mask << "' in '" << t << "'"); delete q; self_destruct(); return NULL; } - if ((q->addr1.s_addr & q->mask.s_addr) != q->addr1.s_addr || - (q->addr2.s_addr & q->mask.s_addr) != q->addr2.s_addr) - debugs(28, 0, "aclParseIpData: WARNING: Netmask masks away part of the specified IP in '" << t << "'"); - - q->addr1.s_addr &= q->mask.s_addr; + changed = 0; + changed += q->addr1.ApplyMask(q->mask); + changed += q->addr2.ApplyMask(q->mask); - q->addr2.s_addr &= q->mask.s_addr; + if (changed) + debugs(28, 0, "aclIpParseIpData: WARNING: Netmask masks away part of the specified IP in '" << t << "'"); /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */ + /* Same as IPv6 (not so trivial to depict) */ return q; } @@ -349,24 +436,24 @@ ACLIP::empty () const } int - -ACLIP::match(struct IN_ADDR &clientip) +ACLIP::match(IPAddress &clientip) { - static acl_ip_data ClientAddress (any_addr, any_addr, no_addr, NULL); + static acl_ip_data ClientAddress; /* * aclIpAddrNetworkCompare() takes two acl_ip_data pointers as * arguments, so we must create a fake one for the client's IP - * address, and use a /32 netmask. However, the current code - * probably only accesses the addr1 element of this argument, - * so it might be possible to leave addr2 and mask unset. + * address. Since we are scanning for a single IP mask and addr2 + * MUST be set to empty. */ ClientAddress.addr1 = clientip; - acl_ip_data *ClientAddressPointer = &ClientAddress; - data = data->splay(ClientAddressPointer, aclIpAddrNetworkCompare); - debugs(28, 3, "aclMatchIp: '" << inet_ntoa(clientip) << "' " << (splayLastResult ? "NOT found" : "found")); + ClientAddress.addr2.SetEmpty(); + ClientAddress.mask.SetEmpty(); + + data = data->splay(&ClientAddress, aclIpAddrNetworkCompare); + debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (splayLastResult ? "NOT found" : "found")); return !splayLastResult; } -acl_ip_data::acl_ip_data () :addr1(any_addr), addr2(any_addr), mask (any_addr), next (NULL) {} +acl_ip_data::acl_ip_data () :addr1(), addr2(), mask(), next (NULL) {} -acl_ip_data::acl_ip_data (struct IN_ADDR const &anAddress1, struct IN_ADDR const &anAddress2, struct IN_ADDR const &aMask, acl_ip_data *aNext) : addr1(anAddress1), addr2(anAddress2), mask(aMask), next(aNext){} +acl_ip_data::acl_ip_data (IPAddress const &anAddress1, IPAddress const &anAddress2, IPAddress const &aMask, acl_ip_data *aNext) : addr1(anAddress1), addr2(anAddress2), mask(aMask), next(aNext){} diff --git a/src/ACLIP.h b/src/ACLIP.h index 891b30073d..e1d25e4f2e 100644 --- a/src/ACLIP.h +++ b/src/ACLIP.h @@ -37,6 +37,7 @@ #define SQUID_ACLIP_H #include "ACL.h" #include "splay.h" +#include "IPAddress.h" class acl_ip_data { @@ -48,19 +49,20 @@ public: acl_ip_data (); - acl_ip_data (struct IN_ADDR const &, struct IN_ADDR const &, struct IN_ADDR const &, acl_ip_data *); + acl_ip_data (IPAddress const &, IPAddress const &, IPAddress const &, acl_ip_data *); void toStr(char *buf, int len) const; - struct IN_ADDR addr1; /* if addr2 non-zero then its a range */ + IPAddress addr1; - struct IN_ADDR addr2; + IPAddress addr2; + + IPAddress mask; /* This should perhapse be stored as a CIDR range now instead of a full IP mask. */ - struct IN_ADDR mask; acl_ip_data *next; /* used for parsing, not for storing */ private: - static bool DecodeMask(const char *asc, struct IN_ADDR *mask); + static bool DecodeMask(const char *asc, IPAddress &mask, int string_format_type); }; MEMPROXY_CLASS_INLINE(acl_ip_data) @@ -87,7 +89,7 @@ public: protected: - int match(struct IN_ADDR &); + int match(IPAddress &); IPSplay *data; private: diff --git a/src/ACLIdent.cc b/src/ACLIdent.cc index e9c2ad1a3b..da842b0824 100644 --- a/src/ACLIdent.cc +++ b/src/ACLIdent.cc @@ -128,7 +128,7 @@ IdentLookup::checkForAsync(ACLChecklist *checklist)const if (checklist->conn() != NULL) { debugs(28, 3, "IdentLookup::checkForAsync: Doing ident lookup" ); checklist->asyncInProgress(true); - identStart(&checklist->conn()->me, &checklist->conn()->peer, + identStart(checklist->conn()->me, checklist->conn()->peer, LookupDone, checklist); } else { debugs(28, 1, "IdentLookup::checkForAsync: Can't start ident lookup. No client connection" ); diff --git a/src/ACLMaxUserIP.cc b/src/ACLMaxUserIP.cc index b5fac9baa6..992ca0ebd6 100644 --- a/src/ACLMaxUserIP.cc +++ b/src/ACLMaxUserIP.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLMaxUserIP.cc,v 1.14 2007/05/09 07:36:24 wessels Exp $ + * $Id: ACLMaxUserIP.cc,v 1.15 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -117,7 +117,7 @@ ACLMaxUserIP::parse() int ACLMaxUserIP::match(AuthUserRequest * auth_user_request, - struct IN_ADDR const &src_addr) + IPAddress const &src_addr) { /* * the logic for flush the ip list when the limit is hit vs keep diff --git a/src/ACLMaxUserIP.h b/src/ACLMaxUserIP.h index 3a4b8d6db2..ddf7a6bf30 100644 --- a/src/ACLMaxUserIP.h +++ b/src/ACLMaxUserIP.h @@ -1,6 +1,6 @@ /* - * $Id: ACLMaxUserIP.h,v 1.9 2007/05/09 07:36:24 wessels Exp $ + * $Id: ACLMaxUserIP.h,v 1.10 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -66,7 +66,7 @@ private: static Prototype RegistryProtoype; static ACLMaxUserIP RegistryEntry_; - int match(AuthUserRequest *, struct IN_ADDR const &); + int match(AuthUserRequest *, IPAddress const &); char const *class_; int maximum; diff --git a/src/ACLMyPort.cc b/src/ACLMyPort.cc index d3f7796134..99e42a2147 100644 --- a/src/ACLMyPort.cc +++ b/src/ACLMyPort.cc @@ -1,6 +1,6 @@ /* - * $Id: ACLMyPort.cc,v 1.2 2003/10/20 12:33:01 robertc Exp $ + * $Id: ACLMyPort.cc,v 1.3 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -51,7 +51,7 @@ ACLStrategised ACLMyPort::RegistryEntry_(new ACLIntRange, ACLMyPortStrategy int ACLMyPortStrategy::match (ACLData * &data, ACLChecklist *checklist) { - return data->match (checklist->my_port); + return data->match (checklist->my_addr.GetPort()); } ACLMyPortStrategy * diff --git a/src/ACLSourceASN.h b/src/ACLSourceASN.h index 7205c2e7c2..f25b2c1d97 100644 --- a/src/ACLSourceASN.h +++ b/src/ACLSourceASN.h @@ -1,6 +1,6 @@ /* - * $Id: ACLSourceASN.h,v 1.2 2005/04/18 21:52:41 hno Exp $ + * $Id: ACLSourceASN.h,v 1.3 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,8 +37,9 @@ #define SQUID_ACLSOURCEASN_H #include "ACLASN.h" #include "ACLStrategy.h" +#include "IPAddress.h" -class ACLSourceASNStrategy : public ACLStrategy +class ACLSourceASNStrategy : public ACLStrategy { public: diff --git a/src/ACLSourceDomain.cc b/src/ACLSourceDomain.cc index 8e544da4b8..da6b9f86e7 100644 --- a/src/ACLSourceDomain.cc +++ b/src/ACLSourceDomain.cc @@ -1,5 +1,5 @@ /* - * $Id: ACLSourceDomain.cc,v 1.6 2007/09/21 11:41:52 amosjeffries Exp $ + * $Id: ACLSourceDomain.cc,v 1.7 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -82,7 +82,7 @@ ACLSourceDomainStrategy::match (ACLData * &data, ACLChecklist *checkl return data->match(fqdn); } else if (!checklist->sourceDomainChecked()) { /* FIXME: Using AclMatchedName here is not OO correct. Should find a way to the current acl */ - debugs(28, 3, "aclMatchAcl: Can't yet compare '" << AclMatchedName << "' ACL for '" << inet_ntoa(checklist->src_addr) << "'"); + debugs(28, 3, "aclMatchAcl: Can't yet compare '" << AclMatchedName << "' ACL for '" << checklist->src_addr << "'"); checklist->changeState(SourceDomainLookup::Instance()); return 0; } diff --git a/src/AccessLogEntry.h b/src/AccessLogEntry.h index bb4408294e..6e53672595 100644 --- a/src/AccessLogEntry.h +++ b/src/AccessLogEntry.h @@ -1,6 +1,6 @@ /* - * $Id: AccessLogEntry.h,v 1.6 2007/08/13 17:20:51 hno Exp $ + * $Id: AccessLogEntry.h,v 1.7 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,6 +37,7 @@ #include "HttpVersion.h" #include "HierarchyLogEntry.h" +#include "IPAddress.h" /* forward decls */ @@ -79,7 +80,8 @@ public: { public: - CacheDetails() : size(0), + CacheDetails() : caddr(), + size(0), highOffset(0), objectSize(0), code (LOG_TAG_NONE), @@ -91,10 +93,10 @@ public: ,ssluser(NULL) #endif { - memset(&caddr, '\0', sizeof(caddr)); + ; } - struct IN_ADDR caddr; + IPAddress caddr; int64_t size; int64_t highOffset; int64_t objectSize; diff --git a/src/AuthUser.cc b/src/AuthUser.cc index 81cbe22d90..b0d49cface 100644 --- a/src/AuthUser.cc +++ b/src/AuthUser.cc @@ -1,6 +1,6 @@ /* - * $Id: AuthUser.cc,v 1.9 2007/05/29 13:31:36 amosjeffries Exp $ + * $Id: AuthUser.cc,v 1.10 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Robert Collins @@ -240,7 +240,7 @@ AuthUser::clearIp() } void -AuthUser::removeIp(struct IN_ADDR ipaddr) +AuthUser::removeIp(IPAddress ipaddr) { auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head; @@ -248,7 +248,7 @@ AuthUser::removeIp(struct IN_ADDR ipaddr) { /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { + if (ipdata->ipaddr == ipaddr) { /* remove the node */ dlinkDelete(&ipdata->node, &ip_list); cbdataFree(ipdata); @@ -264,10 +264,9 @@ AuthUser::removeIp(struct IN_ADDR ipaddr) } void -AuthUser::addIp(struct IN_ADDR ipaddr) +AuthUser::addIp(IPAddress ipaddr) { auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head; - char *ip1; int found = 0; CBDATA_INIT_TYPE(auth_user_ip_t); @@ -282,8 +281,8 @@ AuthUser::addIp(struct IN_ADDR ipaddr) auth_user_ip_t *tempnode = (auth_user_ip_t *) ipdata->node.next; /* walk the ip list */ - if (ipdata->ipaddr.s_addr == ipaddr.s_addr) { - /* This ip has alreadu been seen. */ + if (ipdata->ipaddr == ipaddr) { + /* This ip has already been seen. */ found = 1; /* update IP ttl */ ipdata->ip_expiretime = squid_curtime; @@ -313,11 +312,7 @@ AuthUser::addIp(struct IN_ADDR ipaddr) ipcount++; - ip1 = xstrdup(inet_ntoa(ipaddr)); - - debugs(29, 2, "authenticateAuthUserAddIp: user '" << username() << "' has been seen at a new IP address (" << ip1 << ")"); - - safe_free(ip1); + debugs(29, 2, "authenticateAuthUserAddIp: user '" << username() << "' has been seen at a new IP address (" << ipaddr << ")"); } diff --git a/src/AuthUser.h b/src/AuthUser.h index 8fa993625b..6fe668fdfa 100644 --- a/src/AuthUser.h +++ b/src/AuthUser.h @@ -1,6 +1,6 @@ /* - * $Id: AuthUser.h,v 1.5 2007/05/09 08:26:57 wessels Exp $ + * $Id: AuthUser.h,v 1.6 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -35,6 +35,8 @@ #ifndef SQUID_AUTHUSER_H #define SQUID_AUTHUSER_H +#include "IPAddress.h" + class AuthUserRequest; class AuthUser @@ -70,8 +72,8 @@ public: _SQUID_INLINE_ char const *username() const; _SQUID_INLINE_ void username(char const *); void clearIp(); - void removeIp(struct IN_ADDR); - void addIp(struct IN_ADDR); + void removeIp(IPAddress); + void addIp(IPAddress); _SQUID_INLINE_ void addRequest(AuthUserRequest *); void lock() diff --git a/src/AuthUserRequest.cc b/src/AuthUserRequest.cc index 51204796be..51bcf0b156 100644 --- a/src/AuthUserRequest.cc +++ b/src/AuthUserRequest.cc @@ -1,6 +1,6 @@ /* - * $Id: AuthUserRequest.cc,v 1.17 2007/08/28 22:35:29 hno Exp $ + * $Id: AuthUserRequest.cc,v 1.18 2007/12/14 23:11:45 amosjeffries Exp $ * * DO NOT MODIFY NEXT 2 LINES: * arch-tag: 6803fde1-d5a2-4c29-9034-1c0c9f650eb4 @@ -200,7 +200,7 @@ AuthUserRequest::denyMessage(char const * const default_message) } static void -authenticateAuthUserRequestSetIp(AuthUserRequest * auth_user_request, struct IN_ADDR ipaddr) +authenticateAuthUserRequestSetIp(AuthUserRequest * auth_user_request, IPAddress &ipaddr) { auth_user_t *auth_user = auth_user_request->user(); @@ -211,7 +211,7 @@ authenticateAuthUserRequestSetIp(AuthUserRequest * auth_user_request, struct IN_ } void -authenticateAuthUserRequestRemoveIp(AuthUserRequest * auth_user_request, struct IN_ADDR ipaddr) +authenticateAuthUserRequestRemoveIp(AuthUserRequest * auth_user_request, IPAddress const &ipaddr) { auth_user_t *auth_user = auth_user_request->user(); @@ -329,7 +329,7 @@ authTryGetUser (AuthUserRequest **auth_user_request, ConnStateData::Pointer & co */ auth_acl_t -AuthUserRequest::authenticate(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct IN_ADDR src_addr) +AuthUserRequest::authenticate(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, IPAddress &src_addr) { const char *proxy_auth; assert(headertype != 0); @@ -402,7 +402,7 @@ AuthUserRequest::authenticate(AuthUserRequest ** auth_user_request, http_hdr_typ debugs(29, 1, "authenticateAuthenticate: Unexpected change of authentication scheme from '" << conn->auth_user_request->user()->config->type() << "' to '" << proxy_auth << "' (client " << - inet_ntoa(src_addr) << ")"); + src_addr << ")"); AUTHUSERREQUESTUNLOCK(conn->auth_user_request, "conn"); conn->auth_type = AUTH_UNKNOWN; @@ -508,7 +508,7 @@ AuthUserRequest::authenticate(AuthUserRequest ** auth_user_request, http_hdr_typ auth_acl_t -AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct IN_ADDR src_addr) +AuthUserRequest::tryToAuthenticateAndSetAuthUser(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, IPAddress &src_addr) { /* If we have already been called, return the cached value */ AuthUserRequest *t = authTryGetUser (auth_user_request, conn, request); diff --git a/src/AuthUserRequest.h b/src/AuthUserRequest.h index ff0534f223..0089d76d08 100644 --- a/src/AuthUserRequest.h +++ b/src/AuthUserRequest.h @@ -1,6 +1,6 @@ /* - * $Id: AuthUserRequest.h,v 1.6 2007/05/09 09:07:38 wessels Exp $ + * $Id: AuthUserRequest.h,v 1.7 2007/12/14 23:11:45 amosjeffries Exp $ * * DO NOT MODIFY NEXT 2 LINES: * arch-tag: 674533af-8b21-4641-b71a-74c4639072a0 @@ -49,7 +49,7 @@ struct AuthUserIP dlink_node node; /* IP addr this user authenticated from */ - struct IN_ADDR ipaddr; + IPAddress ipaddr; time_t ip_expiretime; }; @@ -78,7 +78,7 @@ public: virtual void user (AuthUser *aUser) {_auth_user=aUser;} - static auth_acl_t tryToAuthenticateAndSetAuthUser(AuthUserRequest **, http_hdr_type, HttpRequest *, ConnStateData::Pointer, struct IN_ADDR); + static auth_acl_t tryToAuthenticateAndSetAuthUser(AuthUserRequest **, http_hdr_type, HttpRequest *, ConnStateData::Pointer, IPAddress &); static void addReplyAuthHeader(HttpReply * rep, AuthUserRequest * auth_user_request, HttpRequest * request, int accelerated, int internal); AuthUserRequest(); @@ -105,7 +105,7 @@ public: private: - static auth_acl_t authenticate(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, struct IN_ADDR src_addr); + static auth_acl_t authenticate(AuthUserRequest ** auth_user_request, http_hdr_type headertype, HttpRequest * request, ConnStateData::Pointer conn, IPAddress &src_addr); /* return a message on the 407 error pages */ char *message; @@ -126,7 +126,7 @@ extern size_t authenticateRequestRefCount (AuthUserRequest *); extern void authenticateFixHeader(HttpReply *, AuthUserRequest *, HttpRequest *, int, int); extern void authenticateAddTrailer(HttpReply *, AuthUserRequest *, HttpRequest *, int); -extern void authenticateAuthUserRequestRemoveIp(AuthUserRequest *, struct IN_ADDR); +extern void authenticateAuthUserRequestRemoveIp(AuthUserRequest *, IPAddress const &); extern void authenticateAuthUserRequestClearIp(AuthUserRequest *); extern int authenticateAuthUserRequestIPCount(AuthUserRequest *); extern int authenticateDirection(AuthUserRequest *); diff --git a/src/CompositePoolNode.h b/src/CompositePoolNode.h index cdc7936d8d..12cdb59586 100644 --- a/src/CompositePoolNode.h +++ b/src/CompositePoolNode.h @@ -1,6 +1,6 @@ /* - * $Id: CompositePoolNode.h,v 1.8 2007/05/29 13:31:36 amosjeffries Exp $ + * $Id: CompositePoolNode.h,v 1.9 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -47,6 +47,7 @@ #include "DelayPools.h" #include "DelayIdComposite.h" #include "CommRead.h" +#include "IPAddress.h" class StoreEntry; @@ -76,7 +77,7 @@ public: public: CompositeSelectionDetails() {} - struct IN_ADDR src_addr; + IPAddress src_addr; AuthUserRequest *user; String tag; }; diff --git a/src/ConnectionDetail.h b/src/ConnectionDetail.h index 1173a487b6..637d434e8c 100644 --- a/src/ConnectionDetail.h +++ b/src/ConnectionDetail.h @@ -1,5 +1,5 @@ /* - * $Id: ConnectionDetail.h,v 1.3 2003/03/08 09:35:15 robertc Exp $ + * $Id: ConnectionDetail.h,v 1.4 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Robert Collins @@ -37,6 +37,8 @@ #ifndef _SQUIDCONNECTIONDETAIL_H_ #define _SQUIDCONNECTIONDETAIL_H_ +#include "IPAddress.h" + class ConnectionDetail { @@ -44,9 +46,9 @@ public: ConnectionDetail(); - struct sockaddr_in me; + IPAddress me; - struct sockaddr_in peer; + IPAddress peer; }; #endif diff --git a/src/Debug.h b/src/Debug.h index 64a64bca4d..dd14f96d3b 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -1,6 +1,5 @@ - /* - * $Id: Debug.h,v 1.10 2007/08/24 01:02:09 amosjeffries Exp $ + * $Id: Debug.h,v 1.11 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -81,9 +80,9 @@ private: * * debugs(1,1, HERE << "some message"); */ -#define HERE __FILE__<<"("<<__LINE__<<") " +#define HERE __FILE__<<"("<<__LINE__<<") "<<__FUNCTION__<<": " -/* AYJ: some uint8_t do not like streaming control-chars (values 0-31, 127+) */ +/* some uint8_t do not like streaming control-chars (values 0-31, 127+) */ inline std::ostream& operator <<(std::ostream &os, const uint8_t d) { return (os << (int)d); } diff --git a/src/DelayConfig.h b/src/DelayConfig.h index 43d2f92157..d5683b9ee4 100644 --- a/src/DelayConfig.h +++ b/src/DelayConfig.h @@ -1,7 +1,8 @@ - /* - * $Id: DelayConfig.h,v 1.3 2006/04/25 12:00:29 robertc Exp $ + * $Id: DelayConfig.h,v 1.4 2007/12/14 23:11:45 amosjeffries Exp $ * + * DEBUG: section 3 Configuration Settings + * AUTHOR: Robert Collins * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- diff --git a/src/DelayId.cc b/src/DelayId.cc index 85e2fea3d9..bd71b95cee 100644 --- a/src/DelayId.cc +++ b/src/DelayId.cc @@ -1,6 +1,6 @@ /* - * $Id: DelayId.cc,v 1.23 2007/09/21 11:41:52 amosjeffries Exp $ + * $Id: DelayId.cc,v 1.24 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -98,8 +98,8 @@ DelayId::DelayClient(ClientHttpRequest * http) assert(http); r = http->request; - if (r->client_addr.s_addr == INADDR_BROADCAST) { - debugs(77, 2, "delayClient: WARNING: Called with 'allones' address, ignoring"); + if (r->client_addr.IsNoAddr()) { + debugs(77, 2, "delayClient: WARNING: Called with 'NO_ADDR' address, ignoring"); return DelayId(); } @@ -107,7 +107,6 @@ DelayId::DelayClient(ClientHttpRequest * http) ACLChecklist ch; ch.src_addr = r->client_addr; ch.my_addr = r->my_addr; - ch.my_port = r->my_port; if (http->getConn() != NULL) ch.conn(http->getConn()); diff --git a/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc b/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc index d73d24c7a1..2152a92df7 100644 --- a/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc +++ b/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc @@ -1,6 +1,5 @@ - /* - * $Id: DiskdIOStrategy.cc,v 1.11 2007/08/16 23:32:28 hno Exp $ + * $Id: DiskdIOStrategy.cc,v 1.12 2007/12/14 23:11:50 amosjeffries Exp $ * * DEBUG: section 79 Squid-side DISKD I/O functions. * AUTHOR: Duane Wessels @@ -158,6 +157,7 @@ DiskdIOStrategy::init() char skey1[32]; char skey2[32]; char skey3[32]; + IPAddress localhost; ikey = (getpid() << 10) + (instanceID << 2); ikey &= 0x7fffffff; @@ -184,10 +184,12 @@ DiskdIOStrategy::init() args[2] = skey2; args[3] = skey3; args[4] = NULL; + localhost.SetLocalhost(); pid = ipcCreate(IPC_STREAM, Config.Program.diskd, args, "diskd", + localhost, &rfd, &wfd, &hIpc); diff --git a/src/ESI.cc b/src/ESI.cc index 6bfbd70732..70e83e5449 100644 --- a/src/ESI.cc +++ b/src/ESI.cc @@ -1,6 +1,6 @@ /* - * $Id: ESI.cc,v 1.26 2007/08/27 12:50:42 hno Exp $ + * $Id: ESI.cc,v 1.27 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -53,6 +53,7 @@ #include "ESIExpression.h" #include "HttpRequest.h" #include "MemBuf.h" +#include "IPAddress.h" /* quick reference on behaviour here. * The ESI specification 1.0 requires the ESI processor to be able to @@ -1451,7 +1452,7 @@ ESIContext::freeResources () /* don't touch incoming, it's a pointer into buffered anyway */ } -extern ErrorState *clientBuildError (err_type, http_status, char const *, struct IN_ADDR *, HttpRequest *); +extern ErrorState *clientBuildError (err_type, http_status, char const *, IPAddress &, HttpRequest *); /* This can ONLY be used before we have sent *any* data to the client */ @@ -1469,8 +1470,7 @@ ESIContext::fail () /* don't honour range requests - for errors we send it all */ flags.error = 1; /* create an error object */ - ErrorState * err = clientBuildError(errorpage, errorstatus, NULL, - http->getConn().getRaw() != NULL ? &http->getConn()->peer.sin_addr : &no_addr, http->request); + ErrorState * err = clientBuildError(errorpage, errorstatus, NULL, http->getConn()->peer, http->request); err->err_msg = errormessage; errormessage = NULL; rep = errorBuildReply (err); diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 80a840dd8d..ddd416b0fc 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.cc,v 1.77 2007/08/13 17:20:51 hno Exp $ + * $Id: HttpRequest.cc,v 1.78 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 73 HTTP Request * AUTHOR: Duane Wessels @@ -82,10 +82,8 @@ HttpRequest::init() imslen = 0; lastmod = -1; max_forwards = -1; - client_addr = no_addr; - my_addr = no_addr; - my_port = 0; - client_port = 0; + client_addr.SetEmpty(); + my_addr.SetEmpty(); body_pipe = NULL; // hier errType = ERR_NONE; diff --git a/src/HttpRequest.h b/src/HttpRequest.h index b926f3449f..f19344fb52 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -1,6 +1,6 @@ /* - * $Id: HttpRequest.h,v 1.30 2007/08/13 17:20:51 hno Exp $ + * $Id: HttpRequest.h,v 1.31 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -68,6 +68,24 @@ public: /* are responses to this request potentially cachable */ bool cacheable() const; + /* Now that we care what host contains it is better off being protected. */ + /* HACK: These two methods are only inline to get around Makefile dependancies */ + /* caused by HttpRequest being used in places it really shouldn't. */ + /* ideally they would be methods of URL instead. */ + inline void SetHost(const char *src) + { + host_addr.SetEmpty(); + host_addr = src; + if( host_addr.IsAnyAddr() ) { + xstrncpy(host, src, SQUIDHOSTNAMELEN); + } + else { + host_addr.ToHostname(host, SQUIDHOSTNAMELEN); + debugs(23, 3, "HttpRequest::SetHost() given IP: " << host_addr); + } + }; + inline const char* GetHost(void) const { return host; }; + protected: void clean(); @@ -78,7 +96,11 @@ public: char login[MAX_LOGIN_SZ]; - char host[SQUIDHOSTNAMELEN + 1]; +private: + char host[SQUIDHOSTNAMELEN]; + +public: + IPAddress host_addr; AuthUserRequest *auth_user_request; @@ -98,15 +120,9 @@ public: int max_forwards; - /* these in_addr's could probably be sockaddr_in's */ - - struct IN_ADDR client_addr; - - struct IN_ADDR my_addr; - - unsigned short my_port; + IPAddress client_addr; - unsigned short client_port; + IPAddress my_addr; HierarchyLogEntry hier; diff --git a/src/ICAP/ICAPModXact.cc b/src/ICAP/ICAPModXact.cc index 99324cab84..e14f89b9e0 100644 --- a/src/ICAP/ICAPModXact.cc +++ b/src/ICAP/ICAPModXact.cc @@ -1074,6 +1074,7 @@ void ICAPModXact::swanSong() void ICAPModXact::makeRequestHeaders(MemBuf &buf) { + char ntoabuf[MAX_IPSTRLEN]; /* * XXX These should use HttpHdr interfaces instead of Printfs */ @@ -1140,9 +1141,8 @@ void ICAPModXact::makeRequestHeaders(MemBuf &buf) } if (TheICAPConfig.send_client_ip && request) - if (request->client_addr.s_addr != any_addr.s_addr && - request->client_addr.s_addr != no_addr.s_addr) - buf.Printf("X-Client-IP: %s\r\n", inet_ntoa(request->client_addr)); + if (!request->client_addr.IsAnyAddr() && !request->client_addr.IsNoAddr()) + buf.Printf("X-Client-IP: %s\r\n", request->client_addr.NtoA(ntoabuf,MAX_IPSTRLEN)); if (TheICAPConfig.send_client_username && request) makeUsernameHeader(request, buf); diff --git a/src/ICMP.h b/src/ICMP.h new file mode 100644 index 0000000000..deb9951d48 --- /dev/null +++ b/src/ICMP.h @@ -0,0 +1,153 @@ +/* + * $Id: ICMP.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _INCLUDE_ICMP_H +#define _INCLUDE_ICMP_H + +#include "config.h" +#include "IPAddress.h" + +#define PINGER_PAYLOAD_SZ 8192 + +#define MAX_PAYLOAD 256 // WAS: SQUIDHOSTNAMELEN +#define MAX_PKT4_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) + sizeof(struct icmphdr) + 1) +#if USE_IPV6 +#define MAX_PKT6_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) + sizeof(struct icmp6_hdr) + 1) +#endif + +#if USE_ICMP + +/* This is a line-data format struct. DO NOT alter. */ +struct pingerEchoData +{ + IPAddress to; + unsigned char opcode; + int psize; + char payload[PINGER_PAYLOAD_SZ]; +}; + +/* This is a line-data format struct. DO NOT alter. */ +struct pingerReplyData +{ + IPAddress from; + unsigned char opcode; + int rtt; + int hops; + int psize; + char payload[PINGER_PAYLOAD_SZ]; +}; + +struct icmpEchoData +{ + struct timeval tv; + unsigned char opcode; + char payload[MAX_PAYLOAD]; +}; + +SQUIDCEXTERN int icmp_pkts_sent; + +#endif /* USE_ICMP */ + + +/** + * Implements the squid interface to access ICMP operations + * + \par + * Child implementations define specific parts of these operations + * using these methods as a naming and parameter template. + * + * ICMPSquid - implements the squid side of squid-pinger interface + * ICMPPinger - implements the pinger side of the squid-pinger interface + * ICMPv4 - implements pinger helper for ICMPv4 + * ICMPv6 - implements pinger helper for ICMPv6 + */ +class ICMP +{ +public: + ICMP(); + virtual ~ICMP() {}; + + /// Start pinger helper and initiate control channel + virtual int Open() =0; + + /// Shutdown pinger helper and control channel + virtual void Close(); + +#if USE_ICMP + + /** + * Construct and Send an ECHO request + * + \param to Destination address being 'pinged' + \param opcode Specific code for ECHO request, see RFC ????. + \param payload A payload MAY be sent in the ICMP message. + * Content longer than MAX_PAYLOAD will be truncated. + \param len Length of the payload in bytes if any is to be sent or 0. + */ + virtual void SendEcho(IPAddress &to, int opcode, const char *payload=NULL, int len=0) =0; + + /// Handle ICMP responses. + virtual void Recv(void) =0; + +protected: + /* shared internal methods */ + + /// Calculate a packet checksum + int CheckSum(unsigned short *ptr, int size); + + /** + * Translate TTL to a hop distance + * + \param ttl negative : n > 33 + \param ttl n(0...32) : 32 >= n >= 1 + \param ttl n(33...62) : 32 >= n >= 1 + \param ttl n(63...64) : 2 >= n >= 1 + \param ttl n(65...128) : 64 >= n >= 1 + \param ttl n(129...192) : 64 >= n >= 1 + \param ttl n(193...) : n < 255 + * + \bug BUG? ttl<0 can produce high hop values + \bug BUG? ttl>255 can produce zero or negative hop values + */ + int ipHops(int ttl); + + /// Log the packet. + void Log(const IPAddress &addr, const u_int8_t type, const char* pkt_str, const int rtt, const int hops); + + /* no use wasting memory */ + int icmp_sock; + int icmp_ident; +#endif /* USE_ICMP */ +}; + +#endif diff --git a/src/ICMPConfig.h b/src/ICMPConfig.h new file mode 100644 index 0000000000..60be4bc68b --- /dev/null +++ b/src/ICMPConfig.h @@ -0,0 +1,73 @@ +/* + * $Id: ICMPConfig.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 3 Configuration Settings + * AUTHOR: Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from the + * Internet community. Development is led by Duane Wessels of the + * National Laboratory for Applied Network Research and funded by the + * National Science Foundation. Squid is Copyrighted (C) 1998 by + * the Regents of the University of California. Please see the + * COPYRIGHT file for full details. Squid incorporates software + * developed and/or copyrighted by other sources. Please see the + * CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + * This code is copyright (C) 2007 by Treehouse Networks Ltd + * of New Zealand. It is published and Lisenced as an extension of + * squid under the same conditions as the main squid application. + */ +#ifndef ICMPCONFIG_H +#define ICMPCONFIG_H + +#include "config.h" + +#if HAVE_STDLIB_H +#include +#endif + +/** + * Squid pinger Configuration settings + * + \par + * This structure is included as a child field of the global Config + * such that if ICMP is built it can be accessed as Config.pinger.* + */ +class ICMPConfig { + +public: + + /** \todo These methods should really be defined in an ICMPConfig.cc file + * alongside any custom parsing routines needed for this component. + * First though, the whole global Config dependancy tree needs fixing */ + ICMPConfig() : program(NULL), enable(0) {}; + ~ICMPConfig() { if(program) delete program; program = NULL; }; + +/* variables */ + + /** pinger helper application path */ + char *program; + + /** Whether the pinger helper is enabled for use or not */ + /** \todo make this much more memory efficient for a boolean */ + int enable; +}; + +#endif /* ICMPCONFIG_H */ diff --git a/src/ICMPPinger.cc b/src/ICMPPinger.cc new file mode 100644 index 0000000000..1d974692f4 --- /dev/null +++ b/src/ICMPPinger.cc @@ -0,0 +1,237 @@ +/* + * $Id: ICMPPinger.cc,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 42 ICMP Pinger program + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#define SQUID_HELPER 1 + +#include "squid.h" + +#if USE_ICMP + +#include "SquidTime.h" +#include "ICMPPinger.h" +#include "ICMPv4.h" +#include "ICMPv6.h" +#include "Debug.h" + +ICMPPinger::ICMPPinger() : ICMP() +{ + // these start invalid. Setup properly in Open() + socket_from_squid = -1; + socket_to_squid = -1; +} + +ICMPPinger::~ICMPPinger() +{ + Close(); +} + +int +ICMPPinger::Open(void) +{ +#ifdef _SQUID_MSWIN_ + + WSADATA wsaData; + WSAPROTOCOL_INFO wpi; + char buf[sizeof(wpi)]; + int x; + + struct sockaddr_in PS; + + WSAStartup(2, &wsaData); + + getCurrentTime(); + _db_init(NULL, "ALL,1"); + setmode(0, O_BINARY); + setmode(1, O_BINARY); + x = read(0, buf, sizeof(wpi)); + + if (x < (int)sizeof(wpi)) { + getCurrentTime(); + debugs(42, 0, HERE << "read: FD 0: " << xstrerror()); + write(1, "ERR\n", 4); + return -1; + } + + xmemcpy(&wpi, buf, sizeof(wpi)); + + write(1, "OK\n", 3); + x = read(0, buf, sizeof(PS)); + + if (x < (int)sizeof(PS)) { + getCurrentTime(); + debugs(42, 0, HERE << "read: FD 0: " << xstrerror()); + write(1, "ERR\n", 4); + return -1; + } + + xmemcpy(&PS, buf, sizeof(PS)); + + icmp_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wpi, 0, 0); + + if (icmp_sock == -1) { + getCurrentTime(); + debugs(42, 0, HERE << "WSASocket: " << xstrerror()); + write(1, "ERR\n", 4); + return -1; + } + + x = connect(icmp_sock, (struct sockaddr *) &PS, sizeof(PS)); + + if (SOCKET_ERROR == x) { + getCurrentTime(); + debugs(42, 0, HERE << "connect: " << xstrerror()); + write(1, "ERR\n", 4); + return -1; + } + + write(1, "OK\n", 3); + memset(buf, 0, sizeof(buf)); + x = recv(icmp_sock, (void *) buf, sizeof(buf), 0); + + if (x < 3) { + debugs(42, 0, HERE << "recv: " << xstrerror()); + return -1; + } + + x = send(icmp_sock, (const void *) buf, strlen(buf), 0); + + if (x < 3 || strncmp("OK\n", buf, 3)) { + debugs(42, 0, HERE << "recv: " << xstrerror()); + return -1; + } + + getCurrentTime(); + debugs(42, 1, "pinger: Squid socket opened"); + + /* windows uses a socket stream as a dual-direction channel */ + socket_to_squid = icmp_sock; + socket_from_squid = icmp_sock; + + return icmp_sock; + +#else /* !_SQUID_MSWIN_ */ + + /* non-windows apps use stdin/out pipes as the squid channel(s) */ + socket_from_squid = 0; // use STDIN macro ?? + socket_to_squid = 1; // use STDOUT macro ?? + return socket_to_squid; +#endif +} + +void +ICMPPinger::Close(void) +{ +#ifdef _SQUID_MSWIN_ + + shutdown(icmp_sock, SD_BOTH); + close(icmp_sock); + icmp_sock = -1; +#endif + + /* also shutdown the helper engines */ + icmp4.Close(); +#if USE_IPV6 + icmp6.Close(); +#endif +} + +void +ICMPPinger::Recv(void) +{ + static pingerEchoData pecho; + int n; + int guess_size; + + memset(&pecho, '\0', sizeof(pecho)); + n = recv(socket_from_squid, &pecho, sizeof(pecho), 0); + + if (n < 0) { + debugs(42, 1, "Pinger exiting."); + Close(); + exit(1); + } + + if (0 == n) { + /* EOF indicator */ + debugs(42, 0, HERE << "EOF encountered. Pinger exiting.\n"); + errno = 0; + Close(); + exit(1); + } + + guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ); + + if (guess_size != pecho.psize) { + debugs(42, 2, HERE << "size mismatch, guess=" << guess_size << ", psize=" << pecho.psize); + /* don't process this message, but keep running */ + return; + } + +#if USE_IPV6 + /* pass request for ICMPv6 handing */ + if(pecho.to.IsIPv6()) { + debugs(42, 2, HERE << " Pass " << pecho.to << " off to ICMPv6 module."); + icmp6.SendEcho(pecho.to, + pecho.opcode, + pecho.payload, + pecho.psize); + } +#endif + + /* pass the packet for ICMP handling */ + else if(pecho.to.IsIPv4()) { + debugs(42, 2, HERE << " Pass " << pecho.to << " off to ICMPv4 module."); + icmp4.SendEcho(pecho.to, + pecho.opcode, + pecho.payload, + pecho.psize); + } + else { + debugs(42, 1, HERE << " IP has unknown Type. " << pecho.to ); + } +} + +void +ICMPPinger::SendResult(pingerReplyData &preply, int len) +{ + debugs(42, 2, HERE << "return result to squid. len=" << len); + + if (send(socket_to_squid, &preply, len, 0) < 0) { + debugs(42, 0, "pinger: FATAL error on send: " << xstrerror()); + Close(); + exit(1); + } +} + +#endif /* USE_ICMP */ diff --git a/src/ICMPPinger.h b/src/ICMPPinger.h new file mode 100644 index 0000000000..8c28c9a8c9 --- /dev/null +++ b/src/ICMPPinger.h @@ -0,0 +1,83 @@ +/* + * $Id: ICMPPinger.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _INCLUDE_ICMPPINGER_H +#define _INCLUDE_ICMPPINGER_H + +#include "config.h" +#include "ICMP.h" + +/** + * Implements the interface to squid for ICMP operations + */ +class ICMPPinger : public ICMP +{ +public: + ICMPPinger(); + virtual ~ICMPPinger(); + + /// Start and initiate control channel to squid + virtual int Open(); + + /// Shutdown pinger helper and control channel + virtual void Close(); + +#if USE_ICMP + + /// Send ICMP results back to squid. + void SendResult(pingerReplyData &preply, int len); + + /// Handle ICMP requests from squid, passing to helpers. + virtual void Recv(void); + +private: + // unused in ICMPPinger + virtual void SendEcho(IPAddress &to, int opcode, const char *payload, int len) {}; + + /** + * Control channel(s) to squid. + * May be STDIN/STDOUT pipes or an IP socket depending on the OS + */ + int socket_from_squid; + int socket_to_squid; +#endif /* USE_ICMP */ +}; + +#if USE_ICMP + +/// pinger helper contains one of these as a global object. +SQUIDCEXTERN ICMPPinger control; + +#endif + +#endif diff --git a/src/ICMPSquid.cc b/src/ICMPSquid.cc new file mode 100644 index 0000000000..188cce381a --- /dev/null +++ b/src/ICMPSquid.cc @@ -0,0 +1,303 @@ +/* + * $Id: ICMPSquid.cc,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "ICMPSquid.h" +#include "comm.h" +#include "SquidTime.h" + +// Instance global to be available in main() and elsewhere. +ICMPSquid icmpEngine; + +#if USE_ICMP + +#define S_ICMP_ECHO 1 +#if DEAD_CODE +#define S_ICMP_ICP 2 +#endif +#define S_ICMP_DOM 3 + +static void * hIpc; +static pid_t pid; + +#endif /* USE_ICMP */ + + +ICMPSquid::ICMPSquid() : ICMP() +{ + ; // nothing new. +} + +ICMPSquid::~ICMPSquid() +{ + Close(); +} + + +#if USE_ICMP + +void +ICMPSquid::SendEcho(IPAddress &to, int opcode, const char *payload, int len) +{ + static pingerEchoData pecho; + int x, slen; + + /** \li Does nothing if the pinger socket is not available. */ + if(icmp_sock < 0) { + debugs(37, 2, HERE << " Socket Closed. Aborted send to " << pecho.to << ", opcode " << opcode << ", len " << pecho.psize); + return; + } + + /** \li If no payload is given or is set as NULL it will ignore payload and len */ + if(!payload) + len = 0; + + /** \li Otherwise if len is 0, uses strlen() to detect length of payload. + \bug This will result in part of the payload being truncated if it contains a NULL character. + \bug Or it may result in a buffer over-run if the payload is not nul-terminated properly. + */ + else if (payload && len == 0) + len = strlen(payload); + + /** \li + \bug If length specified or auto-detected is greater than the possible payload squid will die with an assert. + \todo This should perhapse be reduced to a truncated payload? or no payload. A WARNING is due anyway. + */ + assert(len <= PINGER_PAYLOAD_SZ); + + pecho.to = to; + + pecho.opcode = (unsigned char) opcode; + + pecho.psize = len; + + if(len > 0) + xmemcpy(pecho.payload, payload, len); + + slen = sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + pecho.psize; + + debugs(37, 2, HERE << "to " << pecho.to << ", opcode " << opcode << ", len " << pecho.psize); + + x = comm_udp_send(icmp_sock, (char *)&pecho, slen, 0); + + if (x < 0) { + debugs(37, 1, HERE << "send: " << xstrerror()); + + /** \li If the send results in ECONNREFUSED or EPIPE errors from helper, will cleanly shutdown the module. */ + /** \todo This should try restarting the helper a few times?? before giving up? */ + if (errno == ECONNREFUSED || errno == EPIPE) { + Close(); + return; + } + /** All other send errors are ignored. */ + } else if (x != len) { + debugs(37, 1, HERE << "Wrote " << x << " of " << slen << " bytes"); + } +} + +// static Callback to wrap the squid-side ICMP handler. +// the ICMPSquid::Recv cannot be declared both static and virtual. +static void +icmpSquidRecv(int unused1, void *unused2) +{ + icmpEngine.Recv(); +} + +void +ICMPSquid::Recv() +{ + int n; + static int fail_count = 0; + pingerReplyData preply; + static IPAddress F; + + commSetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0); + memset(&preply, '\0', sizeof(pingerReplyData)); + n = comm_udp_recv(icmp_sock, + (char *) &preply, + sizeof(pingerReplyData), + 0); + + if (n < 0 && EAGAIN != errno) { + debugs(37, 1, HERE << "recv: " << xstrerror()); + + if (errno == ECONNREFUSED) + Close(); + + if (errno == ECONNRESET) + Close(); + + if (++fail_count == 10) + Close(); + + return; + } + + fail_count = 0; + + /** If its a test probe from the pinger. Do nothing. */ + if (n == 0) { + return; + } + + F = preply.from; + + F.SetPort(0); + + switch (preply.opcode) { + + case S_ICMP_ECHO: + debugs(37,4, HERE << " ICMP_ECHO of " << preply.from << " gave: hops=" << preply.hops <<", rtt=" << preply.rtt); + break; + + case S_ICMP_DOM: + debugs(37,4, HERE << " DomainPing of " << preply.from << " gave: hops=" << preply.hops <<", rtt=" << preply.rtt); + netdbHandlePingReply(F, preply.hops, preply.rtt); + break; + + default: + debugs(37, 1, HERE << "Bad opcode: " << preply.opcode << " from " << F); + break; + } +} + +#endif /* USE_ICMP */ + +void +ICMPSquid::DomainPing(IPAddress &to, const char *domain) +{ +#if USE_ICMP + debugs(37, 4, HERE << "'" << domain << "' (" << to << ")"); + SendEcho(to, S_ICMP_DOM, domain, 0); +#endif +} + +int +ICMPSquid::Open(void) +{ +#if USE_ICMP + const char *args[2]; + int rfd; + int wfd; + IPAddress localhost; + + /* User configured disabled. */ + if(!Config.pinger.enable) { + Close(); + return -1; + } + + args[0] = "(pinger)"; + args[1] = NULL; + localhost.SetLocalhost(); + + /* + * Do NOT use IPC_DGRAM (=IPC_UNIX_DGRAM) here because you can't + * send() more than 4096 bytes on a socketpair() socket (at + * least on FreeBSD). + */ + pid = ipcCreate(IPC_UDP_SOCKET, + Config.pinger.program, + args, + "Pinger Socket", + localhost, + &rfd, + &wfd, + &hIpc); + + if (pid < 0) + return -1; + + assert(rfd == wfd); + + icmp_sock = rfd; + + fd_note(icmp_sock, "pinger"); + + commSetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0); + + commSetTimeout(icmp_sock, -1, NULL, NULL); + + debugs(37, 1, HERE << "Pinger socket opened on FD " << icmp_sock); + + /* Tests the pinger immediately using localhost */ +#if USE_IPV6 + SendEcho(localhost, S_ICMP_ECHO, "ip6-localhost"); +#endif + if(localhost.SetIPv4()) + SendEcho(localhost, S_ICMP_ECHO, "localhost"); + +#ifdef _SQUID_MSWIN_ + + debugs(37, 4, HERE << "Pinger handle: 0x" << std::hex << hIpc << std::dec << ", PID: " << pid); + +#endif /* _SQUID_MSWIN_ */ +#endif /* USE_ICMP */ + return icmp_sock; +} + +void +ICMPSquid::Close(void) +{ +#if USE_ICMP + + if (icmp_sock < 0) + return; + + debugs(37, 1, HERE << "Closing Pinger socket on FD " << icmp_sock); + +#ifdef _SQUID_MSWIN_ + + send(icmp_sock, (const void *) "$shutdown\n", 10, 0); + +#endif + + comm_close(icmp_sock); + +#ifdef _SQUID_MSWIN_ + + if (hIpc) { + if (WaitForSingleObject(hIpc, 12000) != WAIT_OBJECT_0) { + getCurrentTime(); + debugs(37, 0, HERE << "WARNING: (pinger," << pid << ") didn't exit in 12 seconds"); + } + + CloseHandle(hIpc); + } + +#endif + icmp_sock = -1; + +#endif +} diff --git a/src/ICMPSquid.h b/src/ICMPSquid.h new file mode 100644 index 0000000000..bca5527044 --- /dev/null +++ b/src/ICMPSquid.h @@ -0,0 +1,69 @@ +/* + * $Id: ICMPSquid.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _INCLUDE_ICMPSQUID_H +#define _INCLUDE_ICMPSQUID_H + +#include "config.h" +#include "ICMP.h" +#include "IPAddress.h" + +/** + * Implements a non-blocking pseudo-ICMP engine for squid internally. + * + * Rather than doing all the work itself it passes each request off to + * an external pinger helper and returns results form that helper to squid. + * + * Provides ECHO-REQUEST, ECHO-REPLY in a protocol-neutral manner. + */ +class ICMPSquid : public ICMP +{ +public: + ICMPSquid(); + virtual ~ICMPSquid(); + + virtual int Open(); + virtual void Close(); + + void DomainPing(IPAddress &to, const char *domain); + +#if USE_ICMP + virtual void SendEcho(IPAddress &to, int opcode, const char* payload=NULL, int len=0); + virtual void Recv(void); +#endif +}; + +// global engine within squid. +SQUIDCEXTERN ICMPSquid icmpEngine; + +#endif /* _INCLUDE_ICMPSQUID_H */ diff --git a/src/ICMPv4.cc b/src/ICMPv4.cc new file mode 100644 index 0000000000..9fceae3487 --- /dev/null +++ b/src/ICMPv4.cc @@ -0,0 +1,247 @@ +/* + * $Id: ICMPv4.cc,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 42 ICMP Pinger program + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +//#define SQUID_HELPER 1 + +#include "squid.h" + +#if USE_ICMP + +#include "SquidTime.h" +#include "ICMPv4.h" +#include "ICMPPinger.h" +#include "Debug.h" + +const char *icmpPktStr[] = + { + "Echo Reply", + "ICMP 1", + "ICMP 2", + "Destination Unreachable", + "Source Quench", + "Redirect", + "ICMP 6", + "ICMP 7", + "Echo", + "ICMP 9", + "ICMP 10", + "Time Exceeded", + "Parameter Problem", + "Timestamp", + "Timestamp Reply", + "Info Request", + "Info Reply", + "Out of Range Type" + }; + +ICMPv4::ICMPv4() : ICMP() +{ + ; +} + +ICMPv4::~ICMPv4() +{ + Close(); +} + +int +ICMPv4::Open(void) +{ + icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); + + if (icmp_sock < 0) { + debugs(50, 0, HERE << " icmp_sock: " << xstrerror()); + return -1; + } + + icmp_ident = getpid() & 0xffff; + debugs(42, 1, "pinger: ICMP socket opened."); + + return icmp_sock; +} + +void +ICMPv4::SendEcho(IPAddress &to, int opcode, const char *payload, int len) +{ + int x; + LOCAL_ARRAY(char, pkt, MAX_PKT4_SZ); + + struct icmphdr *icmp = NULL; + icmpEchoData *echo; + size_t icmp_pktsize = sizeof(struct icmphdr); + struct addrinfo *S = NULL; + + memset(pkt, '\0', MAX_PKT4_SZ); + + icmp = (struct icmphdr *) (void *) pkt; + + /* + * cevans - beware signed/unsigned issues in untrusted data from + * the network!! + */ + if (len < 0) + { + len = 0; + } + + // Construct ICMP packet header + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_id = icmp_ident; + icmp->icmp_seq = (u_short) icmp_pkts_sent++; + + // Construct ICMP packet data content + echo = (icmpEchoData *) (icmp + 1); + echo->opcode = (unsigned char) opcode; + echo->tv = current_time; + + icmp_pktsize += sizeof(struct timeval) + sizeof(char); + + if (payload) + { + if (len > MAX_PAYLOAD) + len = MAX_PAYLOAD; + + xmemcpy(echo->payload, payload, len); + + icmp_pktsize += len; + } + + icmp->icmp_cksum = CheckSum((u_short *) icmp, icmp_pktsize); + + to.GetAddrInfo(S); + ((sockaddr_in*)S->ai_addr)->sin_port = 0; + assert(icmp_pktsize <= MAX_PKT4_SZ); + + debugs(42, 2, HERE << "Send ICMP packet to " << to << "."); + + x = sendto(icmp_sock, + (const void *) pkt, + icmp_pktsize, + 0, + S->ai_addr, + S->ai_addrlen); + + if(x < 0) { + debugs(42, 1, HERE << "Error sending to ICMP packet to " << to << ". ERR: " << xstrerror()); + } + + Log(to, ' ', NULL, 0, 0); +} + +void +ICMPv4::Recv(void) +{ + int n; + struct addrinfo *from = NULL; + int iphdrlen = sizeof(iphdr); + struct iphdr *ip = NULL; + struct icmphdr *icmp = NULL; + static char *pkt = NULL; + struct timeval now; + icmpEchoData *echo; + static pingerReplyData preply; + + if(icmp_sock < 0) { + debugs(42, 0, HERE << "No socket! Recv() should not be called."); + return; + } + + if (pkt == NULL) + pkt = (char *)xmalloc(MAX_PKT4_SZ); + + preply.from.InitAddrInfo(from); + n = recvfrom(icmp_sock, + (void *)pkt, + MAX_PKT4_SZ, + 0, + from->ai_addr, + &from->ai_addrlen); + + preply.from = *from; + +#if GETTIMEOFDAY_NO_TZP + + gettimeofday(&now); + +#else + + gettimeofday(&now, NULL); + +#endif + + debugs(42, 8, HERE << n << " bytes from " << preply.from); + + ip = (struct iphdr *) (void *) pkt; + +#if HAVE_STRUCT_IPHDR_IP_HL + + iphdrlen = ip->ip_hl << 2; + +#else /* HAVE_STRUCT_IPHDR_IP_HL */ +#if WORDS_BIGENDIAN + + iphdrlen = (ip->ip_vhl >> 4) << 2; + +#else + + iphdrlen = (ip->ip_vhl & 0xF) << 2; + +#endif +#endif /* HAVE_STRUCT_IPHDR_IP_HL */ + + icmp = (struct icmphdr *) (void *) (pkt + iphdrlen); + + if (icmp->icmp_type != ICMP_ECHOREPLY) + return; + + if (icmp->icmp_id != icmp_ident) + return; + + echo = (icmpEchoData *) (void *) (icmp + 1); + + preply.opcode = echo->opcode; + + preply.hops = ipHops(ip->ip_ttl); + + preply.rtt = tvSubMsec(echo->tv, now); + + preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT4_SZ); + + control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT4_SZ + preply.psize) ); + + Log(preply.from, icmp->icmp_type, icmpPktStr[icmp->icmp_type], preply.rtt, preply.hops); +} + +#endif /* USE_ICMP */ diff --git a/src/ICMPv4.h b/src/ICMPv4.h new file mode 100644 index 0000000000..05c06c2603 --- /dev/null +++ b/src/ICMPv4.h @@ -0,0 +1,179 @@ +/* + * $Id: ICMPv4.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _INCLUDE_ICMPV4_H +#define _INCLUDE_ICMPV4_H + +#include "config.h" +#include "ICMP.h" +#include "IPAddress.h" + +#if HAVE_NETINET_IN_SYSTM_H +#include +#endif +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETINET_IP_H +#include +#endif +#if HAVE_NETINET_IP_ICMP_H +#include +#endif + +/* Linux uses its own field names. */ +#if defined (_SQUID_LINUX_) +#ifdef icmp_id +#undef icmp_id +#endif +#ifdef icmp_seq +#undef icmp_seq +#endif +#define icmp_type type +#define icmp_code code +#define icmp_cksum checksum +#define icmp_id un.echo.id +#define icmp_seq un.echo.sequence +#define ip_hl ihl +#define ip_v version +#define ip_tos tos +#define ip_len tot_len +#define ip_id id +#define ip_off frag_off +#define ip_ttl ttl +#define ip_p protocol +#define ip_sum check +#define ip_src saddr +#define ip_dst daddr +#endif + + +/* Native Windows port doesn't have netinet support, so we emulate it. + At this time, Cygwin lacks icmp support in its include files, so we need + to use the native Windows port definitions. + */ + +#ifdef _SQUID_WIN32_ + +#include "fde.h" + +#ifdef _SQUID_MSWIN_ + +#include +#include + +#endif + +/* IP Header */ +typedef struct iphdr +{ + +u_int8_t ip_vhl: + 4; /* Length of the header in dwords */ + +u_int8_t version: + 4; /* Version of IP */ + u_int8_t tos; /* Type of service */ + u_int16_t total_len; /* Length of the packet in dwords */ + u_int16_t ident; /* unique identifier */ + u_int16_t flags; /* Flags */ + u_int8_t ip_ttl; /* Time to live */ + u_int8_t proto; /* Protocol number (TCP, UDP etc) */ + u_int16_t checksum; /* IP checksum */ + u_int32_t source_ip; + u_int32_t dest_ip; +} +iphdr; + +/* ICMP header */ +typedef struct icmphdr +{ + u_int8_t icmp_type; /* ICMP packet type */ + u_int8_t icmp_code; /* Type sub code */ + u_int16_t icmp_cksum; + u_int16_t icmp_id; + u_int16_t icmp_seq; + u_int32_t timestamp; /* not part of ICMP, but we need it */ +} +icmphdr; + +#endif /* _SQUID_MSWIN_ */ + +#ifndef ICMP_ECHO +#define ICMP_ECHO 8 +#endif + +#ifndef ICMP_ECHOREPLY +#define ICMP_ECHOREPLY 0 +#endif + +#ifndef IPPROTO_ICMP +#define IPPROTO_ICMP 1 +#endif + +/* some OS apparently define icmp instead of icmphdr */ +#if !defined(icmphdr) && defined(icmp) +#define icmphdr icmp +#endif + +/* some OS apparently define ip instead of iphdr */ +#if !defined(iphdr) && defined(ip) +#define iphdr ip +#endif + +/** + * Class partially implementing RFC 792 - ICMP for IP version 4. + * Provides ECHO-REQUEST, ECHO-REPLY (secion 4.1) + */ +class ICMPv4 : public ICMP +{ +public: + ICMPv4(); + virtual ~ICMPv4(); + + virtual int Open(); + +#if USE_ICMP + virtual void SendEcho(IPAddress &, int, const char*, int); + virtual void Recv(void); +#endif +}; + +#if USE_ICMP + +/// pinger helper contains one of these as a global object. +SQUIDCEXTERN ICMPv4 icmp4; + +#endif /* USE_ICMP && SQUID_HELPER */ + +#endif diff --git a/src/ICMPv6.cc b/src/ICMPv6.cc new file mode 100644 index 0000000000..4fd2d0e4b7 --- /dev/null +++ b/src/ICMPv6.cc @@ -0,0 +1,343 @@ +/* + * $Id: ICMPv6.cc,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 42 ICMP Pinger program + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +//#define SQUID_HELPER 1 + +#include "squid.h" + +#if USE_ICMP && USE_IPV6 + +#include "SquidTime.h" +#include "Debug.h" +#include "ICMPv6.h" +#include "ICMPPinger.h" + +// Some system headers are only neeed internally here. +// They should not be included via the header. + +#if HAVE_NETINET_IP6_H +#include +#endif + +// ICMPv6 OP-Codes +// see http://www.iana.org/assignments/icmpv6-parameters +// NP: LowPktStr is for codes 0-127 +static const char *icmp6LowPktStr[] = + { + "ICMP 0", // 0 + "Destination Unreachable", // 1 - RFC2463 + "Packet Too Big", // 2 - RFC2463 + "Time Exceeded", // 3 - RFC2463 + "Parameter Problem", // 4 - RFC2463 + "ICMP 5", // 5 + "ICMP 6", // 6 + "ICMP 7", // 7 + "ICMP 8", // 8 + "ICMP 9", // 9 + "ICMP 10" // 10 + }; + +// NP: HighPktStr is for codes 128-255 +static const char *icmp6HighPktStr[] = + { + "Echo Request", // 128 - RFC2463 + "Echo Reply", // 129 - RFC2463 + "Multicast Listener Query", // 130 - RFC2710 + "Multicast Listener Report", // 131 - RFC2710 + "Multicast Listener Done", // 132 - RFC2710 + "Router Solicitation", // 133 - RFC4861 + "Router Advertisement", // 134 - RFC4861 + "Neighbor Solicitation", // 135 - RFC4861 + "Neighbor Advertisement", // 136 - RFC4861 + "Redirect Message", // 137 - RFC4861 + "Router Renumbering", // 138 - Crawford + "ICMP Node Information Query", // 139 - RFC4620 + "ICMP Node Information Response", // 140 - RFC4620 + "Inverse Neighbor Discovery Solicitation", // 141 - RFC3122 + "Inverse Neighbor Discovery Advertisement", // 142 - RFC3122 + "Version 2 Multicast Listener Report", // 143 - RFC3810 + "Home Agent Address Discovery Request", // 144 - RFC3775 + "Home Agent Address Discovery Reply", // 145 - RFC3775 + "Mobile Prefix Solicitation", // 146 - RFC3775 + "Mobile Prefix Advertisement", // 147 - RFC3775 + "Certification Path Solicitation", // 148 - RFC3971 + "Certification Path Advertisement", // 149 - RFC3971 + "ICMP Experimental (150)", // 150 - RFC4065 + "Multicast Router Advertisement", // 151 - RFC4286 + "Multicast Router Solicitation", // 152 - RFC4286 + "Multicast Router Termination", // 153 - [RFC4286] + "ICMP 154", + "ICMP 155", + "ICMP 156", + "ICMP 157", + "ICMP 158", + "ICMP 159", + "ICMP 160" + }; + +ICMPv6::ICMPv6() : ICMP() +{ + ; // nothing new. +} + +ICMPv6::~ICMPv6() +{ + Close(); +} + +int +ICMPv6::Open(void) +{ + icmp_sock = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + + if (icmp_sock < 0) { + debugs(50, 0, HERE << " icmp_sock: " << xstrerror()); + return -1; + } + + icmp_ident = getpid() & 0xffff; + debugs(42, 1, "pinger: ICMPv6 socket opened"); + + return icmp_sock; +} + +/** + * Generates an RFC 4443 ICMPv6 ECHO Packet and sends into the network. + */ +void +ICMPv6::SendEcho(IPAddress &to, int opcode, const char *payload, int len) +{ + int x; + LOCAL_ARRAY(char, pkt, MAX_PKT6_SZ); + struct icmp6_hdr *icmp = NULL; + icmpEchoData *echo = NULL; + struct addrinfo *S = NULL; + size_t icmp6_pktsize = 0; + + memset(pkt, '\0', MAX_PKT6_SZ); + icmp = (struct icmp6_hdr *)pkt; + + /* + * cevans - beware signed/unsigned issues in untrusted data from + * the network!! + */ + if (len < 0) { + len = 0; + } + + // Construct ICMPv6 ECHO header + icmp->icmp6_type = ICMP6_ECHO_REQUEST; + icmp->icmp6_code = 0; + icmp->icmp6_cksum = 0; + icmp->icmp6_id = icmp_ident; + icmp->icmp6_seq = (u_short) icmp_pkts_sent++; + + icmp6_pktsize = sizeof(struct icmp6_hdr); + + + // Fill ICMPv6 ECHO data content + echo = (icmpEchoData *) (pkt + sizeof(icmp6_hdr)); + echo->opcode = (unsigned char) opcode; + echo->tv = current_time; + + icmp6_pktsize += sizeof(struct timeval) + sizeof(char); + + if (payload) + { + if (len > MAX_PAYLOAD) + len = MAX_PAYLOAD; + + xmemcpy(echo->payload, payload, len); + + icmp6_pktsize += len; + } + + icmp->icmp6_cksum = CheckSum((u_short *) icmp, icmp6_pktsize); + + to.GetAddrInfo(S); + ((sockaddr_in6*)S->ai_addr)->sin6_port = 0; + + assert(icmp6_pktsize <= MAX_PKT6_SZ); + + debugs(42, 5, HERE << "Send ICMPv6 packet to " << to << "."); + + x = sendto(icmp_sock, + (const void *) pkt, + icmp6_pktsize, + 0, + S->ai_addr, + S->ai_addrlen); + + if(x < 0) { + debugs(42, 1, HERE << "Error sending to ICMPv6 packet to " << to << ". ERR: " << xstrerror()); + } + debugs(42,9, HERE << "x=" << x); + + Log(to, 0, NULL, 0, 0); +} + +/** + * Reads an RFC 4443 ICMPv6 ECHO-REPLY Packet from the network. + */ +void +ICMPv6::Recv(void) +{ + int n; + struct addrinfo *from = NULL; +// struct ip6_hdr *ip = NULL; + static char *pkt = NULL; + struct icmp6_hdr *icmp6 = NULL; + icmpEchoData *echo = NULL; + struct timeval now; + static pingerReplyData preply; + + if(icmp_sock < 0) { + debugs(42,0, HERE << "dropping ICMPv6 read. No socket!?"); + return; + } + + if (pkt == NULL) { + pkt = (char *)xmalloc(MAX_PKT6_SZ); + } + + preply.from.InitAddrInfo(from); + + n = recvfrom(icmp_sock, + (void *)pkt, + MAX_PKT6_SZ, + 0, + from->ai_addr, + &from->ai_addrlen); + + preply.from = *from; + +#if GETTIMEOFDAY_NO_TZP + + gettimeofday(&now); + +#else + + gettimeofday(&now, NULL); + +#endif + + debugs(42, 8, HERE << n << " bytes from " << preply.from); + +// FIXME INET6 : The IPv6 Header (ip6_hdr) is not availble directly >:-( +// +// TTL still has to come from the IP header somewhere. +// still need to strip and process it properly. +// probably have to rely on RTT as given by timestamp in data sent and current. +/* IPv6 Header Structures (linux) +struct ip6_hdr + +// fields (via simple define) +#define ip6_vfc // N.A +#define ip6_flow // N/A +#define ip6_plen // payload length. +#define ip6_nxt // expect to be type 0x3a - ICMPv6 +#define ip6_hlim // MAX hops (always 64, but no guarantee) +#define ip6_hops // HOPS!!! (can it be true??) + + + ip = (struct ip6_hdr *) pkt; + pkt += sizeof(ip6_hdr); + +debugs(42,0, HERE << "ip6_nxt=" << ip->ip6_nxt << + ", ip6_plen=" << ip->ip6_plen << + ", ip6_hlim=" << ip->ip6_hlim << + ", ip6_hops=" << ip->ip6_hops << + " ::: 40 == sizef(ip6_hdr) == " << sizeof(ip6_hdr) +); +*/ + + icmp6 = (struct icmp6_hdr *) pkt; + pkt += sizeof(icmp6_hdr); + + if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { + + switch(icmp6->icmp6_type) { + case 134: + case 135: + case 136: + /* ignore Router/Neighbour Advertisements */ + break; + + default: + debugs(42, 8, HERE << preply.from << " said: " << icmp6->icmp6_type << "/" << (int)icmp6->icmp6_code << " " << + ( icmp6->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6->icmp6_type&0x7f)] ) + ); + } + return; + } + + if (icmp6->icmp6_id != icmp_ident) { + debugs(42, 8, HERE << "dropping ICMPv6 read. IDENT check failed. ident=='" << icmp_ident << "'=='" << icmp6->icmp6_id << "'"); + return; + } + + echo = (icmpEchoData *) pkt; + + preply.opcode = echo->opcode; + + preply.rtt = tvSubMsec(echo->tv, now); + +/* + * FIXME INET6: Without access to the IPv6-Hops header we must rely on the total RTT + * and could caculate the hops from that, but it produces some weird value mappings using ipHops + * for now everything is 1 v6 hop away with variant RTT + * WANT: preply.hops = ip->ip6_hops; // ipHops(ip->ip_hops); + */ + preply.hops = 1; + + preply.psize = n - /* sizeof(ip6_hdr) - */ sizeof(icmp6_hdr) - (sizeof(icmpEchoData) - MAX_PKT6_SZ); + + /* Ensure the response packet has safe payload size */ + if( preply.psize > (unsigned short) MAX_PKT6_SZ) { + preply.psize = MAX_PKT6_SZ; + } + else if( preply.psize < (unsigned short)0) { + preply.psize = 0; + } + + Log(preply.from, + icmp6->icmp6_type, + ( icmp6->icmp6_type&0x80 ? icmp6HighPktStr[(int)(icmp6->icmp6_type&0x7f)] : icmp6LowPktStr[(int)(icmp6->icmp6_type&0x7f)] ), + preply.rtt, + preply.hops); + + /* send results of the lookup back to squid.*/ + control.SendResult(preply, (sizeof(pingerReplyData) - PINGER_PAYLOAD_SZ + preply.psize) ); +} + +#endif /* USE_ICMP && USE_IPV6 */ diff --git a/src/ICMPv6.h b/src/ICMPv6.h new file mode 100644 index 0000000000..4639ddc2b5 --- /dev/null +++ b/src/ICMPv6.h @@ -0,0 +1,96 @@ +/* + * $Id: ICMPv6.h,v 1.1 2007/12/14 23:11:45 amosjeffries Exp $ + * + * DEBUG: section 37 ICMP Routines + * AUTHOR: Duane Wessels, Amos Jeffries + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ +#ifndef _INCLUDE_ICMPV6_H +#define _INCLUDE_ICMPV6_H + +#include "config.h" + +#if USE_IPV6 + +#include "ICMP.h" +#include "IPAddress.h" + +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETINET_ICMP6_H +#include +#endif +#if HAVE_NETINET_IP6_H +#include +#endif + +/* see RFC 4443 section 2.1 */ +#ifndef ICMP6_ECHOREQUEST +#define ICMP6_ECHOREQUEST 128 +#endif + +/* see RFC 4443 section 2.1 */ +#ifndef ICMP6_ECHOREPLY +#define ICMP6_ECHOREPLY 129 +#endif + +/* see RFC 4443 section 2.1 */ +#ifndef IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif + +/** + * Class partially implementing RFC 4443 - ICMPv6 for IP version 6. + * Provides ECHO-REQUEST, ECHO-REPLY (secion 4) + */ +class ICMPv6 : public ICMP +{ +public: + ICMPv6(); + virtual ~ICMPv6(); + + virtual int Open(); + +#if USE_ICMP + virtual void SendEcho(IPAddress &, int, const char*, int); + virtual void Recv(void); +#endif +}; + +#if USE_ICMP + +/// pinger helper contains one of these as a global object. +SQUIDCEXTERN ICMPv6 icmp6; + +#endif /* USE_ICMP && SQUID_HELPER */ + +#endif /* USE_IPV6 */ + +#endif /* _INCLUDE_ICMPV6_H */ diff --git a/src/ICP.h b/src/ICP.h index fd3f9045e9..e57256c6f8 100644 --- a/src/ICP.h +++ b/src/ICP.h @@ -1,6 +1,6 @@ /* - * $Id: ICP.h,v 1.9 2007/10/31 04:52:15 amosjeffries Exp $ + * $Id: ICP.h,v 1.10 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -55,7 +55,7 @@ struct _icp_common_t _icp_common_t(); _icp_common_t(char *buf, unsigned int len); - void handleReply(char *buf, struct sockaddr_in *from); + void handleReply(char *buf, IPAddress &from); static _icp_common_t *createMessage(icp_opcode opcode, int flags, const char *url, int reqnum, int pad); icp_opcode getOpCode() const; #endif @@ -82,7 +82,7 @@ public: HttpRequest *request; int fd; - struct sockaddr_in from; + IPAddress from; char *url; }; @@ -90,8 +90,7 @@ public: struct icpUdpData { - - struct sockaddr_in address; + IPAddress address; void *msg; size_t len; icpUdpData *next; @@ -106,21 +105,21 @@ struct icpUdpData }; -HttpRequest* icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in *from); +HttpRequest* icpGetRequest(char *url, int reqnum, int fd, IPAddress &from); -int icpAccessAllowed(struct sockaddr_in *from, HttpRequest * icp_request); +int icpAccessAllowed(IPAddress &from, HttpRequest * icp_request); -SQUIDCEXTERN void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const struct sockaddr_in *from); +SQUIDCEXTERN void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const IPAddress &from); extern icp_opcode icpGetCommonOpcode(); -SQUIDCEXTERN int icpUdpSend(int, const struct sockaddr_in *, icp_common_t *, log_type, int); +SQUIDCEXTERN int icpUdpSend(int, const IPAddress &, icp_common_t *, log_type, int); SQUIDCEXTERN log_type icpLogFromICPCode(icp_opcode opcode); -void icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd); +void icpDenyAccess(IPAddress &from, char *url, int reqnum, int fd); SQUIDCEXTERN PF icpHandleUdp; SQUIDCEXTERN PF icpUdpSendQueue; -SQUIDCEXTERN void icpHandleIcpV3(int, struct sockaddr_in, char *, int); +SQUIDCEXTERN void icpHandleIcpV3(int, IPAddress &, char *, int); SQUIDCEXTERN int icpCheckUdpHit(StoreEntry *, HttpRequest * request); SQUIDCEXTERN void icpConnectionsOpen(void); SQUIDCEXTERN void icpConnectionShutdown(void); diff --git a/src/IPInterception.cc b/src/IPInterception.cc index 83a9c21667..a8ec83b0bd 100644 --- a/src/IPInterception.cc +++ b/src/IPInterception.cc @@ -1,6 +1,6 @@ /* - * $Id: IPInterception.cc,v 1.18 2007/11/07 10:20:47 amosjeffries Exp $ + * $Id: IPInterception.cc,v 1.19 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 89 NAT / IP Interception * AUTHOR: Robert Collins @@ -91,8 +91,11 @@ #if IPF_TRANSPARENT int -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst) { + dst = me; + if( !me.IsIPv4() ) return -1; + if( !peer.IsIPv4() ) return -1; #if defined(IPFILTER_VERSION) && (IPFILTER_VERSION >= 4000027) @@ -117,10 +120,10 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s obj.ipfo_offset = 0; #endif - natLookup.nl_inport = me.sin_port; - natLookup.nl_outport = peer.sin_port; - natLookup.nl_inip = me.sin_addr; - natLookup.nl_outip = peer.sin_addr; + natLookup.nl_inport = htons(me.GetPort()); + natLookup.nl_outport = htons(peer.GetPort()); + me.GetInAddr(natLookup.nl_inip); + peer.GetInAddr(natLookup.nl_outip); natLookup.nl_flags = IPN_TCP; if (natfd < 0) @@ -186,12 +189,12 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s return -1; } else { - if (me.sin_addr.s_addr != natLookup.nl_realip.s_addr) - dst->sin_family = AF_INET; + if (me != natLookup.nl_realip) { + dst = natLookup.nl_realip; - dst->sin_port = natLookup.nl_realport; - - dst->sin_addr = natLookup.nl_realip; + dst.SetPort(ntohs(natLookup.nl_realport)); + } + // else. we already copied it. return 0; } @@ -199,15 +202,21 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s #elif LINUX_NETFILTER int - -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst) { + dst = me; + if( !me.IsIPv4() ) return -1; + if( !peer.IsIPv4() ) return -1; + static time_t last_reported = 0; - socklen_t sock_sz = sizeof(*dst); - memcpy(dst, &me, sizeof(*dst)); + struct addrinfo *lookup = NULL; + + dst.GetAddrInfo(lookup,AF_INET); - if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, dst, &sock_sz) != 0) + if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, lookup->ai_addr, &lookup->ai_addrlen) != 0) { + dst.FreeAddrInfo(lookup); + if (squid_curtime - last_reported > 60) { debugs(89, 1, "clientNatLookup: NF getsockopt(SO_ORIGINAL_DST) failed: " << xstrerror()); last_reported = squid_curtime; @@ -215,10 +224,13 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s return -1; } + dst = *lookup; - debugs(89, 5, "clientNatLookup: addr = " << inet_ntoa(dst->sin_addr) << ""); + dst.FreeAddrInfo(lookup); - if (me.sin_addr.s_addr != dst->sin_addr.s_addr) + debugs(89, 5, "clientNatLookup: addr = " << dst << ""); + + if (me != dst) return 0; else return -1; @@ -227,13 +239,16 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s #elif PF_TRANSPARENT int -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress dst) { struct pfioc_natlook nl; static int pffd = -1; static time_t last_reported = 0; + if( !me.IsIPv4() ) return -1; + if( !peer.IsIPv4() ) return -1; + if (pffd < 0) pffd = open("/dev/pf", O_RDWR); @@ -248,13 +263,15 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s } - memset(dst, 0, sizeof(*dst)); + dst.SetEmpty(); memset(&nl, 0, sizeof(struct pfioc_natlook)); - nl.saddr.v4.s_addr = peer.sin_addr.s_addr; - nl.sport = peer.sin_port; - nl.daddr.v4.s_addr = me.sin_addr.s_addr; - nl.dport = me.sin_port; + peer.GetInAddr(nl.saddr.v4); + nl.sport = htons(peer.GetPort()); + + me.GetInAddr(nl.daddr.v4); + nl.dport = htons(me.GetPort()); + nl.af = AF_INET; nl.proto = IPPROTO_TCP; nl.direction = PF_OUT; @@ -274,10 +291,9 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s return -1; } else { - int natted = me.sin_addr.s_addr != nl.rdaddr.v4.s_addr; - dst->sin_family = AF_INET; - dst->sin_port = nl.rdport; - dst->sin_addr = nl.rdaddr.v4; + int natted = (me != nl.rdaddr.v4); + dst = nl.rdaddr.v4; + dst.SetPort(ntohs(nl.rdport)); if (natted) return 0; @@ -288,27 +304,40 @@ clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct s #elif IPFW_TRANSPARENT int -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst) { - int ret; - struct sockaddr_in s; - int slen = sizeof(struct sockaddr_in); - - ret = getsockname(fd, (struct sockaddr *) &s, (socklen_t * )&slen); - if (ret < 0) { - debugs(89, 1, "clientNatLookup: getpeername failed (fd " << fd << "), errstr " << xstrerror()); - return -1; - } - *dst = s; - return 0; + int ret; + struct addrinfo *lookup = NULL; + + if( !me.IsIPv4() ) return -1; + if( !peer.IsIPv4() ) return -1; + + dst.GetAddrInfo(lookup,AF_INET); + + ret = getsockname(fd, lookup->ai_addr, &lookup->ai_addrlen); + + if (ret < 0) { + + dst.FreeAddrInfo(lookup); + + debugs(89, 1, "clientNatLookup: getpeername failed (fd " << fd << "), errstr " << xstrerror()); + + return -1; + } + + dst = *lookup; + + dst.FreeAddrInfo(lookup); + + return 0; } #else int -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst) +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst) { - debugs(89, 1, "WARNING: transparent proxying not supported"); - return -1; + debugs(89, 1, "WARNING: transparent proxying not supported"); + return -1; } #endif diff --git a/src/IPInterception.h b/src/IPInterception.h index 5a6bf609f7..7c810de544 100644 --- a/src/IPInterception.h +++ b/src/IPInterception.h @@ -1,6 +1,6 @@ /* - * $Id: IPInterception.h,v 1.6 2003/02/21 22:50:05 robertc Exp $ + * $Id: IPInterception.h,v 1.7 2007/12/14 23:11:45 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,8 +34,9 @@ #ifndef SQUID_IPINTERCEPTION_H #define SQUID_IPINTERCEPTION_H -SQUIDCEXTERN int +#include "IPAddress.h" -clientNatLookup(int fd, struct sockaddr_in me, struct sockaddr_in peer, struct sockaddr_in *dst); +SQUIDCEXTERN int +clientNatLookup(int fd, const IPAddress &me, const IPAddress &peer, IPAddress &dst); #endif /* SQUID_IPINTERCEPTION_H */ diff --git a/src/Makefile.am b/src/Makefile.am index d4775064a9..4c9b5391d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.193 2007/10/31 04:52:15 amosjeffries Exp $ +# $Id: Makefile.am,v 1.194 2007/12/14 23:11:45 amosjeffries Exp $ # # Uncomment and customize the following to suit your needs: # @@ -127,6 +127,14 @@ else PINGER = endif +# Squid Internal ICMP sources +ICMPSOURCE = \ + ICMP.h \ + icmp.cc \ + ICMPConfig.h \ + ICMPSquid.h \ + ICMPSquid.cc + SSL_ALL_SOURCE = \ ACLCertificateData.cc \ ACLCertificateData.h \ @@ -134,6 +142,7 @@ SSL_ALL_SOURCE = \ ACLCertificate.h \ ssl_support.cc \ ssl_support.h + if ENABLE_SSL SSL_SOURCE = $(SSL_ALL_SOURCE) else @@ -507,7 +516,7 @@ squid_SOURCES = \ HttpRequestMethod.cc \ HttpRequestMethod.h \ HttpVersion.h \ - icmp.cc \ + $(ICMPSOURCE) \ ICP.h \ icp_v2.cc \ icp_v3.cc \ @@ -704,7 +713,17 @@ ICAP_libicap_a_SOURCES = \ unlinkd_SOURCES = unlinkd_daemon.cc SquidNew.cc +## NP: the pinger contains the squid-external helper code +## $(ICMPSOURCE) contains the interface bit to go inside squid pinger_SOURCES = \ + ICMP.h \ + icmp.cc \ + ICMPPinger.h \ + ICMPPinger.cc \ + ICMPv4.h \ + ICMPv4.cc \ + ICMPv6.h \ + ICMPv6.cc \ pinger.cc \ debug.cc \ time.cc \ @@ -812,7 +831,7 @@ ufsdump_SOURCES = \ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1121,6 +1140,7 @@ check_PROGRAMS+= \ tests/testHeaders \ tests/test_http_range \ tests/testHttpRequest \ + tests/testICMP \ tests/testStore \ tests/testString \ tests/testURL \ @@ -1337,7 +1357,7 @@ tests_testCacheManager_SOURCES = \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1503,7 +1523,7 @@ tests_testEvent_SOURCES = \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1655,7 +1675,7 @@ tests_testEventLoop_SOURCES = \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1835,7 +1855,7 @@ tests_test_http_range_SOURCES = \ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1990,7 +2010,7 @@ tests_testHttpRequest_SOURCES = \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -2075,6 +2095,24 @@ tests_testHttpRequest_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ @SQUID_CPPUNIT_LA@ \ @ICAP_LIBS@ +## Tests of the ICMP base module. +# Its used by pinger so SHOULD NOT require more dependancies! :-( +tests_testICMP_SOURCES=\ + ICMP.h \ + icmp.cc \ + tests/testICMP.h \ + tests/testICMP.cc \ + tests/testMain.cc \ + SquidTime.h \ + time.cc \ + $(TESTSOURCES) +tests_testICMP_LDFLAGS = $(LIBADD_DL) +tests_testICMP_LDADD=\ + @SQUID_CPPUNIT_LIBS@ \ + @SQUID_CPPUNIT_LA@ \ + -L../lib -lmiscutil +tests_testICMP_DEPENDENCIES= @SQUID_CPPUNIT_LA@ \ + $(top_builddir)/lib/libmiscutil.a # TODO:mime.cc drags in HttpReply.cc # delay pools need client_side_request.cc @@ -2328,7 +2366,7 @@ tests_testURL_SOURCES = \ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - icmp.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ diff --git a/src/PeerSelectState.h b/src/PeerSelectState.h index 84f162beda..4a5bef1bb5 100644 --- a/src/PeerSelectState.h +++ b/src/PeerSelectState.h @@ -1,6 +1,6 @@ /* - * $Id: PeerSelectState.h,v 1.2 2006/08/21 00:50:41 robertc Exp $ + * $Id: PeerSelectState.h,v 1.3 2007/12/14 23:11:45 amosjeffries Exp $ * * AUTHOR: Robert Collins * @@ -38,6 +38,7 @@ #include "cbdata.h" #include "PingData.h" +#include "IPAddress.h" class ps_state { @@ -54,27 +55,22 @@ public: void *callback_data; FwdServer *servers; /* - * Why are these struct sockaddr_in instead of peer *? Because a + * Why are these IPAddress instead of peer *? Because a * peer structure can become invalid during the peer selection * phase, specifically after a reconfigure. Thus we need to lookup * the peer * based on the address when we are finally ready to * reference the peer structure. */ - struct sockaddr_in first_parent_miss; + IPAddress first_parent_miss; - struct sockaddr_in closest_parent_miss; + IPAddress closest_parent_miss; /* - * ->hit and ->secho can be peer* because they should only be - * accessed during the thread when they are set + * ->hit can be peer* because it should only be + * accessed during the thread when it is set */ peer *hit; peer_t hit_type; -#if ALLOW_SOURCE_PING - - peer *secho; -#endif - ping_data ping; ACLChecklist *acl_checklist; private: diff --git a/src/SquidTime.h b/src/SquidTime.h index 499521dcd6..0b88c955d1 100644 --- a/src/SquidTime.h +++ b/src/SquidTime.h @@ -1,5 +1,5 @@ /* - * $Id: SquidTime.h,v 1.3 2007/10/31 04:52:16 amosjeffries Exp $ + * $Id: SquidTime.h,v 1.4 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 21 Time Functions * AUTHOR: Harvest Derived @@ -36,6 +36,10 @@ #include "squid.h" +/* globals for accessing time */ +extern struct timeval current_time; +extern double current_dtime; + extern time_t squid_curtime; /* 0 */ time_t getCurrentTime(void); diff --git a/src/access_log.cc b/src/access_log.cc index d763038dc5..bc010f1687 100644 --- a/src/access_log.cc +++ b/src/access_log.cc @@ -1,6 +1,6 @@ /* - * $Id: access_log.cc,v 1.128 2007/08/13 18:25:14 hno Exp $ + * $Id: access_log.cc,v 1.129 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 46 Access Log * AUTHOR: Duane Wessels @@ -545,20 +545,22 @@ accessLogCustom(AccessLogEntry * al, customlog * log) break; case LFT_CLIENT_IP_ADDRESS: - out = inet_ntoa(al->cache.caddr); + if (!out) { + out = al->cache.caddr.NtoA(tmp,1024); + } break; case LFT_CLIENT_FQDN: out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); - - if (!out) - out = inet_ntoa(al->cache.caddr); + if (!out) { + out = al->cache.caddr.NtoA(tmp,1024); + } break; case LFT_CLIENT_PORT: if (al->request) { - outint = al->request->client_port; + outint = al->request->client_addr.GetPort(); doint = 1; } break; @@ -573,14 +575,15 @@ accessLogCustom(AccessLogEntry * al, customlog * log) /* case LFT_SERVER_PORT: */ case LFT_LOCAL_IP: - if (al->request) - out = inet_ntoa(al->request->my_addr); + if (al->request) { + out = al->request->my_addr.NtoA(tmp,1024); + } break; case LFT_LOCAL_PORT: if (al->request) { - outint = al->request->my_port; + outint = al->request->my_addr.GetPort(); doint = 1; } @@ -1269,12 +1272,15 @@ accessLogSquid(AccessLogEntry * al, Logfile * logfile) { const char *client = NULL; const char *user = NULL; + char buf[MAX_IPSTRLEN]; - if (Config.onoff.log_fqdn) + if (Config.onoff.log_fqdn) { client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS); + } - if (client == NULL) - client = inet_ntoa(al->cache.caddr); + if (client == NULL) { + client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN); + } user = accessLogFormatName(al->cache.authuser); @@ -1342,12 +1348,15 @@ accessLogCommon(AccessLogEntry * al, Logfile * logfile) { const char *client = NULL; char *user1 = NULL, *user2 = NULL; + char buf[MAX_IPSTRLEN]; - if (Config.onoff.log_fqdn) + if (Config.onoff.log_fqdn) { client = fqdncache_gethostbyaddr(al->cache.caddr, 0); + } - if (client == NULL) - client = inet_ntoa(al->cache.caddr); + if (client == NULL) { + client = al->cache.caddr.NtoA(buf,MAX_IPSTRLEN); + } user1 = accessLogFormatName(al->cache.authuser); diff --git a/src/asn.cc b/src/asn.cc index a533f2dd11..f123753a45 100644 --- a/src/asn.cc +++ b/src/asn.cc @@ -1,6 +1,6 @@ /* - * $Id: asn.cc,v 1.115 2007/09/21 11:41:52 amosjeffries Exp $ + * $Id: asn.cc,v 1.116 2007/12/14 23:11:45 amosjeffries Exp $ * * DEBUG: section 53 AS Number handling * AUTHOR: Duane Wessels, Kostas Anagnostakis @@ -53,12 +53,15 @@ /* BEGIN of definitions for radix tree entries */ -/* int in memory with length */ -typedef u_char m_int[1 + sizeof(unsigned int)]; -#define store_m_int(i, m) \ - (i = htonl(i), m[0] = sizeof(m_int), xmemcpy(m+1, &i, sizeof(unsigned int))) -#define get_m_int(i, m) \ - (xmemcpy(&i, m+1, sizeof(unsigned int)), ntohl(i)) + +/* AYJ INET6 : Why are these objects being converted to raw u_char memory for use ? */ + +/* 32/128 bits address in memory with length */ +typedef u_char m_ADDR[1 + sizeof(IPAddress)]; +#define store_m_ADDR(i, m) \ + (m[0] = sizeof(IPAddress), xmemcpy(m+1, &i, sizeof(IPAddress)) ) +#define get_m_ADDR(i, m) \ + xmemcpy(&i, m+1, sizeof(IPAddress)) /* END of definitions for radix tree entries */ @@ -100,8 +103,8 @@ struct rtentry_t { struct squid_radix_node e_nodes[2]; as_info *e_info; - m_int e_addr; - m_int e_mask; + m_ADDR e_addr; + m_ADDR e_mask; }; static int asnAddNet(char *, int); @@ -125,28 +128,26 @@ static OBJH asnStats; /* PUBLIC */ int -asnMatchIp(List *data, struct IN_ADDR addr) +asnMatchIp(List *data, IPAddress &addr) { - unsigned long lh; - struct squid_radix_node *rn; as_info *e; - m_int m_addr; + m_ADDR m_addr; List *a = NULL; List *b = NULL; - lh = ntohl(addr.s_addr); - debugs(53, 3, "asnMatchIp: Called for " << inet_ntoa(addr) << "."); + + debugs(53, 3, "asnMatchIp: Called for " << addr ); if (AS_tree_head == NULL) return 0; - if (addr.s_addr == no_addr.s_addr) + if (addr.IsNoAddr()) return 0; - if (addr.s_addr == any_addr.s_addr) + if (addr.IsAnyAddr()) return 0; - store_m_int(lh, m_addr); + store_m_ADDR(addr, m_addr); rn = squid_rn_match(m_addr, AS_tree_head); @@ -389,13 +390,12 @@ asnAddNet(char *as_string, int as_number) rtentry_t *e; struct squid_radix_node *rn; - char dbg1[32], dbg2[32]; List **Tail = NULL; List *q = NULL; as_info *asinfo = NULL; - struct IN_ADDR in_a, in_m; - long mask, addr; + IPAddress mask; + IPAddress addr; char *t; int bitl; @@ -407,37 +407,28 @@ asnAddNet(char *as_string, int as_number) } *t = '\0'; - addr = inet_addr(as_string); + addr = as_string; bitl = atoi(t + 1); if (bitl < 0) bitl = 0; - if (bitl > 32) - bitl = 32; - - mask = bitl ? 0xfffffffful << (32 - bitl) : 0; - - in_a.s_addr = addr; + // INET6 TODO : find a better way of identifying the base IPA family for mask than this. + t = strchr(as_string, '.'); - in_m.s_addr = mask; + // generate Netbits Format Mask + mask.SetNoAddr(); + mask.ApplyMask(bitl, (t!=NULL?AF_INET:AF_INET6) ); - xstrncpy(dbg1, inet_ntoa(in_a), 32); - - xstrncpy(dbg2, inet_ntoa(in_m), 32); - - addr = ntohl(addr); - - /*mask = ntohl(mask); */ - debugs(53, 3, "asnAddNet: called for " << dbg1 << "/" << dbg2); + debugs(53, 3, "asnAddNet: called for " << addr << "/" << mask ); e = (rtentry_t *)xmalloc(sizeof(rtentry_t)); memset(e, '\0', sizeof(rtentry_t)); - store_m_int(addr, e->e_addr); + store_m_ADDR(addr, e->e_addr); - store_m_int(mask, e->e_mask); + store_m_ADDR(mask, e->e_mask); rn = squid_rn_lookup(e->e_addr, e->e_mask, AS_tree_head); @@ -445,7 +436,7 @@ asnAddNet(char *as_string, int as_number) asinfo = ((rtentry_t *) rn)->e_info; if (asinfo->as_number->find(as_number)) { - debugs(53, 3, "asnAddNet: Ignoring repeated network '" << dbg1 << "/" << bitl << "' for AS " << as_number); + debugs(53, 3, "asnAddNet: Ignoring repeated network '" << addr << "/" << bitl << "' for AS " << as_number); } else { debugs(53, 3, "asnAddNet: Warning: Found a network with multiple AS numbers!"); @@ -481,7 +472,6 @@ asnAddNet(char *as_string, int as_number) } static int - destroyRadixNode(struct squid_radix_node *rn, void *w) { @@ -519,39 +509,23 @@ destroyRadixNodeInfo(as_info * e_info) } static int -mask_len(u_long mask) -{ - int len = 32; - - if (mask == 0) - return 0; - - while ((mask & 1) == 0) { - len--; - mask >>= 1; - } - - return len; -} - -static int - printRadixNode(struct squid_radix_node *rn, void *_sentry) { StoreEntry *sentry = (StoreEntry *)_sentry; rtentry_t *e = (rtentry_t *) rn; List *q; as_info *asinfo; + char buf[MAX_IPSTRLEN]; + IPAddress addr; + IPAddress mask; - struct IN_ADDR addr; - - struct IN_ADDR mask; assert(e); assert(e->e_info); - (void) get_m_int(addr.s_addr, e->e_addr); - (void) get_m_int(mask.s_addr, e->e_mask); - storeAppendPrintf(sentry, "%15s/%d\t", - inet_ntoa(addr), mask_len(ntohl(mask.s_addr))); + (void) get_m_ADDR(addr, e->e_addr); + (void) get_m_ADDR(mask, e->e_mask); + storeAppendPrintf(sentry, "%s/%d\t", + addr.NtoA(buf, MAX_IPSTRLEN), + mask.GetCIDR() ); asinfo = e->e_info; assert(asinfo->as_number); @@ -571,7 +545,7 @@ ACLASN::~ACLASN() bool -ACLASN::match(struct IN_ADDR toMatch) +ACLASN::match(IPAddress toMatch) { return asnMatchIp(data, toMatch); } @@ -616,7 +590,7 @@ ACLASN::parse() } } -ACLData * +ACLData * ACLASN::clone() const { if (data) @@ -627,20 +601,20 @@ ACLASN::clone() const /* explicit template instantiation required for some systems */ -template class ACLStrategised +template class ACLStrategised ; ACL::Prototype ACLASN::SourceRegistryProtoype(&ACLASN::SourceRegistryEntry_, "src_as"); -ACLStrategised ACLASN::SourceRegistryEntry_(new ACLASN, ACLSourceASNStrategy::Instance(), "src_as"); +ACLStrategised ACLASN::SourceRegistryEntry_(new ACLASN, ACLSourceASNStrategy::Instance(), "src_as"); ACL::Prototype ACLASN::DestinationRegistryProtoype(&ACLASN::DestinationRegistryEntry_, "dst_as"); -ACLStrategised ACLASN::DestinationRegistryEntry_(new ACLASN, ACLDestinationASNStrategy::Instance(), "dst_as"); +ACLStrategised ACLASN::DestinationRegistryEntry_(new ACLASN, ACLDestinationASNStrategy::Instance(), "dst_as"); int -ACLSourceASNStrategy::match (ACLData * &data, ACLChecklist *checklist) +ACLSourceASNStrategy::match (ACLData * &data, ACLChecklist *checklist) { return data->match(checklist->src_addr); } @@ -657,7 +631,7 @@ ACLSourceASNStrategy ACLSourceASNStrategy::Instance_; int ACLDestinationASNStrategy::match (ACLData * &data, ACLChecklist *checklist) { - const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->host, IP_LOOKUP_IF_MISS); + const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->GetHost(), IP_LOOKUP_IF_MISS); if (ia) { for (int k = 0; k < (int) ia->count; k++) { @@ -666,13 +640,15 @@ ACLDestinationASNStrategy::match (ACLData * &data, ACLChecklist *chec } return 0; + } else if (!checklist->request->flags.destinationIPLookedUp()) { /* No entry in cache, lookup not attempted */ /* XXX FIXME: allow accessing the acl name here */ - debugs(28, 3, "asnMatchAcl: Can't yet compare '" << "unknown" /*name*/ << "' ACL for '" << checklist->request->host << "'"); + debugs(28, 3, "asnMatchAcl: Can't yet compare '" << "unknown" /*name*/ << "' ACL for '" << checklist->request->GetHost() << "'"); checklist->changeState (DestinationIPLookup::Instance()); } else { - return data->match(no_addr); + IPAddress noaddr; noaddr.SetNoAddr(); + return data->match(noaddr); } return 0; diff --git a/src/auth/digest/auth_digest.cc b/src/auth/digest/auth_digest.cc index 8e6a93148e..b01c4a69ed 100644 --- a/src/auth/digest/auth_digest.cc +++ b/src/auth/digest/auth_digest.cc @@ -1,6 +1,5 @@ - /* - * $Id: auth_digest.cc,v 1.59 2007/08/27 12:50:45 hno Exp $ + * $Id: auth_digest.cc,v 1.60 2007/12/14 23:11:51 amosjeffries Exp $ * * DEBUG: section 29 Authenticator * AUTHOR: Robert Collins @@ -48,6 +47,7 @@ #include "HttpRequest.h" #include "HttpReply.h" #include "wordlist.h" +#include "SquidTime.h" /* TODO don't include this */ #include "digestScheme.h" @@ -647,17 +647,17 @@ AuthDigestUserRequest::authenticate(HttpRequest * request, ConnStateData::Pointe } else { const char *useragent = request->header.getStr(HDR_USER_AGENT); - static struct IN_ADDR last_broken_addr; + static IPAddress last_broken_addr; static int seen_broken_client = 0; if (!seen_broken_client) { - last_broken_addr = no_addr; + last_broken_addr.SetNoAddr(); seen_broken_client = 1; } - if (memcmp(&last_broken_addr, &request->client_addr, sizeof(last_broken_addr)) != 0) { + if (last_broken_addr != request->client_addr) { debugs(29, 1, "\nDigest POST bug detected from " << - inet_ntoa(request->client_addr) << " using '" << + request->client_addr << " using '" << (useragent ? useragent : "-") << "'. Please upgrade browser. See Bug #630 for details."); diff --git a/src/auth/negotiate/auth_negotiate.cc b/src/auth/negotiate/auth_negotiate.cc index 9f7ceaccdc..0f7431c571 100644 --- a/src/auth/negotiate/auth_negotiate.cc +++ b/src/auth/negotiate/auth_negotiate.cc @@ -1,6 +1,5 @@ - /* - * $Id: auth_negotiate.cc,v 1.27 2007/09/01 03:51:22 amosjeffries Exp $ + * $Id: auth_negotiate.cc,v 1.28 2007/12/14 23:11:51 amosjeffries Exp $ * * DEBUG: section 29 Negotiate Authenticator * AUTHOR: Robert Collins, Henrik Nordstrom, Francesco Chemolli @@ -46,6 +45,7 @@ #include "client_side.h" #include "HttpReply.h" #include "HttpRequest.h" +#include "SquidTime.h" /* TODO remove this include */ #include "negotiateScheme.h" #include "wordlist.h" diff --git a/src/auth/ntlm/auth_ntlm.cc b/src/auth/ntlm/auth_ntlm.cc index 6e6d963bdf..461c760df9 100644 --- a/src/auth/ntlm/auth_ntlm.cc +++ b/src/auth/ntlm/auth_ntlm.cc @@ -1,6 +1,5 @@ - /* - * $Id: auth_ntlm.cc,v 1.77 2007/09/01 03:51:23 amosjeffries Exp $ + * $Id: auth_ntlm.cc,v 1.78 2007/12/14 23:11:51 amosjeffries Exp $ * * DEBUG: section 29 NTLM Authenticator * AUTHOR: Robert Collins, Henrik Nordstrom, Francesco Chemolli @@ -49,6 +48,7 @@ /* TODO remove this include */ #include "ntlmScheme.h" #include "wordlist.h" +#include "SquidTime.h" static void authenticateNTLMReleaseServer(AuthUserRequest * auth_user_request); diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 0420478e07..0323d93d76 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -1,6 +1,6 @@ /* - * $Id: cache_cf.cc,v 1.528 2007/11/15 23:33:05 wessels Exp $ + * $Id: cache_cf.cc,v 1.529 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 3 Configuration File Parsing * AUTHOR: Harvest Derived @@ -127,11 +127,11 @@ static void dump_denyinfo(StoreEntry * entry, const char *name, acl_deny_info_li static void free_denyinfo(acl_deny_info_list ** var); #if USE_WCCPv2 -static void parse_sockaddr_in_list(sockaddr_in_list **); -static void dump_sockaddr_in_list(StoreEntry *, const char *, const sockaddr_in_list *); -static void free_sockaddr_in_list(sockaddr_in_list **); +static void parse_IPAddress_list(IPAddress_list **); +static void dump_IPAddress_list(StoreEntry *, const char *, const IPAddress_list *); +static void free_IPAddress_list(IPAddress_list **); #if CURRENTLY_UNUSED -static int check_null_sockaddr_in_list(const sockaddr_in_list *); +static int check_null_IPAddress_list(const IPAddress_list *); #endif /* CURRENTLY_UNUSED */ #endif /* USE_WCCPv2 */ @@ -637,9 +637,7 @@ configDoConfigure(void) https_port_list *s; for (s = Config.Sockaddr.https; s != NULL; s = (https_port_list *) s->http.next) { - debugs(3, 1, "Initializing https_port " << - inet_ntoa(s->http.s.sin_addr) << ":" << - ntohs(s->http.s.sin_port) << " SSL context"); + debugs(3, 1, "Initializing https_port " << s->http.s << " SSL context"); s->sslContext = sslCreateServerContext(s->cert, s->key, s->version, s->cipher, s->options, s->sslflags, s->clientca, s->cafile, s->capath, s->crlfile, s->dhfile, s->sslcontext); } @@ -905,18 +903,15 @@ free_acl_access(acl_access ** head) } static void - -dump_address(StoreEntry * entry, const char *name, struct IN_ADDR addr) +dump_address(StoreEntry * entry, const char *name, IPAddress &addr) { - storeAppendPrintf(entry, "%s %s\n", name, inet_ntoa(addr)); + char buf[MAX_IPSTRLEN]; + storeAppendPrintf(entry, "%s %s\n", name, addr.NtoA(buf,MAX_IPSTRLEN) ); } static void - -parse_address(struct IN_ADDR *addr) +parse_address(IPAddress *addr) { - - const struct hostent *hp; char *token = strtok(NULL, w_space); if (!token) { @@ -924,20 +919,24 @@ parse_address(struct IN_ADDR *addr) return; } - if (safe_inet_addr(token, addr) == 1) - (void) 0; - else if ((hp = gethostbyname(token))) /* dont use ipcache */ - *addr = inaddrFromHostent(hp); + if (!strcmp(token,"any_addr")) + { + addr->SetAnyAddr(); + (void) 0; + } + else if ( (!strcmp(token,"no_addr")) || (!strcmp(token,"full_mask")) ) + { + addr->SetNoAddr(); + (void) 0; + } else - self_destruct(); + *addr = token; } static void - -free_address(struct IN_ADDR *addr) +free_address(IPAddress *addr) { - - memset(addr, '\0', sizeof(struct IN_ADDR)); + addr->SetEmpty(); } CBDATA_TYPE(acl_address); @@ -945,11 +944,12 @@ CBDATA_TYPE(acl_address); static void dump_acl_address(StoreEntry * entry, const char *name, acl_address * head) { + char buf[MAX_IPSTRLEN]; acl_address *l; for (l = head; l; l = l->next) { - if (l->addr.s_addr != INADDR_ANY) - storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr)); + if (!l->addr.IsAnyAddr()) + storeAppendPrintf(entry, "%s %s", name, l->addr.NtoA(buf,MAX_IPSTRLEN)); else storeAppendPrintf(entry, "%s autoselect", name); @@ -1598,7 +1598,7 @@ parse_peer(peer ** head) self_destruct(); p->host = xstrdup(token); - + p->name = xstrdup(token); if ((token = strtok(NULL, w_space)) == NULL) @@ -1771,13 +1771,15 @@ parse_peer(peer ** head) } #endif + + p->index = ++Config.npeers; + +// FIXME INET6 : maybe sort peers so the SNMP indexing works better? while (*head != NULL) head = &(*head)->next; *head = p; - Config.npeers++; - peerClearRR(p); } @@ -2667,19 +2669,32 @@ parseNeighborType(const char *s) #if USE_WCCPv2 void -parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token) +parse_IPAddress_list_token(IPAddress_list ** head, char *token) { char *t; char *host; char *tmp; - const struct hostent *hp; + IPAddress ipa; unsigned short port; - sockaddr_in_list *s; + IPAddress_list *s; host = NULL; port = 0; +#if USE_IPV6 + if (*token == '[') { + /* [host]:port */ + host = token + 1; + t = strchr(host, ']'); + if (!t) + self_destruct(); + *t++ = '\0'; + if (*t != ':') + self_destruct(); + port = xatos(t + 1); + } else +#endif if ((t = strchr(token, ':'))) { /* host:port */ host = token; @@ -2695,55 +2710,52 @@ parse_sockaddr_in_list_token(sockaddr_in_list ** head, char *token) port = 0; } - s = static_cast(xcalloc(1, sizeof(*s))); - s->s.sin_port = htons(port); - if (NULL == host) - s->s.sin_addr = any_addr; - else if (1 == safe_inet_addr(host, &s->s.sin_addr)) + ipa.SetAnyAddr(); + else if ( ipa.GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */ (void) 0; - else if ((hp = gethostbyname(host))) /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); else self_destruct(); + /* port MUST be set after the IPA lookup/conversion is perofrmed. */ + ipa.SetPort(port); + while (*head) head = &(*head)->next; + s = static_cast(xcalloc(1, sizeof(*s))); + s->s = ipa; + *head = s; } static void -parse_sockaddr_in_list(sockaddr_in_list ** head) +parse_IPAddress_list(IPAddress_list ** head) { char *token; while ((token = strtok(NULL, w_space))) { - parse_sockaddr_in_list_token(head, token); + parse_IPAddress_list_token(head, token); } } static void -dump_sockaddr_in_list(StoreEntry * e, const char *n, const sockaddr_in_list * s) +dump_IPAddress_list(StoreEntry * e, const char *n, const IPAddress_list * s) { + char ntoabuf[MAX_IPSTRLEN]; + while (s) { - storeAppendPrintf(e, "%s %s:%d\n", + storeAppendPrintf(e, "%s %s\n", n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); + s->s.NtoA(ntoabuf,MAX_IPSTRLEN)); s = s->next; } } static void -free_sockaddr_in_list(sockaddr_in_list ** head) +free_IPAddress_list(IPAddress_list ** head) { - sockaddr_in_list *s; - - while ((s = *head) != NULL) { - *head = s->next; - xfree(s); - } + if(*head) delete *head; *head = NULL; } #if CURRENTLY_UNUSED @@ -2751,7 +2763,7 @@ free_sockaddr_in_list(sockaddr_in_list ** head) * be used by icp_port and htcp_port */ static int -check_null_sockaddr_in_list(const sockaddr_in_list * s) +check_null_IPAddress_list(const IPAdress_list * s) { return NULL == s; } @@ -2763,38 +2775,68 @@ static void parse_http_port_specification(http_port_list * s, char *token) { char *host = NULL; - - const struct hostent *hp; unsigned short port = 0; - char *t; + char *t = NULL; + char *junk = NULL; s->disable_pmtu_discovery = DISABLE_PMTU_OFF; +#if USE_IPV6 + if (*token == '[') { + /* [ipv6]:port */ + host = token + 1; + t = strchr(host, ']'); + if (!t) { + debugs(3, 0, "http(s)_port: missing ']' on IPv6 address: " << token); + self_destruct(); + } + *t++ = '\0'; + if (*t != ':') { + debugs(3, 0, "http(s)_port: missing Port in: " << token); + self_destruct(); + } + port = xatos(t + 1); + } else +#endif if ((t = strchr(token, ':'))) { /* host:port */ + /* ipv4:port */ host = token; *t = '\0'; port = xatos(t + 1); - } else { + + } else if ((port = strtol(token, &junk, 10)), !*junk) { /* port */ - port = xatos(token); + debugs(3, 3, "http(s)_port: found Listen on Port: " << port); + } else { + debugs(3, 0, "http(s)_port: missing Port: " << token); + self_destruct(); } - if (port == 0) + if (port == 0) { + debugs(3, 0, "http(s)_port: Port cannot be 0: " << token); self_destruct(); + } - s->s.sin_port = htons(port); - - if (NULL == host) - s->s.sin_addr = any_addr; - else if (1 == safe_inet_addr(host, &s->s.sin_addr)) - (void) 0; - else if ((hp = gethostbyname(host))) { + if (NULL == host) { + s->s.SetAnyAddr(); + s->s.SetPort(port); + debugs(3, 3, "http(s)_port: found Listen on wildcard address: " << s->s); + } + else if ( s->s = host ) { /* check/parse numeric IPA */ + s->s.SetPort(port); + debugs(3, 3, "http(s)_port: Listen on Host/IP: " << host << " --> " << s->s); + } + else if ( s->s.GetHostByName(host) ) { /* check/parse for FQDN */ /* dont use ipcache */ - s->s.sin_addr = inaddrFromHostent(hp); s->defaultsite = xstrdup(host); - } else + s->s.SetPort(port); + debugs(3, 3, "http(s)_port: found Listen as Host " << s->defaultsite << " on IP: " << s->s); + } + else { + debugs(3, 0, "http(s)_port: failed to resolve Host/IP: " << host); self_destruct(); + } } static void @@ -2809,6 +2851,13 @@ parse_http_port_option(http_port_list * s, char *token) s->name = xstrdup(token + 5); } else if (strcmp(token, "transparent") == 0) { s->transparent = 1; +#if USE_IPV6 + /* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */ + if( !s->s.SetIPv4() ) { + debugs(3, 0, "http(s)_port: IPv6 addresses cannot be 'transparent' (protocol does not provide NAT)" << s->s ); + self_destruct(); + } +#endif } else if (strcmp(token, "vhost") == 0) { s->vhost = 1; s->accel = 1; @@ -2838,8 +2887,21 @@ parse_http_port_option(http_port_list * s, char *token) } else if (strcmp(token, "tproxy") == 0) { s->tproxy = 1; need_linux_tproxy = 1; +#if USE_IPV6 + /* INET6: until transparent REDIRECT works on IPv6 SOCKET, force wildcard to IPv4 */ + if( s->s.IsIPv6() && !s->s.SetIPv4() ) { + debugs(3, 0, "http(s)_port: IPv6 addresses cannot be transparent (protocol does not provide NAT)" << s->s ); + self_destruct(); + } +#endif +#endif + } else if (strcmp(token, "ipv4") == 0) { +#if USE_IPV6 + if( !s->s.SetIPv4() ) { + debugs(3, 0, "http(s)_port: IPv6 addresses cannot be used a IPv4-Only." << s->s ); + self_destruct(); + } #endif - } else { self_destruct(); } @@ -2905,10 +2967,11 @@ parse_http_port_list(http_port_list ** head) static void dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s) { - storeAppendPrintf(e, "%s %s:%d", + char buf[MAX_IPSTRLEN]; + + storeAppendPrintf(e, "%s %s", n, - inet_ntoa(s->s.sin_addr), - ntohs(s->s.sin_port)); + s->s.ToURL(buf,MAX_IPSTRLEN)); if (s->defaultsite) storeAppendPrintf(e, " defaultsite=%s", s->defaultsite); diff --git a/src/cf.data.depend b/src/cf.data.depend index dfce077457..389f5107f3 100644 --- a/src/cf.data.depend +++ b/src/cf.data.depend @@ -38,7 +38,7 @@ peer_access cache_peer acl refreshpattern removalpolicy size_t -sockaddr_in_list +IPAddress_list string string time_t diff --git a/src/cf.data.pre b/src/cf.data.pre index 01070d1702..aa85737cee 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.488 2007/11/15 23:33:05 wessels Exp $ +# $Id: cf.data.pre,v 1.489 2007/12/14 23:11:46 amosjeffries Exp $ # # SQUID Web Proxy Cache http://www.squid-cache.org/ # ---------------------------------------------------------- @@ -368,6 +368,11 @@ DOC_START cached entry should be initiated without needing to wait for a new reply. (default 0 for no grace period) protocol=2.5 Compatibility mode for Squid-2.5 external acl helpers + ipv4 / ipv6 IP-mode used to communicate to this helper. + For compatability with older configurations and helpers + 'ipv4' is the default unless --with-localhost-ipv6 is used. + --with-localhost-ipv6 changes the default to 'ipv6'. + SPECIAL NOTE: these options override --with-localhost-ipv6 FORMAT specifications @@ -1110,6 +1115,28 @@ DOC_START incompatible with the use of server side persistent connections. To ensure correct results it is best to set server_persistent_connections to off when using this directive in such configurations. + + + IPv6 Magic: + + Squid is built with a capability of bridging the IPv4 and IPv6 internets. + tcp_outgoing_address as exampled above breaks this bridging by forcing + all outbound traffic through a certain IPv4 which may be on the wrong + side of the IPv4/IPv6 boundary. + + To operate with tcp_outgoing_address and keep the bridging benefits + an additional ACL needs to be used which ensures the IPv6-bound traffic + is never forced or permitted out the IPv4 interface. + + acl to_ipv6 dst ipv6 + tcp_outgoing_address 2002::c001 good_service_net to_ipv6 + tcp_outgoing_address 10.0.0.2 good_service_net !to_ipv6 + + tcp_outgoing_address 2002::beef normal_service_net to_ipv6 + tcp_outgoing_address 10.0.0.1 normal_service_net !to_ipv6 + + tcp_outgoing_address 2002::1 to_ipv6 + tcp_outgoing_address 10.0.0.3 !to_ipv6 DOC_END COMMENT_START @@ -2343,12 +2370,23 @@ DOC_END NAME: pinger_program TYPE: string DEFAULT: @DEFAULT_PINGER@ -LOC: Config.Program.pinger +LOC: Config.pinger.program IFDEF: USE_ICMP DOC_START Specify the location of the executable for the pinger process. DOC_END +NAME: pinger_enable +TYPE: onoff +DEFAULT: on +LOC: Config.pinger.enable +IFDEF: USE_ICMP +DOC_START + Control whether the pinger is active at run-time. + Enables turning ICMP pinger on and off with a simple squid -k reconfigure. +DOC_END + + COMMENT_START OPTIONS FOR URL REWRITING ----------------------------------------------------------------------------- @@ -3603,7 +3641,7 @@ DEFAULT: 0.0.0.0 IFDEF: USE_WCCP DOC_NONE NAME: wccp2_router -TYPE: sockaddr_in_list +TYPE: IPAddress_list LOC: Config.Wccp2.router DEFAULT: none IFDEF: USE_WCCPv2 @@ -5045,6 +5083,26 @@ DOC_START nameservers by setting this option to 'off'. DOC_END +NAME: dns_v4_fallback +TYPE: onoff +DEFAULT: on +LOC: Config.onoff.dns_require_A +DOC_START + Standard practice with DNS is to lookup either A or AAAA records + and use the results if it succeeds. Only looking up the other if + the first attempt fails or otherwise produces no results. + + That policy however will cause squid to produce error pages for some + servers that advertise AAAA but are unreachable over IPv6. + + If this is ON squid will always lookup both AAAA and A, using both. + If this is OFF squid will lookup AAAA and only try A if none found. + + WARNING: There are some possibly unwanted side-effects with this on: + *) Doubles the load placed by squid on the DNS network. + *) May negatively impact connection delay times. +DOC_END + NAME: ipcache_size COMMENT: (number of entries) TYPE: int @@ -5349,14 +5407,17 @@ DOC_END NAME: balance_on_multiple_ip TYPE: onoff LOC: Config.onoff.balance_on_multiple_ip -DEFAULT: on +DEFAULT: off DOC_START + Modern IP resolvers in squid sort lookup results by preferred access. + By default squid will use these IP in order and only rotates to + the next listed when the most preffered fails. + Some load balancing servers based on round robin DNS have been found not to preserve user session state across requests to different IP addresses. - By default Squid rotates IP's per request. By disabling - this directive only connection failure triggers rotation. + Enabling this directive Squid rotates IP's per request. DOC_END NAME: pipeline_prefetch diff --git a/src/client_db.cc b/src/client_db.cc index 5ce4ae61c0..39df170a53 100644 --- a/src/client_db.cc +++ b/src/client_db.cc @@ -1,6 +1,6 @@ /* - * $Id: client_db.cc,v 1.71 2007/09/21 11:41:52 amosjeffries Exp $ + * $Id: client_db.cc,v 1.72 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 0 Client Database * AUTHOR: Duane Wessels @@ -42,7 +42,7 @@ static hash_table *client_table = NULL; -static ClientInfo *clientdbAdd(struct IN_ADDR addr); +static ClientInfo *clientdbAdd(const IPAddress &addr); static FREE clientdbFreeItem; static void clientdbStartGC(void); static void clientdbScheduledGC(void *); @@ -56,11 +56,12 @@ static int cleanup_removed; static ClientInfo * -clientdbAdd(struct IN_ADDR addr) +clientdbAdd(const IPAddress &addr) { ClientInfo *c; + char *buf = new char[MAX_IPSTRLEN]; c = (ClientInfo *)memAllocate(MEM_CLIENT_INFO); - c->hash.key = xstrdup(inet_ntoa(addr)); + c->hash.key = addr.NtoA(buf,MAX_IPSTRLEN); c->addr = addr; hash_join(client_table, &c->hash); statCounter.client_http.clients++; @@ -94,15 +95,15 @@ clientdbRegisterWithCacheManager(CacheManager & manager) void -clientdbUpdate(struct IN_ADDR addr, log_type ltype, protocol_t p, size_t size) +clientdbUpdate(const IPAddress &addr, log_type ltype, protocol_t p, size_t size) { - char *key; + char key[MAX_IPSTRLEN]; ClientInfo *c; if (!Config.onoff.client_db) return; - key = inet_ntoa(addr); + addr.NtoA(key,MAX_IPSTRLEN); c = (ClientInfo *) hash_lookup(client_table, key); @@ -140,21 +141,21 @@ clientdbUpdate(struct IN_ADDR addr, log_type ltype, protocol_t p, size_t size) * -1. To get the current value, simply call with delta = 0. */ int - -clientdbEstablished(struct IN_ADDR addr, int delta) +clientdbEstablished(const IPAddress &addr, int delta) { - char *key; + char key[MAX_IPSTRLEN]; ClientInfo *c; if (!Config.onoff.client_db) return 0; - key = inet_ntoa(addr); + addr.NtoA(key,MAX_IPSTRLEN); c = (ClientInfo *) hash_lookup(client_table, key); - if (c == NULL) + if (c == NULL) { c = clientdbAdd(addr); + } if (c == NULL) debug_trap("clientdbUpdate: Failed to add entry"); @@ -167,9 +168,9 @@ clientdbEstablished(struct IN_ADDR addr, int delta) #define CUTOFF_SECONDS 3600 int -clientdbCutoffDenied(struct IN_ADDR addr) +clientdbCutoffDenied(const IPAddress &addr) { - char *key; + char key[MAX_IPSTRLEN]; int NR; int ND; double p; @@ -178,7 +179,7 @@ clientdbCutoffDenied(struct IN_ADDR addr) if (!Config.onoff.client_db) return 0; - key = inet_ntoa(addr); + addr.NtoA(key,MAX_IPSTRLEN); c = (ClientInfo *) hash_lookup(client_table, key); @@ -384,36 +385,35 @@ clientdbStartGC(void) #if SQUID_SNMP -struct in_addr* -client_entry(struct IN_ADDR *current) +IPAddress * +client_entry(IPAddress *current) { ClientInfo *c = NULL; - char *key; + char key[MAX_IPSTRLEN]; if (current) { - key = inet_ntoa(*current); + current->NtoA(key,MAX_IPSTRLEN); hash_first(client_table); - while ((c = (ClientInfo *) hash_next(client_table))) { - if (!strcmp(key, hashKeyStr(&c->hash))) + if (!strcmp(key, hashKeyStr(&c->hash))) break; } - + c = (ClientInfo *) hash_next(client_table); } else { - hash_first(client_table); - c = (ClientInfo *) hash_next(client_table); + hash_first(client_table); + c = (ClientInfo *) hash_next(client_table); } hash_last(client_table); if (c) - return (&c->addr); + return (&c->addr); else - return (NULL); - + return (NULL); + } variable_list * @@ -423,10 +423,12 @@ snmp_meshCtblFn(variable_list * Var, snint * ErrP) static char key[16]; ClientInfo *c = NULL; int aggr = 0; + log_type l; *ErrP = SNMP_ERR_NOERROR; debugs(49, 6, "snmp_meshCtblFn: Current : "); snmpDebugOid(6, Var->name, Var->name_length); + /* FIXME INET6 : This must implement the key for IPv6 address */ 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]); debugs(49, 5, "snmp_meshCtblFn: [" << key << "] requested!"); @@ -440,12 +442,28 @@ snmp_meshCtblFn(variable_list * Var, snint * ErrP) switch (Var->name[LEN_SQ_NET + 2]) { - case MESH_CTBL_ADDR: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) c->addr.s_addr, - SMI_IPADDRESS); + case MESH_CTBL_ADDR_TYPE: + { + int ival; + ival = c->addr.IsIPv4() ? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + ival, SMI_INTEGER); + } break; + case MESH_CTBL_ADDR: + { + Answer = snmp_var_new(Var->name, Var->name_length); + // InetAddress doesn't have its own ASN.1 type, + // like IpAddr does (SMI_IPADDRESS) + // See: rfc4001.txt + Answer->type = ASN_OCTET_STR; + char client[MAX_IPSTRLEN]; + c->addr.NtoA(client,MAX_IPSTRLEN); + Answer->val_len = strlen(client); + Answer->val.string = (u_char *) xstrdup(client); + } + break; case MESH_CTBL_HTBYTES: Answer = snmp_var_new_integer(Var->name, Var->name_length, (snint) c->Http.kbytes_out.kb, diff --git a/src/client_side.cc b/src/client_side.cc index 06c9bb42ef..8ee8a62c79 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.770 2007/12/04 03:35:52 hno Exp $ + * $Id: client_side.cc,v 1.771 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -161,7 +161,7 @@ static void connNoteUseOfBuffer(ConnStateData* conn, size_t byteCount); static int connKeepReadingIncompleteRequest(ConnStateData::Pointer & conn); static void connCancelIncompleteRequests(ConnStateData::Pointer & conn); -static ConnStateData *connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port); +static ConnStateData *connStateCreate(const IPAddress &peer, const IPAddress &me, int fd, http_port_list *port); int ClientSocketContext::fd() const @@ -492,7 +492,9 @@ ClientHttpRequest::logRequest() if (loggingEntry() && loggingEntry()->mem_obj) al.cache.objectSize = loggingEntry()->contentLen(); - al.cache.caddr = getConn() != NULL ? getConn()->log_addr : no_addr; + al.cache.caddr.SetNoAddr(); + + if(getConn() != NULL) al.cache.caddr = getConn()->log_addr; al.cache.size = out.size; @@ -529,7 +531,7 @@ ClientHttpRequest::logRequest() updateCounters(); if (getConn() != NULL) - clientdbUpdate(getConn()->peer.sin_addr, logType, PROTO_HTTP, out.size); + clientdbUpdate(getConn()->peer, logType, PROTO_HTTP, out.size); } delete checklist; @@ -604,7 +606,7 @@ ConnStateData::close() openReference = NULL; fd = -1; flags.readMoreRequests = false; - clientdbEstablished(peer.sin_addr, -1); /* decrement */ + clientdbEstablished(peer, -1); /* decrement */ assert(areAllContextsForThisConnection()); freeAllContexts(); @@ -1720,6 +1722,7 @@ prepareAcceleratedURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, ch int vhost = conn->port->vhost; int vport = conn->port->vport; char *host; + char ntoabuf[MAX_IPSTRLEN]; http->flags.accel = 1; @@ -1772,8 +1775,8 @@ prepareAcceleratedURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, ch http->uri = (char *)xcalloc(url_sz, 1); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - inet_ntoa(http->getConn()->me.sin_addr), - ntohs(http->getConn()->me.sin_port), url); + http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), + http->getConn()->me.GetPort(), url); debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'"); } else if (vport > 0) { /* Put the local socket IP address as the hostname, but static port */ @@ -1781,7 +1784,7 @@ prepareAcceleratedURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, ch http->uri = (char *)xcalloc(url_sz, 1); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - inet_ntoa(http->getConn()->me.sin_addr), + http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), vport, url); debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'"); } @@ -1791,6 +1794,7 @@ static void prepareTransparentURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, const char *req_hdr) { char *host; + char ntoabuf[MAX_IPSTRLEN]; http->flags.transparent = 1; @@ -1812,8 +1816,8 @@ prepareTransparentURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, ch http->uri = (char *)xcalloc(url_sz, 1); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - inet_ntoa(http->getConn()->me.sin_addr), - ntohs(http->getConn()->me.sin_port), url); + http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), + http->getConn()->me.GetPort(), url); debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'"); } } @@ -2096,7 +2100,7 @@ connCancelIncompleteRequests(ConnStateData::Pointer & conn) assert (repContext); repContext->setReplyToError(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, - &conn->peer.sin_addr, NULL, NULL, NULL); + conn->peer, NULL, NULL, NULL); context->registerWithConn(); context->pullData(); } @@ -2147,8 +2151,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC debugs(33, 1, "clientProcessRequest: Invalid Request"); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL, - &conn->peer.sin_addr, NULL, conn->in.buf, NULL); + repContext->setReplyToError(ERR_INVALID_REQ, HTTP_BAD_REQUEST, method, NULL, conn->peer, NULL, conn->in.buf, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; @@ -2160,9 +2163,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC debugs(33, 5, "Invalid URL: " << http->uri); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - repContext->setReplyToError( - ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, - &conn->peer.sin_addr, NULL, NULL, NULL); + repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; @@ -2177,9 +2178,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp)); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); - repContext->setReplyToError( - ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, - &conn->peer.sin_addr, NULL, NULL, NULL); + repContext->setReplyToError(ERR_INVALID_URL, HTTP_BAD_REQUEST, method, http->uri, conn->peer, NULL, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; @@ -2196,12 +2195,11 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC #endif if (internalCheck(request->urlpath.buf())) { - if (internalHostnameIs(request->host) && + if (internalHostnameIs(request->GetHost()) && request->port == getMyPort()) { http->flags.internal = 1; } else if (Config.onoff.global_internal_static && internalStaticCheck(request->urlpath.buf())) { - xstrncpy(request->host, internalHostname(), - SQUIDHOSTNAMELEN); + request->SetHost(internalHostname()); request->port = getMyPort(); http->flags.internal = 1; } @@ -2214,10 +2212,8 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC request->flags.internal = http->flags.internal; setLogUri (http, urlCanonicalClean(request)); - request->client_addr = conn->peer.sin_addr; - request->client_port = ntohs(conn->peer.sin_port); - request->my_addr = conn->me.sin_addr; - request->my_port = ntohs(conn->me.sin_port); + request->client_addr = conn->peer; + request->my_addr = conn->me; request->http_ver = http_ver; if (!urlCheckRequest(request) || @@ -2227,7 +2223,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC assert (repContext); repContext->setReplyToError(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); + conn->peer, request, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; @@ -2241,7 +2237,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC assert (repContext); repContext->setReplyToError(ERR_INVALID_REQ, HTTP_LENGTH_REQUIRED, request->method, NULL, - &conn->peer.sin_addr, request, NULL, NULL); + conn->peer, request, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); conn->flags.readMoreRequests = false; @@ -2277,7 +2273,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC assert (repContext); repContext->setReplyToError(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, - &conn->peer.sin_addr, http->request, NULL, NULL); + conn->peer, http->request, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); goto finish; @@ -2449,6 +2445,7 @@ clientReadRequest(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, /* Bail out quickly on COMM_ERR_CLOSING - close handlers will tidy up */ if (flag == COMM_ERR_CLOSING) { + debugs(33,5, HERE << " FD " << fd << " closing Bailout."); return; } @@ -2666,8 +2663,7 @@ static void clientLifetimeTimeout(int fd, void *data) { ClientHttpRequest *http = (ClientHttpRequest *)data; - debugs(33, 1, "WARNING: Closing client " << inet_ntoa(http->getConn()->peer.sin_addr) << - " connection due to lifetime timeout"); + debugs(33, 1, "WARNING: Closing client " << http->getConn()->peer << " connection due to lifetime timeout"); debugs(33, 1, "\t" << http->uri); comm_close(fd); } @@ -2690,13 +2686,13 @@ okToAccept() ConnStateData * -connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_port_list *port) +connStateCreate(const IPAddress &peer, const IPAddress &me, int fd, http_port_list *port) { ConnStateData *result = new ConnStateData; - result->peer = *peer; - result->log_addr = peer->sin_addr; - result->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; - result->me = *me; + result->peer = peer; + result->log_addr = peer; + result->log_addr.ApplyMask(Config.Addrs.client_netmask.GetCIDR()); + result->me = me; result->fd = fd; result->in.buf = (char *)memAllocBuf(CLIENT_REQ_BUF_SZ, &result->in.allocatedSize); result->port = cbdataReference(port); @@ -2704,10 +2700,10 @@ connStateCreate(struct sockaddr_in *peer, struct sockaddr_in *me, int fd, http_p if (port->transparent) { - struct sockaddr_in dst; + IPAddress dst; - if (clientNatLookup(fd, *me, *peer, &dst) == 0) { - result->me = dst; /* XXX This should be moved to another field */ + if (clientNatLookup(fd, me, peer, dst) == 0) { + result-> me = dst; /* XXX This should be moved to another field */ result->transparent(true); } } @@ -2761,11 +2757,11 @@ httpAccept(int sock, int newfd, ConnectionDetail *details, debugs(33, 4, "httpAccept: FD " << newfd << ": accepted"); fd_note(newfd, "client http connect"); - connState = connStateCreate(&details->peer, &details->me, newfd, s); + connState = connStateCreate(details->peer, details->me, newfd, s); comm_add_close_handler(newfd, connStateClosed, connState); if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(details->peer, FQDN_LOOKUP_IF_MISS); commSetTimeout(newfd, Config.Timeout.request, requestTimeout, connState); @@ -2773,25 +2769,22 @@ httpAccept(int sock, int newfd, ConnectionDetail *details, ACLChecklist identChecklist; - identChecklist.src_addr = details->peer.sin_addr; - - identChecklist.my_addr = details->me.sin_addr; + identChecklist.src_addr = details->peer; - identChecklist.my_port = ntohs(details->me.sin_port); + identChecklist.my_addr = details->me; identChecklist.accessList = cbdataReference(Config.accessList.identLookup); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ if (identChecklist.fastCheck()) - identStart(&details->me, &details->peer, clientIdentDone, connState); - + identStart(details->me, details->peer, clientIdentDone, connState); #endif connState->readSomeData(); - clientdbEstablished(details->peer.sin_addr, 1); + clientdbEstablished(details->peer, 1); incoming_sockets_accepted++; } @@ -2958,11 +2951,11 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details, debugs(33, 5, "httpsAccept: FD " << newfd << " accepted, starting SSL negotiation."); fd_note(newfd, "client https connect"); - connState = connStateCreate(&details->peer, &details->me, newfd, (http_port_list *)s); + connState = connStateCreate(details->peer, details->me, newfd, (http_port_list *)s); comm_add_close_handler(newfd, connStateClosed, connState); if (Config.onoff.log_fqdn) - fqdncache_gethostbyaddr(details->peer.sin_addr, FQDN_LOOKUP_IF_MISS); + fqdncache_gethostbyaddr(details->peer, FQDN_LOOKUP_IF_MISS); commSetTimeout(newfd, Config.Timeout.request, requestTimeout, connState); @@ -2970,24 +2963,22 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details, ACLChecklist identChecklist; - identChecklist.src_addr = details->peer.sin_addr; + identChecklist.src_addr = details->peer; - identChecklist.my_addr = details->me.sin_addr; - - identChecklist.my_port = ntohs(details->me.sin_port); + identChecklist.my_addr = details->me; identChecklist.accessList = cbdataReference(Config.accessList.identLookup); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ if (identChecklist.fastCheck()) - identStart(&details->me, &details->peer, clientIdentDone, connState); + identStart(details->me, details->peer, clientIdentDone, connState); #endif commSetSelect(newfd, COMM_SELECT_READ, clientNegotiateSSL, connState, 0); - clientdbEstablished(details->peer.sin_addr, 1); + clientdbEstablished(details->peer, 1); incoming_sockets_accepted++; } @@ -2998,8 +2989,8 @@ httpsAccept(int sock, int newfd, ConnectionDetail *details, static void clientHttpConnectionsOpen(void) { - http_port_list *s; - int fd; + http_port_list *s = NULL; + int fd = -1; for (s = Config.Sockaddr.http; s; s = s->next) { if (MAXHTTPPORTS == NHttpSockets) { @@ -3011,8 +3002,8 @@ clientHttpConnectionsOpen(void) enter_suid(); fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - s->s.sin_addr, - ntohs(s->s.sin_port), COMM_NONBLOCKING, "HTTP Socket"); + s->s, + COMM_NONBLOCKING, "HTTP Socket"); leave_suid(); if (fd < 0) @@ -3025,9 +3016,8 @@ clientHttpConnectionsOpen(void) debugs(1, 1, "Accepting " << (s->transparent ? "transparently proxied" : s->accel ? "accelerated" : "" ) - << " HTTP connections at " - << inet_ntoa(s->s.sin_addr) << ", port " - << (int) ntohs(s->s.sin_port) << ", FD " << fd << "." ); + << " HTTP connections at " << s->s + << ", FD " << fd << "." ); HttpSockets[NHttpSockets++] = fd; } @@ -3048,16 +3038,14 @@ clientHttpsConnectionsOpen(void) } if (s->sslContext == NULL) { - debugs(1, 1, "Can not accept HTTPS connections at " << - inet_ntoa(s->http.s.sin_addr) << ", port " << - (int) ntohs(s->http.s.sin_port)); + debugs(1, 1, "Can not accept HTTPS connections at " << s->http.s); } enter_suid(); fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - s->http.s.sin_addr, - ntohs(s->http.s.sin_port), COMM_NONBLOCKING, "HTTPS Socket"); + s->http.s, + COMM_NONBLOCKING, "HTTPS Socket"); leave_suid(); if (fd < 0) @@ -3067,9 +3055,7 @@ clientHttpsConnectionsOpen(void) comm_accept(fd, httpsAccept, s); - debugs(1, 1, "Accepting HTTPS connections at " << - inet_ntoa(s->http.s.sin_addr) << ", port " << - (int) ntohs(s->http.s.sin_port) << ", FD " << fd << "."); + debugs(1, 1, "Accepting HTTPS connections at " << s->http.s << ", FD " << fd << "."); HttpSockets[NHttpSockets++] = fd; } diff --git a/src/client_side.h b/src/client_side.h index 5f40f37e1e..8b7e73aa46 100644 --- a/src/client_side.h +++ b/src/client_side.h @@ -1,5 +1,5 @@ /* - * $Id: client_side.h,v 1.26 2007/10/31 04:52:16 amosjeffries Exp $ + * $Id: client_side.h,v 1.27 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -177,11 +177,11 @@ public: */ ClientSocketContext::Pointer currentobject; - struct sockaddr_in peer; + IPAddress peer; - struct sockaddr_in me; + IPAddress me; - struct IN_ADDR log_addr; + IPAddress log_addr; char rfc931[USER_IDENT_SZ]; int nrequests; diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index 05ba37748e..8847abd622 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.cc,v 1.144 2007/11/27 09:36:07 amosjeffries Exp $ + * $Id: client_side_reply.cc,v 1.145 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 88 Client-side Reply Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -60,9 +60,7 @@ CBDATA_CLASS_INIT(clientReplyContext); /* Local functions */ extern "C" CSS clientReplyStatus; -extern ErrorState *clientBuildError(err_type, http_status, char const *, - - struct IN_ADDR *, HttpRequest *); +extern ErrorState *clientBuildError(err_type, http_status, char const *, IPAddress &, HttpRequest *); /* privates */ @@ -91,7 +89,7 @@ clientReplyContext::clientReplyContext(ClientHttpRequest *clientContext) : http void clientReplyContext::setReplyToError( err_type err, http_status status, method_t method, char const *uri, - struct IN_ADDR *addr, HttpRequest * failedrequest, char *unparsedrequest, + IPAddress &addr, HttpRequest * failedrequest, char *unparsedrequest, AuthUserRequest * auth_user_request) { ErrorState *errstate = @@ -690,9 +688,7 @@ clientReplyContext::processMiss() */ if (http->flags.accel && r->flags.loopdetect) { http->al.http.code = HTTP_FORBIDDEN; - err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - &http->getConn()->peer.sin_addr, http->request); + err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request); createStoreEntry(r->method, request_flags()); errorAppendEntry(http->storeEntry(), err); triggerInitialStoreRead(); @@ -738,8 +734,7 @@ clientReplyContext::processOnlyIfCachedMiss() debugs(88, 4, "clientProcessOnlyIfCachedMiss: '" << RequestMethodStr[http->request->method] << " " << http->uri << "'"); http->al.http.code = HTTP_GATEWAY_TIMEOUT; - err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL, - &http->getConn()->peer.sin_addr, http->request); + err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT, NULL, http->getConn()->peer, http->request); removeClientStoreReference(&sc, http); startError(err); } @@ -794,9 +789,7 @@ clientReplyContext::purgeFoundObject(StoreEntry *entry) if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) { http->logType = LOG_TCP_DENIED; - ErrorState *err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - &http->getConn()->peer.sin_addr, http->request); + ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request); startError(err); return; } @@ -836,15 +829,13 @@ clientReplyContext::purgeRequest() if (!Config2.onoff.enable_purge) { http->logType = LOG_TCP_DENIED; - ErrorState *err = - clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, - &http->getConn()->peer.sin_addr, http->request); + ErrorState *err = clientBuildError(ERR_ACCESS_DENIED, HTTP_FORBIDDEN, NULL, http->getConn()->peer, http->request); startError(err); return; } /* Release both IP cache */ - ipcacheInvalidate(http->request->host); + ipcacheInvalidate(http->request->GetHost()); if (!http->flags.purging) purgeRequestFindObjectToPurge(); @@ -1054,7 +1045,7 @@ clientHttpRequestStatus(int fd, ClientHttpRequest const *http) #if SIZEOF_INT64_T == 4 if (http->out.size > 0x7FFF0000) { debugs(88, 1, "WARNING: closing FD " << fd << " to prevent out.size counter overflow"); - debugs(88, 1, "\tclient " << (inet_ntoa(http->getConn() != NULL ? http->getConn()->peer.sin_addr : no_addr))); + debugs(88, 1, "\tclient " << http->getConn()->peer); debugs(88, 1, "\treceived " << http->out.size << " bytes"); debugs(88, 1, "\tURI " << http->log_uri); return 1; @@ -1064,7 +1055,7 @@ clientHttpRequestStatus(int fd, ClientHttpRequest const *http) #if SIZEOF_INT64_T == 4 if (http->out.offset > 0x7FFF0000) { debugs(88, 1, "WARNING: closing FD " << fd < " to prevent out.offset counter overflow"); - debugs(88, 1, "\tclient " << (inet_ntoa(http->getConn() != NULL ? http->getConn()->peer.sin_addr : no_addr))); + debugs(88, 1, "\tclient " << http->getConn()->peer); debugs(88, 1, "\treceived " << http->out.size << " bytes, offset " << http->out.offset); debugs(88, 1, "\tURI " << http->log_uri); return 1; @@ -1431,11 +1422,11 @@ clientReplyContext::identifyFoundObject(StoreEntry *newEntry) #if USE_DNSSERVERS - ipcacheInvalidate(r->host); + ipcacheInvalidate(r->GetHost()); #else - ipcacheInvalidateNegative(r->host); + ipcacheInvalidateNegative(r->GetHost()); #endif /* USE_DNSSERVERS */ @@ -1447,11 +1438,11 @@ clientReplyContext::identifyFoundObject(StoreEntry *newEntry) #if USE_DNSSERVERS - ipcacheInvalidate(r->host); + ipcacheInvalidate(r->GetHost()); #else - ipcacheInvalidateNegative(r->host); + ipcacheInvalidateNegative(r->GetHost()); #endif /* USE_DNSSERVERS */ @@ -1768,10 +1759,10 @@ clientReplyContext::processReplyAccess () } if (http->isReplyBodyTooLarge(reply->content_length)) { - ErrorState *err = - clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, - http->getConn() != NULL ? &http->getConn()->peer.sin_addr : &no_addr, - http->request); + IPAddress tmp_noaddr; tmp_noaddr.SetNoAddr(); + ErrorState *err = clientBuildError(ERR_TOO_BIG, HTTP_FORBIDDEN, NULL, + http->getConn() != NULL ? http->getConn()->peer : tmp_noaddr, + http->request); removeClientStoreReference(&sc, http); HTTPMSGUNLOCK(reply); startError(err); @@ -1817,9 +1808,9 @@ clientReplyContext::processReplyAccessResult(bool accessAllowed) if (page_id == ERR_NONE) page_id = ERR_ACCESS_DENIED; - err = - clientBuildError(page_id, HTTP_FORBIDDEN, NULL, - http->getConn() != NULL ? &http->getConn()->peer.sin_addr : &no_addr, + IPAddress tmp_noaddr; tmp_noaddr.SetNoAddr(); + err = clientBuildError(page_id, HTTP_FORBIDDEN, NULL, + http->getConn() != NULL ? http->getConn()->peer : tmp_noaddr, http->request); removeClientStoreReference(&sc, http); @@ -2078,11 +2069,10 @@ clientReplyContext::createStoreEntry(method_t m, request_flags flags) ErrorState * clientBuildError(err_type page_id, http_status status, char const *url, - - struct IN_ADDR * src_addr, HttpRequest * request) + IPAddress &src_addr, HttpRequest * request) { ErrorState *err = errorCon(page_id, status, request); - err->src_addr = *src_addr; + err->src_addr = src_addr; if (url) err->url = xstrdup(url); diff --git a/src/client_side_reply.h b/src/client_side_reply.h index de223bbc30..0b44eb4201 100644 --- a/src/client_side_reply.h +++ b/src/client_side_reply.h @@ -1,6 +1,6 @@ /* - * $Id: client_side_reply.h,v 1.17 2007/05/09 07:36:24 wessels Exp $ + * $Id: client_side_reply.h,v 1.18 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -40,7 +40,7 @@ #include "clientStream.h" #include "StoreClient.h" #include "client_side_request.h" - +#include "IPAddress.h" class ErrorState; @@ -76,7 +76,7 @@ public: int storeOKTransferDone() const; int storeNotOKTransferDone() const; - void setReplyToError(err_type, http_status, method_t, char const *, struct IN_ADDR *, HttpRequest *, char *, AuthUserRequest *); + void setReplyToError(err_type, http_status, method_t, char const *, IPAddress &, HttpRequest *, char *, AuthUserRequest *); void createStoreEntry(method_t m, request_flags flags); void removeStoreReference(store_client ** scp, StoreEntry ** ep); void removeClientStoreReference(store_client **scp, ClientHttpRequest *http); diff --git a/src/client_side_request.cc b/src/client_side_request.cc index f94e03ebeb..81a5f9be31 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.cc,v 1.96 2007/11/15 23:33:05 wessels Exp $ + * $Id: client_side_request.cc,v 1.97 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 85 Client-side Request Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -334,11 +334,11 @@ clientBeginRequest(method_t method, char const *url, CSCB * streamcallback, /* Internally created requests cannot have bodies today */ request->content_length = 0; - request->client_addr = no_addr; + request->client_addr.SetNoAddr(); - request->my_addr = no_addr; /* undefined for internal requests */ + request->my_addr.SetNoAddr(); /* undefined for internal requests */ - request->my_port = 0; + request->my_addr.SetPort(0); request->http_ver = http_ver; @@ -452,12 +452,15 @@ ClientRequestContext::clientAccessCheckDone(int answer) clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data; clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); + IPAddress tmpnoaddr; tmpnoaddr.SetNoAddr(); repContext->setReplyToError(page_id, status, http->request->method, NULL, - http->getConn() != NULL ? &http->getConn()->peer.sin_addr : &no_addr, http->request, - NULL, http->getConn() != NULL - && http->getConn()->auth_user_request ? http->getConn()-> - auth_user_request : http->request->auth_user_request); + http->getConn() != NULL ? http->getConn()->peer : tmpnoaddr, + http->request, + NULL, + http->getConn() != NULL && http->getConn()->auth_user_request ? + http->getConn()->auth_user_request : http->request->auth_user_request); + node = (clientStreamNode *)http->client_stream.tail->data; clientStreamRead(node, http, node->readBuffer); return; @@ -808,9 +811,7 @@ ClientRequestContext::clientRedirectDone(char *result) new_request->http_ver = old_request->http_ver; new_request->header.append(&old_request->header); new_request->client_addr = old_request->client_addr; - new_request->client_port = old_request->client_port; new_request->my_addr = old_request->my_addr; - new_request->my_port = old_request->my_port; new_request->flags = old_request->flags; new_request->flags.redirected = 1; @@ -1051,7 +1052,6 @@ ClientHttpRequest::doCallouts() ACLChecklist ch; ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; - ch.my_port = request->my_port; ch.request = HTTPMSGLOCK(request); int tos = aclMapTOS(Config.accessList.clientside_tos, &ch); if (tos) diff --git a/src/comm.cc b/src/comm.cc index 02157c5389..c2915271fd 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1,5 +1,6 @@ + /* - * $Id: comm.cc,v 1.438 2007/10/31 04:52:16 amosjeffries Exp $ + * $Id: comm.cc,v 1.439 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 5 Socket Functions * AUTHOR: Harvest Derived @@ -45,6 +46,7 @@ #include "MemBuf.h" #include "pconn.h" #include "SquidTime.h" +#include "IPAddress.h" #if defined(_SQUID_CYGWIN_) #include @@ -229,13 +231,16 @@ public: void connect(); void callCallback(comm_err_t status, int xerrno); void defaults(); + +// defaults given by client char *host; - u_short port; + u_short default_port; + IPAddress default_addr; + // NP: CANNOT store the default addr:port together as it gets set/reset differently. - struct sockaddr_in S; + IPAddress S; CallBack callback; - struct IN_ADDR in_addr; int fd; int tries; int addrcount; @@ -249,7 +254,7 @@ private: /* STATIC */ -static comm_err_t commBind(int s, struct IN_ADDR, u_short port); +static comm_err_t commBind(int s, struct addrinfo &); static void commSetReuseAddr(int); static void commSetNoLinger(int); #ifdef TCP_NODELAY @@ -595,10 +600,9 @@ comm_empty_os_read_buffers(int fd) /* prevent those nasty RST packets */ char buf[SQUID_TCP_SO_RCVBUF]; - if (fd_table[fd].flags.nonblocking == 1) - while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0) - - ; + if (fd_table[fd].flags.nonblocking == 1) { + while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0) {}; + } #endif } @@ -713,17 +717,32 @@ fdc_open(int fd, unsigned int type, char const *desc) * synchronous wrapper around udp socket functions */ int -comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) +comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, IPAddress &from) { statCounter.syscalls.sock.recvfroms++; - return recvfrom(fd, buf, len, flags, from, fromlen); + int x = 0; + struct addrinfo *AI = NULL; + + debugs(5,8, "comm_udp_recvfrom: FD " << fd << " from " << from); + + assert( NULL == AI ); + + from.InitAddrInfo(AI); + + x = recvfrom(fd, buf, len, flags, AI->ai_addr, &AI->ai_addrlen); + + from = *AI; + + from.FreeAddrInfo(AI); + + return x; } int comm_udp_recv(int fd, void *buf, size_t len, int flags) { - return comm_udp_recvfrom(fd, buf, len, flags, NULL, 0); + IPAddress nul; + return comm_udp_recvfrom(fd, buf, len, flags, nul); } ssize_t @@ -749,9 +768,8 @@ comm_has_incomplete_write(int fd) u_short comm_local_port(int fd) { - - struct sockaddr_in addr; - socklen_t addr_len = 0; + IPAddress temp; + struct addrinfo *addr = NULL; fde *F = &fd_table[fd]; /* If the fd is closed already, just return */ @@ -761,38 +779,42 @@ comm_local_port(int fd) return 0; } - if (F->local_port) - return F->local_port; + if (F->local_addr.GetPort()) + return F->local_addr.GetPort(); - addr_len = sizeof(addr); + temp.InitAddrInfo(addr); - if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) { + if (getsockname(fd, addr->ai_addr, &(addr->ai_addrlen)) ) { debugs(50, 1, "comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD " << fd << ": " << xstrerror()); + temp.FreeAddrInfo(addr); return 0; } + temp = *addr; + + temp.FreeAddrInfo(addr); + + F->local_addr.SetPort(temp.GetPort()); + + // grab default socket information for this address + temp.GetAddrInfo(addr); + + F->sock_family = addr->ai_family; + + temp.FreeAddrInfo(addr); - F->local_port = ntohs(addr.sin_port); - debugs(5, 6, "comm_local_port: FD " << fd << ": port " << F->local_port); - return F->local_port; + debugs(5, 6, "comm_local_port: FD " << fd << ": port " << F->local_addr.GetPort()); + return F->local_addr.GetPort(); } static comm_err_t -commBind(int s, struct IN_ADDR in_addr, u_short port) +commBind(int s, struct addrinfo &inaddr) { - struct sockaddr_in S; - - memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; - S.sin_port = htons(port); - S.sin_addr = in_addr; statCounter.syscalls.sock.binds++; - if (bind(s, (struct sockaddr *) &S, sizeof(S)) == 0) + if (bind(s, inaddr.ai_addr, inaddr.ai_addrlen) == 0) return COMM_OK; - debugs(50, 0, "commBind: Cannot bind socket FD " << s << " to " << - (S.sin_addr.s_addr == INADDR_ANY ? "*" : inet_ntoa(S.sin_addr)) << - ":" << (int) port << ": " << xstrerror()); + debugs(50, 0, "commBind: Cannot bind socket FD " << s << " to " << fd_table[s].local_addr << ": " << xstrerror()); return COMM_ERROR; } @@ -804,12 +826,11 @@ commBind(int s, struct IN_ADDR in_addr, u_short port) int comm_open(int sock_type, int proto, - struct IN_ADDR addr, - u_short port, + IPAddress &addr, int flags, const char *note) { - return comm_openex(sock_type, proto, addr, port, flags, 0, note); + return comm_openex(sock_type, proto, addr, flags, 0, note); } static bool @@ -832,6 +853,17 @@ comm_set_tos(int fd, int tos) #endif } +void +comm_set_v6only(int fd, int tos) +{ +#ifdef IPV6_V6ONLY + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &tos, sizeof(int)) < 0) { + debugs(50, 1, "comm_open: setsockopt(IPV6_V6ONLY) on FD " << fd << ": " << xstrerror()); + } +#else + debugs(50, 0, "WARNING: comm_open: setsockopt(IPV6_V6ONLY) not supported on this platform"); +#endif /* sockopt */ +} /** * Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE @@ -840,21 +872,29 @@ comm_set_tos(int fd, int tos) int comm_openex(int sock_type, int proto, - struct IN_ADDR addr, - u_short port, + IPAddress &addr, int flags, unsigned char TOS, const char *note) { int new_socket; - int tos = 0; fde *F = NULL; + int tos = 0; + struct addrinfo *AI = NULL; PROF_start(comm_open); /* Create socket for accepting new connections. */ statCounter.syscalls.sock.sockets++; - if ((new_socket = socket(AF_INET, sock_type, proto)) < 0) + /* Setup the socket addrinfo details for use */ + addr.GetAddrInfo(AI); + AI->ai_socktype = sock_type; + AI->ai_protocol = proto; + AI->ai_flags = flags; + + debugs(50, 3, "comm_openex: Attempt open socket for: " << addr ); + + if ((new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) { /* Increase the number of reserved fd's if calls to socket() * are failing because the open file table is full. This @@ -867,27 +907,33 @@ comm_openex(int sock_type, debugs(50, 0, "comm_open: socket failure: " << xstrerror()); } + addr.FreeAddrInfo(AI); + PROF_stop(comm_open); return -1; } + debugs(50, 3, "comm_openex: Opened socket FD " << new_socket << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol ); + /* set TOS if needed */ - if (TOS) - { -#ifdef IP_TOS + if (TOS && comm_set_tos(new_socket, TOS) ) { tos = TOS; + } - if (setsockopt(new_socket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) { - debugs(50, 1, "comm_open: setsockopt(IP_TOS) on FD " << new_socket << ": " << xstrerror()); - } - -#else +#if IPV6_SPECIAL_SPLITSTACK - debugs(50, 0, "comm_open: setsockopt(IP_TOS) not supported on this platform"); + if( addr.IsIPv6() ) + comm_set_v6only(new_socket, tos); #endif - } +#if IPV6_SPECIAL_V4MAPPED && defined(_SQUID_MSWIN_) + + /* Windows Vista supports Dual-Sockets. BUT defaults them to V6ONLY. Turn it OFF. */ + if( addr.IsIPv6() ) + comm_set_v6only(new_socket, 0); + +#endif /* update fdstat */ debugs(5, 5, "comm_open: FD " << new_socket << " is a new socket"); @@ -906,7 +952,9 @@ comm_openex(int sock_type, F->local_addr = addr; - F->tos = tos; + F->tos = TOS; + + F->sock_family = AI->ai_family; if (!(flags & COMM_NOCLOEXEC)) commSetCloseOnExec(new_socket); @@ -914,7 +962,7 @@ comm_openex(int sock_type, if ((flags & COMM_REUSEADDR)) commSetReuseAddr(new_socket); - if (port > (u_short) 0) + if (addr.GetPort() > (u_short) 0) { #ifdef _SQUID_MSWIN_ @@ -927,16 +975,17 @@ comm_openex(int sock_type, commSetReuseAddr(new_socket); } - if (addr.s_addr != no_addr.s_addr) + if (!addr.IsNoAddr()) { - if (commBind(new_socket, addr, port) != COMM_OK) { + if (commBind(new_socket, *AI) != COMM_OK) { comm_close(new_socket); + addr.FreeAddrInfo(AI); return -1; PROF_stop(comm_open); } } - F->local_port = port; + addr.FreeAddrInfo(AI); if (flags & COMM_NONBLOCKING) if (commSetNonBlocking(new_socket) == COMM_ERROR) @@ -982,7 +1031,7 @@ commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void * cs = new ConnectStateData; cs->fd = fd; cs->host = xstrdup(host); - cs->port = port; + cs->default_port = port; cs->callback = CallBack(callback, data); comm_add_close_handler(fd, commConnectFree, cs); ipcache_nbgethostbyname(host, commConnectDnsHandle, cs); @@ -1007,7 +1056,8 @@ commConnectDnsHandle(const ipcache_addrs * ia, void *data) } assert(ia->cur < ia->count); - cs->in_addr = ia->in_addrs[ia->cur]; + + cs->default_addr = ia->in_addrs[ia->cur]; if (Config.onoff.balance_on_multiple_ip) ipcacheCycleAddr(cs->host, NULL); @@ -1022,7 +1072,7 @@ commConnectDnsHandle(const ipcache_addrs * ia, void *data) void ConnectStateData::callCallback(comm_err_t status, int xerrno) { - debugs(5, 3, "commConnectCallback: FD " << fd << ", data " << callback.data); + debugs(5, 3, "commConnectCallback: FD " << fd << ", data " << callback.data << ", status " << status); comm_remove_close_handler(fd, commConnectFree, this); CallBack aCallback = callback; @@ -1069,12 +1119,20 @@ copyFDFlags(int to, fde *F) int ConnectStateData::commResetFD() { + struct addrinfo *AI = NULL; + IPAddress nul; + if (!cbdataReferenceValid(callback.data)) return 0; statCounter.syscalls.sock.sockets++; - int fd2 = socket(AF_INET, SOCK_STREAM, 0); + /* setup a bare-bones addrinfo */ + nul.GetAddrInfo(AI); + + int fd2 = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol); + + nul.FreeAddrInfo(AI); if (fd2 < 0) { debugs(5, 0, "commResetFD: socket: " << xstrerror()); @@ -1112,18 +1170,26 @@ ConnectStateData::commResetFD() * the original socket */ - if (commBind(fd, F->local_addr, F->local_port) != COMM_OK) { + AI = NULL; + F->local_addr.GetAddrInfo(AI); + + if (commBind(fd, *AI) != COMM_OK) { debugs(5, 0, "commResetFD: bind: " << xstrerror()); + F->local_addr.FreeAddrInfo(AI); return 0; } + F->local_addr.FreeAddrInfo(AI); -#ifdef IP_TOS - if (F->tos) { - if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &F->tos, sizeof(int)) < 0) - debugs(50, 1, "commResetFD: setsockopt(IP_TOS) on FD " << fd << ": " << xstrerror()); - } + if (F->tos) + comm_set_tos(fd, F->tos); + +#if IPV6_SPECIAL_SPLITSTACK + + if( F->local_addr.IsIPv6() ) + comm_set_v6only(fd, F->tos); #endif + copyFDFlags (fd, F); return 1; @@ -1167,18 +1233,19 @@ ConnectStateData::Connect (int fd, void *me) void ConnectStateData::defaults() { - S.sin_family = AF_INET; - S.sin_addr = in_addr; - S.sin_port = htons(port); + S = default_addr; + S.SetPort(default_port); } void ConnectStateData::connect() { - if (S.sin_addr.s_addr == 0) + if (S.IsAnyAddr()) defaults(); - switch (comm_connect_addr(fd, &S)) { + debugs(5,5, "ConnectSateData::connect: to " << S); + + switch (comm_connect_addr(fd, S) ) { case COMM_INPROGRESS: debugs(5, 5, "ConnectStateData::connect: FD " << fd << ": COMM_INPROGRESS"); @@ -1186,20 +1253,23 @@ ConnectStateData::connect() break; case COMM_OK: - ipcacheMarkGoodAddr(host, S.sin_addr); + debugs(5, 5, "ConnectStateData::connect: FD " << fd << ": COMM_OK - connected"); + ipcacheMarkGoodAddr(host, S); callCallback(COMM_OK, 0); break; default: + debugs(5, 5, "ConnectStateData::connect: FD " << fd << ": * - try again"); tries++; - ipcacheMarkBadAddr(host, S.sin_addr); + ipcacheMarkBadAddr(host, S); if (Config.onoff.test_reachability) - netdbDeleteAddrNetwork(S.sin_addr); + netdbDeleteAddrNetwork(S); if (commRetryConnect()) { eventAdd("commReconnect", commReconnect, this, this->addrcount == 1 ? 0.05 : 0.0, 0); } else { + debugs(5, 5, "ConnectStateData::connect: FD " << fd << ": * - ERR tried too many times already."); callCallback(COMM_ERR_CONNECT, errno); } } @@ -1232,16 +1302,23 @@ commSetTimeout(int fd, int timeout, PF * handler, void *data) } int - -comm_connect_addr(int sock, const struct sockaddr_in *address) +comm_connect_addr(int sock, const IPAddress &address) { comm_err_t status = COMM_OK; fde *F = &fd_table[sock]; - int x; + int x = 0; int err = 0; socklen_t errlen; - assert(ntohs(address->sin_port) != 0); + struct addrinfo *AI = NULL; PROF_start(comm_connect_addr); + + assert(address.GetPort() != 0); + + debugs(5, 9, "comm_connect_addr: connecting socket " << sock << " to " << address << " (want family: " << F->sock_family << + ") Old-State=" << fdc_table[sock].active); + + address.GetAddrInfo(AI, F->sock_family); + /* Establish connection. */ errno = 0; @@ -1250,16 +1327,27 @@ comm_connect_addr(int sock, const struct sockaddr_in *address) F->flags.called_connect = 1; statCounter.syscalls.sock.connects++; - x = connect(sock, (struct sockaddr *) address, sizeof(*address)); + x = connect(sock, AI->ai_addr, AI->ai_addrlen); if (x < 0) - debugs(5, 9, "connect FD " << sock << ": " << xstrerror()); + { + debugs(5,5, "comm_connect_addr: sock=" << sock << ", addrinfo( " << + " flags=" << AI->ai_flags << + ", family=" << AI->ai_family << + ", socktype=" << AI->ai_socktype << + ", protocol=" << AI->ai_protocol << + ", &addr=" << AI->ai_addr << + ", addrlen=" << AI->ai_addrlen << + " )" ); + debugs(5, 9, "connect FD " << sock << ": (" << x << ") " << xstrerror()); + debugs(14,9, "connecting to: " << address ); + } } else { #if defined(_SQUID_NEWSOS6_) /* Makoto MATSUSHITA */ - connect(sock, (struct sockaddr *) address, sizeof(*address)); + connect(sock, AI->ai_addr, AI->ai_addrlen); if (errno == EINVAL) { errlen = sizeof(err); @@ -1292,6 +1380,20 @@ comm_connect_addr(int sock, const struct sockaddr_in *address) } +#ifdef _SQUID_LINUX_ + /* 2007-11-27: + * Linux Debian replaces our allocated AI pointer with garbage when + * connect() fails. This leads to segmentation faults deallocating + * the system-allocated memory when we go to clean up our pointer. + * HACK: is to leak the memory returned since we can't deallocate. + */ + if(errno != 0) { + AI = NULL; + } +#endif + + address.FreeAddrInfo(AI); + PROF_stop(comm_connect_addr); if (errno == 0 || errno == EISCONN) @@ -1299,15 +1401,31 @@ comm_connect_addr(int sock, const struct sockaddr_in *address) else if (ignoreErrno(errno)) status = COMM_INPROGRESS; else +#if USE_IPV6 + if( address.IsIPv4() && F->sock_family == AF_INET6 ) { + + /* failover to trying IPv4-only link if an IPv6 one fails */ + /* to catch the edge case of apps listening on IPv4-localhost */ + F->sock_family = AF_INET; + int res = comm_connect_addr(sock, address); + + /* if that fails too, undo our temporary socktype hack so the repeat works properly. */ + if(res == COMM_ERROR) + F->sock_family = AF_INET6; + + return res; + } + else +#endif return COMM_ERROR; - xstrncpy(F->ipaddr, inet_ntoa(address->sin_addr), 16); + address.NtoA(F->ipaddr, MAX_IPSTRLEN); - F->remote_port = ntohs(address->sin_port); + F->remote_port = address.GetPort(); /* remote_port is HS */ if (status == COMM_OK) { - debugs(5, 10, "comm_connect_addr: FD " << sock << " connected to " << F->ipaddr << ":" << F->remote_port); + debugs(5, 10, "comm_connect_addr: FD " << sock << " connected to " << address); } else if (status == COMM_INPROGRESS) { debugs(5, 10, "comm_connect_addr: FD " << sock << " connection pending"); @@ -1324,9 +1442,13 @@ comm_old_accept(int fd, ConnectionDetail &details) PROF_start(comm_accept); statCounter.syscalls.sock.accepts++; int sock; - socklen_t Slen = sizeof(details.peer); + struct addrinfo *gai = NULL; + details.me.InitAddrInfo(gai); + + if ((sock = accept(fd, gai->ai_addr, &gai->ai_addrlen)) < 0) { + + details.me.FreeAddrInfo(gai); - if ((sock = accept(fd, (struct sockaddr *) &details.peer, &Slen)) < 0) { PROF_stop(comm_accept); if (ignoreErrno(errno)) @@ -1344,21 +1466,29 @@ comm_old_accept(int fd, ConnectionDetail &details) } } - Slen = sizeof(details.me); - memset(&details.me, '\0', Slen); + details.peer = *gai; + + details.me.SetEmpty(); + getsockname(sock, gai->ai_addr, &gai->ai_addrlen); + details.me = *gai; - getsockname(sock, (struct sockaddr *) &details.me, &Slen); commSetCloseOnExec(sock); + /* fdstat update */ fd_open(sock, FD_SOCKET, "HTTP Request"); fdd_table[sock].close_file = NULL; fdd_table[sock].close_line = 0; fdc_table[sock].active = 1; fde *F = &fd_table[sock]; - xstrncpy(F->ipaddr, inet_ntoa(details.peer.sin_addr), 16); - F->remote_port = htons(details.peer.sin_port); - F->local_port = htons(details.me.sin_port); + details.peer.NtoA(F->ipaddr,MAX_IPSTRLEN); + F->remote_port = details.peer.GetPort(); + F->local_addr.SetPort(details.me.GetPort()); + F->sock_family = gai->ai_family; + commSetNonBlocking(sock); + + details.me.FreeAddrInfo(gai); + PROF_stop(comm_accept); return sock; } @@ -1592,17 +1722,29 @@ _comm_close(int fd, char const *file, int line) /* Send a udp datagram to specified TO_ADDR. */ int comm_udp_sendto(int fd, - - const struct sockaddr_in *to_addr, - int addr_len, + const IPAddress &to_addr, const void *buf, int len) { - int x; + int x = 0; + struct addrinfo *AI = NULL; + PROF_start(comm_udp_sendto); statCounter.syscalls.sock.sendtos++; - x = sendto(fd, buf, len, 0, (struct sockaddr *) to_addr, addr_len); + debugs(50, 3, "comm_udp_sendto: Attempt to send UDP packet to " << to_addr << + " using FD " << fd << " using Port " << comm_local_port(fd) ); + + /* BUG: something in the above macro appears to occasionally be setting AI to garbage. */ + /* AYJ: 2007-08-27 : or was it because I wasn't then setting 'fd_table[fd].sock_family' to fill properly. */ + assert( NULL == AI ); + + to_addr.GetAddrInfo(AI, fd_table[fd].sock_family); + + x = sendto(fd, buf, len, 0, AI->ai_addr, AI->ai_addrlen); + + to_addr.FreeAddrInfo(AI); + PROF_stop(comm_udp_sendto); if (x >= 0) @@ -1613,9 +1755,7 @@ comm_udp_sendto(int fd, if (ECONNREFUSED != errno) #endif - debugs(50, 1, "comm_udp_sendto: FD " << fd << ", " << - inet_ntoa(to_addr->sin_addr) << ", port " << - (int) htons(to_addr->sin_port) << ": " << xstrerror()); + debugs(50, 1, "comm_udp_sendto: FD " << fd << ", (family=" << fd_table[fd].sock_family << ") " << to_addr << ": " << xstrerror()); return COMM_ERROR; } @@ -2508,9 +2648,7 @@ DeferredRead::markCancelled() { cancelled = true; } -ConnectionDetail::ConnectionDetail() { - memset(&me, 0, sizeof(me)); - memset(&peer, 0, sizeof(peer)); +ConnectionDetail::ConnectionDetail() : me(), peer() { } bool diff --git a/src/comm.h b/src/comm.h index db8b62a9bb..89ca9f09c7 100644 --- a/src/comm.h +++ b/src/comm.h @@ -6,6 +6,7 @@ #include "CompletionDispatcher.h" #include "StoreIOBuffer.h" #include "Array.h" +#include "IPAddress.h" #define COMMIO_FD_READCB(fd) (&commfd_table[(fd)].readcb) #define COMMIO_FD_WRITECB(fd) (&commfd_table[(fd)].writecb) @@ -46,19 +47,19 @@ SQUIDCEXTERN void comm_lingering_close(int fd); #endif SQUIDCEXTERN void commConnectStart(int fd, const char *, u_short, CNCB *, void *); -SQUIDCEXTERN int comm_connect_addr(int sock, const struct sockaddr_in *); +SQUIDCEXTERN int comm_connect_addr(int sock, const IPAddress &addr); SQUIDCEXTERN void comm_init(void); SQUIDCEXTERN void comm_exit(void); -SQUIDCEXTERN int comm_open(int, int, struct IN_ADDR, u_short port, int, const char *note); +SQUIDCEXTERN int comm_open(int, int, IPAddress &, int, const char *note); -SQUIDCEXTERN int comm_openex(int, int, struct IN_ADDR, u_short, int, unsigned char TOS, const char *); +SQUIDCEXTERN int comm_openex(int, int, IPAddress &, int, unsigned char TOS, const char *); SQUIDCEXTERN u_short comm_local_port(int fd); SQUIDCEXTERN int comm_set_tos(int fd, int tos); SQUIDCEXTERN void commSetSelect(int, unsigned int, PF *, void *, time_t); -SQUIDCEXTERN int comm_udp_sendto(int, const struct sockaddr_in *, int, const void *, int); +SQUIDCEXTERN int comm_udp_sendto(int sock, const IPAddress &to, const void *buf, int buflen); extern void comm_write(int fd, const char *buf, int len, IOCB *callback, void *callback_data, FREE *func); SQUIDCEXTERN void comm_write_mbuf(int fd, MemBuf *mb, IOCB * handler, void *handler_data); SQUIDCEXTERN void commCallCloseHandlers(int fd); @@ -86,9 +87,7 @@ extern bool comm_has_pending_read(int fd); extern void comm_read(int fd, char *buf, int len, IOCB *handler, void *data); extern void comm_read_cancel(int fd, IOCB *callback, void *data); extern void fdc_open(int fd, unsigned int type, char const *desc); -extern int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, - - struct sockaddr *from, socklen_t *fromlen); +extern int comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, IPAddress &from); extern int comm_udp_recv(int fd, void *buf, size_t len, int flags); extern ssize_t comm_udp_send(int s, const void *buf, size_t len, int flags); extern void commMarkHalfClosed(int); diff --git a/src/comm_select.cc b/src/comm_select.cc index 64d90092e1..ec4ddf842d 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -1,6 +1,6 @@ /* - * $Id: comm_select.cc,v 1.81 2007/06/10 12:13:31 hno Exp $ + * $Id: comm_select.cc,v 1.82 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 5 Socket Functions * @@ -227,7 +227,11 @@ comm_check_incoming_select_handlers(int nfds, int *fds) getCurrentTime(); +#if USE_POLL + statCounter.syscalls.polls++; +#else statCounter.syscalls.selects++; +#endif if (select(maxfd, &read_mask, &write_mask, NULL, &zero_tv) < 1) return incoming_sockets_accepted; @@ -438,7 +442,11 @@ comm_select(int msec) for (;;) { poll_time.tv_sec = msec / 1000; poll_time.tv_usec = (msec % 1000) * 1000; +#if USE_POLL + statCounter.syscalls.polls++; +#else statCounter.syscalls.selects++; +#endif num = select(maxfd, &readfds, &writefds, NULL, &poll_time); statCounter.select_loops++; @@ -709,7 +717,11 @@ examine_select(fd_set * readfds, fd_set * writefds) else continue; +#if USE_POLL + statCounter.syscalls.polls++; +#else statCounter.syscalls.selects++; +#endif errno = 0; diff --git a/src/debug.cc b/src/debug.cc index c707ce80bb..e14f25dc22 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1,5 +1,5 @@ /* - * $Id: debug.cc,v 1.106 2007/12/04 15:20:22 rousskov Exp $ + * $Id: debug.cc,v 1.107 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -173,7 +173,7 @@ _db_print_file(const char *format, va_list args) { vfprintf(debug_log, format, args); - if (!Config.onoff.buffered_logs) +//*AYJ:*/ if (!Config.onoff.buffered_logs) fflush(debug_log); } diff --git a/src/defines.h b/src/defines.h index 50865647a2..9d9beb71fa 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1,6 +1,6 @@ /* - * $Id: defines.h,v 1.122 2007/08/13 17:20:51 hno Exp $ + * $Id: defines.h,v 1.123 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -205,8 +205,6 @@ #define STORE_HDR_METASIZE (4*sizeof(time_t)+2*sizeof(u_short)+sizeof(uint64_t)) #define STORE_HDR_METASIZE_OLD (4*sizeof(time_t)+2*sizeof(u_short)+sizeof(size_t)) -#define PINGER_PAYLOAD_SZ 8192 - #define COUNT_INTERVAL 60 /* * keep 60 minutes' worth of per-minute readings (+ current reading) diff --git a/src/delay_pools.cc b/src/delay_pools.cc index 7ac7af73ad..5b3203d117 100644 --- a/src/delay_pools.cc +++ b/src/delay_pools.cc @@ -1,6 +1,6 @@ /* - * $Id: delay_pools.cc,v 1.49 2007/11/13 23:25:34 rousskov Exp $ + * $Id: delay_pools.cc,v 1.50 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 77 Delay Pools * AUTHOR: Robert Collins @@ -62,6 +62,7 @@ #include "DelayBucket.h" #include "DelayUser.h" #include "DelayTagged.h" +#include "IPAddress.h" long DelayPools::MemoryUsed = 0; @@ -152,7 +153,7 @@ protected: virtual char const *label() const = 0; - virtual unsigned int makeKey (struct IN_ADDR &src_addr) const = 0; + virtual unsigned int makeKey (IPAddress &src_addr) const = 0; DelaySpec spec; @@ -182,7 +183,7 @@ public: protected: virtual char const *label() const {return "Individual";} - virtual unsigned int makeKey (struct IN_ADDR &src_addr) const; + virtual unsigned int makeKey (IPAddress &src_addr) const; }; @@ -196,7 +197,7 @@ public: protected: virtual char const *label() const {return "Network";} - virtual unsigned int makeKey (struct IN_ADDR &src_addr) const; + virtual unsigned int makeKey (IPAddress &src_addr) const; }; /* don't use remote storage for these */ @@ -239,9 +240,9 @@ protected: virtual char const *label() const {return "Individual";} - virtual unsigned int makeKey (struct IN_ADDR &src_addr) const; + virtual unsigned int makeKey (IPAddress &src_addr) const; - unsigned char makeHostKey (struct IN_ADDR &src_addr) const; + unsigned char makeHostKey (IPAddress &src_addr) const; DelaySpec spec; VectorMap buckets; @@ -843,13 +844,17 @@ VectorPool::Id::bytesIn(int qty) theVector->buckets.values[theIndex].bytesIn (qty); } - unsigned int -IndividualPool::makeKey (struct IN_ADDR &src_addr) const +IndividualPool::makeKey (IPAddress &src_addr) const { - unsigned int host; - host = ntohl(src_addr.s_addr) & 0xff; - return host; + /* FIXME INET6 : IPv6 requires a 64-128 bit result from this function */ + if( !src_addr.IsIPv4() ) + return 1; + + /* Temporary bypass for IPv4-only */ + struct in_addr host; + src_addr.GetInAddr(host); + return (ntohl(host.s_addr) & 0xff); } void * @@ -867,11 +872,16 @@ ClassCNetPool::operator delete (void *address) } unsigned int -ClassCNetPool::makeKey (struct IN_ADDR &src_addr) const +ClassCNetPool::makeKey (IPAddress &src_addr) const { - unsigned int net; - net = (ntohl(src_addr.s_addr) >> 8) & 0xff; - return net; + /* FIXME INET6 : IPv6 requires a 64-128 bit result from this function */ + if( !src_addr.IsIPv4() ) + return 1; + + /* Temporary bypass for IPv4-only */ + struct in_addr net; + src_addr.GetInAddr(net); + return ( (ntohl(net.s_addr) >> 8) & 0xff); } @@ -936,19 +946,29 @@ ClassCHostPool::keyAllocated (unsigned char const key) const } unsigned char -ClassCHostPool::makeHostKey (struct IN_ADDR &src_addr) const +ClassCHostPool::makeHostKey (IPAddress &src_addr) const { - unsigned int host; - host = ntohl(src_addr.s_addr) & 0xff; - return host; + /* FIXME INET6 : IPv6 requires a 64-128 bit result from this function */ + if( !src_addr.IsIPv4() ) + return 1; + + /* Temporary bypass for IPv4-only */ + struct in_addr host; + src_addr.GetInAddr(host); + return (ntohl(host.s_addr) & 0xff); } unsigned int -ClassCHostPool::makeKey (struct IN_ADDR &src_addr) const +ClassCHostPool::makeKey (IPAddress &src_addr) const { - unsigned int net; - net = (ntohl(src_addr.s_addr) >> 8) & 0xff; - return net; + /* FIXME INET6 : IPv6 requires a 64-128 bit result from this function */ + if( !src_addr.IsIPv4() ) + return 1; + + /* Temporary bypass for IPv4-only */ + struct in_addr net; + src_addr.GetInAddr(net); + return ( (ntohl(net.s_addr) >> 8) & 0xff); } DelayIdComposite::Pointer diff --git a/src/dns_internal.cc b/src/dns_internal.cc index f927147477..7d16ac9c50 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -1,6 +1,6 @@ /* - * $Id: dns_internal.cc,v 1.101 2007/06/23 21:08:39 hno Exp $ + * $Id: dns_internal.cc,v 1.102 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 78 DNS lookups; interacts with lib/rfc1035.c * AUTHOR: Duane Wessels @@ -116,6 +116,7 @@ struct _idns_query idns_query *queue; unsigned short domain; unsigned short do_searchpath; + bool need_A; }; struct _nsvc @@ -131,8 +132,7 @@ struct _nsvc struct _ns { - - struct sockaddr_in S; + IPAddress S; int nqueries; int nreplies; nsvc *vc; @@ -176,7 +176,7 @@ static void idnsSendQuery(idns_query * q); static IOCB idnsReadVCHeader; static void idnsDoSendQueryVC(nsvc *vc); -static int idnsFromKnownNameserver(struct sockaddr_in *from); +static int idnsFromKnownNameserver(IPAddress const &from); static idns_query *idnsFindQuery(unsigned short id); static void idnsGrokReply(const char *buf, size_t sz); static PF idnsRead; @@ -187,18 +187,17 @@ static void idnsRcodeCount(int, int); static void idnsAddNameserver(const char *buf) { + IPAddress A; - struct IN_ADDR A; - - if (!safe_inet_addr(buf, &A)) { + if (!(A = buf)) { debugs(78, 0, "WARNING: rejecting '" << buf << "' as a name server, because it is not a numeric IP address"); return; } - if (A.s_addr == 0) { - debugs(78, 0, "WARNING: Squid does not accept 0.0.0.0 in DNS server specifications."); - debugs(78, 0, "Will be using 127.0.0.1 instead, assuming you meant that DNS is running on the same machine"); - safe_inet_addr("127.0.0.1", &A); + if (A.IsAnyAddr()) { + debugs(78, 0, "WARNING: Squid does not accept " << A << " in DNS server specifications."); + A = "127.0.0.1"; + debugs(78, 0, "Will be using " << A << " instead, assuming you meant that DNS is running on the same machine"); } if (nns == nns_alloc) { @@ -220,10 +219,9 @@ idnsAddNameserver(const char *buf) } assert(nns < nns_alloc); - nameservers[nns].S.sin_family = AF_INET; - nameservers[nns].S.sin_port = htons(NS_DEFAULTPORT); - nameservers[nns].S.sin_addr.s_addr = A.s_addr; - debugs(78, 3, "idnsAddNameserver: Added nameserver #" << nns << ": " << inet_ntoa(nameservers[nns].S.sin_addr)); + A.SetPort(NS_DEFAULTPORT); + nameservers[nns].S = A; + debugs(78, 3, "idnsAddNameserver: Added nameserver #" << nns << " (" << A << ")"); nns++; } @@ -567,6 +565,7 @@ idnsStats(StoreEntry * sentry) idns_query *q; int i; int j; + char buf[MAX_IPSTRLEN]; storeAppendPrintf(sentry, "Internal DNS Statistics:\n"); storeAppendPrintf(sentry, "\nThe Queue:\n"); storeAppendPrintf(sentry, " DELAY SINCE\n"); @@ -582,12 +581,12 @@ idnsStats(StoreEntry * sentry) } storeAppendPrintf(sentry, "\nNameservers:\n"); - storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES\n"); - storeAppendPrintf(sentry, "--------------- --------- ---------\n"); + storeAppendPrintf(sentry, "IP ADDRESS # QUERIES # REPLIES\n"); + storeAppendPrintf(sentry, "---------------------------------------------- --------- ---------\n"); for (i = 0; i < nns; i++) { - storeAppendPrintf(sentry, "%-15s %9d %9d\n", - inet_ntoa(nameservers[i].S.sin_addr), + storeAppendPrintf(sentry, "%-45s %9d %9d\n", /* Let's take the maximum: (15 IPv4/45 IPv6) */ + nameservers[i].S.NtoA(buf,MAX_IPSTRLEN), nameservers[i].nqueries, nameservers[i].nreplies); } @@ -700,12 +699,14 @@ idnsVCClosed(int fd, void *data) static void idnsInitVC(int ns) { + char buf[MAX_IPSTRLEN]; + nsvc *vc = cbdataAlloc(nsvc); nameservers[ns].vc = vc; - struct IN_ADDR addr; + IPAddress addr; - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) + if (!Config.Addrs.udp_outgoing.IsNoAddr()) addr = Config.Addrs.udp_outgoing; else addr = Config.Addrs.udp_incoming; @@ -717,7 +718,6 @@ idnsInitVC(int ns) vc->fd = comm_open(SOCK_STREAM, IPPROTO_TCP, addr, - 0, COMM_NONBLOCKING, "DNS TCP Socket"); @@ -728,7 +728,7 @@ idnsInitVC(int ns) vc->busy = 1; - commConnectStart(vc->fd, inet_ntoa(nameservers[ns].S.sin_addr), ntohs(nameservers[ns].S.sin_port), idnsInitVCConnected, vc); + commConnectStart(vc->fd, nameservers[ns].S.NtoA(buf,MAX_IPSTRLEN), nameservers[ns].S.GetPort(), idnsInitVCConnected, vc); } static void @@ -757,12 +757,14 @@ idnsSendQuery(idns_query * q) int ns; if (DnsSocket < 0) { - debugs(78, 1, "idnsSendQuery: Can't send query, no DNS socket!"); + debugs(78, 1, "WARNING: idnsSendQuery: Can't send query, no DNS socket!"); return; } - /* XXX Select nameserver */ - assert(nns > 0); + if (nns <= 0) { + debugs(78, 1, "WARNING: idnsSendQuery: Can't send query, no DNS nameservers known!"); + return; + } assert(q->lru.next == NULL); @@ -776,8 +778,7 @@ try_again: x = 0; } else x = comm_udp_sendto(DnsSocket, - &nameservers[ns].S, - sizeof(nameservers[ns].S), + nameservers[ns].S, q->buf, q->sz); @@ -801,17 +802,16 @@ try_again: } static int - -idnsFromKnownNameserver(struct sockaddr_in *from) +idnsFromKnownNameserver(IPAddress const &from) { int i; for (i = 0; i < nns; i++) { - if (nameservers[i].S.sin_addr.s_addr != from->sin_addr.s_addr) + if (nameservers[i].S != from) continue; - if (nameservers[i].S.sin_port != from->sin_port) + if (nameservers[i].S.GetPort() != from.GetPort()) continue; return i; @@ -884,6 +884,16 @@ idnsCallback(idns_query *q, rfc1035_rr *answers, int n, const char *error) } } +void +idnsDropMessage(rfc1035_message *message, idns_query *q) +{ + rfc1035MessageDestroy(&message); + if (q->hash.key) { + hash_remove_link(idns_lookup_hash, &q->hash); + q->hash.key = NULL; + } +} + static void idnsGrokReply(const char *buf, size_t sz) { @@ -891,34 +901,32 @@ idnsGrokReply(const char *buf, size_t sz) rfc1035_message *message = NULL; idns_query *q; - n = rfc1035MessageUnpack(buf, - sz, - &message); + n = rfc1035MessageUnpack(buf, sz, &message); if (message == NULL) { debugs(78, 1, "idnsGrokReply: Malformed DNS response"); return; } - debugs(78, 3, "idnsGrokReply: ID 0x" << std::hex << message->id << ", " << std::dec << n << "answers"); + debugs(78, 3, "idnsGrokReply: ID 0x" << std::hex << message->id << ", " << std::dec << n << " answers"); q = idnsFindQuery(message->id); if (q == NULL) { debugs(78, 3, "idnsGrokReply: Late response"); - rfc1035MessageDestroy(message); + rfc1035MessageDestroy(&message); return; } if (rfc1035QueryCompare(&q->query, message->query) != 0) { debugs(78, 3, "idnsGrokReply: Query mismatch (" << q->query.name << " != " << message->query->name << ")"); - rfc1035MessageDestroy(message); + rfc1035MessageDestroy(&message); return; } if (message->tc) { dlinkDelete(&q->lru, &lru_list); - rfc1035MessageDestroy(message); + rfc1035MessageDestroy(&message); if (!q->need_vc) { q->need_vc = 1; @@ -945,7 +953,8 @@ idnsGrokReply(const char *buf, size_t sz) * unable to process this query due to a problem with * the name server." */ - rfc1035MessageDestroy(message); + debugs(78, 3, "idnsGrokReply: Query result: SERV_FAIL"); + rfc1035MessageDestroy(&message); q->start_t = current_time; q->id = idnsQueryID(); rfc1035SetQueryID(q->buf, q->id); @@ -957,6 +966,8 @@ idnsGrokReply(const char *buf, size_t sz) assert(NULL == message->answer); strcpy(q->name, q->orig); + debugs(78, 3, "idnsGrokReply: Query result: NXDOMAIN - " << q->name ); + if (q->domain < npc) { strcat(q->name, "."); strcat(q->name, searchpath[q->domain].domain); @@ -966,25 +977,60 @@ idnsGrokReply(const char *buf, size_t sz) q->attempt++; } - rfc1035MessageDestroy(message); - if (q->hash.key) { - hash_remove_link(idns_lookup_hash, &q->hash); - q->hash.key = NULL; - } + idnsDropMessage(message, q); + q->start_t = current_time; q->id = idnsQueryID(); rfc1035SetQueryID(q->buf, q->id); - q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, - &q->query); - +#if USE_IPV6 + if(q->query.qtype == RFC1035_TYPE_AAAA) { + debugs(78, 3, "idnsGrokReply: Trying AAAA Query for " << q->name); + q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query); + } + else +#endif + { + debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name); + q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query); + } idnsCacheQuery(q); idnsSendQuery(q); return; } } +#if USE_IPV6 + if(q->need_A && (Config.onoff.dns_require_A == 1 || n <= 0 ) ) + { + /* ERROR or NO AAAA exist. Failover to A records. */ + /* AYJ: Apparently its also a good idea to lookup and store the A records + * just in case the AAAA are not available when we need them. + * This could occur due to number of network failings beyond our control + * thus the || above allowing the user to request always both. + */ + + if(n == 0) + debugs(78, 3, "idnsGrokReply: " << q->name << " has no AAAA records. Looking up A record instead."); + else if(q->need_A && n <= 0) + debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query failed. Trying A now instead."); + else // admin requested this. + debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query done. Configured to retrieve A now also."); + + idnsDropMessage(message, q); + + q->start_t = current_time; + q->id = idnsQueryID(); + rfc1035SetQueryID(q->buf, q->id); + q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query); + q->need_A = false; + idnsCacheQuery(q); + idnsSendQuery(q); + return; + } +#endif + idnsCallback(q, message->answer, n, q->error); - rfc1035MessageDestroy(message); + rfc1035MessageDestroy(&message); cbdataFree(q); } @@ -994,18 +1040,26 @@ idnsRead(int fd, void *data) { int *N = &incoming_sockets_accepted; int len; - - struct sockaddr_in from; - socklen_t from_len; int max = INCOMING_DNS_MAX; static char rbuf[SQUID_UDP_SO_RCVBUF]; int ns; + IPAddress from; + + debugs(78, 1, "idnsRead: starting with FD " << fd); + + /* BUG (UNRESOLVED) + * two code lines after returning from comm_udprecvfrom() + * something overwrites the memory behind the from parameter. + * NO matter where in the stack declaration list above it is placed + * The cause of this is still unknown, however copying the data appears + * to allow it to be passed further without this erasure. + */ + IPAddress bugbypass; while (max--) { - from_len = sizeof(from); - memset(&from, '\0', from_len); + len = comm_udp_recvfrom(fd, rbuf, SQUID_UDP_SO_RCVBUF, 0, bugbypass); - len = comm_udp_recvfrom(fd, rbuf, sizeof(rbuf), 0, (struct sockaddr *) &from, &from_len); + from = bugbypass; // BUG BYPASS. see notes above. if (len == 0) break; @@ -1030,8 +1084,11 @@ idnsRead(int fd, void *data) fd_bytes(DnsSocket, len, FD_READ); assert(N); (*N)++; - debugs(78, 3, "idnsRead: FD " << fd << ": received " << len << " bytes from " << inet_ntoa(from.sin_addr) << "."); - ns = idnsFromKnownNameserver(&from); + + debugs(78, 3, "idnsRead: FD " << fd << ": received " << len << " bytes from " << from); + + /* BUG: see above. Its here that it becomes apparent that the content of bugbypass is gone. */ + ns = idnsFromKnownNameserver(from); if (ns >= 0) { nameservers[ns].nreplies++; @@ -1039,9 +1096,12 @@ idnsRead(int fd, void *data) static time_t last_warning = 0; if (squid_curtime - last_warning > 60) { - debugs(78, 1, "WARNING: Reply from unknown nameserver [" << inet_ntoa(from.sin_addr) << "]"); + debugs(78, 1, "WARNING: Reply from unknown nameserver " << from); last_warning = squid_curtime; } + else { + debugs(78, 1, "WARNING: Reply from unknown nameserver " << from << " (retrying..." << (squid_curtime-last_warning) << "<=60)" ); + } continue; } @@ -1118,7 +1178,7 @@ idnsReadVC(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *dat debugs(78, 3, "idnsReadVC: FD " << fd << ": received " << (int) vc->msg->contentSize() << " bytes via tcp from " << - inet_ntoa(nameservers[vc->ns].S.sin_addr) << "."); + nameservers[vc->ns].S << "."); idnsGrokReply(vc->msg->buf, vc->msg->contentSize()); vc->msg->clean(); @@ -1184,9 +1244,9 @@ idnsInit(void) if (DnsSocket < 0) { int port; - struct IN_ADDR addr; + IPAddress addr; - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) + if (!Config.Addrs.udp_outgoing.IsNoAddr()) addr = Config.Addrs.udp_outgoing; else addr = Config.Addrs.udp_incoming; @@ -1194,10 +1254,11 @@ idnsInit(void) DnsSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, addr, - 0, COMM_NONBLOCKING, "DNS Socket"); + debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addr); + if (DnsSocket < 0) fatal("Could not create a DNS socket"); @@ -1206,8 +1267,7 @@ idnsInit(void) */ port = comm_local_port(DnsSocket); - debugs(78, 1, "DNS Socket created at " << inet_ntoa(addr) << ", port " << - port << ", FD " << DnsSocket); + debugs(78, 1, "DNS Socket created at " << addr << ", FD " << DnsSocket); } assert(0 == nns); @@ -1339,8 +1399,13 @@ idnsALookup(const char *name, IDNSCB * callback, void *data) debugs(78, 3, "idnsALookup: searchpath used for " << q->name); } - q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, - &q->query); +#if USE_IPV6 + q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query); + q->need_A = true; +#else + q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id, &q->query); + q->need_A = false; +#endif if (q->sz < 0) { /* problem with query data -- query not sent */ @@ -1364,18 +1429,34 @@ idnsALookup(const char *name, IDNSCB * callback, void *data) } void - -idnsPTRLookup(const struct IN_ADDR addr, IDNSCB * callback, void *data) +idnsPTRLookup(const IPAddress &addr, IDNSCB * callback, void *data) { idns_query *q; - const char *ip = inet_ntoa(addr); + char ip[MAX_IPSTRLEN]; + + addr.NtoA(ip,MAX_IPSTRLEN); q = cbdataAlloc(idns_query); q->id = idnsQueryID(); - q->sz = rfc1035BuildPTRQuery(addr, q->buf, sizeof(q->buf), q->id, &q->query); +#if USE_IPV6 + if( addr.IsIPv6() ) { + struct in6_addr addr6; + addr.GetInAddr(addr6); + q->sz = rfc3596BuildPTRQuery6(addr6, q->buf, sizeof(q->buf), q->id, &q->query); + } + else +#endif + { + struct in_addr addr4; + addr.GetInAddr(addr4); + q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), q->id, &q->query); + } + + /* PTR does not do inbound A/AAAA */ + q->need_A = false; if (q->sz < 0) { diff --git a/src/dnsserver.cc b/src/dnsserver.cc index eb5deb4db4..f5fd7f8981 100644 --- a/src/dnsserver.cc +++ b/src/dnsserver.cc @@ -1,6 +1,6 @@ /* - * $Id: dnsserver.cc,v 1.72 2007/12/06 18:01:53 rousskov Exp $ + * $Id: dnsserver.cc,v 1.73 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 0 DNS Resolver * AUTHOR: Harvest Derived @@ -140,56 +140,38 @@ #endif #include "util.h" - -#if !defined(_SQUID_AIX_) && !defined(_SQUID_MSWIN_) -extern int h_errno; -#endif +#include "IPAddress.h" #if LIBRESOLV_DNS_TTL_HACK extern int _dns_ttl_; /* this is a really *dirty* hack - bne */ #endif -#ifdef _SQUID_NEXT_ -/* This is a really bloody hack. frank@langen.bull.de - * Workaround bug in gethostbyname which sets h_errno wrong - * WARNING: This hack queries only the resolver and not NetInfo or YP +/* + * res_init() is a macro re-definition of __res_init on: Debian */ +#if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT) +#ifndef res_init +#define res_init __res_init +#endif +#define HAVE_RES_INIT HAVE___RES_INIT +#endif -struct hostent *_res_gethostbyname(char *name); -#define gethostbyname _res_gethostbyname -#endif /* _SQUID_NEXT_ */ - -static struct IN_ADDR no_addr; - -/* error messages from gethostbyname() */ -static char * -my_h_msgs(int x) -{ - if (x == HOST_NOT_FOUND) - return (char *)"Host not found (authoritative)"; - else if (x == TRY_AGAIN) - return (char *)"Host not found (non-authoritative)"; - else if (x == NO_RECOVERY) - return (char *)"Non recoverable errors"; - else if (x == NO_DATA || x == NO_ADDRESS) - return (char *)"Valid name, no data record of requested type"; - else - return (char *)"Unknown DNS problem"; -} #define REQ_SZ 512 static void lookup(const char *buf) { - - const struct hostent *result = NULL; - int reverse = 0; int ttl = 0; int retry = 0; - int i; - - struct IN_ADDR addr; + unsigned int i = 0; + IPAddress ipa; + char ntoabuf[MAX_IPSTRLEN]; + struct addrinfo hints; + struct addrinfo *AI = NULL; + struct addrinfo *aiptr = NULL; + struct addrinfo *prev_addr = NULL; + int res = 0; if (0 == strcmp(buf, "$shutdown")) exit(0); @@ -199,19 +181,19 @@ lookup(const char *buf) return; } - /* check if it's already an IP address in text form. */ + /* setup 'hints' for the system lookup */ + memset(&hints, '\0', sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_CANONNAME; + for (;;) { - if (safe_inet_addr(buf, &addr)) { - reverse = 1; - result = gethostbyaddr((char *) &addr.s_addr, 4, AF_INET); - } else { - result = gethostbyname(buf); - } + xfreeaddrinfo(AI); + AI = NULL; - if (NULL != result) + if( 0 == (res = xgetaddrinfo(buf,NULL,&hints,&AI)) ) break; - if (h_errno != TRY_AGAIN) + if (res != EAI_AGAIN) break; if (++retry == 3) @@ -220,147 +202,243 @@ lookup(const char *buf) sleep(1); } - if (NULL == result) { - if (h_errno == TRY_AGAIN) { - printf("$fail Name Server for domain '%s' is unavailable.\n", buf); - } else { - printf("$fail DNS Domain '%s' is invalid: %s.\n", - buf, my_h_msgs(h_errno)); - } + /* check if it's already an IP address in text form. */ + ipa = buf; + if( ipa.IsAnyAddr() ) { + /* its a domain name. Use the forward-DNS lookup already done */ - return; + if(res == 0) { +#if LIBRESOLV_DNS_TTL_HACK + /* DNS TTL handling - bne@CareNet.hu + * for first try it's a dirty hack, by hacking getanswer + * to place the ttl in a global variable */ + if (_dns_ttl_ > -1) + ttl = _dns_ttl_; +#endif + printf("$addr %d", ttl); + + i = 0; + aiptr = AI; + while(NULL != aiptr && 32 >= i) { + memset(ntoabuf, 0, MAX_IPSTRLEN); + + /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */ + /* BUT sorted fortunately, so we can drop most of them easily */ + if( prev_addr && + prev_addr->ai_family==aiptr->ai_family && + memcmp(aiptr->ai_addr, prev_addr->ai_addr, aiptr->ai_addrlen)==0 + ) { + prev_addr = aiptr; + aiptr = aiptr->ai_next; + continue; + } + else { + prev_addr = aiptr; + } + + /* annoying inet_ntop breaks the nice code by requiring the in*_addr */ + switch(aiptr->ai_family) { + case AF_INET: + xinet_ntop(aiptr->ai_family, &((struct sockaddr_in*)aiptr->ai_addr)->sin_addr, ntoabuf, MAX_IPSTRLEN); + break; +#if USE_IPV6 + case AF_INET6: + xinet_ntop(aiptr->ai_family, &((struct sockaddr_in6*)aiptr->ai_addr)->sin6_addr, ntoabuf, MAX_IPSTRLEN); + break; +#endif + default: + aiptr = aiptr->ai_next; + continue; + } + printf(" %s", ntoabuf); + i++; + aiptr = aiptr->ai_next; + } + + prev_addr=NULL; + printf("\n"); + } } + else /* its an IPA in text form. perform rDNS */ + { + /* You'd expect getaddrinfo given AI_CANONNAME would do a lookup on + * missing FQDN. But no, it only copies the input string to that + * position regardless of its content. + */ + if(NULL != AI && NULL != AI->ai_addr) { + for(;;) { + if( 0 == (res = xgetnameinfo(AI->ai_addr, AI->ai_addrlen, ntoabuf, MAX_IPSTRLEN, NULL,0,0)) ) + break; + + if (res != EAI_AGAIN) + break; + + if (++retry == 3) + break; + + sleep(1); + } + } + if(res == 0) { #if LIBRESOLV_DNS_TTL_HACK - /* DNS TTL handling - bne@CareNet.hu - * for first try it's a dirty hack, by hacking getanswer - * to place the ttl in a global variable */ - if (_dns_ttl_ > -1) - ttl = _dns_ttl_; - + /* DNS TTL handling - bne@CareNet.hu + * for first try it's a dirty hack, by hacking getanswer + * to place the ttl in a global variable */ + if (_dns_ttl_ > -1) + ttl = _dns_ttl_; #endif - if (reverse) { - printf("$name %d %s\n", ttl, result->h_name); - return; + printf("$name %d %s\n", ttl, ntoabuf); + } } - printf("$addr %d", ttl); + switch(res) { + case 0: + /* no error. */ + break; - for (i = 0; NULL != result->h_addr_list[i]; i++) { - if (32 == i) + case EAI_AGAIN: + printf("$fail Name Server for domain '%s' is unavailable.\n", buf); break; - xmemcpy(&addr, result->h_addr_list[i], sizeof(addr)); + case EAI_FAIL: + printf("$fail DNS Domain/IP '%s' does not exist: %s.\n", buf, xgai_strerror(res)); + break; - printf(" %s", inet_ntoa(addr)); +#if defined(EAI_NODATA) || defined(EAI_NONAME) +#ifdef EAI_NODATA + /* deprecated. obsolete on some OS */ + case EAI_NODATA: +#endif +#ifdef EAI_NONAME + case EAI_NONAME: +#endif + printf("$fail DNS Domain/IP '%s' exists without any FQDN/IPs: %s.\n", buf, xgai_strerror(res)); + break; +#endif + default: + printf("$fail A system error occured looking up Domain/IP '%s': %s.\n", buf, xgai_strerror(res)); } - printf("\n"); + xfreeaddrinfo(AI); } static void usage(void) { - fprintf(stderr, "usage: dnsserver -Dhv -s nameserver\n" - "\t-D Enable resolver RES_DEFNAMES and RES_DNSRCH options\n" + fprintf(stderr, "usage: dnsserver -hv -s nameserver\n" "\t-h Help\n" "\t-v Version\n" "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" - "\t must be an IP address, -s option may be repeated\n"); + "\t must be an IPv4 address, -s option may be repeated\n" + ); } +#ifdef _SQUID_RES_NSADDR6_LARRAY +#define _SQUID_RES_NSADDR6_LIST(i) _SQUID_RES_NSADDR6_LARRAY[i].sin6_addr +#endif +#ifdef _SQUID_RES_NSADDR6_LPTR +#define _SQUID_RES_NSADDR6_LIST(i) _SQUID_RES_NSADDR6_LPTR[i]->sin6_addr +#endif + int main(int argc, char *argv[]) { char request[512]; char *t = NULL; int c; +#if defined(_SQUID_FREEBSD_) && defined(_SQUID_RES_NSADDR6_COUNT) + /* Only seems to be valid on FreeBSD 5.5 where _res_ext was provided without an ns6addr counter! */ + /* Gone again on FreeBSD 6.2 along with _res_ext itself in any form. */ + int ns6count = 0; +#endif #if HAVE_RES_INIT + IPAddress ipa; int opt_s = 0; -#if HAVE_RES_NSADDR_LIST || HAVE_RES_NS_LIST +#ifdef _SQUID_RES_NSADDR_LIST extern char *optarg; #endif #endif - safe_inet_addr("255.255.255.255", &no_addr); - #if HAVE_RES_INIT - res_init(); -#ifdef RES_DEFAULT - - _res.options = RES_DEFAULT; -#endif -#ifdef RES_DEFNAMES - - _res.options &= ~RES_DEFNAMES; #endif -#ifdef RES_DNSRCH - _res.options &= ~RES_DNSRCH; -#endif +#if USE_IPV6 + /* perform AAAA lookups *before* A lookups in IPv6 mode. */ + _res.options |= RES_USE_INET6; #endif while ((c = getopt(argc, argv, "Dhs:v")) != -1) { switch (c) { case 'D': -#ifdef RES_DEFNAMES - - _res.options |= RES_DEFNAMES; -#endif -#ifdef RES_DNSRCH - - _res.options |= RES_DNSRCH; -#endif - + fprintf(stderr, "-D is now default behaviour from this tool.\n"); break; case 's': -#if HAVE_RES_INIT +#if HAVE_RES_INIT && (defined(_SQUID_RES_NSADDR_LIST) || defined(_SQUID_RES_NSADDR6_LIST)) if (opt_s == 0) { - _res.nscount = 0; - /* - * Setting RES_INIT here causes coredumps when -s is - * used with -D option. It looks to me like setting - * RES_INIT is wrong. The resolver code sets RES_INIT - * after calling res_init(). When we change the _res - * structure and set RES_INIT, some internal resolver - * structures get confused. -DW 2.1.p1 - */ -#if SEEMS_WRONG - - _res.options |= RES_INIT; +#if defined(_SQUID_RES_NSADDR_COUNT) + _SQUID_RES_NSADDR_COUNT = 0; + /* because I don't trust the nscount super-count entirely, make sure these are ALL invalid */ + memset(_SQUID_RES_NSADDR_LIST, 0, sizeof(struct sockaddr_in)*MAXNS); +#endif +#if defined(_SQUID_RES_NSADDR6_COUNT) + _SQUID_RES_NSADDR6_COUNT = 0; #endif - opt_s = 1; - } else if (_res.nscount == MAXNS) { - fprintf(stderr, "Too many -s options, only %d are allowed\n", - MAXNS); - break; } -#if HAVE_RES_NSADDR_LIST - _res.nsaddr_list[_res.nscount] = _res.nsaddr_list[0]; - - safe_inet_addr(optarg, &_res.nsaddr_list[_res.nscount++].sin_addr); - -#elif HAVE_RES_NS_LIST - - _res.ns_list[_res.nscount] = _res.ns_list[0]; - - safe_inet_addr(optarg, &_res.ns_list[_res.nscount++].addr.sin_addr); - -#else /* Unknown NS list format */ +/* AYJ: + * I experimented with all the permutations of mixed/unmixed nscount/nscount6 IPv4/IPv6/Both/invalid + * + * I'm not sure if splitting them really helps. + * I've seen no evidence of IPv4 resolver *ever* being used when some IPv6 are set (or not even) + * BUT, have seen segfault when IPv4 is added to NSADDR6 list (_res._u._ext). + * It also appears to not do ANY lookup when _res.nscount==0. + * + * BUT, even if _res.nsaddrs is memset to NULL, it resolves IFF IPv6 set in _ext. + * + * SO, am splittig the IPv4/v6 into the seperate _res fields + * and making nscount a total of IPv4+IPv6 /w nscount6 the IPv6 sub-counter + * ie. nscount = count(NSv4)+count(NSv6) & nscount6 = count(NSv6) + * + * If ANYONE knows better please let us know. + * + */ + if( !(ipa = optarg) ) { + fprintf(stderr, "%s appears to be a bad nameserver FQDN/IP.\n",optarg); + } + else if( ipa.IsIPv4() ) { + if (_SQUID_RES_NSADDR_COUNT == MAXNS) { + fprintf(stderr, "Too many -s options, only %d are allowed\n", MAXNS); + break; + } + _SQUID_RES_NSADDR_LIST[_SQUID_RES_NSADDR_COUNT] = _SQUID_RES_NSADDR_LIST[0]; + ipa.GetInAddr(_SQUID_RES_NSADDR_LIST[_SQUID_RES_NSADDR_COUNT++].sin_addr); + } + else if( ipa.IsIPv6() ) { +#if USE_IPV6 && defined(_SQUID_RES_NSADDR6_LIST) - fprintf(stderr, "-s is not supported on this resolver\n"); + /* because things NEVER seem to resolve in tests without _res.nscount being a total. */ + if (_SQUID_RES_NSADDR_COUNT == MAXNS) { + fprintf(stderr, "Too many -s options, only %d are allowed\n", MAXNS); + break; + } + _SQUID_RES_NSADDR_COUNT++; + ipa.GetInAddr(_SQUID_RES_NSADDR6_LIST(_SQUID_RES_NSADDR6_COUNT++)); +#else + fprintf(stderr, "IPv6 nameservers not supported on this resolver\n"); #endif -#else /* !HAVE_RES_INIT */ + } + +#else /* !HAVE_RES_INIT || !defined(_SQUID_RES_NSADDR_LIST) */ fprintf(stderr, "-s is not supported on this resolver\n"); diff --git a/src/errorpage.cc b/src/errorpage.cc index 22d07f3e0d..1f2da04f4f 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -1,6 +1,6 @@ /* - * $Id: errorpage.cc,v 1.227 2007/05/29 13:31:39 amosjeffries Exp $ + * $Id: errorpage.cc,v 1.228 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels @@ -493,6 +493,8 @@ errorDump(ErrorState * err, MemBuf * mb) HttpRequest *r = err->request; MemBuf str; const char *p = NULL; /* takes priority over mb if set */ + char ntoabuf[MAX_IPSTRLEN]; + str.reset(); /* email subject line */ str.Printf("CacheErrorInfo - %s", errorPageName(err->type)); @@ -520,7 +522,7 @@ errorDump(ErrorState * err, MemBuf * mb) str.Printf("TimeStamp: %s\r\n\r\n", mkrfc1123(squid_curtime)); /* - IP stuff */ - str.Printf("ClientIP: %s\r\n", inet_ntoa(err->src_addr)); + str.Printf("ClientIP: %s\r\n", err->src_addr.NtoA(ntoabuf,MAX_IPSTRLEN)); if (r && r->hier.host) { str.Printf("ServerIP: %s\r\n", r->hier.host); @@ -604,6 +606,7 @@ errorConvert(char token, ErrorState * err) static MemBuf mb; const char *p = NULL; /* takes priority over mb if set */ int do_quote = 1; + char ntoabuf[MAX_IPSTRLEN]; mb.reset(); @@ -677,14 +680,14 @@ errorConvert(char token, ErrorState * err) if (r->hier.host) p = r->hier.host; else - p = r->host; + p = r->GetHost(); } else p = "[unknown host]"; break; case 'i': - mb.Printf("%s", inet_ntoa(err->src_addr)); + mb.Printf("%s", err->src_addr.NtoA(ntoabuf,MAX_IPSTRLEN)); break; diff --git a/src/errorpage.h b/src/errorpage.h index 316917f084..203f615123 100644 --- a/src/errorpage.h +++ b/src/errorpage.h @@ -1,6 +1,6 @@ /* - * $Id: errorpage.h,v 1.4 2007/05/09 07:45:58 wessels Exp $ + * $Id: errorpage.h,v 1.5 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,6 +37,7 @@ #include "squid.h" #include "cbdata.h" +#include "IPAddress.h" class AuthUserRequest; @@ -55,7 +56,7 @@ public: char *dnsserver_msg; time_t ttl; - struct IN_ADDR src_addr; + IPAddress src_addr; char *redirect_url; ERCB *callback; void *callback_data; diff --git a/src/event.cc b/src/event.cc index 93947595f4..6b2d8f6ef0 100644 --- a/src/event.cc +++ b/src/event.cc @@ -1,6 +1,5 @@ - /* - * $Id: event.cc,v 1.49 2007/07/30 15:05:42 hno Exp $ + * $Id: event.cc,v 1.50 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 41 Event Processing * AUTHOR: Henrik Nordstrom @@ -36,6 +35,7 @@ #include "event.h" #include "CacheManager.h" #include "Store.h" +#include "SquidTime.h" /* The list of event processes */ @@ -268,14 +268,14 @@ EventScheduler::dump(StoreEntry * sentry) if (last_event_ran) storeAppendPrintf(sentry, "Last event to run: %s\n\n", last_event_ran); - storeAppendPrintf(sentry, "%s\t%s\t%s\t%s\n", + storeAppendPrintf(sentry, "%-25s\t%-15s\t%s\t%s\n", "Operation", "Next Execution", "Weight", "Callback Valid?"); while (e != NULL) { - storeAppendPrintf(sentry, "%s\t%f seconds\t%d\t%s\n", + storeAppendPrintf(sentry, "%-25s\t%0.3f sec\t%5d\t %s\n", e->name, e->when ? e->when - current_dtime : 0, e->weight, (e->arg && e->cbdata) ? cbdataReferenceValid(e->arg) ? "yes" : "no" : "N/A"); e = e->next; diff --git a/src/external_acl.cc b/src/external_acl.cc index 81b979cfe9..c7fb9c6113 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -1,6 +1,6 @@ /* - * $Id: external_acl.cc,v 1.80 2007/05/29 13:31:39 amosjeffries Exp $ + * $Id: external_acl.cc,v 1.81 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -129,6 +129,8 @@ public: } quote; + + IPAddress local_addr; }; struct _external_acl_format @@ -220,9 +222,13 @@ parse_externalAclHelper(external_acl ** list) a = cbdataAlloc(external_acl); + /* set defaults */ a->ttl = DEFAULT_EXTERNAL_ACL_TTL; a->negative_ttl = -1; a->children = DEFAULT_EXTERNAL_ACL_CHILDREN; + a->local_addr.SetLocalhost(); + a->quote = external_acl::QUOTE_METHOD_URL; + token = strtok(NULL, w_space); @@ -233,8 +239,6 @@ parse_externalAclHelper(external_acl ** list) token = strtok(NULL, w_space); - a->quote = external_acl::QUOTE_METHOD_URL; - /* Parse options */ while (token) { if (strncmp(token, "ttl=", 4) == 0) { @@ -257,6 +261,22 @@ parse_externalAclHelper(external_acl ** list) a->quote = external_acl::QUOTE_METHOD_URL; } else if (strcmp(token, "quote=shell") == 0) { a->quote = external_acl::QUOTE_METHOD_SHELL; + + /* INET6: allow admin to configure some helpers explicitly to + bind to IPv4/v6 localhost port. */ + } else if (strcmp(token, "ipv4") == 0) { +#if IPV6_SPECIAL_LOCALHOST + debugs(3, 0, "WARNING: --with-localhost-ipv6 conflicts with external ACL helper to using IPv4: " << a->name ); +#endif + if( !a->local_addr.SetIPv4() ) { + debugs(3, 0, "WARNING: Error converting " << a->local_addr << " to IPv4 in " << a->name ); + } + } else if (strcmp(token, "ipv6") == 0) { +#if !USE_IPV6 + debugs(3, 0, "WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->name ); +#else + (void)0; +#endif } else { break; } @@ -406,6 +426,11 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl for (node = list; node; node = node->next) { storeAppendPrintf(sentry, "%s %s", name, node->name); + if (!node->local_addr.IsIPv6()) + storeAppendPrintf(sentry, " ipv4"); + else + storeAppendPrintf(sentry, " ipv6"); + if (node->ttl != DEFAULT_EXTERNAL_ACL_TTL) storeAppendPrintf(sentry, " ttl=%d", node->ttl); @@ -785,20 +810,20 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) #endif case _external_acl_format::EXT_ACL_SRC: - str = inet_ntoa(ch->src_addr); + str = ch->src_addr.NtoA(buf,sizeof(buf)); break; case _external_acl_format::EXT_ACL_SRCPORT: - snprintf(buf, sizeof(buf), "%d", request->client_port); + snprintf(buf, sizeof(buf), "%d", request->client_addr.GetPort()); str = buf; break; case _external_acl_format::EXT_ACL_MYADDR: - str = inet_ntoa(request->my_addr); + str = request->my_addr.NtoA(buf, sizeof(buf)); break; case _external_acl_format::EXT_ACL_MYPORT: - snprintf(buf, sizeof(buf), "%d", request->my_port); + snprintf(buf, sizeof(buf), "%d", request->my_addr.GetPort()); str = buf; break; @@ -807,7 +832,7 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data) break; case _external_acl_format::EXT_ACL_DST: - str = request->host; + str = request->GetHost(); break; case _external_acl_format::EXT_ACL_PROTO: @@ -1291,6 +1316,8 @@ externalAclInit(void) p->theHelper->ipc_type = IPC_TCP_SOCKET; + p->theHelper->addr = p->local_addr; + helperOpenServers(p->theHelper); } diff --git a/src/fd.cc b/src/fd.cc index 12ee236e1d..04b5f7b0d7 100644 --- a/src/fd.cc +++ b/src/fd.cc @@ -1,6 +1,6 @@ /* - * $Id: fd.cc,v 1.59 2007/09/25 13:24:59 hno Exp $ + * $Id: fd.cc,v 1.60 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 51 Filedescriptor Functions * AUTHOR: Duane Wessels @@ -103,7 +103,7 @@ fd_close(int fd) F->flags.open = 0; fdUpdateBiggest(fd, 0); Number_FD--; - memset(F, '\0', sizeof(fde)); + F->clear(); F->timeout = 0; } @@ -181,7 +181,7 @@ fd_open(int fd, unsigned int type, const char *desc) } assert(!F->flags.open); - debugs(51, 3, "fd_open FD " << fd << " " << desc); + debugs(51, 3, "fd_open() FD " << fd << " " << desc); F->type = type; F->flags.open = 1; F->epoll_state = 0; diff --git a/src/fde.h b/src/fde.h index d53a17c73b..72954e8bef 100644 --- a/src/fde.h +++ b/src/fde.h @@ -1,6 +1,6 @@ /* - * $Id: fde.h,v 1.13 2007/08/13 17:20:51 hno Exp $ + * $Id: fde.h,v 1.14 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -33,7 +33,9 @@ #ifndef SQUID_FDE_H #define SQUID_FDE_H + #include "comm.h" +#include "IPAddress.h" class PconnPool; @@ -41,6 +43,13 @@ class fde { public: + fde() { clear(); }; + /** Clear the fde class properly back to NULL equivalent. */ + inline void clear() { + memset(this, 0, sizeof(fde)); + local_addr.SetEmpty(); // IPAddress likes to be setup nicely. + } + /* NOTE: memset is used on fdes today. 20030715 RBC */ static void DumpStats (StoreEntry *); @@ -50,12 +59,12 @@ public: void noteUse(PconnPool *); unsigned int type; - u_short local_port; u_short remote_port; - struct IN_ADDR local_addr; + IPAddress local_addr; unsigned char tos; - char ipaddr[16]; /* dotted decimal address of peer */ + int sock_family; + char ipaddr[MAX_IPSTRLEN]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; struct diff --git a/src/forward.cc b/src/forward.cc index 69a2bf2765..0da586558f 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -1,6 +1,6 @@ /* - * $Id: forward.cc,v 1.168 2007/07/21 16:32:03 hno Exp $ + * $Id: forward.cc,v 1.169 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 17 Request Forwarding * AUTHOR: Duane Wessels @@ -207,14 +207,13 @@ FwdState::fwdStart(int client_fd, StoreEntry *entry, HttpRequest *request) * be allowed. yuck, I know. */ - if (request->client_addr.s_addr != no_addr.s_addr && request->protocol != PROTO_INTERNAL && request->protocol != PROTO_CACHEOBJ) { + if ( !request->client_addr.IsNoAddr() && request->protocol != PROTO_INTERNAL && request->protocol != PROTO_CACHEOBJ) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ ACLChecklist ch; ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; - ch.my_port = request->my_port; ch.request = HTTPMSGLOCK(request); ch.accessList = cbdataReference(Config.accessList.miss); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ @@ -271,10 +270,8 @@ FwdState::fwdStart(int client_fd, StoreEntry *entry, HttpRequest *request) FwdState::Pointer fwd = new FwdState(client_fd, entry, request); #if LINUX_TPROXY /* If we need to transparently proxy the request - * then we need the client source address and port */ - fwd->src.sin_family = AF_INET; - fwd->src.sin_addr = request->client_addr; - fwd->src.sin_port = request->client_port; + * then we need the client source protocol, address and port */ + fwd->src = request->client_addr; #endif fwd->start(fwd); @@ -660,7 +657,7 @@ FwdState::initiateSSL() SSL_set_session(ssl, peer->sslSession); } else { - SSL_set_ex_data(ssl, ssl_ex_index_server, request->host); + SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)request->GetHost()); } fd_table[fd].ssl = ssl; @@ -690,7 +687,7 @@ FwdState::connectDone(int aServerFD, comm_err_t status, int xerrno) if (NULL == fs->_peer) flags.dont_retry = 1; - debugs(17, 4, "fwdConnectDone: Unknown host: " << request->host); + debugs(17, 4, "fwdConnectDone: Unknown host: " << request->GetHost()); ErrorState *anErr = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, request); @@ -772,10 +769,10 @@ FwdState::connectStart() struct in_tproxy itp; #endif - struct IN_ADDR outgoing; + IPAddress outgoing; unsigned short tos; - struct IN_ADDR *client_addr = NULL; + IPAddress client_addr; assert(fs); assert(server_fd == -1); debugs(17, 3, "fwdConnectStart: " << url); @@ -787,16 +784,16 @@ FwdState::connectStart() : Config.Timeout.peer_connect; if (fs->_peer->options.originserver) - domain = request->host; + domain = request->GetHost(); } else { - host = request->host; + host = request->GetHost(); port = request->port; ctimeout = Config.Timeout.connect; } #if LINUX_TPROXY if (request->flags.tproxy) - client_addr = &request->client_addr; + client_addr = request->client_addr; #endif @@ -831,16 +828,17 @@ FwdState::connectStart() tos = getOutgoingTOS(request); - debugs(17, 3, "fwdConnectStart: got addr " << inet_ntoa(outgoing) << ", tos " << tos); + debugs(17, 3, "fwdConnectStart: got outgoing addr " << outgoing << ", tos " << tos); fd = comm_openex(SOCK_STREAM, IPPROTO_TCP, outgoing, - 0, COMM_NONBLOCKING, tos, url); + debugs(17, 3, "fwdConnectStart: got TCP FD " << fd); + if (fd < 0) { debugs(50, 4, "fwdConnectStart: " << xstrerror()); ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request); @@ -878,6 +876,8 @@ FwdState::connectStart() #if LINUX_TPROXY if (request->flags.tproxy) { + IPAddress addr; + itp.v.addr.faddr.s_addr = src.sin_addr.s_addr; itp.v.addr.fport = 0; @@ -886,10 +886,11 @@ FwdState::connectStart() */ itp.op = TPROXY_ASSIGN; + addr = (struct in_addr)itp.v.addr.faddr; + addr.SetPort(itp.v.addr.fport); + if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) { - debugs(20, 1, "tproxy ip=" << inet_ntoa(itp.v.addr.faddr) << - ",0x" << std::hex << itp.v.addr.faddr.s_addr << std::dec << - ",port=" << itp.v.addr.fport << " ERROR ASSIGN"); + debugs(20, 1, "tproxy ip=" << addr << " ERROR ASSIGN"); request->flags.tproxy = 0; } else { @@ -897,9 +898,7 @@ FwdState::connectStart() itp.v.flags = ITP_CONNECT; if (setsockopt(fd, SOL_IP, IP_TPROXY, &itp, sizeof(itp)) == -1) { - debugs(20, 1, "tproxy ip=" << std::hex << - itp.v.addr.faddr.s_addr << std::dec << ",port=" << - itp.v.addr.fport << " ERROR CONNECT"); + debugs(20, 1, "tproxy ip=" << addr << " ERROR CONNECT"); request->flags.tproxy = 0; } @@ -907,7 +906,7 @@ FwdState::connectStart() } #endif - hierarchyNote(&request->hier, fs->code, request->host); + hierarchyNote(&request->hier, fs->code, request->GetHost()); } commConnectStart(fd, host, port, fwdConnectDoneWrapper, this); @@ -959,7 +958,7 @@ FwdState::dispatch() EBIT_SET(entry->flags, ENTRY_DISPATCHED); - netdbPingSite(request->host); + netdbPingSite(request->GetHost()); if (servers && (p = servers->_peer)) { p->stats.fetches++; @@ -1136,7 +1135,7 @@ FwdState::reforwardableStatus(http_status s) void -FwdState::pconnPush(int fd, const char *host, int port, const char *domain, struct IN_ADDR *client_addr) +FwdState::pconnPush(int fd, const char *host, int port, const char *domain, IPAddress &client_addr) { fwdPconnPool->push(fd, host, port, domain, client_addr); } @@ -1202,12 +1201,12 @@ fwdServerFree(FwdServer * fs) memFree(fs, MEM_FWD_SERVER); } -static struct IN_ADDR - aclMapAddr(acl_address * head, ACLChecklist * ch) +static IPAddress +aclMapAddr(acl_address * head, ACLChecklist * ch) { acl_address *l; - struct IN_ADDR addr; + IPAddress addr; for (l = head; l; l = l->next) { @@ -1215,7 +1214,7 @@ static struct IN_ADDR return l->addr; } - addr.s_addr = INADDR_ANY; + addr.SetAnyAddr(); return addr; } @@ -1236,8 +1235,8 @@ aclMapTOS(acl_tos * head, ACLChecklist * ch) return 0; } -struct IN_ADDR - getOutgoingAddr(HttpRequest * request) +IPAddress +getOutgoingAddr(HttpRequest * request) { ACLChecklist ch; @@ -1245,7 +1244,6 @@ struct IN_ADDR { ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; - ch.my_port = request->my_port; ch.request = HTTPMSGLOCK(request); } @@ -1260,7 +1258,6 @@ getOutgoingTOS(HttpRequest * request) if (request) { ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; - ch.my_port = request->my_port; ch.request = HTTPMSGLOCK(request); } diff --git a/src/forward.h b/src/forward.h index be43dfe6a1..60a6edd0ff 100644 --- a/src/forward.h +++ b/src/forward.h @@ -7,6 +7,7 @@ class CacheManager; class ErrorState; #include "comm.h" +#include "IPAddress.h" class FwdServer { @@ -44,7 +45,7 @@ public: bool checkRetry(); bool checkRetriable(); void dispatch(); - void pconnPush(int fd, const char *host, int port, const char *domain, struct IN_ADDR *client_addr); + void pconnPush(int fd, const char *host, int port, const char *domain, IPAddress &client_addr); bool dontRetry() { return flags.dont_retry; } @@ -106,7 +107,7 @@ unsigned int forward_completed:1; flags; #if LINUX_NETFILTER - struct sockaddr_in src; + IPAddress src; #endif }; diff --git a/src/fqdncache.cc b/src/fqdncache.cc index adcf02eb4e..713f73e665 100644 --- a/src/fqdncache.cc +++ b/src/fqdncache.cc @@ -1,6 +1,6 @@ /* - * $Id: fqdncache.cc,v 1.175 2007/10/13 00:02:28 hno Exp $ + * $Id: fqdncache.cc,v 1.176 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 35 FQDN Cache * AUTHOR: Harvest Derived @@ -440,17 +440,17 @@ fqdncacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error } void - -fqdncache_nbgethostbyaddr(struct IN_ADDR addr, FQDNH * handler, void *handlerData) +fqdncache_nbgethostbyaddr(IPAddress &addr, FQDNH * handler, void *handlerData) { fqdncache_entry *f = NULL; - char *name = inet_ntoa(addr); + char name[MAX_IPSTRLEN]; generic_cbdata *c; assert(handler); + addr.NtoA(name,MAX_IPSTRLEN); debugs(35, 4, "fqdncache_nbgethostbyaddr: Name '" << name << "'."); FqdncacheStats.requests++; - if (name == NULL || name[0] == '\0') + if (name[0] == '\0') { debugs(35, 4, "fqdncache_nbgethostbyaddr: Invalid name!"); dns_error_message = "Invalid hostname"; @@ -499,7 +499,6 @@ fqdncache_nbgethostbyaddr(struct IN_ADDR addr, FQDNH * handler, void *handlerDat dnsSubmit(hashKeyStr(&f->hash), fqdncacheHandleReply, c); #else - idnsPTRLookup(addr, fqdncacheHandleReply, c); #endif } @@ -543,14 +542,13 @@ fqdncacheRegisterWithCacheManager(CacheManager & manager) } const char * - -fqdncache_gethostbyaddr(struct IN_ADDR addr, int flags) +fqdncache_gethostbyaddr(IPAddress &addr, int flags) { - char *name = inet_ntoa(addr); + char name[MAX_IPSTRLEN]; fqdncache_entry *f = NULL; - struct IN_ADDR ip; - assert(name); + assert(!addr.IsAnyAddr() && !addr.IsNoAddr()); + addr.NtoA(name,MAX_IPSTRLEN); FqdncacheStats.requests++; f = fqdncache_get(name); @@ -576,15 +574,12 @@ fqdncache_gethostbyaddr(struct IN_ADDR addr, int flags) dns_error_message = NULL; - /* check if it's already a FQDN address in text form. */ - - if (!safe_inet_addr(name, &ip)) - return name; - FqdncacheStats.misses++; if (flags & FQDN_LOOKUP_IF_MISS) + { fqdncache_nbgethostbyaddr(addr, dummy_handler, NULL); + } return NULL; } @@ -620,14 +615,14 @@ fqdnStats(StoreEntry * sentry) storeAppendPrintf(sentry, "FQDN Cache Contents:\n\n"); - storeAppendPrintf(sentry, "%-15.15s %3s %3s %3s %s\n", + storeAppendPrintf(sentry, "%-45.45s %3s %3s %3s %s\n", "Address", "Flg", "TTL", "Cnt", "Hostnames"); hash_first(fqdn_table); while ((f = (fqdncache_entry *) hash_next(fqdn_table))) { ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime)); - storeAppendPrintf(sentry, "%-15.15s %c%c %3.3d % 3d", + storeAppendPrintf(sentry, "%-45.45s %c%c %3.3d % 3d", hashKeyStr(&f->hash), f->flags.negcached ? 'N' : ' ', f->flags.fromhosts ? 'H' : ' ', @@ -648,16 +643,15 @@ dummy_handler(const char *bufnotused, void *datanotused) } const char * - -fqdnFromAddr(struct IN_ADDR addr) +fqdnFromAddr(IPAddress &addr) { const char *n; - static char buf[32]; + static char buf[MAX_IPSTRLEN]; if (Config.onoff.log_fqdn && (n = fqdncache_gethostbyaddr(addr, 0))) return n; - xstrncpy(buf, inet_ntoa(addr), 32); + addr.NtoA(buf, MAX_IPSTRLEN); return buf; } diff --git a/src/ftp.cc b/src/ftp.cc index 4607c2b790..a816cb2180 100644 --- a/src/ftp.cc +++ b/src/ftp.cc @@ -1,5 +1,5 @@ /* - * $Id: ftp.cc,v 1.441 2007/09/27 14:34:06 rousskov Exp $ + * $Id: ftp.cc,v 1.442 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 9 File Transfer Protocol (FTP) * AUTHOR: Harvest Derived @@ -64,7 +64,9 @@ typedef enum { SENT_TYPE, SENT_MDTM, SENT_SIZE, + SENT_EPRT, SENT_PORT, + SENT_EPSV, SENT_PASV, SENT_CWD, SENT_LIST, @@ -275,8 +277,12 @@ static FTPSM ftpSendMdtm; static FTPSM ftpReadMdtm; static FTPSM ftpSendSize; static FTPSM ftpReadSize; -static FTPSM ftpSendPort; -static FTPSM ftpReadPort; +static FTPSM ftpSendEPRT; +static FTPSM ftpReadEPRT; +static FTPSM ftpSendPORT; +static FTPSM ftpReadPORT; +//static FTPSM ftpSendEPSV; +static FTPSM ftpReadEPSV; static FTPSM ftpSendPasv; static FTPSM ftpReadPasv; static FTPSM ftpTraverseDirectory; @@ -339,7 +345,9 @@ FTPSM *FTP_SM_FUNCS[] = ftpReadType, /* SENT_TYPE */ ftpReadMdtm, /* SENT_MDTM */ ftpReadSize, /* SENT_SIZE */ - ftpReadPort, /* SENT_PORT */ + ftpReadEPRT, /* SENT_EPRT */ + ftpReadPORT, /* SENT_PORT */ + ftpReadEPSV, /* SENT_EPSV */ ftpReadPasv, /* SENT_PASV */ ftpReadCwd, /* SENT_CWD */ ftpReadList, /* SENT_LIST */ @@ -1439,7 +1447,7 @@ FtpStateData::buildTitleUrl() title_url.append("@"); } - title_url.append(request->host); + title_url.append(request->GetHost()); if (request->port != urlDefaultPort(PROTO_FTP)) { title_url.append(":"); @@ -1461,7 +1469,7 @@ FtpStateData::buildTitleUrl() base_href.append("@"); } - base_href.append(request->host); + base_href.append(request->GetHost()); if (request->port != urlDefaultPort(PROTO_FTP)) { base_href.append(":"); @@ -1505,7 +1513,7 @@ FtpStateData::start() checkUrlpath(); buildTitleUrl(); - debugs(9, 5, "ftpStart: host=" << request->host << ", path=" << + debugs(9, 5, "ftpStart: host=" << request->GetHost() << ", path=" << request->urlpath.buf() << ", user=" << user << ", passwd=" << password); @@ -1862,7 +1870,7 @@ ftpSendUser(FtpStateData * ftpState) if (ftpState->proxy_host != NULL) snprintf(cbuf, 1024, "USER %s@%s\r\n", ftpState->user, - ftpState->request->host); + ftpState->request->GetHost()); else snprintf(cbuf, 1024, "USER %s\r\n", ftpState->user); @@ -2206,7 +2214,7 @@ static void ftpReadSize(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; - debugs(9, 3, "This is ftpReadSize"); + debugs(9, 3, HERE << "ftpReadSize()"); if (code == 213) { ftpState->unhack(); @@ -2226,11 +2234,30 @@ ftpReadSize(FtpStateData * ftpState) ftpSendPasv(ftpState); } +/* FIXME INET6 : EPASV command not yet coded. */ +/* +static void +ftpSendEPSV(FtpStateData* ftpstate) +{ + // TODO. +} +*/ + +static void +ftpReadEPSV(FtpStateData* ftpstate) +{ + /* FIXME INET6 : EPASV command not yet coded. */ + + /* Failover to PASV */ + ftpReadPasv(ftpstate); +} + + static void ftpSendPasv(FtpStateData * ftpState) { - struct sockaddr_in addr; - socklen_t addr_len; + IPAddress addr; + struct addrinfo *AI = NULL; /* check the server control channel is still available */ if(!ftpState || !ftpState->haveControlChannel("ftpSendPasv")) @@ -2250,23 +2277,27 @@ ftpSendPasv(FtpStateData * ftpState) } if (!ftpState->flags.pasv_supported) { - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } - addr_len = sizeof(addr); + addr.InitAddrInfo(AI); - if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &addr, &addr_len)) { - debugs(9, 0, "ftpSendPasv: getsockname(" << ftpState->ctrl.fd << ",..): " << xstrerror()); + if (getsockname(ftpState->ctrl.fd, AI->ai_addr, &AI->ai_addrlen)) { + addr.FreeAddrInfo(AI); + debugs(9, 0, "ftpSendPasv: getsockname(" << ftpState->ctrl.fd << ",'" << addr << "',...): " << xstrerror()); ftpFail(ftpState); return; } + addr = *AI; + + addr.FreeAddrInfo(AI); + /* Open data channel with the same local address as control channel */ int fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - addr.sin_addr, - 0, + addr, COMM_NONBLOCKING, ftpState->entry->url()); @@ -2338,14 +2369,15 @@ ftpReadPasv(FtpStateData * ftpState) int p1, p2; int n; u_short port; + IPAddress ipa_remote; int fd = ftpState->data.fd; char *buf; LOCAL_ARRAY(char, ipaddr, 1024); - debugs(9, 3, "This is ftpReadPasv"); + debugs(9, 3, HERE << "ftpReadSize started"); if (code != 227) { debugs(9, 3, "PASV not supported by remote end"); - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } @@ -2362,18 +2394,20 @@ ftpReadPasv(FtpStateData * ftpState) fd_table[ftpState->ctrl.fd].ipaddr << ": " << ftpState->ctrl.last_reply); - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } snprintf(ipaddr, 1024, "%d.%d.%d.%d", h1, h2, h3, h4); - if (!safe_inet_addr(ipaddr, NULL)) { + ipa_remote = ipaddr; + + if( ipa_remote.IsAnyAddr() ) { debugs(9, 1, "Unsafe PASV reply from " << fd_table[ftpState->ctrl.fd].ipaddr << ": " << ftpState->ctrl.last_reply); - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } @@ -2384,7 +2418,7 @@ ftpReadPasv(FtpStateData * ftpState) fd_table[ftpState->ctrl.fd].ipaddr << ": " << ftpState->ctrl.last_reply); - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } @@ -2394,7 +2428,7 @@ ftpReadPasv(FtpStateData * ftpState) fd_table[ftpState->ctrl.fd].ipaddr << ": " << ftpState->ctrl.last_reply); - ftpSendPort(ftpState); + ftpSendEPRT(ftpState); return; } } @@ -2440,10 +2474,10 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) { int fd; - struct sockaddr_in addr; - socklen_t addr_len; + IPAddress addr; + struct addrinfo *AI = NULL; int on = 1; - u_short port = 0; + int x = 0; /* * Tear down any old data connection if any. We are about to * establish a new one. @@ -2458,9 +2492,16 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) * Set up a listen socket on the same local address as the * control connection. */ - addr_len = sizeof(addr); - if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &addr, &addr_len)) { + addr.InitAddrInfo(AI); + + x = getsockname(ftpState->ctrl.fd, AI->ai_addr, &AI->ai_addrlen); + + addr = *AI; + + addr.FreeAddrInfo(AI); + + if(x) { debugs(9, 0, "ftpOpenListenSocket: getsockname(" << ftpState->ctrl.fd << ",..): " << xstrerror()); return -1; } @@ -2471,13 +2512,11 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) */ if (fallback) { setsockopt(ftpState->ctrl.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); - port = ntohs(addr.sin_port); } fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - addr.sin_addr, - port, + addr, COMM_NONBLOCKING | (fallback ? COMM_REUSEADDR : 0), ftpState->entry->url()); debugs(9, 3, "ftpOpenListenSocket: Unconnected data socket created on FD " << fd ); @@ -2499,12 +2538,12 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) } static void -ftpSendPort(FtpStateData * ftpState) +ftpSendPORT(FtpStateData * ftpState) { int fd; - struct sockaddr_in addr; - socklen_t addr_len; + IPAddress ipa; + struct addrinfo *AI = NULL; unsigned char *addrptr; unsigned char *portptr; @@ -2515,30 +2554,44 @@ ftpSendPort(FtpStateData * ftpState) debugs(9, 3, "This is ftpSendPort"); ftpState->flags.pasv_supported = 0; fd = ftpOpenListenSocket(ftpState, 0); - addr_len = sizeof(addr); + ipa.InitAddrInfo(AI); - if (getsockname(fd, (struct sockaddr *) &addr, &addr_len)) { - debugs(9, 0, "ftpSendPort: getsockname(" << fd << ",..): " << xstrerror()); + if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen)) { + ipa.FreeAddrInfo(AI); + debugs(9, 0, "ftpSendPORT: getsockname(" << fd << ",..): " << xstrerror()); /* XXX Need to set error message */ ftpFail(ftpState); return; } - addrptr = (unsigned char *) &addr.sin_addr.s_addr; - portptr = (unsigned char *) &addr.sin_port; +#if USE_IPV6 + if( AI->ai_addrlen != sizeof(struct sockaddr_in) ) { + ipa.FreeAddrInfo(AI); + /* IPv6 CANNOT send PORT command. */ + /* we got here by attempting and failing an EPRT */ + /* using the same reply code should simulate a PORT failure */ + ftpReadPORT(ftpState); + return; + } +#endif + + addrptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_addr; + portptr = (unsigned char *) &((struct sockaddr_in*)AI->ai_addr)->sin_port; snprintf(cbuf, 1024, "PORT %d,%d,%d,%d,%d,%d\r\n", addrptr[0], addrptr[1], addrptr[2], addrptr[3], portptr[0], portptr[1]); ftpState->writeCommand(cbuf); ftpState->state = SENT_PORT; + + ipa.FreeAddrInfo(AI); } static void -ftpReadPort(FtpStateData * ftpState) +ftpReadPORT(FtpStateData * ftpState) { int code = ftpState->ctrl.replycode; - debugs(9, 3, "This is ftpReadPort"); + debugs(9, 3, HERE << "ftpReadPORT started"); if (code != 200) { /* Fall back on using the same port as the control connection */ @@ -2549,11 +2602,66 @@ ftpReadPort(FtpStateData * ftpState) ftpRestOrList(ftpState); } +static void +ftpSendEPRT(FtpStateData * ftpState) +{ + int fd; + IPAddress addr; + struct addrinfo *AI = NULL; + char buf[MAX_IPSTRLEN]; + + debugs(9, 3, HERE << "ftpSendEPRT started"); + ftpState->flags.pasv_supported = 0; + fd = ftpOpenListenSocket(ftpState, 0); + + addr.InitAddrInfo(AI); + + if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen)) { + addr.FreeAddrInfo(AI); + debugs(9, 0, "ftpSendEPRT: getsockname(" << fd << ",..): " << xstrerror()); + + /* XXX Need to set error message */ + ftpFail(ftpState); + return; + } + + addr = *AI; + + /* RFC 2428 defines EPRT as IPv6 equivalent to IPv4 PORT command. */ + /* Which can be used by EITHER protocol. */ + snprintf(cbuf, 1024, "EPRT |%d|%s|%d|\r\n", + AI->ai_family, + addr.NtoA(buf,MAX_IPSTRLEN), + addr.GetPort() ); + + ftpState->writeCommand(cbuf); + ftpState->state = SENT_EPRT; + + addr.FreeAddrInfo(AI); +} + +static void +ftpReadEPRT(FtpStateData * ftpState) +{ + int code = ftpState->ctrl.replycode; + debugs(9, 3, HERE << " ftpReadEPRT started"); + + if (code != 200) { + /* Failover to attempting old PORT command. */ + debugs(9, 3, "EPRT not supported by remote end"); + ftpSendPORT(ftpState); + return; + } + + ftpRestOrList(ftpState); +} + /* "read" handler to accept data connection */ static void ftpAcceptDataConnection(int fd, int newfd, ConnectionDetail *details, comm_err_t flag, int xerrno, void *data) { + char ntoapeer[MAX_IPSTRLEN]; FtpStateData *ftpState = (FtpStateData *)data; debugs(9, 3, "ftpAcceptDataConnection"); @@ -2566,12 +2674,11 @@ ftpAcceptDataConnection(int fd, int newfd, ConnectionDetail *details, } if (Config.Ftp.sanitycheck) { - char *ipaddr = inet_ntoa(details->peer.sin_addr); + details->peer.NtoA(ntoapeer,MAX_IPSTRLEN); - if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ipaddr) != 0) { + if (strcmp(fd_table[ftpState->ctrl.fd].ipaddr, ntoapeer) != 0) { debugs(9, 1, "FTP data connection from unexpected server (" << - ipaddr << ":" << (int) ntohs(details->peer.sin_port) << - "), expecting " << fd_table[ftpState->ctrl.fd].ipaddr); + details->peer << "), expecting " << fd_table[ftpState->ctrl.fd].ipaddr); comm_close(newfd); comm_accept(ftpState->data.fd, ftpAcceptDataConnection, ftpState); @@ -2593,14 +2700,13 @@ ftpAcceptDataConnection(int fd, int newfd, ConnectionDetail *details, ftpState->data.fd = newfd; - ftpState->data.port = ntohs(details->peer.sin_port); + ftpState->data.port = details->peer.GetPort(); - ftpState->data.host = xstrdup(inet_ntoa(details->peer.sin_addr)); + details->peer.NtoA(ftpState->data.host,SQUIDHOSTNAMELEN); commSetTimeout(ftpState->ctrl.fd, -1, NULL, NULL); - commSetTimeout(ftpState->data.fd, Config.Timeout.read, FtpStateData::ftpTimeout, - ftpState); + commSetTimeout(ftpState->data.fd, Config.Timeout.read, FtpStateData::ftpTimeout, ftpState); /* XXX We should have a flag to track connect state... * host NULL -> not connected, port == local port @@ -3286,44 +3392,35 @@ FtpStateData::ftpAuthRequired(HttpRequest * request, const char *realm) return newrep; } -char * -ftpUrlWith2f(const HttpRequest * request) +/** + * Construct an URI with leading / in PATH portion for use by CWD command + * possibly others. FTP encodes absolute paths as beginning with '/' + * after the initial URI path delimiter, which happens to be / itself. + * This makes FTP absolute URI appear as: ftp:host:port//root/path + * To encompass older software which compacts multiple // to / in transit + * We use standard URI-encoding on the second / making it + * ftp:host:port/%2froot/path AKA 'the FTP %2f hack'. + */ +const char * +ftpUrlWith2f(HttpRequest * request) { - LOCAL_ARRAY(char, buf, MAX_URL); - LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1); - LOCAL_ARRAY(char, portbuf, 32); - char *t; - portbuf[0] = '\0'; + String newbuf = "%2f"; if (request->protocol != PROTO_FTP) return NULL; - if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); - - loginbuf[0] = '\0'; - - if ((int) strlen(request->login) > 0) { - xstrncpy(loginbuf, request->login, sizeof(loginbuf) - 2); - - if ((t = strchr(loginbuf, ':'))) - *t = '\0'; - - strcat(loginbuf, "@"); + if( !strncmp(request->urlpath.buf(), "/", 1) ) { + newbuf.append(request->urlpath); + request->urlpath.absorb(newbuf); + safe_free(request->canonical); + } + else if( !strncmp(request->urlpath.buf(), "%2f", 3) ) { + newbuf.append(request->urlpath.buf() +1); + request->urlpath.absorb(newbuf); + safe_free(request->canonical); } - snprintf(buf, MAX_URL, "%s://%s%s%s%s%s", - ProtocolStr[request->protocol], - loginbuf, - request->host, - portbuf, - "/%2f", - request->urlpath.buf()); - - if ((t = strchr(buf, '?'))) - *t = '\0'; - - return buf; + return urlCanonical(request); } void diff --git a/src/globals.h b/src/globals.h index d34a28d165..1df6f33772 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * $Id: globals.h,v 1.141 2007/08/13 17:20:51 hno Exp $ + * $Id: globals.h,v 1.142 2007/12/14 23:11:46 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -55,7 +55,6 @@ extern "C" extern const char *cfg_filename; /* NULL */ extern const char *const appname; /* "squid" */ extern const char *const dash_str; /* "-" */ - extern const char *const localhost; /* "127.0.0.1" */ extern const char *const null_string; /* "" */ extern const char *const version_string; /* VERSION */ extern const char *const full_appname_string; /* PACKAGE "/" VERSION */ @@ -112,17 +111,9 @@ extern "C" extern struct _acl_deny_info_list *DenyInfoList; /* NULL */ - extern struct IN_ADDR any_addr; + extern IPAddress theOutICPAddr; - extern struct IN_ADDR local_addr; - - extern struct IN_ADDR no_addr; - - extern struct IN_ADDR theOutICPAddr; - - extern struct IN_ADDR theOutSNMPAddr; - - extern struct timeval current_time; + extern IPAddress theOutSNMPAddr; extern struct timeval squid_start; extern int shutting_down; /* 0 */ @@ -135,7 +126,6 @@ extern "C" extern char *swap_log_op_str[]; extern char *lookup_t_str[]; extern double request_failure_ratio; /* 0.0 */ - extern double current_dtime; extern int store_hash_buckets; /* 0 */ extern hash_table *store_table; /* NULL */ extern dlink_list ClientActiveRequests; diff --git a/src/helper.cc b/src/helper.cc index b95c28a61d..7be7352bde 100644 --- a/src/helper.cc +++ b/src/helper.cc @@ -1,6 +1,6 @@ /* - * $Id: helper.cc,v 1.90 2007/11/13 21:25:35 rousskov Exp $ + * $Id: helper.cc,v 1.91 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 84 Helper process maintenance * AUTHOR: Harvest Derived? @@ -120,6 +120,7 @@ helperOpenServers(helper * hlp) progname, args, shortname, + hlp->addr, &rfd, &wfd, &hIpc); @@ -136,6 +137,7 @@ helperOpenServers(helper * hlp) srv->hIpc = hIpc; srv->pid = pid; srv->index = k; + srv->addr = hlp->addr; srv->rfd = rfd; srv->wfd = wfd; srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz); @@ -219,6 +221,7 @@ helperStatefulOpenServers(statefulhelper * hlp) progname, args, shortname, + hlp->addr, &rfd, &wfd, &hIpc); @@ -241,6 +244,7 @@ helperStatefulOpenServers(statefulhelper * hlp) srv->stats.submits = 0; srv->stats.releases = 0; srv->index = k; + srv->addr = hlp->addr; srv->rfd = rfd; srv->wfd = wfd; srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz); diff --git a/src/helper.h b/src/helper.h index 67992019d0..504fc1726b 100644 --- a/src/helper.h +++ b/src/helper.h @@ -1,6 +1,6 @@ /* - * $Id: helper.h,v 1.9 2007/05/07 18:38:40 wessels Exp $ + * $Id: helper.h,v 1.10 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 84 Helper process maintenance * AUTHOR: Harvest Derived? @@ -38,6 +38,7 @@ #include "squid.h" #include "cbdata.h" +#include "IPAddress.h" class helper_request; @@ -65,6 +66,7 @@ struct _helper int n_running; int n_active; int ipc_type; + IPAddress addr; unsigned int concurrency; time_t last_queue_warn; time_t last_restart; @@ -90,6 +92,7 @@ struct _helper_stateful int n_running; int n_active; int ipc_type; + IPAddress addr; MemAllocator *datapool; HLPSAVAIL *IsAvailable; HLPSONEQ *OnEmptyQueue; @@ -111,6 +114,7 @@ struct _helper_server { int index; int pid; + IPAddress addr; int rfd; int wfd; MemBuf *wqueue; @@ -149,6 +153,7 @@ unsigned int shutdown: } stats; + void *hIpc; }; @@ -158,6 +163,7 @@ struct _helper_stateful_server { int index; int pid; + IPAddress addr; int rfd; int wfd; /* MemBuf wqueue; */ diff --git a/src/htcp.cc b/src/htcp.cc index 6a9ce5455d..0455090d8c 100644 --- a/src/htcp.cc +++ b/src/htcp.cc @@ -1,6 +1,6 @@ /* - * $Id: htcp.cc,v 1.77 2007/11/15 16:47:35 wessels Exp $ + * $Id: htcp.cc,v 1.78 2007/12/14 23:11:46 amosjeffries Exp $ * * DEBUG: section 31 Hypertext Caching Protocol * AUTHOR: Duane Wesssels @@ -182,7 +182,7 @@ public: void checkHit(); void checkedHit(StoreEntry *e); - void setFrom (struct sockaddr_in *from); + void setFrom (IPAddress &from); void setDataHeader (htcpDataHeader *); char *method; char *uri; @@ -193,7 +193,7 @@ public: private: HttpRequest *checkHitRequest; - struct sockaddr_in *from; + IPAddress from; // was a ptr. return to such IFF needed. otherwise copy should do. htcpDataHeader *dhdr; }; @@ -263,7 +263,7 @@ static int htcpOutSocket = -1; static u_int32_t queried_id[N_QUERIED_KEYS]; static cache_key queried_keys[N_QUERIED_KEYS][SQUID_MD5_DIGEST_LENGTH]; -static struct sockaddr_in queried_addr[N_QUERIED_KEYS]; +static IPAddress queried_addr[N_QUERIED_KEYS]; static MemAllocator *htcpDetailPool = NULL; static int old_squid_format = 0; @@ -282,26 +282,26 @@ static ssize_t htcpBuildTstOpData(char *buf, size_t buflen, htcpStuff * stuff); static void htcpFreeSpecifier(htcpSpecifier * s); static void htcpFreeDetail(htcpDetail * s); -static void htcpHandle(char *buf, int sz, struct sockaddr_in *from); +static void htcpHandle(char *buf, int sz, IPAddress &from); -static void htcpHandleData(char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleData(char *buf, int sz, IPAddress &from); -static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleMon(htcpDataHeader *, char *buf, int sz, IPAddress &from); -static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleNop(htcpDataHeader *, char *buf, int sz, IPAddress &from); -static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleSet(htcpDataHeader *, char *buf, int sz, IPAddress &from); -static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleTst(htcpDataHeader *, char *buf, int sz, IPAddress &from); static void htcpRecv(int fd, void *data); -static void htcpSend(const char *buf, int len, struct sockaddr_in *to); +static void htcpSend(const char *buf, int len, IPAddress &to); -static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, struct sockaddr_in *); +static void htcpTstReply(htcpDataHeader *, StoreEntry *, htcpSpecifier *, IPAddress &); -static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, struct sockaddr_in *from); +static void htcpHandleTstRequest(htcpDataHeader *, char *buf, int sz, IPAddress &from); -static void htcpHandleTstResponse(htcpDataHeader *, char *, int, struct sockaddr_in *); +static void htcpHandleTstResponse(htcpDataHeader *, char *, int, IPAddress &); static void htcpHexdump(const char *tag, const char *s, int sz) @@ -604,15 +604,15 @@ htcpBuildPacket(char *buf, size_t buflen, htcpStuff * stuff) static void -htcpSend(const char *buf, int len, struct sockaddr_in *to) +htcpSend(const char *buf, int len, IPAddress &to) { int x; - debugs(31, 3, "htcpSend: " << inet_ntoa(to->sin_addr) << "/" << ntohs(to->sin_port)); + + debugs(31, 3, "htcpSend: " << to ); htcpHexdump("htcpSend", buf, len); + x = comm_udp_sendto(htcpOutSocket, to, - - sizeof(struct sockaddr_in), buf, len); @@ -628,7 +628,7 @@ htcpSend(const char *buf, int len, struct sockaddr_in *to) void -htcpSpecifier::setFrom (struct sockaddr_in *aSocket) +htcpSpecifier::setFrom (IPAddress &aSocket) { from = aSocket; } @@ -859,11 +859,11 @@ htcpUnpackDetail(char *buf, int sz) static int -htcpAccessCheck(acl_access * acl, htcpSpecifier * s, struct sockaddr_in *from) +htcpAccessCheck(acl_access * acl, htcpSpecifier * s, IPAddress &from) { ACLChecklist checklist; - checklist.src_addr = from->sin_addr; - checklist.my_addr = no_addr; + checklist.src_addr = from; + checklist.my_addr.SetNoAddr(); checklist.request = HTTPMSGLOCK(s->request); checklist.accessList = cbdataReference(acl); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ @@ -873,7 +873,7 @@ htcpAccessCheck(acl_access * acl, htcpSpecifier * s, struct sockaddr_in *from) static void -htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct sockaddr_in *from) +htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, IPAddress &from) { htcpStuff stuff; static char pkt[8192]; @@ -962,7 +962,7 @@ htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, struct static void -htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr_in *from) +htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, IPAddress &from) { htcpStuff stuff; static char pkt[8192]; @@ -1000,7 +1000,7 @@ htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr_in *from static void -htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleNop(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { debugs(31, 3, "htcpHandleNop: Unimplemented"); } @@ -1038,23 +1038,18 @@ htcpSpecifier::created (StoreEntry *e) if (e->isNull()) { debugs(31, 3, "htcpCheckHit: NO; public object not found"); - goto miss; } - - if (!e->validToSend()) { + else if (!e->validToSend()) { debugs(31, 3, "htcpCheckHit: NO; entry not valid to send" ); - goto miss; } - - if (refreshCheckHTCP(e, checkHitRequest)) { + else if (refreshCheckHTCP(e, checkHitRequest)) { debugs(31, 3, "htcpCheckHit: NO; cached response is stale"); - goto miss; + } + else { + debugs(31, 3, "htcpCheckHit: YES!?"); + hit = e; } - debugs(31, 3, "htcpCheckHit: YES!?"); - hit = e; - -miss: checkedHit (hit); } @@ -1105,7 +1100,7 @@ htcpClrStore(const htcpSpecifier * s) static void -htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTst(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { debugs(31, 3, "htcpHandleTst: sz = " << sz); @@ -1120,22 +1115,21 @@ HtcpReplyData::HtcpReplyData() : hdr(hoHtcpReply) static void -htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { htcpReplyData htcpReply; cache_key *key = NULL; - struct sockaddr_in *peer; + IPAddress *peer; htcpDetail *d = NULL; char *t; - if (queried_id[hdr->msg_id % N_QUERIED_KEYS] != hdr->msg_id) { debugs(31, 2, "htcpHandleTstResponse: No matching query id '" << hdr->msg_id << "' (expected " << queried_id[hdr->msg_id % N_QUERIED_KEYS] << ") from '" << - inet_ntoa(from->sin_addr) << "'"); + from << "'"); return; } @@ -1144,15 +1138,15 @@ htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_i if (!key) { - debugs(31, 1, "htcpHandleTstResponse: No query key for response id '" << hdr->msg_id << "' from '" << inet_ntoa(from->sin_addr) << "'"); + debugs(31, 1, "htcpHandleTstResponse: No query key for response id '" << hdr->msg_id << "' from '" << from << "'"); return; } peer = &queried_addr[hdr->msg_id % N_QUERIED_KEYS]; - if (peer->sin_addr.s_addr != from->sin_addr.s_addr || peer->sin_port != from->sin_port) + if ( *peer != from || peer->GetPort() != from.GetPort() ) { - debugs(31, 1, "htcpHandleTstResponse: Unexpected response source " << inet_ntoa(from->sin_addr)); + debugs(31, 1, "htcpHandleTstResponse: Unexpected response source " << from ); return; } @@ -1199,7 +1193,7 @@ htcpHandleTstResponse(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_i static void -htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleTstRequest(htcpDataHeader * dhdr, char *buf, int sz, IPAddress &from) { /* buf should be a SPECIFIER */ htcpSpecifier *s; @@ -1258,21 +1252,21 @@ htcpSpecifier::checkedHit(StoreEntry *e) static void -htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleMon(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { debugs(31, 3, "htcpHandleMon: Unimplemented"); } static void -htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleSet(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { debugs(31, 3, "htcpHandleSet: Unimplemented"); } static void -htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) +htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, IPAddress &from) { htcpSpecifier *s; /* buf[0/1] is reserved and reason */ @@ -1331,7 +1325,7 @@ htcpHandleClr(htcpDataHeader * hdr, char *buf, int sz, struct sockaddr_in *from) static void -htcpHandleData(char *buf, int sz, struct sockaddr_in *from) +htcpHandleData(char *buf, int sz, IPAddress &from) { htcpDataHeader hdr; @@ -1364,7 +1358,7 @@ htcpHandleData(char *buf, int sz, struct sockaddr_in *from) if (hdr.opcode >= HTCP_END) { - debugs(31, 1, "htcpHandleData: client " << inet_ntoa(from->sin_addr) << ", opcode " << hdr.opcode << " out of range"); + debugs(31, 1, "htcpHandleData: client " << from << ", opcode " << hdr.opcode << " out of range"); return; } @@ -1424,7 +1418,7 @@ htcpHandleData(char *buf, int sz, struct sockaddr_in *from) static void -htcpHandle(char *buf, int sz, struct sockaddr_in *from) +htcpHandle(char *buf, int sz, IPAddress &from) { htcpHeader htcpHdr; assert (sz >= 0); @@ -1451,17 +1445,14 @@ htcpHandle(char *buf, int sz, struct sockaddr_in *from) if (sz != htcpHdr.length) { debugs(31, 1, "htcpHandle: sz/" << sz << " != htcpHdr.length/" << - htcpHdr.length << " from " << inet_ntoa(from->sin_addr) << ":" << - (int) ntohs(from->sin_port)); + htcpHdr.length << " from " << from ); return; } if (htcpHdr.major != 0) { - debugs(31, 1, "htcpHandle: Unknown major version " << htcpHdr.major << - " from " << inet_ntoa(from->sin_addr) << ":" << - (int) ntohs(from->sin_port)); + debugs(31, 1, "htcpHandle: Unknown major version " << htcpHdr.major << " from " << from ); return; } @@ -1476,22 +1467,18 @@ htcpRecv(int fd, void *data) { static char buf[8192]; int len; - - static struct sockaddr_in from; - - socklen_t flen = sizeof(struct sockaddr_in); - memset(&from, '\0', flen); + static IPAddress from; /* Receive up to 8191 bytes, leaving room for a null */ - len = comm_udp_recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &from, &flen); - debugs(31, 3, "htcpRecv: FD " << fd << ", " << len << " bytes from " << - inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port)); + len = comm_udp_recvfrom(fd, buf, sizeof(buf) - 1, 0, from); + + debugs(31, 3, "htcpRecv: FD " << fd << ", " << len << " bytes from " << from ); if (len) statCounter.htcp.pkts_recv++; - htcpHandle(buf, len, &from); + htcpHandle(buf, len, from); commSetSelect(fd, COMM_SELECT_READ, htcpRecv, NULL, 0); } @@ -1505,16 +1492,19 @@ htcpRecv(int fd, void *data) void htcpInit(void) { + IPAddress sendOn; + if (Config.Port.htcp <= 0) { debugs(31, 1, "HTCP Disabled."); return; } + sendOn = Config.Addrs.udp_outgoing; + sendOn.SetPort(Config.Port.htcp); enter_suid(); htcpInSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_incoming, - Config.Port.htcp, + sendOn, COMM_NONBLOCKING, "HTCP Socket"); leave_suid(); @@ -1526,12 +1516,11 @@ htcpInit(void) debugs(31, 1, "Accepting HTCP messages on port " << Config.Port.htcp << ", FD " << htcpInSocket << "."); - if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) { + if (!Config.Addrs.udp_outgoing.IsNoAddr()) { enter_suid(); htcpOutSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_outgoing, - Config.Port.htcp, + sendOn, COMM_NONBLOCKING, "Outgoing HTCP Socket"); leave_suid(); @@ -1615,7 +1604,8 @@ htcpQuery(StoreEntry * e, HttpRequest * req, peer * p) return; } - htcpSend(pkt, (int) pktlen, &p->in_addr); + htcpSend(pkt, (int) pktlen, p->in_addr); + queried_id[stuff.msg_id % N_QUERIED_KEYS] = stuff.msg_id; save_key = queried_keys[stuff.msg_id % N_QUERIED_KEYS]; storeKeyCopy(save_key, (const cache_key *)e->key); diff --git a/src/htcp.h b/src/htcp.h index 5f3791462c..992dc77a8f 100644 --- a/src/htcp.h +++ b/src/htcp.h @@ -1,6 +1,6 @@ /* - * $Id: htcp.h,v 1.5 2003/08/10 11:00:43 robertc Exp $ + * $Id: htcp.h,v 1.6 2007/12/14 23:11:47 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -36,6 +36,7 @@ #if USE_HTCP #include "HttpHeader.h" +#include "IPAddress.h" class HtcpReplyData { @@ -60,7 +61,7 @@ public: typedef class HtcpReplyData htcpReplyData; -SQUIDCEXTERN void neighborsHtcpReply(const cache_key *, htcpReplyData *, const struct sockaddr_in *); +SQUIDCEXTERN void neighborsHtcpReply(const cache_key *, htcpReplyData *, const IPAddress &); SQUIDCEXTERN void htcpInit(void); SQUIDCEXTERN void htcpQuery(StoreEntry * e, HttpRequest * req, peer * p); SQUIDCEXTERN void htcpSocketShutdown(void); diff --git a/src/http.cc b/src/http.cc index 41913774a4..33c4a8d416 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.541 2007/11/18 22:00:58 hno Exp $ + * $Id: http.cc,v 1.542 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -92,7 +92,7 @@ HttpStateData::HttpStateData(FwdState *theFwdState) : ServerStateData(theFwdStat HttpRequest * proxy_req = new HttpRequest(orig_request->method, orig_request->protocol, url); - xstrncpy(proxy_req->host, _peer->host, SQUIDHOSTNAMELEN); + proxy_req->SetHost(_peer->host); proxy_req->port = _peer->http_port; @@ -672,7 +672,7 @@ HttpStateData::checkDateSkew(HttpReply *reply) int skew = abs((int)(reply->date - squid_curtime)); if (skew > 86400) - debugs(11, 3, "" << request->host << "'s clock is skewed by " << skew << " seconds!"); + debugs(11, 3, "" << request->GetHost() << "'s clock is skewed by " << skew << " seconds!"); } } @@ -1115,7 +1115,7 @@ void HttpStateData::processReplyBody() { - struct IN_ADDR *client_addr = NULL; + IPAddress client_addr; if (!flags.headers_parsed) { flags.do_next_read = 1; @@ -1170,17 +1170,17 @@ HttpStateData::processReplyBody() #if LINUX_TPROXY if (orig_request->flags.tproxy) - client_addr = &orig_request->client_addr; + client_addr = orig_request->client_addr; #endif if (_peer) { if (_peer->options.originserver) - fwd->pconnPush(fd, _peer->name, orig_request->port, orig_request->host, client_addr); + fwd->pconnPush(fd, _peer->name, orig_request->port, orig_request->GetHost(), client_addr); else fwd->pconnPush(fd, _peer->name, _peer->http_port, NULL, client_addr); } else { - fwd->pconnPush(fd, request->host, request->port, NULL, client_addr); + fwd->pconnPush(fd, request->GetHost(), request->port, NULL, client_addr); } fd = -1; @@ -1356,8 +1356,10 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request, /* append X-Forwarded-For */ strFwd = hdr_in->getList(HDR_X_FORWARDED_FOR); - if (opt_forwarded_for && orig_request->client_addr.s_addr != no_addr.s_addr) - strListAdd(&strFwd, inet_ntoa(orig_request->client_addr), ','); + if (opt_forwarded_for && !orig_request->client_addr.IsNoAddr()) { + orig_request->client_addr.NtoA(bbuf,MAX_IPSTRLEN); + strListAdd(&strFwd, bbuf, ','); + } else strListAdd(&strFwd, "unknown", ','); @@ -1371,10 +1373,11 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request, hdr_out->putStr(HDR_HOST, orig_request->peer_domain); } else if (orig_request->port == urlDefaultPort(orig_request->protocol)) { /* use port# only if not default */ - hdr_out->putStr(HDR_HOST, orig_request->host); + hdr_out->putStr(HDR_HOST, orig_request->GetHost()); } else { httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d", - orig_request->host, (int) orig_request->port); + orig_request->GetHost(), + (int) orig_request->port); } } @@ -1566,10 +1569,11 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, St /* use port# only if not default */ if (orig_request->port == urlDefaultPort(orig_request->protocol)) { - hdr_out->putStr(HDR_HOST, orig_request->host); + hdr_out->putStr(HDR_HOST, orig_request->GetHost()); } else { httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d", - orig_request->host, (int) orig_request->port); + orig_request->GetHost(), + (int) orig_request->port); } } @@ -1818,7 +1822,7 @@ HttpStateData::handleMoreRequestBodyAvailable() if (flags.headers_parsed && !flags.abuse_detected) { flags.abuse_detected = 1; - debugs(11, 1, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << inet_ntoa(orig_request->client_addr) << "' -> '" << entry->url() << "'" ); + debugs(11, 1, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << orig_request->client_addr << "' -> '" << entry->url() << "'" ); if (virginReply()->sline.status == HTTP_INVALID_HEADER) { comm_close(fd); diff --git a/src/icmp.cc b/src/icmp.cc index 51d4d797a5..ab4e77ec13 100644 --- a/src/icmp.cc +++ b/src/icmp.cc @@ -1,9 +1,8 @@ - /* - * $Id: icmp.cc,v 1.93 2007/04/30 16:56:09 wessels Exp $ + * $Id: icmp.cc,v 1.94 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines - * AUTHOR: Duane Wessels + * AUTHOR: Duane Wessels, Amos Jeffries * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -32,279 +31,90 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ - - #include "squid.h" -#include "comm.h" +#include "ICMP.h" #include "SquidTime.h" +#include "Debug.h" +ICMP::ICMP() +{ #if USE_ICMP - -#define S_ICMP_ECHO 1 -#if ALLOW_SOURCE_PING -#define S_ICMP_ICP 2 -#endif -#define S_ICMP_DOM 3 - -static PF icmpRecv; -static void icmpSend(pingerEchoData * pkt, int len); -#if ALLOW_SOURCE_PING - -static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf); + icmp_sock = -1; + icmp_ident = 0; #endif - -static void * hIpc; -static pid_t pid; - -static void - -icmpSendEcho(struct IN_ADDR to, int opcode, const char *payload, int len) -{ - static pingerEchoData pecho; - - if (payload && len == 0) - len = strlen(payload); - - assert(len <= PINGER_PAYLOAD_SZ); - - pecho.to = to; - - pecho.opcode = (unsigned char) opcode; - - pecho.psize = len; - - xmemcpy(pecho.payload, payload, len); - - icmpSend(&pecho, sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + len); } -static void -icmpRecv(int unused1, void *unused2) +void +ICMP::Close() { - int n; - static int fail_count = 0; - pingerReplyData preply; - - static struct sockaddr_in F; - commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); - memset(&preply, '\0', sizeof(pingerReplyData)); - n = comm_udp_recv(icmp_sock, - (char *) &preply, - sizeof(pingerReplyData), - 0); - - if (n < 0 && EAGAIN != errno) { - debugs(37, 1, "icmpRecv: recv: " << xstrerror()); - - if (errno == ECONNREFUSED) - icmpClose(); - - if (errno == ECONNRESET) - icmpClose(); - - if (++fail_count == 10) - icmpClose(); - - return; - } - - fail_count = 0; - - if (n == 0) /* test probe from pinger */ - return; - - F.sin_family = AF_INET; - - F.sin_addr = preply.from; - - F.sin_port = 0; - - switch (preply.opcode) { - - case S_ICMP_ECHO: - break; -#if ALLOW_SOURCE_PING - - case S_ICMP_ICP: - icmpHandleSourcePing(&F, preply.payload); - break; +#if USE_ICMP + if(icmp_sock > 0) + close(icmp_sock); + icmp_sock = -1; + icmp_ident = 0; #endif - - case S_ICMP_DOM: - netdbHandlePingReply(&F, preply.hops, preply.rtt); - break; - - default: - debugs(37, 1, "icmpRecv: Bad opcode: " << preply.opcode); - break; - } } -static void -icmpSend(pingerEchoData * pkt, int len) -{ - int x; - - if (icmp_sock < 0) - return; +#if USE_ICMP - debugs(37, 2, "icmpSend: to " << inet_ntoa(pkt->to) << ", opcode " << - (int) pkt->opcode << ", len " << pkt->psize); +int +ICMP::CheckSum(unsigned short *ptr, int size) +{ + long sum; + unsigned short oddbyte; + unsigned short answer; - x = comm_udp_send(icmp_sock, (char *) pkt, len, 0); + if(!ptr) return 65535; // bad input. - if (x < 0) { - debugs(37, 1, "icmpSend: send: " << xstrerror()); + sum = 0; - if (errno == ECONNREFUSED || errno == EPIPE) { - icmpClose(); - return; - } - } else if (x != len) { - debugs(37, 1, "icmpSend: Wrote " << x << " of " << len << " bytes"); + while (size > 1) { + sum += *ptr++; + size -= 2; } -} -#if ALLOW_SOURCE_PING -static void - -icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf) -{ - const cache_key *key; - icp_common_t header; - const char *url; - xmemcpy(&header, buf, sizeof(icp_common_t)); - url = buf + sizeof(icp_common_t); - key = icpGetCacheKey(url, (int) header.reqnum); - debugs(37, 3, "icmpHandleSourcePing: from " << inet_ntoa(from->sin_addr) << ", key '" << storeKeyText(key) << "'"); + if (size == 1) { + oddbyte = 0; + *((unsigned char *) &oddbyte) = *(unsigned char *) ptr; + sum += oddbyte; + } - /* call neighborsUdpAck even if ping_status != PING_WAITING */ - neighborsUdpAck(key, &header, from); + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + answer = (unsigned short) ~sum; + return (answer); } -#endif - -#endif /* USE_ICMP */ - -#if ALLOW_SOURCE_PING -void - -icmpSourcePing(struct IN_ADDR to, const icp_common_t * header, const char *url) +int +ICMP::ipHops(int ttl) { -#if USE_ICMP - char *payload; - int len; - int ulen; - debugs(37, 3, "icmpSourcePing: '" << url << "'"); - - if ((ulen = strlen(url)) > MAX_URL) - return; - - payload = memAllocate(MEM_8K_BUF); - - len = sizeof(icp_common_t); + if (ttl < 33) + return 33 - ttl; - xmemcpy(payload, header, len); + if (ttl < 63) + return 63 - ttl; /* 62 = (64+60)/2 */ - strcpy(payload + len, url); - - len += ulen + 1; - - icmpSendEcho(to, S_ICMP_ICP, payload, len); - - memFree(payload, MEM_8K_BUF); - -#endif -} + if (ttl < 65) + return 65 - ttl; /* 62 = (64+60)/2 */ -#endif + if (ttl < 129) + return 129 - ttl; -void + if (ttl < 193) + return 193 - ttl; -icmpDomainPing(struct IN_ADDR to, const char *domain) -{ -#if USE_ICMP - debugs(37, 3, "icmpDomainPing: '" << domain << "'"); - icmpSendEcho(to, S_ICMP_DOM, domain, 0); -#endif + return 256 - ttl; } void -icmpOpen(void) +ICMP::Log(const IPAddress &addr, const u_int8_t type, const char* pkt_str, const int rtt, const int hops) { -#if USE_ICMP - const char *args[2]; - int rfd; - int wfd; - args[0] = "(pinger)"; - args[1] = NULL; - /* - * Do NOT use IPC_DGRAM (=IPC_UNIX_DGRAM) here because you can't - * send() more than 4096 bytes on a socketpair() socket (at - * least on FreeBSD). - */ - pid = ipcCreate(IPC_UDP_SOCKET, - Config.Program.pinger, - args, - "Pinger Socket", - &rfd, - &wfd, - &hIpc); - - if (pid < 0) - return; - - assert(rfd == wfd); - - icmp_sock = rfd; - - fd_note(icmp_sock, "pinger"); - - commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0); - - commSetTimeout(icmp_sock, -1, NULL, NULL); - - debugs(37, 1, "Pinger socket opened on FD " << icmp_sock); - -#ifdef _SQUID_MSWIN_ - - debugs(37, 4, "Pinger handle: 0x" << std::hex << hIpc << std::dec << ", PID: " << pid); - -#endif -#endif + debugs(42, 2, "pingerLog: " << std::setw(9) << current_time.tv_sec << + "." << std::setfill('0') << std::setw(6) << + current_time.tv_usec << " " << std::left << std::setfill(' ') << + std::setw(45) << addr << " " << type << + " " << std::setw(15) << pkt_str << " " << rtt << + "ms " << hops << " hops"); } -void -icmpClose(void) -{ -#if USE_ICMP - - if (icmp_sock < 0) - return; - - debugs(37, 1, "Closing Pinger socket on FD " << icmp_sock); - -#ifdef _SQUID_MSWIN_ - - send(icmp_sock, (const void *) "$shutdown\n", 10, 0); - -#endif - - comm_close(icmp_sock); - -#ifdef _SQUID_MSWIN_ - - if (hIpc) { - if (WaitForSingleObject(hIpc, 12000) != WAIT_OBJECT_0) { - getCurrentTime(); - debugs(37, 1, "icmpClose: WARNING: (pinger," << pid << ") didn't exit in 12 seconds"); - } - - CloseHandle(hIpc); - } - -#endif - icmp_sock = -1; - -#endif -} +#endif /* USE_ICMP */ diff --git a/src/icp_v2.cc b/src/icp_v2.cc index 9ee1c1a9df..771095fb95 100644 --- a/src/icp_v2.cc +++ b/src/icp_v2.cc @@ -1,8 +1,8 @@ /* - * $Id: icp_v2.cc,v 1.101 2007/11/15 16:47:35 wessels Exp $ + * $Id: icp_v2.cc,v 1.102 2007/12/14 23:11:47 amosjeffries Exp $ * - * DEBUG: section 12 Internet Cache Protocol + * DEBUG: section 12 Internet Cache Protocol (ICP) * AUTHOR: Duane Wessels * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -45,9 +45,9 @@ #include "SquidTime.h" #include "SwapDir.h" -static void icpLogIcp(struct IN_ADDR, log_type, int, const char *, int); +static void icpLogIcp(const IPAddress &, log_type, int, const char *, int); -static void icpHandleIcpV2(int, struct sockaddr_in, char *, int); +static void icpHandleIcpV2(int, IPAddress &, char *, int); static void icpCount(void *, int, size_t, int); /* @@ -138,8 +138,8 @@ ICP2State::created (StoreEntry *newEntry) codeToSend = ICP_HIT; } else { if (Config.onoff.test_reachability && rtt == 0) { - if ((rtt = netdbHostRtt(request->host)) == 0) - netdbPingSite(request->host); + if ((rtt = netdbHostRtt(request->GetHost())) == 0) + netdbPingSite(request->GetHost()); } if (icpGetCommonOpcode() != ICP_ERR) @@ -150,7 +150,7 @@ ICP2State::created (StoreEntry *newEntry) codeToSend = ICP_MISS; } - icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, &from); + icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, from); delete this; } @@ -158,7 +158,7 @@ ICP2State::created (StoreEntry *newEntry) static void -icpLogIcp(struct IN_ADDR caddr, log_type logcode, int len, const char *url, int delay) +icpLogIcp(const IPAddress &caddr, log_type logcode, int len, const char *url, int delay) { AccessLogEntry al; @@ -198,7 +198,7 @@ icpUdpSendQueue(int fd, void *unused) while ((q = IcpQueueHead) != NULL) { delay = tvSubUsec(q->queue_time, current_time); /* increment delay to prevent looping */ - x = icpUdpSend(fd, &q->address, (icp_common_t *) q->msg, q->logcode, ++delay); + x = icpUdpSend(fd, q->address, (icp_common_t *) q->msg, q->logcode, ++delay); IcpQueueHead = q->next; safe_free(q); @@ -240,7 +240,7 @@ _icp_common_t::createMessage( headerp->pad = htonl(pad); - headerp->shostid = theOutICPAddr.s_addr; + theOutICPAddr.GetInAddr( *((struct in_addr*)&headerp->shostid) ); urloffset = buf + sizeof(icp_common_t); @@ -254,8 +254,7 @@ _icp_common_t::createMessage( int icpUdpSend(int fd, - - const struct sockaddr_in *to, + const IPAddress &to, icp_common_t * msg, log_type logcode, int delay) @@ -265,22 +264,21 @@ icpUdpSend(int fd, int len; len = (int) ntohs(msg->length); debugs(12, 5, "icpUdpSend: FD " << fd << " sending " << - icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << - inet_ntoa(to->sin_addr) << ":" << ntohs(to->sin_port)); + icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << to); - x = comm_udp_sendto(fd, to, sizeof(*to), msg, len); + x = comm_udp_sendto(fd, to, msg, len); if (x >= 0) { /* successfully written */ - icpLogIcp(to->sin_addr, logcode, len, (char *) (msg + 1), delay); + icpLogIcp(to, logcode, len, (char *) (msg + 1), delay); icpCount(msg, SENT, (size_t) len, delay); safe_free(msg); } else if (0 == delay) { /* send failed, but queue it */ queue = (icpUdpData *) xcalloc(1, sizeof(icpUdpData)); - queue->address = *to; + queue->address = to; queue->msg = msg; queue->len = (int) ntohs(msg->length); queue->queue_time = current_time; @@ -368,7 +366,7 @@ icpLogFromICPCode(icp_opcode opcode) void -icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const struct sockaddr_in *from) +icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const IPAddress &from) { icp_common_t *reply = _icp_common_t::createMessage(opcode, flags, url, reqnum, pad); icpUdpSend(fd, from, reply, icpLogFromICPCode(opcode), 0); @@ -376,17 +374,17 @@ icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int void -icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd) +icpDenyAccess(IPAddress &from, char *url, int reqnum, int fd) { - debugs(12, 2, "icpDenyAccess: Access Denied for " << inet_ntoa(from->sin_addr) << " by " << AclMatchedName << "."); + debugs(12, 2, "icpDenyAccess: Access Denied for " << from << " by " << AclMatchedName << "."); - if (clientdbCutoffDenied(from->sin_addr)) + if (clientdbCutoffDenied(from)) { /* * count this DENIED query in the clientdb, even though * we're not sending an ICP reply... */ - clientdbUpdate(from->sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0); + clientdbUpdate(from, LOG_UDP_DENIED, PROTO_ICP, 0); } else { icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from); @@ -395,11 +393,11 @@ icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd) int -icpAccessAllowed(struct sockaddr_in *from, HttpRequest * icp_request) +icpAccessAllowed(IPAddress &from, HttpRequest * icp_request) { ACLChecklist checklist; - checklist.src_addr = from->sin_addr; - checklist.my_addr = no_addr; + checklist.src_addr = from; + checklist.my_addr.SetNoAddr(); checklist.request = HTTPMSGLOCK(icp_request); checklist.accessList = cbdataReference(Config.accessList.icp); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ @@ -418,7 +416,7 @@ icpGetUrlToSend(char *url) HttpRequest * -icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in * from) +icpGetRequest(char *url, int reqnum, int fd, IPAddress &from) { if (strpbrk(url, w_space)) { @@ -438,31 +436,31 @@ icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in * from) static void -doV2Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header) +doV2Query(int fd, IPAddress &from, char *buf, icp_common_t header) { int rtt = 0; int src_rtt = 0; u_int32_t flags = 0; /* We have a valid packet */ char *url = buf + sizeof(icp_common_t) + sizeof(u_int32_t); - HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, &from); + HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from); if (!icp_request) return; HTTPMSGLOCK(icp_request); - if (!icpAccessAllowed(&from, icp_request)) + if (!icpAccessAllowed(from, icp_request)) { - icpDenyAccess(&from, url, header.reqnum, fd); + icpDenyAccess(from, url, header.reqnum, fd); HTTPMSGUNLOCK(icp_request); return; } if (header.flags & ICP_FLAG_SRC_RTT) { - rtt = netdbHostRtt(icp_request->host); - int hops = netdbHostHops(icp_request->host); + rtt = netdbHostRtt(icp_request->GetHost()); + int hops = netdbHostHops(icp_request->GetHost()); src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF); if (rtt) @@ -491,17 +489,17 @@ doV2Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header) void -_icp_common_t::handleReply(char *buf, struct sockaddr_in *from) +_icp_common_t::handleReply(char *buf, IPAddress &from) { if (neighbors_do_private_keys && reqnum == 0) { - debugs(12, 0, "icpHandleIcpV2: Neighbor " << inet_ntoa(from->sin_addr) << " returned reqnum = 0"); + debugs(12, 0, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0"); debugs(12, 0, "icpHandleIcpV2: Disabling use of private keys"); neighbors_do_private_keys = 0; } char *url = buf + sizeof(icp_common_t); - debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << inet_ntoa(from->sin_addr) << " for '" << url << "'"); + debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << from << " for '" << url << "'"); const cache_key *key = icpGetCacheKey(url, (int) reqnum); /* call neighborsUdpAck even if ping_status != PING_WAITING */ @@ -510,7 +508,7 @@ _icp_common_t::handleReply(char *buf, struct sockaddr_in *from) static void -icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) +icpHandleIcpV2(int fd, IPAddress &from, char *buf, int len) { if (len <= 0) { @@ -538,10 +536,6 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) break; case ICP_HIT: -#if ALLOW_SOURCE_PING - - case ICP_SECHO: -#endif case ICP_DECHO: @@ -550,7 +544,7 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) case ICP_DENIED: case ICP_MISS_NOFETCH: - header.handleReply(buf, &from); + header.handleReply(buf, from); break; case ICP_INVALID: @@ -559,7 +553,7 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len) break; default: - debugs(12, 0, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << inet_ntoa(from.sin_addr)); + debugs(12, 0, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from); break; } @@ -570,15 +564,15 @@ static void icpPktDump(icp_common_t * pkt) { - struct IN_ADDR a; + IPAddress a; debugs(12, 9, "opcode: " << std::setw(3) << pkt->opcode << " " << icp_opcode_str[pkt->opcode]); debugs(12, 9, "version: "<< std::left << std::setw(8) << pkt->version); debugs(12, 9, "length: "<< std::left << std::setw(8) << ntohs(pkt->length)); debugs(12, 9, "reqnum: "<< std::left << std::setw(8) << ntohl(pkt->reqnum)); debugs(12, 9, "flags: "<< std::left << std::hex << std::setw(8) << ntohl(pkt->flags)); - a.s_addr = pkt->shostid; - debugs(12, 9, "shostid: " << inet_ntoa(a)); + a = (struct in_addr)pkt->shostid; + debugs(12, 9, "shostid: " << a ); debugs(12, 9, "payload: " << (char *) pkt + sizeof(icp_common_t)); } @@ -589,8 +583,7 @@ icpHandleUdp(int sock, void *data) { int *N = &incoming_sockets_accepted; - struct sockaddr_in from; - socklen_t from_len; + IPAddress from; LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF); int len; int icp_version; @@ -598,15 +591,11 @@ icpHandleUdp(int sock, void *data) commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0); while (max--) { - from_len = sizeof(from); - memset(&from, '\0', from_len); len = comm_udp_recvfrom(sock, buf, SQUID_UDP_SO_RCVBUF - 1, 0, - - (struct sockaddr *) &from, - &from_len); + from); if (len == 0) break; @@ -632,8 +621,7 @@ icpHandleUdp(int sock, void *data) icpCount(buf, RECV, (size_t) len, 0); buf[len] = '\0'; debugs(12, 4, "icpHandleUdp: FD " << sock << ": received " << - (unsigned long int)len << " bytes from " << - inet_ntoa(from.sin_addr) << "."); + (unsigned long int)len << " bytes from " << from); #ifdef ICP_PACKET_DUMP @@ -653,7 +641,7 @@ icpHandleUdp(int sock, void *data) icpHandleIcpV3(sock, from, buf, len); else debugs(12, 1, "WARNING: Unused ICP version " << icp_version << - " received from " << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port)); + " received from " << from); } } @@ -662,11 +650,10 @@ icpConnectionsOpen(void) { u_int16_t port; - struct IN_ADDR addr; + IPAddress addr; - struct sockaddr_in xaddr; + struct addrinfo *xai = NULL; int x; - socklen_t len; wordlist *s; if ((port = Config.Port.icp) <= 0) @@ -674,13 +661,13 @@ icpConnectionsOpen(void) enter_suid(); + addr = Config.Addrs.udp_incoming; + addr.SetPort(port); theInIcpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, - Config.Addrs.udp_incoming, - port, + addr, COMM_NONBLOCKING, "ICP Socket"); - leave_suid(); if (theInIcpConnection < 0) @@ -695,17 +682,16 @@ icpConnectionsOpen(void) for (s = Config.mcast_group_list; s; s = s->next) ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); - debugs(12, 1, "Accepting ICP messages at " << - inet_ntoa(Config.Addrs.udp_incoming) << ", port " << (int) port << - ", FD " << theInIcpConnection << "."); - + debugs(12, 1, "Accepting ICP messages at " << addr << ", FD " << theInIcpConnection << "."); - if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) { + addr.SetEmpty(); // clear for next use. + addr = Config.Addrs.udp_outgoing; + if ( !addr.IsNoAddr() ) { enter_suid(); + addr.SetPort(port); theOutIcpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, addr, - port, COMM_NONBLOCKING, "ICP Port"); leave_suid(); @@ -719,7 +705,7 @@ icpConnectionsOpen(void) NULL, 0); - debugs(12, 1, "Outgoing ICP messages on port " << port << ", FD " << theOutIcpConnection << "."); + debugs(12, 1, "Outgoing ICP messages on port " << addr.GetPort() << ", FD " << theOutIcpConnection << "."); fd_note(theOutIcpConnection, "Outgoing ICP socket"); @@ -728,18 +714,18 @@ icpConnectionsOpen(void) theOutIcpConnection = theInIcpConnection; } - memset(&theOutICPAddr, '\0', sizeof(struct IN_ADDR)); + theOutICPAddr.SetEmpty(); - len = sizeof(struct sockaddr_in); - memset(&xaddr, '\0', len); - x = getsockname(theOutIcpConnection, + theOutICPAddr.InitAddrInfo(xai); - (struct sockaddr *) &xaddr, &len); + x = getsockname(theOutIcpConnection, xai->ai_addr, &xai->ai_addrlen); if (x < 0) debugs(50, 1, "theOutIcpConnection FD " << theOutIcpConnection << ": getsockname: " << xstrerror()); else - theOutICPAddr = xaddr.sin_addr; + theOutICPAddr = *xai; + + theOutICPAddr.FreeAddrInfo(xai); } /* diff --git a/src/icp_v3.cc b/src/icp_v3.cc index 8b8c5874b7..b318fe2391 100644 --- a/src/icp_v3.cc +++ b/src/icp_v3.cc @@ -1,8 +1,8 @@ /* - * $Id: icp_v3.cc,v 1.42 2007/04/28 22:26:37 hno Exp $ + * $Id: icp_v3.cc,v 1.43 2007/12/14 23:11:47 amosjeffries Exp $ * - * DEBUG: section 12 Internet Cache Protocol + * DEBUG: section 12 Internet Cache Protocol (ICP) * AUTHOR: Duane Wessels * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -52,18 +52,18 @@ public: static void -doV3Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header) +doV3Query(int fd, IPAddress &from, char *buf, icp_common_t header) { /* We have a valid packet */ char *url = buf + sizeof(icp_common_t) + sizeof(u_int32_t); - HttpRequest *icp_request = icpGetRequest (url, header.reqnum, fd, &from); + HttpRequest *icp_request = icpGetRequest (url, header.reqnum, fd, from); if (!icp_request) return; - if (!icpAccessAllowed(&from, icp_request)) + if (!icpAccessAllowed(from, icp_request)) { - icpDenyAccess (&from, url, header.reqnum, fd); + icpDenyAccess (from, url, header.reqnum, fd); delete icp_request; return; } @@ -97,7 +97,7 @@ ICP3State::created (StoreEntry *newEntry) else codeToSend = icpGetCommonOpcode(); - icpCreateAndSend (codeToSend, 0, url, header.reqnum, 0, fd, &from); + icpCreateAndSend (codeToSend, 0, url, header.reqnum, 0, fd, from); delete this; } @@ -105,7 +105,7 @@ ICP3State::created (StoreEntry *newEntry) /* Currently Harvest cached-2.x uses ICP_VERSION_3 */ void -icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) +icpHandleIcpV3(int fd, IPAddress&from, char *buf, int len) { if (len <= 0) { @@ -128,14 +128,10 @@ icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) { case ICP_QUERY: - doV3Query(fd, from,buf, header); + doV3Query(fd, from, buf, header); break; case ICP_HIT: -#if ALLOW_SOURCE_PING - - case ICP_SECHO: -#endif case ICP_DECHO: @@ -144,7 +140,7 @@ icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) case ICP_DENIED: case ICP_MISS_NOFETCH: - header.handleReply(buf, &from); + header.handleReply(buf, from); break; case ICP_INVALID: @@ -153,7 +149,7 @@ icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len) break; default: - debugs(12, 0, "icpHandleIcpV3: UNKNOWN OPCODE: " << header.opcode << " from " << inet_ntoa(from.sin_addr)); + debugs(12, 0, "icpHandleIcpV3: UNKNOWN OPCODE: " << header.opcode << " from " << from); break; } } diff --git a/src/ident.cc b/src/ident.cc index 7669782ed6..ece329c276 100644 --- a/src/ident.cc +++ b/src/ident.cc @@ -1,6 +1,6 @@ /* - * $Id: ident.cc,v 1.77 2007/05/29 13:31:40 amosjeffries Exp $ + * $Id: ident.cc,v 1.78 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 30 Ident (RFC 931) * AUTHOR: Duane Wessels @@ -55,9 +55,9 @@ typedef struct _IdentStateData hash_link hash; /* must be first */ int fd; /* IDENT fd */ - struct sockaddr_in me; + IPAddress me; - struct sockaddr_in my_peer; + IPAddress my_peer; IdentClient *clients; char buf[4096]; } @@ -107,7 +107,7 @@ static void identTimeout(int fd, void *data) { IdentStateData *state = (IdentStateData *)data; - debugs(30, 3, "identTimeout: FD " << fd << ", " << inet_ntoa(state->my_peer.sin_addr)); + debugs(30, 3, "identTimeout: FD " << fd << ", " << state->my_peer); comm_close(fd); } @@ -141,8 +141,8 @@ identConnectDone(int fd, comm_err_t status, int xerrno, void *data) MemBuf mb; mb.init(); mb.Printf("%d, %d\r\n", - ntohs(state->my_peer.sin_port), - ntohs(state->me.sin_port)); + state->my_peer.GetPort(), + state->me.GetPort()); comm_write_mbuf(fd, &mb, NULL, state); comm_read(fd, state->buf, BUFSIZ, identReadReply, state); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); @@ -212,20 +212,17 @@ CBDATA_TYPE(IdentStateData); * start a TCP connection to the peer host on port 113 */ void - -identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) +identStart(IPAddress &me, IPAddress &my_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(my_peer->sin_addr), - ntohs(my_peer->sin_port)); + char ntoabuf[MAX_IPSTRLEN]; + + me.ToURL(key1, IDENT_KEY_SZ); + my_peer.ToURL(key2, IDENT_KEY_SZ); snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); if ((state = (IdentStateData *)hash_lookup(ident_hash, key)) != NULL) @@ -236,8 +233,7 @@ identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, fd = comm_open(SOCK_STREAM, IPPROTO_TCP, - me->sin_addr, - 0, + me, COMM_NONBLOCKING, "ident"); @@ -252,8 +248,8 @@ identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, state = cbdataAlloc(IdentStateData); state->hash.key = xstrdup(key); state->fd = fd; - state->me = *me; - state->my_peer = *my_peer; + state->me = me; + state->my_peer = my_peer; identClientAdd(state, callback, data); hash_join(ident_hash, &state->hash); comm_add_close_handler(fd, @@ -261,7 +257,7 @@ identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, state); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); commConnectStart(fd, - inet_ntoa(state->my_peer.sin_addr), + state->my_peer.NtoA(ntoabuf,MAX_IPSTRLEN), IDENT_PORT, identConnectDone, state); diff --git a/src/internal.cc b/src/internal.cc index 472270928f..d4a1ddeb0d 100644 --- a/src/internal.cc +++ b/src/internal.cc @@ -1,6 +1,6 @@ /* - * $Id: internal.cc,v 1.47 2007/05/29 13:31:40 amosjeffries Exp $ + * $Id: internal.cc,v 1.48 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 76 Internal Squid Object handling * AUTHOR: Duane, Alex, Henrik @@ -51,7 +51,7 @@ internalStart(HttpRequest * request, StoreEntry * entry) { ErrorState *err; const char *upath = request->urlpath.buf(); - debugs(76, 3, "internalStart: " << inet_ntoa(request->client_addr) << " requesting '" << upath << "'"); + debugs(76, 3, "internalStart: " << request->client_addr << " requesting '" << upath << "'"); if (0 == strcmp(upath, "/squid-internal-dynamic/netdb")) { netdbBinaryExchange(entry); @@ -106,6 +106,15 @@ internalRemoteUri(const char *host, u_short port, const char *dir, const char *n /* convert host name to lower case */ xstrncpy(lc_host, host, SQUIDHOSTNAMELEN); Tolower(lc_host); + +#if USE_IPV6 + /* check for an IP address and format appropriately if found */ + IPAddress test = lc_host; + if ( !test.IsAnyAddr() ) { + test.ToHostname(lc_host,SQUIDHOSTNAMELEN); + } +#endif + /* * append the domain in order to mirror the requests with appended * domains diff --git a/src/ipc.cc b/src/ipc.cc index c844d136ee..09339eaa4b 100644 --- a/src/ipc.cc +++ b/src/ipc.cc @@ -1,6 +1,6 @@ /* - * $Id: ipc.cc,v 1.46 2007/06/10 10:43:17 hno Exp $ + * $Id: ipc.cc,v 1.47 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 54 Interprocess Communication * AUTHOR: Duane Wessels @@ -36,6 +36,7 @@ #include "squid.h" #include "comm.h" #include "fde.h" +#include "IPAddress.h" static const char *hello_string = "hi there\n"; #define HELLO_BUF_SZ 32 @@ -74,20 +75,18 @@ PutEnvironment() } pid_t -ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) +ipcCreate(int type, const char *prog, const char *const args[], const char *name, IPAddress &local_addr, int *rfd, int *wfd, void **hIpc) { pid_t pid; - - struct sockaddr_in ChS; - - struct sockaddr_in PaS; + IPAddress ChS; + IPAddress PaS; + struct addrinfo *AI = NULL; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; int fd; int t1, t2, t3; - socklen_t len; int x; #if USE_POLL && defined(_SQUID_OSF_) @@ -108,27 +107,23 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name crfd = cwfd = comm_open(SOCK_STREAM, 0, local_addr, - 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, 0, /* protocol */ local_addr, - 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, 0, local_addr, - 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, 0, local_addr, 0, - 0, name); } else if (type == IPC_FIFO) { int p2c[2]; @@ -197,25 +192,33 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name } if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { - len = sizeof(PaS); - memset(&PaS, '\0', len); + PaS.InitAddrInfo(AI); - if (getsockname(pwfd, (struct sockaddr *) &PaS, &len) < 0) { + if (getsockname(pwfd, AI->ai_addr, &AI->ai_addrlen) < 0) { + PaS.FreeAddrInfo(AI); debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - debugs(54, 3, "ipcCreate: FD " << pwfd << " sockaddr " << inet_ntoa(PaS.sin_addr) << ":" << ntohs(PaS.sin_port)); + PaS = *AI; - len = sizeof(ChS); - memset(&ChS, '\0', len); + debugs(54, 3, "ipcCreate: FD " << pwfd << " sockaddr " << PaS); - if (getsockname(crfd, (struct sockaddr *) &ChS, &len) < 0) { + PaS.FreeAddrInfo(AI); + + ChS.InitAddrInfo(AI); + + if (getsockname(crfd, AI->ai_addr, &AI->ai_addrlen) < 0) { + ChS.FreeAddrInfo(AI); debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - debugs(54, 3, "ipcCreate: FD " << crfd << " sockaddr " << inet_ntoa(ChS.sin_addr) << ":" << ntohs(ChS.sin_port)); + ChS = *AI; + + ChS.FreeAddrInfo(AI); + + debugs(54, 3, "ipcCreate: FD " << crfd << " sockaddr " << ChS ); } @@ -246,7 +249,7 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name cwfd = crfd = -1; if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { - if (comm_connect_addr(pwfd, &ChS) == COMM_ERROR) + if (comm_connect_addr(pwfd, ChS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } @@ -317,7 +320,7 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name close(crfd); cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { - if (comm_connect_addr(crfd, &PaS) == COMM_ERROR) + if (comm_connect_addr(crfd, PaS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } diff --git a/src/ipc_win32.cc b/src/ipc_win32.cc index 905f4f8327..dc813966b5 100755 --- a/src/ipc_win32.cc +++ b/src/ipc_win32.cc @@ -1,6 +1,5 @@ - /* - * $Id: ipc_win32.cc,v 1.4 2007/04/30 16:56:09 wessels Exp $ + * $Id: ipc_win32.cc,v 1.5 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 54 Windows Interprocess Communication * AUTHOR: Andrey Shorin @@ -49,8 +48,8 @@ struct ipc_params int type; int crfd; int cwfd; - - struct sockaddr_in PS; + IPAddress local_addr; + struct addrinfo PS; const char *prog; char **args; }; @@ -108,7 +107,7 @@ PutEnvironment() } pid_t -ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) +ipcCreate(int type, const char *prog, const char *const args[], const char *name, IPAddress &local_addr, int *rfd, int *wfd, void **hIpc) { unsigned long thread; @@ -118,14 +117,14 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name DWORD ecode = 0; pid_t pid; - struct sockaddr_in CS; + IPAddress tmp_addr; + struct addrinfo *aiCS = NULL; + struct addrinfo *aiPS = NULL; - struct sockaddr_in PS; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; - socklen_t len; int x; requirePathnameExists(name, prog); @@ -149,27 +148,23 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name crfd = cwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, local_addr, - 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, /* protocol */ local_addr, - 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, - 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, - 0, name); } else if (type == IPC_FIFO) { debugs(54, 0, "ipcCreate: " << prog << ": use IPC_TCP_SOCKET instead of IP_FIFO on Windows"); @@ -199,25 +194,31 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } +// AYJ: these flags should be neutral, but if not IPv6 version needs adding if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { - len = sizeof(PS); - memset(&PS, '\0', len); - if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { + tmp_addr.InitAddrInfo(aiPS); + + if (getsockname(pwfd, aiPS->ai_addr, &(aiPS->ai_addrlen) ) < 0) { debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - debugs(54, 3, "ipcCreate: FD " << pwfd << " sockaddr " << inet_ntoa(PS.sin_addr) << ":" << ntohs(PS.sin_port)); - len = sizeof(CS); - memset(&CS, '\0', len); + tmp_addr = *aiPS; + + debugs(54, 3, "ipcCreate: FD " << pwfd << " sockaddr " << tmp_addr ); - if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { + tmp_addr.InitAddrInfo(aiCS); + + if (getsockname(crfd, aiCS->ai_addr, &(aiCS->ai_addrlen) ) < 0) { debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - debugs(54, 3, "ipcCreate: FD " << crfd << " sockaddr " << inet_ntoa(CS.sin_addr) << ":" << ntohs(CS.sin_port)); + tmp_addr.SetEmpty(); + tmp_addr = *aiCS; + + debugs(54, 3, "ipcCreate: FD " << crfd << " sockaddr " << tmp_addr ); } if (type == IPC_TCP_SOCKET) { @@ -238,7 +239,9 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name params.cwfd = cwfd; - params.PS = PS; + params.PS = *aiPS; + + params.local_addr = local_addr; params.prog = prog; @@ -251,7 +254,8 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) { + /* NP: tmp_addr was left with eiether empty or aiCS in IPAddress format */ + if (comm_connect_addr(pwfd, tmp_addr) == COMM_ERROR) { CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } @@ -369,7 +373,7 @@ ipc_thread_1(void *in_params) struct thread_params thread_params; ssize_t x; - int tmp_s, fd = -1; + int fd = -1; char *str; STARTUPINFO si; PROCESS_INFORMATION pi; @@ -377,7 +381,10 @@ ipc_thread_1(void *in_params) int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1; char *prog = NULL, *buf1 = NULL; - struct sockaddr_in CS_ipc, PS_ipc; + IPAddress PS_ipc; + IPAddress CS_ipc; + struct addrinfo *aiPS_ipc = NULL; + struct addrinfo *aiCS_ipc = NULL; struct ipc_params *params = (struct ipc_params *) in_params; int type = params->type; @@ -385,9 +392,9 @@ ipc_thread_1(void *in_params) int cwfd = params->cwfd; char **args = params->args; - struct sockaddr_in PS = params->PS; - - + IPAddress PS = params->PS; + IPAddress local_addr = params->local_addr; + buf1 = (char *)xcalloc(1, 8192); strcpy(buf1, params->prog); prog = strtok(buf1, w_space); @@ -415,7 +422,7 @@ ipc_thread_1(void *in_params) fd_table[fd].flags.ipc = 1; cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { - if (comm_connect_addr(crfd, &PS) == COMM_ERROR) + if (comm_connect_addr(crfd, params->PS) == COMM_ERROR) goto cleanup; } @@ -457,7 +464,7 @@ ipc_thread_1(void *in_params) if (type == IPC_UDP_SOCKET) { snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L); - crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); + crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, buf1); if (crfd_ipc < 0) { debugs(54, 0, "ipcCreate: CHILD: Failed to create child FD for " << prog << "."); @@ -466,7 +473,7 @@ ipc_thread_1(void *in_params) } snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L); - prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); + prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, buf1); if (pwfd_ipc < 0) { debugs(54, 0, "ipcCreate: CHILD: Failed to create server FD for " << prog << "."); @@ -474,36 +481,38 @@ ipc_thread_1(void *in_params) goto cleanup; } - tmp_s = sizeof(PS_ipc); - memset(&PS_ipc, '\0', tmp_s); + PS_ipc.InitAddrInfo(aiPS_ipc); - if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) { + if (getsockname(pwfd_ipc, aiPS_ipc->ai_addr, &(aiPS_ipc->ai_addrlen)) < 0) { debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } - debugs(54, 3, "ipcCreate: FD " << pwfd_ipc << " sockaddr " << inet_ntoa(PS_ipc.sin_addr) << ":" << ntohs(PS_ipc.sin_port)); + PS_ipc = *aiPS_ipc; + + debugs(54, 3, "ipcCreate: FD " << pwfd_ipc << " sockaddr " << PS_ipc); - tmp_s = sizeof(CS_ipc); - memset(&CS_ipc, '\0', tmp_s); + CS_ipc.InitAddrInfo(aiCS_ipc); - if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) { + if (getsockname(crfd_ipc, aiCS_ipc->ai_addr, &(aiCS_ipc->ai_addrlen)) < 0) { debugs(54, 0, "ipcCreate: getsockname: " << xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } - debugs(54, 3, "ipcCreate: FD " << crfd_ipc << " sockaddr " << inet_ntoa(CS_ipc.sin_addr) << ":" << ntohs(CS_ipc.sin_port)); + CS_ipc = *aiCS_ipc; + + debugs(54, 3, "ipcCreate: FD " << crfd_ipc << " sockaddr " << CS_ipc); - if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) { + if (comm_connect_addr(pwfd_ipc, CS_ipc) == COMM_ERROR) { ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } fd = crfd; - if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) { + if (comm_connect_addr(crfd_ipc, PS_ipc) == COMM_ERROR) { ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } diff --git a/src/ipcache.cc b/src/ipcache.cc index 05c4f9d856..0c134307c7 100644 --- a/src/ipcache.cc +++ b/src/ipcache.cc @@ -1,6 +1,6 @@ /* - * $Id: ipcache.cc,v 1.264 2007/10/13 00:02:28 hno Exp $ + * $Id: ipcache.cc,v 1.265 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 14 IP Cache * AUTHOR: Harvest Derived @@ -40,6 +40,7 @@ #include "SquidTime.h" #include "Store.h" #include "wordlist.h" +#include "IPAddress.h" typedef struct _ipcache_entry ipcache_entry; @@ -56,6 +57,7 @@ struct _ipcache_entry struct timeval request_time; dlink_node lru; unsigned short locks; + unsigned short cname_wait; struct { @@ -90,7 +92,7 @@ static HLPCB ipcacheHandleReply; #else static IDNSCB ipcacheHandleReply; #endif -static IPH dummy_handler; +static IPH ipcacheHandleCnameRecurse; static int ipcacheExpiredEntry(ipcache_entry *); static int ipcache_testname(void); #if USE_DNSSERVERS @@ -102,7 +104,7 @@ static ipcache_entry *ipcache_get(const char *); static void ipcacheLockEntry(ipcache_entry *); static void ipcacheStatPrint(ipcache_entry *, StoreEntry *); static void ipcacheUnlockEntry(ipcache_entry *); -static void ipcacheRelease(ipcache_entry *); +static void ipcacheRelease(ipcache_entry *, bool dofree = true); static ipcache_addrs static_addrs; static hash_table *ip_table = NULL; @@ -133,13 +135,24 @@ ipcache_testname(void) /* removes the given ipcache entry */ static void -ipcacheRelease(ipcache_entry * i) +ipcacheRelease(ipcache_entry * i, bool dofree) { + if(!i) { + debugs(14, 0, "ipcacheRelease: Releasing entry with i="); + return; + } + + if(!i || !i->hash.key) { + debugs(14, 0, "ipcacheRelease: Releasing entry without hash link!"); + return; + } + debugs(14, 3, "ipcacheRelease: Releasing entry for '" << (const char *) i->hash.key << "'"); hash_remove_link(ip_table, (hash_link *) i); dlinkDelete(&i->lru, &lru_list); - ipcacheFreeEntry(i); + if(dofree) + ipcacheFreeEntry(i); } static ipcache_entry * @@ -238,10 +251,19 @@ ipcacheAddEntry(ipcache_entry * i) { hash_link *e = (hash_link *)hash_lookup(ip_table, i->hash.key); + /* INET6 : should NOT be adding this entry until all CNAME have been received. */ + assert(i->cname_wait == 0); + if (NULL != e) { /* avoid colission */ ipcache_entry *q = (ipcache_entry *) e; - ipcacheRelease(q); + if(q == i) { + /* can occur with Multiple-depth CNAME Recursion if parent returned early with additional */ + /* just need to drop from the hash without releasing actual memory */ + ipcacheRelease(q, false); + } + else + ipcacheRelease(q); } hash_join(ip_table, &i->hash); @@ -254,7 +276,7 @@ static void ipcacheCallback(ipcache_entry * i) { IPH *callback = i->handler; - void *cbdata; + void *cbdata = NULL; i->lastref = squid_curtime; if (!i->handler) @@ -343,11 +365,14 @@ ipcacheParse(ipcache_entry *i, const char *inbuf) if (ipcount > 0) { int j, k; - i->addrs.in_addrs = (struct IN_ADDR *)xcalloc(ipcount, sizeof(struct IN_ADDR)); + i->addrs.in_addrs = (IPAddress *)xcalloc(ipcount, sizeof(IPAddress)); + for(int l = 0; l < ipcount; l++) + i->addrs.in_addrs[l].SetEmpty(); // perform same init actions as constructor would. i->addrs.bad_mask = (unsigned char *)xcalloc(ipcount, sizeof(unsigned char)); + memset(i->addrs.bad_mask, 0, sizeof(unsigned char) * ipcount); for (j = 0, k = 0; k < ipcount; k++) { - if (safe_inet_addr(A[k], &i->addrs.in_addrs[j])) + if ( i->addrs.in_addrs[j] = A[k] ) j++; else debugs(14, 1, "ipcacheParse: Invalid IP address '" << A[k] << "' in response to '" << name << "'"); @@ -379,15 +404,18 @@ static int ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_message) { int k; - int j; + int j = 0; int na = 0; int ttl = 0; const char *name = (const char *)i->hash.key; i->expires = squid_curtime + Config.negativeDnsTtl; i->flags.negcached = 1; safe_free(i->addrs.in_addrs); + assert(i->addrs.in_addrs == NULL); safe_free(i->addrs.bad_mask); + assert(i->addrs.bad_mask == NULL); safe_free(i->error_message); + assert(i->error_message == NULL); i->addrs.count = 0; if (nr < 0) { @@ -399,24 +427,54 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m if (nr == 0) { debugs(14, 3, "ipcacheParse: No DNS records in response to '" << name << "'"); i->error_message = xstrdup("No DNS records"); - return 0; + return -1; } assert(answers); for (k = 0; k < nr; k++) { - if (answers[k].type != RFC1035_TYPE_A) - continue; - if (answers[k]._class != RFC1035_CLASS_IN) - continue; +#if USE_IPV6 + if (answers[k].type == RFC1035_TYPE_AAAA) { + if (answers[k].rdlength != sizeof(struct in6_addr)) { + debugs(14, 1, "ipcacheParse: Invalid IPv6 address in response to '" << name << "'"); + continue; + } + na++; + continue; + } +#endif - if (answers[k].rdlength != 4) { - debugs(14, 1, "ipcacheParse: Invalid IP address in response to '" << name << "'"); + if (answers[k].type == RFC1035_TYPE_A) { + if (answers[k].rdlength != sizeof(struct in_addr)) { + debugs(14, 1, "ipcacheParse: Invalid IPv4 address in response to '" << name << "'"); + continue; + } + na++; + continue; + } + + /* With A and AAAA, the CNAME does not necessarily come with additional records to use. */ + if (answers[k].type == RFC1035_TYPE_CNAME) { + debugs(14, 5, "ipcacheParse: " << name << " CNAME " << answers[k].rdata << " (checking destination: " << i << ")."); + const ipcache_addrs *res = ipcache_gethostbyname(answers[k].rdata, 0); + if(res) { + na += res->count; + debugs(14, 5, "ipcacheParse: CNAME " << answers[k].rdata << " already has " << res->count << " IPs cached."); + } + else { + /* keep going on this, but flag the fact that we need to wait for a CNAME lookup to finish */ + debugs(14, 5, "ipcacheParse: CNAME " << answers[k].rdata << " has no IPs! Recursing."); + ipcache_nbgethostbyname(answers[k].rdata, ipcacheHandleCnameRecurse, new generic_cbdata(i) ); + i->cname_wait++; + } continue; } + } - na++; + if(na == 0 && i->cname_wait >0 ) { + /* don't set any error message (yet). Allow recursion to do its work first. */ + return 0; } if (na == 0) { @@ -425,27 +483,54 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m return 0; } - i->addrs.in_addrs = (struct IN_ADDR *)xcalloc(na, sizeof(struct IN_ADDR)); + i->addrs.in_addrs = (IPAddress *)xcalloc(na, sizeof(IPAddress)); + for(int l = 0; l < na; l++) + i->addrs.in_addrs[l].SetEmpty(); // perform same init actions as constructor would. i->addrs.bad_mask = (unsigned char *)xcalloc(na, sizeof(unsigned char)); for (j = 0, k = 0; k < nr; k++) { - if (answers[k]._class != RFC1035_CLASS_IN) - continue; if (answers[k].type == RFC1035_TYPE_A) { - if (answers[k].rdlength != 4) + if (answers[k].rdlength != sizeof(struct in_addr)) continue; - xmemcpy(&i->addrs.in_addrs[j++], answers[k].rdata, 4); + struct in_addr temp; + xmemcpy(&temp, answers[k].rdata, sizeof(struct in_addr)); + i->addrs.in_addrs[j] = temp; - debugs(14, 3, "ipcacheParse: #" << j - 1 << " " << inet_ntoa(i->addrs.in_addrs[j - 1])); + debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j]); + j++; - } else if (answers[k].type != RFC1035_TYPE_CNAME) - continue; +#if USE_IPV6 + } else if (answers[k].type == RFC1035_TYPE_AAAA) { + if (answers[k].rdlength != sizeof(struct in6_addr)) + continue; + + struct in6_addr temp; + xmemcpy(&temp, answers[k].rdata, sizeof(struct in6_addr)); + i->addrs.in_addrs[j] = temp; + + debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j] ); + j++; +#endif + } else if (answers[k].type == RFC1035_TYPE_CNAME) { + debugs(14, 3, "ipcacheParse: " << name << " #x CNAME " << answers[k].rdata); + const ipcache_addrs *res = ipcache_gethostbyname(answers[k].rdata, 0); + if(res) { + /* NP: the results of *that* query need to be integrated in place of the CNAME */ + /* Ideally we should also integrate the min TTL of the above IPA's into ttl. */ + for(int l = 0; l < res->count; l++, j++) { + i->addrs.in_addrs[j] = res->in_addrs[l]; + debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j] ); + } + } + else { + debugs(14, 9, "ipcacheParse: " << answers[k].rdata << " (CNAME) waiting on A/AAAA records."); + } + } if (ttl == 0 || (int) answers[k].ttl < ttl) ttl = answers[k].ttl; - } assert(j == na); @@ -465,7 +550,13 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m i->flags.negcached = 0; - return i->addrs.count; + /* SPECIAL CASE: may get here IFF CNAME received with Additional records */ + /* reurn 0/'wait for further details' value. */ + /* NP: 'No DNS Results' is a return -1 +msg */ + if(i->cname_wait) + return 0; + else + return i->addrs.count; } #endif @@ -477,6 +568,7 @@ ipcacheHandleReply(void *data, char *reply) ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message) #endif { + int done; ipcache_entry *i; static_cast(data)->unwrap(&i); IpcacheStats.replies++; @@ -484,14 +576,19 @@ ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_m tvSubMsec(i->request_time, current_time)); #if USE_DNSSERVERS - ipcacheParse(i, reply); + done = ipcacheParse(i, reply); #else - ipcacheParse(i, answers, na, error_message); + done = ipcacheParse(i, answers, na, error_message); + + /* If we have not produced either IPs or Error immediately, wait for recursion to finish. */ + if(done != 0 || error_message != NULL) #endif - ipcacheAddEntry(i); - ipcacheCallback(i); + { + ipcacheAddEntry(i); + ipcacheCallback(i); + } } void @@ -513,6 +610,7 @@ ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData) } if ((addrs = ipcacheCheckNumeric(name))) { + debugs(14, 4, "ipcache_nbgethostbyname: BYPASS for '" << name << "' (already numeric)"); dns_error_message = NULL; IpcacheStats.numeric_hits++; handler(addrs, handlerData); @@ -582,7 +680,8 @@ ipcache_init(void) memset(&static_addrs, '\0', sizeof(ipcache_addrs)); - static_addrs.in_addrs = (struct IN_ADDR *)xcalloc(1, sizeof(struct IN_ADDR)); + static_addrs.in_addrs = (IPAddress *)xcalloc(1, sizeof(IPAddress)); + static_addrs.in_addrs->SetEmpty(); // properly setup the IPAddress! static_addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char)); ipcache_high = (long) (((float) Config.ipcache.size * (float) Config.ipcache.high) / (float) 100); @@ -637,7 +736,7 @@ ipcache_gethostbyname(const char *name, int flags) IpcacheStats.misses++; if (flags & IP_LOOKUP_IF_MISS) - ipcache_nbgethostbyname(name, dummy_handler, NULL); + ipcache_nbgethostbyname(name, ipcacheHandleCnameRecurse, NULL); return NULL; } @@ -646,6 +745,19 @@ static void ipcacheStatPrint(ipcache_entry * i, StoreEntry * sentry) { int k; + int count = i->addrs.count; + char buf[MAX_IPSTRLEN]; + + if(!sentry) { + debugs(14, 0, HERE << "CRITICAL: sentry is NULL!"); + } + + if(!i) { + debugs(14, 0, HERE << "CRITICAL: ipcache_entry is NULL!"); + storeAppendPrintf(sentry, "CRITICAL ERROR\n"); + return; + } + storeAppendPrintf(sentry, " %-32.32s %c%c %6d %6d %2d(%2d)", hashKeyStr(&i->hash), i->flags.fromhosts ? 'H' : ' ', @@ -655,12 +767,27 @@ ipcacheStatPrint(ipcache_entry * i, StoreEntry * sentry) (int) i->addrs.count, (int) i->addrs.badcount); - for (k = 0; k < (int) i->addrs.count; k++) { - storeAppendPrintf(sentry, " %15s-%3s", inet_ntoa(i->addrs.in_addrs[k]), - i->addrs.bad_mask[k] ? "BAD" : "OK "); + /** \par + * Negative-cached entries have no IPs listed. */ + if(i->flags.negcached) { + storeAppendPrintf(sentry, "\n"); + return; } - storeAppendPrintf(sentry, "\n"); + /** \par + * Cached entries have IPs listed with a BNF of: '-' ('OK'|'BAD') */ + for (k = 0; k < count; k++) { + /* Display tidy-up: IPv6 are so big make the list vertical */ + if(k == 0) + storeAppendPrintf(sentry, " %45.45s-%3s\n", + i->addrs.in_addrs[k].NtoA(buf,MAX_IPSTRLEN), + i->addrs.bad_mask[k] ? "BAD" : "OK "); + else + storeAppendPrintf(sentry, "%s %45.45s-%3s\n", + " ", /* blank-space indenting IP list */ + i->addrs.in_addrs[k].NtoA(buf,MAX_IPSTRLEN), + i->addrs.bad_mask[k] ? "BAD" : "OK "); + } } /* process objects list */ @@ -686,21 +813,229 @@ stat_ipcache_get(StoreEntry * sentry) IpcacheStats.invalid); storeAppendPrintf(sentry, "\n\n"); storeAppendPrintf(sentry, "IP Cache Contents:\n\n"); - storeAppendPrintf(sentry, " %-29.29s %3s %6s %6s %1s\n", + storeAppendPrintf(sentry, " %-31.31s %3s %6s %6s %4s\n", "Hostname", "Flg", "lstref", "TTL", - "N"); + "N(b)"); - for (m = lru_list.head; m; m = m->next) + for (m = lru_list.head; m; m = m->next) { + assert( m->next != m ); ipcacheStatPrint((ipcache_entry *)m->data, sentry); + } +} + +/** + * Takes two IPAddress arrays and merges them into a single array + * which is allocated dynamically to fit the number of unique addresses + * + \param aaddrs One list to merge + \param alen Size of list aaddrs + \param baddrs Other list to merge + \param alen Size of list baddrs + \param out Combined list of unique addresses (sorted with IPv6 first in IPv6-mode) + \param outlen Size of list out + */ +void +ipcacheMergeIPLists(IPAddress *aaddrs, int alen, + IPAddress *baddrs, int blen, + IPAddress **out, int &outlen ) +{ + int fc=0, t=0, c=0; + + IPAddress *ip4ptrs[255]; +#if USE_IPV6 + IPAddress *ip6ptrs[255]; +#endif + int num_ip4 = 0; + int num_ip6 = 0; + + memset(ip4ptrs, 0, sizeof(IPAddress*)*255); +#if USE_IPV6 + memset(ip6ptrs, 0, sizeof(IPAddress*)*255); +#endif + + // for each unique address in list A - grab ptr + for(t = 0; t < alen; t++) { + if(aaddrs[t].IsIPv4()) { + // check against IPv4 pruned list + for(c = 0; c <= num_ip4; c++) { + if(ip4ptrs[c] && aaddrs[t] == *(ip4ptrs[c]) ) break; // duplicate. + } + if(c > num_ip4) { + ip4ptrs[num_ip4] = &aaddrs[t]; + num_ip4++; + } + } +#if USE_IPV6 + else if(aaddrs[t].IsIPv6()) { +debugs(14,8, HERE << "A[" << t << "]=IPv6 " << aaddrs[t]); + // check against IPv6 pruned list + for(c = 0; c <= num_ip6; c++) { + if(ip6ptrs[c] && aaddrs[t] == *ip6ptrs[c]) break; // duplicate. + } + if(c > num_ip6) { + ip6ptrs[num_ip6] = &aaddrs[t]; + num_ip6++; + } + } +#endif + } + + // for each unique address in list B - grab ptr + for(t = 0; t < blen; t++) { + if(baddrs[t].IsIPv4()) { + // check against IPv4 pruned list + for(c = 0; c <= num_ip4; c++) { + if(ip4ptrs[c] && baddrs[t] == *ip4ptrs[c]) break; // duplicate. + } + if(c > num_ip4) { + ip4ptrs[num_ip4] = &baddrs[t]; + num_ip4++; + } + } +#if USE_IPV6 + else if(baddrs[t].IsIPv6()) { + // check against IPv6 pruned list + for(c = 0; c <= num_ip6; c++) { + if(ip6ptrs[c] && baddrs[t] == *ip6ptrs[c]) break; // duplicate. + } + if(c > num_ip6) { + ip6ptrs[num_ip6] = &baddrs[t]; + num_ip6++; + } + } +#endif + } + + fc = num_ip6 + num_ip4; + + assert(fc > 0); + + debugs(14, 5, "ipcacheMergeIPLists: Merge " << alen << "+" << blen << " into " << fc << " unique IPs."); + + // copy the old IPs into the new list buffer. + (*out) = (IPAddress*)xcalloc(fc, sizeof(IPAddress)); + outlen=0; + + assert(out != NULL); + +#if USE_IPV6 + /* IPv6 are preferred (tried first) over IPv4 */ + + for(int l = 0; outlen < num_ip6; l++, outlen++) { + (*out)[outlen] = *ip6ptrs[l]; + debugs(14, 5, "ipcacheMergeIPLists: #" << outlen << " " << (*out)[outlen] ); + } +#endif /* USE_IPV6 */ + + for(int l = 0; outlen < num_ip4; l++, outlen++) { + (*out)[outlen] = *ip4ptrs[l]; + debugs(14, 5, "ipcacheMergeIPLists: #" << outlen << " " << (*out)[outlen] ); + } + + assert(outlen == fc); // otherwise something broke badly! } static void -dummy_handler(const ipcache_addrs * addrsnotused, void *datanotused) +ipcacheHandleCnameRecurse(const ipcache_addrs *addrs, void *cbdata) { - return; + ipcache_entry *i = NULL; + char *pname = NULL; + IPAddress *tmpbuf = NULL; + int fc = 0; + int ttl = 0; + generic_cbdata* gcb = (generic_cbdata*)cbdata; + // count of addrs at parent and child (REQ as .count is a char type!) + int ccount = 0, pcount = 0; + + debugs(14, 5, "ipcacheHandleCnameRecurse: Handling basic A/AAAA response."); + + /* IFF no CNAME recursion being processed. do nothing. */ + if(cbdata == NULL) + return; + + gcb->unwrap(&i); + assert(i != NULL); + + // make sure we are actualy waiting for a CNAME callback to be run. + assert(i->cname_wait > 0); + // count this event. its being handled. + i->cname_wait--; + + pname = (char*)i->hash.key; + assert(pname != NULL); + + debugs(14, 5, "ipcacheHandleCnameRecurse: Handling CNAME recursion. CBDATA('" << gcb->data << "')='" << pname << "' -> " << std::hex << i); + + if(i == NULL) { + return; // Parent has expired. Don't merge, just leave for future Ref: + } + + /* IFF addrs is NULL (Usually an Error or Timeout occured on lookup.) */ + /* Ignore it and HOPE that we got some Additional records to use. */ + if(addrs == NULL) + return; + + ccount = (0+ addrs->count); + pcount = (0+ i->addrs.count); + ttl = i->expires; + + /* IFF no CNAME results. do none of the processing BUT finish anyway. */ + if(addrs) { + + debugs(14, 5, "ipcacheHandleCnameRecurse: Merge IP Lists for " << pname << " (" << pcount << "+" << ccount << ")"); + + /* add new IP records to entry */ + tmpbuf = i->addrs.in_addrs; + i->addrs.in_addrs = NULL; + ipcacheMergeIPLists(tmpbuf, pcount, addrs->in_addrs, ccount, &(i->addrs.in_addrs), fc); + debugs(14,8, HERE << "in=" << tmpbuf << ", out=" << i->addrs.in_addrs ); + assert(tmpbuf); + safe_free(tmpbuf); + + if( pcount > 0) { + /* IFF the parent initial lookup was given Additional records with A */ + // clear the 'bad IP mask' + safe_free(i->addrs.bad_mask); + } + // create a new bad IP mask to fit the new size needed. + if(fc > 0) { + i->addrs.bad_mask = (unsigned char*)xcalloc(fc, sizeof(unsigned char)); + memset(i->addrs.bad_mask, 0, sizeof(unsigned char)*fc); + } + + if (fc < 256) + i->addrs.count = (unsigned char) fc; + else + i->addrs.count = 255; + + if (ttl == 0 || ttl > Config.positiveDnsTtl) + ttl = Config.positiveDnsTtl; + + if (ttl < Config.negativeDnsTtl) + ttl = Config.negativeDnsTtl; + + i->expires = squid_curtime + ttl; + + i->flags.negcached = 0; + + i->addrs.cur = 0; + + i->addrs.badcount = 0; + } + + if(fc == 0) { + i->error_message = xstrdup("No DNS Records"); + } + + /* finish the lookup we were doing on parent when we got side-tracked for CNAME loop */ + if(i->cname_wait == 0) { + ipcacheAddEntry(i); + ipcacheCallback(i); + } + // else still more CNAME to be found. } void @@ -740,17 +1075,29 @@ ipcache_addrs * ipcacheCheckNumeric(const char *name) { - struct IN_ADDR ip; + IPAddress ip; /* check if it's already a IP address in text form. */ - if (!safe_inet_addr(name, &ip)) + /* it may be IPv6-wrapped */ + if(name[0] == '[') { + char *tmp = xstrdup(&name[1]); + tmp[strlen(tmp)-1] = '\0'; + if (!(ip = tmp)) { + delete tmp; + return NULL; + } + delete tmp; + } + else if (!(ip = name)) return NULL; + debugs(14, 4, "ipcacheCheckNumeric: HIT_BYPASS for '" << name << "' == " << ip ); + static_addrs.count = 1; static_addrs.cur = 0; - static_addrs.in_addrs[0].s_addr = ip.s_addr; + static_addrs.in_addrs[0] = ip; static_addrs.bad_mask[0] = FALSE; @@ -771,7 +1118,11 @@ ipcacheLockEntry(ipcache_entry * i) static void ipcacheUnlockEntry(ipcache_entry * i) { - assert(i->locks > 0); + if(i->locks < 1) { + debugs(14, 1, "WARNING: ipcacheEntry unlocked with no lock! locks=" << i->locks); + return; + } + i->locks--; if (ipcacheExpiredEntry(i)) @@ -815,7 +1166,7 @@ ipcacheCycleAddr(const char *name, ipcache_addrs * ia) ia->cur = 0; } - debugs(14, 3, "ipcacheCycleAddr: " << name << " now at " << inet_ntoa(ia->in_addrs[ia->cur])); + debugs(14, 3, "ipcacheCycleAddr: " << name << " now at " << ia->in_addrs[ia->cur] << " (" << ia->cur << " of " << ia->count << ")"); } /* @@ -823,8 +1174,7 @@ ipcacheCycleAddr(const char *name, ipcache_addrs * ia) * advance the current pointer to the next OK address. */ void - -ipcacheMarkBadAddr(const char *name, struct IN_ADDR addr) +ipcacheMarkBadAddr(const char *name, IPAddress &addr) { ipcache_entry *i; ipcache_addrs *ia; @@ -837,7 +1187,7 @@ ipcacheMarkBadAddr(const char *name, struct IN_ADDR addr) for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) + if (addr == ia->in_addrs[k] ) break; } @@ -849,7 +1199,7 @@ ipcacheMarkBadAddr(const char *name, struct IN_ADDR addr) ia->bad_mask[k] = TRUE; ia->badcount++; i->expires = XMIN(squid_curtime + XMAX((time_t)60, Config.negativeDnsTtl), i->expires); - debugs(14, 2, "ipcacheMarkBadAddr: " << name << " [" << inet_ntoa(addr) << "]"); + debugs(14, 2, "ipcacheMarkBadAddr: " << name << " " << addr ); } ipcacheCycleAddr(name, ia); @@ -857,7 +1207,7 @@ ipcacheMarkBadAddr(const char *name, struct IN_ADDR addr) void -ipcacheMarkGoodAddr(const char *name, struct IN_ADDR addr) +ipcacheMarkGoodAddr(const char *name, IPAddress &addr) { ipcache_entry *i; ipcache_addrs *ia; @@ -870,7 +1220,7 @@ ipcacheMarkGoodAddr(const char *name, struct IN_ADDR addr) for (k = 0; k < (int) ia->count; k++) { - if (ia->in_addrs[k].s_addr == addr.s_addr) + if (addr == ia->in_addrs[k]) break; } @@ -884,7 +1234,7 @@ ipcacheMarkGoodAddr(const char *name, struct IN_ADDR addr) ia->badcount--; - debugs(14, 2, "ipcacheMarkGoodAddr: " << name << " [" << inet_ntoa(addr) << "]"); + debugs(14, 2, "ipcacheMarkGoodAddr: " << name << " " << addr ); } static void @@ -926,14 +1276,18 @@ ipcacheAddEntryFromHosts(const char *name, const char *ipaddr) { ipcache_entry *i; - struct IN_ADDR ip; + IPAddress ip; - if (!safe_inet_addr(ipaddr, &ip)) { + if (!(ip = ipaddr)) { +#if USE_IPV6 if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) { debugs(14, 3, "ipcacheAddEntryFromHosts: Skipping IPv6 address '" << ipaddr << "'"); } else { debugs(14, 1, "ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr << "'"); } +#else + debugs(14, 1, "ipcacheAddEntryFromHosts: Bad IP address '" << ipaddr << "'"); +#endif return 1; } @@ -954,9 +1308,9 @@ ipcacheAddEntryFromHosts(const char *name, const char *ipaddr) i->addrs.cur = 0; i->addrs.badcount = 0; - i->addrs.in_addrs = (struct IN_ADDR *)xcalloc(1, sizeof(struct IN_ADDR)); + i->addrs.in_addrs = (IPAddress *)xcalloc(1, sizeof(IPAddress)); i->addrs.bad_mask = (unsigned char *)xcalloc(1, sizeof(unsigned char)); - i->addrs.in_addrs[0].s_addr = ip.s_addr; + i->addrs.in_addrs[0] = ip; i->addrs.bad_mask[0] = FALSE; i->flags.fromhosts = 1; ipcacheAddEntry(i); diff --git a/src/main.cc b/src/main.cc index cd3f631f75..ed11df33db 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.451 2007/12/02 08:23:56 amosjeffries Exp $ + * $Id: main.cc,v 1.452 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -72,6 +72,7 @@ #include "SwapDir.h" #include "forward.h" #include "MemPool.h" +#include "ICMPSquid.h" #if USE_WIN32_SERVICE @@ -561,7 +562,7 @@ serverConnectionsOpen(void) #endif clientdbInit(); - icmpOpen(); + icmpEngine.Open(); netdbInit(); asnInit(); ACL::Initialize(); @@ -583,7 +584,7 @@ serverConnectionsClose(void) htcpSocketShutdown(); #endif - icmpClose(); + icmpEngine.Close(); #ifdef SQUID_SNMP snmpConnectionShutdown(); @@ -693,7 +694,7 @@ mainReconfigure(void) static void mainRotate(void) { - icmpClose(); + icmpEngine.Close(); #if USE_DNSSERVERS dnsShutdown(); @@ -713,7 +714,7 @@ mainRotate(void) fwdLogRotate(); #endif - icmpOpen(); + icmpEngine.Open(); #if USE_DNSSERVERS dnsInit(); @@ -1124,18 +1125,6 @@ main(int argc, char **argv) if (oldmask) umask(oldmask); - memset(&local_addr, '\0', sizeof(struct IN_ADDR)); - - safe_inet_addr(localhost, &local_addr); - - memset(&any_addr, '\0', sizeof(struct IN_ADDR)); - - safe_inet_addr("0.0.0.0", &any_addr); - - memset(&no_addr, '\0', sizeof(struct IN_ADDR)); - - safe_inet_addr("255.255.255.255", &no_addr); - squid_srandom(time(NULL)); getCurrentTime(); @@ -1550,8 +1539,8 @@ watch_child(char *argv[]) pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { syslog(LOG_NOTICE, - "Squid Parent: child process %d exited due to signal %d", - pid, WTERMSIG(status)); + "Squid Parent: child process %d exited due to signal %d with status %d", + pid, WTERMSIG(status), WEXITSTATUS(status)); } else { syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid); } diff --git a/src/mib.txt b/src/mib.txt index 09432e94a3..aa3d352481 100644 --- a/src/mib.txt +++ b/src/mib.txt @@ -2,7 +2,7 @@ SQUID-MIB DEFINITIONS ::= BEGIN -- --- $Id: mib.txt,v 1.31 2007/08/27 12:50:43 hno Exp $ +-- $Id: mib.txt,v 1.32 2007/12/14 23:11:47 amosjeffries Exp $ -- IMPORTS @@ -11,12 +11,15 @@ IMPORTS FROM SNMPv2-SMI DisplayString - FROM SNMPv2-TC; + FROM SNMPv2-TC + + InetAddressType, InetAddress + FROM INET-ADDRESS-MIB; nlanr OBJECT IDENTIFIER ::= { enterprises 3495 } squid MODULE-IDENTITY - LAST-UPDATED "9809220000Z" + LAST-UPDATED "9708120000Z" ORGANIZATION "National Laboratory for Applied Network Research" CONTACT-INFO " Squid Developers @@ -26,6 +29,9 @@ squid MODULE-IDENTITY "Squid MIB defined for the management of the Squid proxy server. See http://www.squid-cache.org/." + REVISION "9708120000Z" + DESCRIPTION + "Added support for IPv6 Technology." REVISION "9809220000Z" DESCRIPTION "Move to SMIv2. Prepare to split into proxy/squid." @@ -47,7 +53,7 @@ squid MODULE-IDENTITY -- --- cacheSystem group +-- cacheSystem group { squid 1 } -- cacheSysVMsize OBJECT-TYPE @@ -75,7 +81,7 @@ squid MODULE-IDENTITY ::= { cacheSystem 3 } -- --- config group +-- cacheConfig group { squid 2 } -- -- Contains configuration information including peers etc. -- @@ -162,7 +168,7 @@ squid MODULE-IDENTITY -- --- performance group { squid 3 } +-- cachePerformance group { squid 3 } -- cacheSysPerf OBJECT IDENTIFIER ::= { cachePerf 1 } @@ -531,7 +537,7 @@ squid MODULE-IDENTITY ::= { cacheMedianSvcEntry 11 } -- --- cacheNetwork group +-- cacheNetwork group { squid 4 } -- -- This material is probably best suited elsewhere, however for now it -- will reside here until the both the Proxy and Squid MIBs are implimented. @@ -698,7 +704,7 @@ squid MODULE-IDENTITY ::= { cacheDns 3 } -- --- cacheMesh group +-- cacheMesh group { squid 5 } -- cachePeerTable OBJECT-TYPE @@ -716,12 +722,14 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " An entry in cachePeerTable " - INDEX { cachePeerAddr } + INDEX { cachePeerIndex } ::= { cachePeerTable 1 } CachePeerEntry ::= SEQUENCE { + cachePeerIndex CachePeerIndex, cachePeerName DisplayString, - cachePeerAddr IpAddress, + cachePeerAddressType InetAddressType, + cachePeerAddress InetAddress, cachePeerPortHttp Integer32 (1..65535), cachePeerPortIcp Integer32 (1..65535), cachePeerType Integer32, @@ -735,6 +743,31 @@ squid MODULE-IDENTITY cachePeerKeepAlRecv Counter32 } + CachePeerIndex ::= TEXTUAL-CONVENTION + DISPLAY-HINT "d" + STATUS current + DESCRIPTION + "A unique value, greater than zero for each + cache peer instance in the managed + system. It is recommended that values are assigned + contiguously starting from 1. The value for each + cache peer index must remain constant + at least from one re-initialization of the entity's + network management system to the next + re-initialization." + SYNTAX Integer32 (1..2147483647) + END + + + cachePeerIndex OBJECT-TYPE + SYNTAX CachePeerIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A unique non-zero value identifying + the particular cache Peer." + ::= { cachePeerEntry 1 } + cachePeerName OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only @@ -742,15 +775,43 @@ squid MODULE-IDENTITY DESCRIPTION " The FQDN name or internal alias for the peer cache " - ::= { cachePeerEntry 1 } + ::= { cachePeerEntry 2 } + + cachePeerAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The type of Internet address by which the peer + cache is reachable." + + ::= { cachePeerEntry 3 } + + cachePeerAddress OBJECT-TYPE + SYNTAX InetAddress (SIZE (1..64)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Internet address for the peer cache. The type of this + address is determined by the value of the peerAddressType + object. Note that implementations must limit themselves + to a single entry in this table per reachable peer. + The peerAddress may not be empty due to the SIZE + restriction. + + If a row is created administratively by an SNMP + operation and the address type value is dns(16), then + the agent stores the DNS name internally. A DNS name + lookup must be performed on the internally stored DNS + name whenever it is being used to contact the peer. + + If a row is created by the managed entity itself and + the address type value is dns(16), then the agent + stores the IP address internally. A DNS reverse lookup + must be performed on the internally stored IP address + whenever the value is retrieved via SNMP." + ::= { cachePeerEntry 4 } - cachePeerAddr OBJECT-TYPE - SYNTAX IpAddress - MAX-ACCESS read-only - STATUS current - DESCRIPTION - " The IP Address of the peer cache " - ::= { cachePeerEntry 2 } cachePeerPortHttp OBJECT-TYPE SYNTAX Integer32 @@ -758,7 +819,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " The port the peer listens for HTTP requests " - ::= { cachePeerEntry 3 } + ::= { cachePeerEntry 5 } cachePeerPortIcp OBJECT-TYPE SYNTAX Integer32 @@ -767,7 +828,7 @@ squid MODULE-IDENTITY DESCRIPTION " The port the peer listens for ICP requests should be 0 if not configured to send ICP requests " - ::= { cachePeerEntry 4 } + ::= { cachePeerEntry 6 } cachePeerType OBJECT-TYPE SYNTAX INTEGER @@ -775,7 +836,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Peer Type " - ::= { cachePeerEntry 5 } + ::= { cachePeerEntry 7 } cachePeerState OBJECT-TYPE SYNTAX INTEGER @@ -783,7 +844,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " The operational state of this peer " - ::= { cachePeerEntry 6 } + ::= { cachePeerEntry 8 } cachePeerPingsSent OBJECT-TYPE SYNTAX Counter32 @@ -791,7 +852,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of pings sent to peer " - ::= { cachePeerEntry 7 } + ::= { cachePeerEntry 9 } cachePeerPingsAcked OBJECT-TYPE SYNTAX Counter32 @@ -799,7 +860,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of pings received from peer " - ::= { cachePeerEntry 8 } + ::= { cachePeerEntry 10 } cachePeerFetches OBJECT-TYPE SYNTAX Counter32 @@ -807,7 +868,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of times this peer was selected " - ::= { cachePeerEntry 9 } + ::= { cachePeerEntry 11 } cachePeerRtt OBJECT-TYPE SYNTAX Integer32 @@ -815,7 +876,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Last known round-trip time to the peer (in ms) " - ::= { cachePeerEntry 10 } + ::= { cachePeerEntry 12 } cachePeerIgnored OBJECT-TYPE SYNTAX Counter32 @@ -823,7 +884,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " How many times this peer was ignored " - ::= { cachePeerEntry 11 } + ::= { cachePeerEntry 13 } cachePeerKeepAlSent OBJECT-TYPE SYNTAX Counter32 @@ -831,7 +892,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of keepalives sent " - ::= { cachePeerEntry 12 } + ::= { cachePeerEntry 14 } cachePeerKeepAlRecv OBJECT-TYPE SYNTAX Counter32 @@ -839,7 +900,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of keepalives received " - ::= { cachePeerEntry 13 } + ::= { cachePeerEntry 15 } --- --- Table of cache's clients, with statistics. Children caches can be identified @@ -854,17 +915,19 @@ squid MODULE-IDENTITY "A list of cache client entries." ::= { cacheMesh 2 } + cacheClientEntry OBJECT-TYPE SYNTAX CacheClientEntry ACCESS not-accessible STATUS mandatory DESCRIPTION "An entry in cacheClientTable " - INDEX { cacheClientAddr } + INDEX { cacheClientAddressType, cacheClientAddress } ::= { cacheClientTable 1 } CacheClientEntry ::= SEQUENCE { - cacheClientAddr IpAddress, + cacheClientAddressType InetAddressType, + cacheClientAddress InetAddress, cacheClientHttpRequests Counter32, cacheClientHttpKb Counter32, cacheClientHttpHits Counter32, @@ -875,21 +938,46 @@ squid MODULE-IDENTITY cacheClientIcpHitKb Counter32 } - cacheClientAddr OBJECT-TYPE - SYNTAX IpAddress + cacheClientAddressType OBJECT-TYPE + SYNTAX InetAddressType MAX-ACCESS read-only STATUS current DESCRIPTION "The client's IP address " ::= { cacheClientEntry 1 } + cacheClientAddress OBJECT-TYPE + SYNTAX InetAddress (SIZE (1..64)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The Internet address for the client. The type of this + address is determined by the value of the peerAddressType + object. Note that implementations must limit themselves + to a single entry in this table per reachable peer. + The peerAddress may not be empty due to the SIZE + restriction. + + If a row is created administratively by an SNMP + operation and the address type value is dns(16), then + the agent stores the DNS name internally. A DNS name + lookup must be performed on the internally stored DNS + name whenever it is being used to contact the peer. + + If a row is created by the managed entity itself and + the address type value is dns(16), then the agent + stores the IP address internally. A DNS reverse lookup + must be performed on the internally stored IP address + whenever the value is retrieved via SNMP." + ::= { cacheClientEntry 2 } + cacheClientHttpRequests OBJECT-TYPE SYNTAX Counter32 MAX-ACCESS read-only STATUS current DESCRIPTION " Number of HTTP requests received from client " - ::= { cacheClientEntry 2 } + ::= { cacheClientEntry 3 } cacheClientHttpKb OBJECT-TYPE SYNTAX Counter32 @@ -897,7 +985,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Amount of total HTTP traffic to this client " - ::= { cacheClientEntry 3 } + ::= { cacheClientEntry 4 } cacheClientHttpHits OBJECT-TYPE SYNTAX Counter32 @@ -905,7 +993,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of hits in response to this client's HTTP requests " - ::= { cacheClientEntry 4 } + ::= { cacheClientEntry 5 } cacheClientHTTPHitKb OBJECT-TYPE SYNTAX Counter32 @@ -913,7 +1001,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Amount of HTTP hit traffic in KB " - ::= { cacheClientEntry 5 } + ::= { cacheClientEntry 6 } cacheClientIcpRequests OBJECT-TYPE SYNTAX Counter32 @@ -921,7 +1009,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of ICP requests received from client " - ::= { cacheClientEntry 6 } + ::= { cacheClientEntry 7 } cacheClientIcpKb OBJECT-TYPE SYNTAX Counter32 @@ -929,7 +1017,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Amount of total ICP traffic to this client (child) " - ::= { cacheClientEntry 7 } + ::= { cacheClientEntry 8 } cacheClientIcpHits OBJECT-TYPE SYNTAX Counter32 @@ -937,7 +1025,7 @@ squid MODULE-IDENTITY STATUS current DESCRIPTION " Number of hits in response to this client's ICP requests " - ::= { cacheClientEntry 8 } + ::= { cacheClientEntry 9 } cacheClientIcpHitKb OBJECT-TYPE SYNTAX Counter32 diff --git a/src/multicast.cc b/src/multicast.cc index b43d0c072b..effe4137bd 100644 --- a/src/multicast.cc +++ b/src/multicast.cc @@ -1,6 +1,6 @@ /* - * $Id: multicast.cc,v 1.12 2007/04/28 22:26:37 hno Exp $ + * $Id: multicast.cc,v 1.13 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 7 Multicast * AUTHOR: Martin Hamilton @@ -66,15 +66,23 @@ mcastJoinGroups(const ipcache_addrs * ia, void *datanotused) } for (i = 0; i < (int) ia->count; i++) { - debugs(7, 10, "Listening for ICP requests on " << inet_ntoa(*(ia->in_addrs + i))); - mr.imr_multiaddr.s_addr = (ia->in_addrs + i)->s_addr; + debugs(7, 10, "Listening for ICP requests on " << ia->in_addrs[i] ); + +#if USE_IPV6 + if( ! ia->in_addrs[i].IsIPv4() ) { + debugs(7, 10, "ERROR: IPv6 Multicast Listen has not been implemented!"); + continue; + } +#endif + + ia->in_addrs[i].GetInAddr(mr.imr_multiaddr); + mr.imr_interface.s_addr = INADDR_ANY; x = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *) &mr, sizeof(struct ip_mreq)); if (x < 0) - debugs(7, 1, "comm_join_mcast_groups: FD " << fd << ", [" << inet_ntoa(*(ia->in_addrs + i)) << "]"); + debugs(7, 1, "comm_join_mcast_groups: FD " << fd << ", IP=" << ia->in_addrs[i]); x = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &c, 1); diff --git a/src/neighbors.cc b/src/neighbors.cc index b4e919eef8..df2aee9044 100644 --- a/src/neighbors.cc +++ b/src/neighbors.cc @@ -1,6 +1,6 @@ /* - * $Id: neighbors.cc,v 1.350 2007/11/13 23:25:34 rousskov Exp $ + * $Id: neighbors.cc,v 1.351 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 15 Neighbor Routines * AUTHOR: Harvest Derived @@ -45,6 +45,7 @@ #include "PeerSelectState.h" #include "SquidTime.h" #include "Store.h" +#include "IPAddress.h" /* count mcast group peers every 15 minutes */ #define MCAST_COUNT_RATE 900 @@ -66,7 +67,7 @@ static void peerCountMcastPeersStart(void *data); static void peerCountMcastPeersSchedule(peer * p, time_t when); static IRCB peerCountHandleIcpReply; -static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode); +static void neighborIgnoreNonPeer(const IPAddress &, icp_opcode); static OBJH neighborDumpPeers; static OBJH neighborDumpNonPeers; static void dump_peers(StoreEntry * sentry, peer * peers); @@ -94,20 +95,17 @@ neighborTypeStr(const peer * p) peer * - -whichPeer(const struct sockaddr_in * from) +whichPeer(const IPAddress &from) { int j; - u_short port = ntohs(from->sin_port); - struct IN_ADDR ip = from->sin_addr; peer *p = NULL; - debugs(15, 3, "whichPeer: from " << inet_ntoa(ip) << " port " << port); + debugs(15, 3, "whichPeer: from " << from); for (p = Config.peers; p; p = p->next) { for (j = 0; j < p->n_addresses; j++) { - if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) { + if (from == p->addresses[j] && from.GetPort() == p->icp.port) { return p; } } @@ -123,7 +121,7 @@ neighborType(const peer * p, const HttpRequest * request) const struct _domain_type *d = NULL; for (d = p->typelist; d; d = d->next) { - if (0 == matchDomainName(request->host, d->domain)) + if (0 == matchDomainName(request->GetHost(), d->domain)) if (d->type != PEER_NONE) return d->type; } @@ -165,7 +163,7 @@ peerAllowedToUse(const peer * p, HttpRequest * request) do_ping = 0; for (d = p->peer_domain; d; d = d->next) { - if (0 == matchDomainName(request->host, d->domain)) { + if (0 == matchDomainName(request->GetHost(), d->domain)) { do_ping = d->do_ping; break; } @@ -185,8 +183,6 @@ peerAllowedToUse(const peer * p, HttpRequest * request) checklist.my_addr = request->my_addr; - checklist.my_port = request->my_port; - checklist.request = HTTPMSGLOCK(request); checklist.accessList = cbdataReference(p->access); @@ -490,33 +486,31 @@ neighborRemove(peer * target) void neighbors_init(void) { - - struct sockaddr_in name; - - socklen_t len = sizeof(struct sockaddr_in); - + IPAddress nul; + struct addrinfo *AI = NULL; struct servent *sep = NULL; const char *me = getMyHostname(); - peer *thisPeer; - peer *next; + peer *thisPeer = NULL; + peer *next = NULL; int fd = theInIcpConnection; - if (fd >= 0) { + /* setup addrinfo for use */ + nul.InitAddrInfo(AI); - memset(&name, '\0', sizeof(struct sockaddr_in)); + if (fd >= 0) { - if (getsockname(fd, (struct sockaddr *) &name, &len) < 0) - debugs(15, 1, "getsockname(" << fd << "," << &name << "," << &len << ") failed."); + if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen) < 0) + debugs(15, 1, "getsockname(" << fd << "," << AI->ai_addr << "," << &AI->ai_addrlen << ") failed."); for (thisPeer = Config.peers; thisPeer; thisPeer = next) { - http_port_list *s; + http_port_list *s = NULL; next = thisPeer->next; if (0 != strcmp(thisPeer->host, me)) continue; for (s = Config.Sockaddr.http; s; s = s->next) { - if (thisPeer->http_port != ntohs(s->s.sin_port)) + if (thisPeer->http_port != s->s.GetPort()) continue; debugs(15, 1, "WARNING: Peer looks like this host"); @@ -526,7 +520,6 @@ neighbors_init(void) "/" << thisPeer->http_port << "/" << thisPeer->icp.port); - neighborRemove(thisPeer); } } @@ -541,12 +534,14 @@ neighbors_init(void) echo_hdr.reqnum = 0; echo_hdr.flags = 0; echo_hdr.pad = 0; - echo_hdr.shostid = name.sin_addr.s_addr; + nul = *AI; + nul.GetInAddr( *((struct in_addr*)&echo_hdr.shostid) ); sep = getservbyname("echo", "udp"); echo_port = sep ? ntohs((u_short) sep->s_port) : 7; } first_ping = Config.peers; + nul.FreeAddrInfo(AI); } void @@ -640,7 +635,7 @@ neighborsUdpPing(HttpRequest * request, echo_hdr.reqnum = reqnum; query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, - &p->in_addr, + p->in_addr, query, LOG_ICP_QUERY, 0); @@ -654,7 +649,7 @@ neighborsUdpPing(HttpRequest * request, query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0); icpUdpSend(theOutIcpConnection, - &p->in_addr, + p->in_addr, query, LOG_ICP_QUERY, 0); @@ -701,39 +696,6 @@ neighborsUdpPing(HttpRequest * request, if ((first_ping = first_ping->next) == NULL) first_ping = Config.peers; -#if ALLOW_SOURCE_PING - /* only do source_ping if we have neighbors */ - if (Config.npeers) { - const ipcache_addrs *ia = NULL; - - struct sockaddr_in to_addr; - char *host = request->host; - - if (!Config.onoff.source_ping) { - debugs(15, 6, "neighborsUdpPing: Source Ping is disabled."); - } else if ((ia = ipcache_gethostbyname(host, 0))) { - debugs(15, 6, "neighborsUdpPing: Source Ping: to " << host << " for '" << url << "'"); - echo_hdr.reqnum = reqnum; - - if (icmp_sock != -1) { - icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url); - } else { - to_addr.sin_family = AF_INET; - to_addr.sin_addr = ia->in_addrs[ia->cur]; - to_addr.sin_port = htons(echo_port); - query = _icp_common_t::createMessage(ICP_SECHO, 0, url, reqnum, 0); - icpUdpSend(theOutIcpConnection, - &to_addr, - query, - LOG_ICP_QUERY, - 0); - } - } else { - debugs(15, 6, "neighborsUdpPing: Source Ping: unknown host: " << host); - } - } - -#endif /* * How many replies to expect? */ @@ -967,17 +929,16 @@ neighborCountIgnored(peer * p) static peer *non_peers = NULL; static void - -neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode) +neighborIgnoreNonPeer(const IPAddress &from, icp_opcode opcode) { peer *np; for (np = non_peers; np; np = np->next) { - if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr) + if (np->in_addr != from) continue; - if (np->in_addr.sin_port != from->sin_port) + if (np->in_addr.GetPort() != from.GetPort()) continue; break; @@ -986,11 +947,11 @@ neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode) if (np == NULL) { np = (peer *)xcalloc(1, sizeof(peer)); - np->in_addr.sin_addr = from->sin_addr; - np->in_addr.sin_port = from->sin_port; - np->icp.port = ntohl(from->sin_port); + np->in_addr = from; + np->icp.port = from.GetPort(); np->type = PEER_NONE; - np->host = xstrdup(inet_ntoa(from->sin_addr)); + np->host = new char[MAX_IPSTRLEN]; + from.NtoA(np->host,MAX_IPSTRLEN); np->next = non_peers; non_peers = np; } @@ -1030,7 +991,7 @@ ignoreMulticastReply(peer * p, MemObject * mem) */ void -neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr_in *from) +neighborsUdpAck(const cache_key * key, icp_common_t * header, const IPAddress &from) { peer *p = NULL; StoreEntry *entry; @@ -1132,14 +1093,8 @@ neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct socka if (p) { debugs(15, 1, "Ignoring SECHO from neighbor " << p->host); neighborCountIgnored(p); -#if ALLOW_SOURCE_PING - - } else if (Config.onoff.source_ping) { - mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data); -#endif - } else { - debugs(15, 1, "Unsolicited SECHO from " << inet_ntoa(from->sin_addr)); + debugs(15, 1, "Unsolicited SECHO from " << from); } } else if (opcode == ICP_DENIED) { @@ -1199,24 +1154,33 @@ int neighborUp(const peer * p) { if (!p->tcp_up) { - if (!peerProbeConnect((peer *) p)) + if (!peerProbeConnect((peer *) p)) { + debugs(15, 8, "neighborUp: DOWN (probed): " << p->host << " (" << p->in_addr << ")"); return 0; + } } /* * The peer can not be UP if we don't have any IP addresses * for it. */ - if (0 == p->n_addresses) + if (0 == p->n_addresses) { + debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")"); return 0; + } - if (p->options.no_query) + if (p->options.no_query) { + debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")"); return 1; + } if (p->stats.probe_start != 0 && - squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer) + squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer) { + debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")"); return 0; + } + debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")"); return 1; } @@ -1260,7 +1224,6 @@ peerDNSConfigure(const ipcache_addrs * ia, void *data) { peer *p = (peer *)data; - struct sockaddr_in *ap; int j; if (p->n_addresses == 0) { @@ -1286,16 +1249,13 @@ peerDNSConfigure(const ipcache_addrs * ia, void *data) for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) { p->addresses[j] = ia->in_addrs[j]; - debugs(15, 2, "--> IP address #" << j << ": " << inet_ntoa(p->addresses[j])); + debugs(15, 2, "--> IP address #" << j << ": " << p->addresses[j]); p->n_addresses++; } - ap = &p->in_addr; - - memset(ap, '\0', sizeof(struct sockaddr_in)); - ap->sin_family = AF_INET; - ap->sin_addr = p->addresses[0]; - ap->sin_port = htons(p->icp.port); + p->in_addr.SetEmpty(); + p->in_addr = p->addresses[0]; + p->in_addr.SetPort(p->icp.port); if (p->type == PEER_MULTICAST) peerCountMcastPeersSchedule(p, 10); @@ -1392,8 +1352,9 @@ peerProbeConnect(peer * p) if (squid_curtime - p->stats.last_connect_probe == 0) return ret;/* don't probe to often */ - fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL), - 0, COMM_NONBLOCKING, p->host); + IPAddress temp(getOutgoingAddr(NULL)); + + fd = comm_open(SOCK_STREAM, IPPROTO_TCP, temp, COMM_NONBLOCKING, p->host); if (fd < 0) return ret; @@ -1455,7 +1416,9 @@ peerCountMcastPeersStart(void *data) LOCAL_ARRAY(char, url, MAX_URL); assert(p->type == PEER_MULTICAST); p->mcast.flags.count_event_pending = 0; - snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr)); + snprintf(url, MAX_URL, "http://"); + p->in_addr.ToURL(url+7, MAX_URL -8 ); + strcat(url, "/"); fake = storeCreateEntry(url, url, request_flags(), METHOD_GET); HttpRequest *req = HttpRequest::CreateFromUrl(url); psstate = new ps_state; @@ -1474,7 +1437,7 @@ peerCountMcastPeersStart(void *data) reqnum = icpSetCacheKey((const cache_key *)fake->key); query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, - &p->in_addr, + p->in_addr, query, LOG_ICP_QUERY, 0); @@ -1634,7 +1597,7 @@ static void dump_peers(StoreEntry * sentry, peer * peers) { peer *e = NULL; - + char ntoabuf[MAX_IPSTRLEN]; struct _domain_ping *d = NULL; icp_opcode op; int i; @@ -1656,7 +1619,7 @@ dump_peers(StoreEntry * sentry, peer * peers) for (i = 0; i < e->n_addresses; i++) { storeAppendPrintf(sentry, "Address[%d] : %s\n", i, - inet_ntoa(e->addresses[i])); + e->addresses[i].NtoA(ntoabuf,MAX_IPSTRLEN) ); } storeAppendPrintf(sentry, "Status : %s\n", @@ -1742,7 +1705,7 @@ dump_peers(StoreEntry * sentry, peer * peers) #if USE_HTCP void -neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr_in *from) +neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const IPAddress &from) { StoreEntry *e = Store::Root().get(key); MemObject *mem = NULL; diff --git a/src/net_db.cc b/src/net_db.cc index 96ceead08a..e6051bdf32 100644 --- a/src/net_db.cc +++ b/src/net_db.cc @@ -1,6 +1,5 @@ - /* - * $Id: net_db.cc,v 1.198 2007/11/27 07:48:40 amosjeffries Exp $ + * $Id: net_db.cc,v 1.199 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 38 Network Measurement Database * AUTHOR: Duane Wessels @@ -54,8 +53,10 @@ #include "forward.h" #include "SquidTime.h" #include "wordlist.h" +#include "IPAddress.h" #if USE_ICMP +#include "ICMPSquid.h" #include "StoreClient.h" #define NETDB_REQBUF_SZ 4096 @@ -84,10 +85,10 @@ netdbExchangeState; static hash_table *addr_table = NULL; static hash_table *host_table = NULL; -static struct IN_ADDR networkFromInaddr(struct IN_ADDR a); +IPAddress networkFromInaddr(const IPAddress &a); static void netdbRelease(netdbEntry * n); -static void netdbHashInsert(netdbEntry * n, struct IN_ADDR addr); +static void netdbHashInsert(netdbEntry * n, IPAddress &addr); static void netdbHashDelete(const char *key); static void netdbHostInsert(netdbEntry * n, const char *hostname); static void netdbHostDelete(const net_db_name * x); @@ -112,10 +113,9 @@ static void netdbExchangeDone(void *); static wordlist *peer_names = NULL; static void - -netdbHashInsert(netdbEntry * n, struct IN_ADDR addr) +netdbHashInsert(netdbEntry * n, IPAddress &addr) { - xstrncpy(n->network, inet_ntoa(networkFromInaddr(addr)), 16); + networkFromInaddr(addr).NtoA(n->network, MAX_IPSTRLEN); n->hash.key = n->network; assert(hash_lookup(addr_table, n->network) == NULL); hash_join(addr_table, &n->hash); @@ -249,18 +249,17 @@ netdbPurgeLRU(void) } static netdbEntry * - -netdbLookupAddr(struct IN_ADDR addr) +netdbLookupAddr(const IPAddress &addr) { netdbEntry *n; - char *key = inet_ntoa(networkFromInaddr(addr)); + char *key = new char[MAX_IPSTRLEN]; + networkFromInaddr(addr).NtoA(key,MAX_IPSTRLEN); n = (netdbEntry *) hash_lookup(addr_table, key); return n; } static netdbEntry * - -netdbAdd(struct IN_ADDR addr) +netdbAdd(IPAddress &addr) { netdbEntry *n; @@ -279,8 +278,7 @@ netdbAdd(struct IN_ADDR addr) static void netdbSendPing(const ipcache_addrs * ia, void *data) { - - struct IN_ADDR addr; + IPAddress addr; char *hostname = NULL; static_cast(data)->unwrap(&hostname); netdbEntry *n; @@ -336,7 +334,7 @@ netdbSendPing(const ipcache_addrs * ia, void *data) if (n->next_ping_time <= squid_curtime) { debugs(38, 3, "netdbSendPing: pinging " << hostname); - icmpDomainPing(addr, hostname); + icmpEngine.DomainPing(addr, hostname); n->pings_sent++; n->next_ping_time = squid_curtime + Config.Netdb.period; n->last_use_time = squid_curtime; @@ -345,14 +343,28 @@ netdbSendPing(const ipcache_addrs * ia, void *data) xfree(hostname); } -static struct IN_ADDR - - networkFromInaddr(struct IN_ADDR a) +IPAddress +networkFromInaddr(const IPAddress &in) { + IPAddress out; + + out = in; +#if USE_IPV6 + + /* in IPv6 the 'network' should be the routing section. */ + + if( in.IsIPv6() ) + { + out.ApplyMask(64, AF_INET6); + debugs(14, 5, "networkFromInaddr : Masked IPv6 Address to " << in << "/64 routing part."); + return out; + } +#endif - struct IN_ADDR b; - b.s_addr = ntohl(a.s_addr); #if USE_CLASSFUL + struct in_addr b; + + in.GetInAddr(b); if (IN_CLASSC(b.s_addr)) b.s_addr &= IN_CLASSC_NET; @@ -361,15 +373,17 @@ static struct IN_ADDR else if (IN_CLASSA(b.s_addr)) b.s_addr &= IN_CLASSA_NET; -#else - /* use /24 for everything */ - b.s_addr &= IN_CLASSC_NET; + out = b; #endif - b.s_addr = htonl(b.s_addr); + debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << out << "/24."); - return b; + /* use /24 for everything under IPv4 */ + out.ApplyMask(24, AF_INET); + debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << in << "/24."); + + return out; } static int @@ -534,7 +548,7 @@ netdbReloadState(void) netdbEntry *n; netdbEntry N; - struct IN_ADDR addr; + IPAddress addr; int count = 0; struct timeval start = current_time; @@ -576,7 +590,7 @@ netdbReloadState(void) if (NULL == q) continue; - if (!safe_inet_addr(q, &addr)) + if (! (addr = q) ) continue; if (netdbLookupAddr(addr) != NULL) /* no dups! */ @@ -676,11 +690,13 @@ netdbFreeNameEntry(void *data) static void netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData) { + IPAddress addr; + netdbExchangeState *ex = (netdbExchangeState *)data; int rec_sz = 0; off_t o; - struct IN_ADDR addr; + struct in_addr line_addr; double rtt; double hops; char *p; @@ -692,7 +708,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData) int oldbufofs = ex->buf_ofs; rec_sz = 0; - rec_sz += 1 + sizeof(addr.s_addr); + rec_sz += 1 + sizeof(struct in_addr); rec_sz += 1 + sizeof(int); rec_sz += 1 + sizeof(int); debugs(38, 3, "netdbExchangeHandleReply: " << receivedData.length << " read bytes"); @@ -769,7 +785,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData) while (size >= rec_sz) { debugs(38, 5, "netdbExchangeHandleReply: in parsing loop, size = " << size); - addr.s_addr = any_addr.s_addr; + addr.SetAnyAddr(); hops = rtt = 0.0; for (o = 0; o < rec_sz;) { @@ -777,8 +793,10 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData) case NETDB_EX_NETWORK: o++; - xmemcpy(&addr.s_addr, p + o, sizeof(addr.s_addr)); - o += sizeof(addr.s_addr); + /* FIXME INET6 : NetDB can still ony send IPv4 */ + xmemcpy(&line_addr, p + o, sizeof(struct in_addr)); + addr = line_addr; + o += sizeof(struct in_addr); break; case NETDB_EX_RTT: @@ -802,7 +820,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData) } } - if (addr.s_addr != any_addr.s_addr && rtt > 0) + if (!addr.IsAnyAddr() && rtt > 0) netdbExchangeUpdatePeer(addr, ex->p, rtt, hops); assert(o == rec_sz); @@ -933,15 +951,14 @@ netdbPingSite(const char *hostname) } void - -netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt) +netdbHandlePingReply(const IPAddress &from, int hops, int rtt) { #if USE_ICMP netdbEntry *n; int N; - debugs(38, 3, "netdbHandlePingReply: from " << inet_ntoa(from->sin_addr)); + debugs(38, 3, "netdbHandlePingReply: from " << from); - if ((n = netdbLookupAddr(from->sin_addr)) == NULL) + if ((n = netdbLookupAddr(from)) == NULL) return; N = ++n->pings_recv; @@ -978,9 +995,10 @@ netdbFreeMemory(void) #endif } -int -netdbHops(struct IN_ADDR addr) +#if 0 // AYJ: Looks to be unused code. +int +netdbHops(IPAddress &addr) { #if USE_ICMP netdbEntry *n = netdbLookupAddr(addr); @@ -994,6 +1012,7 @@ netdbHops(struct IN_ADDR addr) #endif return 256; } +#endif void netdbDump(StoreEntry * sentry) @@ -1007,7 +1026,7 @@ netdbDump(StoreEntry * sentry) int j; net_db_peer *p; storeAppendPrintf(sentry, "Network DB Statistics:\n"); - storeAppendPrintf(sentry, "%-16.16s %9s %7s %5s %s\n", + storeAppendPrintf(sentry, "%-46.46s %9s %7s %5s %s\n", /* Max between 16 (IPv4) or 46 (IPv6) */ "Network", "recv/sent", "RTT", @@ -1031,7 +1050,7 @@ netdbDump(StoreEntry * sentry) for (k = 0; k < i; k++) { n = *(list + k); - storeAppendPrintf(sentry, "%-16.16s %4d/%4d %7.1f %5.1f", + storeAppendPrintf(sentry, "%-46.46s %4d/%4d %7.1f %5.1f", /* Max between 16 (IPv4) or 46 (IPv6) */ n->network, n->pings_recv, n->pings_sent, @@ -1119,11 +1138,11 @@ netdbUpdatePeer(HttpRequest * r, peer * e, int irtt, int ihops) double rtt = (double) irtt; double hops = (double) ihops; net_db_peer *p; - debugs(38, 3, "netdbUpdatePeer: '" << r->host << "', " << ihops << " hops, " << irtt << " rtt"); - n = netdbLookupHost(r->host); + debugs(38, 3, "netdbUpdatePeer: '" << r->GetHost() << "', " << ihops << " hops, " << irtt << " rtt"); + n = netdbLookupHost(r->GetHost()); if (n == NULL) { - debugs(38, 3, "netdbUpdatePeer: host '" << r->host << "' not found"); + debugs(38, 3, "netdbUpdatePeer: host '" << r->GetHost() << "' not found"); return; } @@ -1148,16 +1167,20 @@ netdbUpdatePeer(HttpRequest * r, peer * e, int irtt, int ihops) } void - -netdbExchangeUpdatePeer(struct IN_ADDR addr, peer * e, double rtt, double hops) +netdbExchangeUpdatePeer(IPAddress &addr, peer * e, double rtt, double hops) { #if USE_ICMP netdbEntry *n; net_db_peer *p; - debugs(38, 5, "netdbExchangeUpdatePeer: '" << inet_ntoa(addr) << "', "<< + debugs(38, 5, "netdbExchangeUpdatePeer: '" << addr << "', "<< std::setfill('0')<< std::setprecision(2) << hops << " hops, " << rtt << " rtt"); + if( !addr.IsIPv4() ) { + debugs(38, 5, "netdbExchangeUpdatePeer: Aborting peer update for '" << addr << "', NetDB cannot handle IPv6."); + return; + } + n = netdbLookupAddr(addr); if (n == NULL) @@ -1187,7 +1210,7 @@ netdbExchangeUpdatePeer(struct IN_ADDR addr, peer * e, double rtt, double hops) void -netdbDeleteAddrNetwork(struct IN_ADDR addr) +netdbDeleteAddrNetwork(IPAddress &addr) { #if USE_ICMP netdbEntry *n = netdbLookupAddr(addr); @@ -1208,19 +1231,21 @@ netdbBinaryExchange(StoreEntry * s) HttpReply *reply = new HttpReply; #if USE_ICMP + IPAddress addr; + netdbEntry *n; int i; int j; int rec_sz; char *buf; - struct IN_ADDR addr; + struct in_addr line_addr; s->buffer(); HttpVersion version(1, 0); reply->setHeaders(version, HTTP_OK, "OK", NULL, -1, squid_curtime, -2); s->replaceHttpReply(reply); rec_sz = 0; - rec_sz += 1 + sizeof(addr.s_addr); + rec_sz += 1 + sizeof(struct in_addr); rec_sz += 1 + sizeof(int); rec_sz += 1 + sizeof(int); buf = (char *)memAllocate(MEM_4K_BUF); @@ -1234,14 +1259,19 @@ netdbBinaryExchange(StoreEntry * s) if (n->rtt > 60000) /* RTT > 1 MIN probably bogus */ continue; - if (!safe_inet_addr(n->network, &addr)) + if (! (addr = n->network) ) + continue; + + /* FIXME INET6 : NetDB cannot yet handle IPv6 addresses. Ensure only IPv4 get sent. */ + if( !addr.IsIPv4() ) continue; buf[i++] = (char) NETDB_EX_NETWORK; - xmemcpy(&buf[i], &addr.s_addr, sizeof(addr.s_addr)); + addr.GetInAddr(line_addr); + xmemcpy(&buf[i], &line_addr, sizeof(struct in_addr)); - i += sizeof(addr.s_addr); + i += sizeof(struct in_addr); buf[i++] = (char) NETDB_EX_RTT; @@ -1342,11 +1372,11 @@ netdbClosestParent(HttpRequest * request) const ipcache_addrs *ia; net_db_peer *h; int i; - n = netdbLookupHost(request->host); + n = netdbLookupHost(request->GetHost()); if (NULL == n) { /* try IP addr */ - ia = ipcache_gethostbyname(request->host, 0); + ia = ipcache_gethostbyname(request->GetHost(), 0); if (NULL != ia) n = netdbLookupAddr(ia->in_addrs[ia->cur]); diff --git a/src/pconn.cc b/src/pconn.cc index d6d3f5f25f..2207115667 100644 --- a/src/pconn.cc +++ b/src/pconn.cc @@ -1,6 +1,6 @@ /* - * $Id: pconn.cc,v 1.53 2007/05/29 13:31:40 amosjeffries Exp $ + * $Id: pconn.cc,v 1.54 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 48 Persistent Connections * AUTHOR: Duane Wessels @@ -175,17 +175,17 @@ IdleConnList::timeout(int fd, void *data) /* ========== PconnPool PRIVATE FUNCTIONS ============================================ */ const char * - -PconnPool::key(const char *host, u_short port, const char *domain, struct IN_ADDR *client_address) +PconnPool::key(const char *host, u_short port, const char *domain, IPAddress &client_address) { LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN * 2 + 10); + char ntoabuf[MAX_IPSTRLEN]; - if (domain && client_address) - snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d-%s/%s", host, (int) port, inet_ntoa(*client_address), domain); - else if (domain && (!client_address)) + if (domain && !client_address.IsAnyAddr()) + snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d-%s/%s", host, (int) port, client_address.NtoA(ntoabuf,MAX_IPSTRLEN), domain); + else if (domain && client_address.IsAnyAddr()) snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d/%s", host, (int) port, domain); - else if ((!domain) && client_address) - snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d-%s", host, (int) port, inet_ntoa(*client_address)); + else if ((!domain) && !client_address.IsAnyAddr()) + snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d-%s", host, (int) port, client_address.NtoA(ntoabuf,MAX_IPSTRLEN)); else snprintf(buf, SQUIDHOSTNAMELEN * 2 + 10, "%s:%d", host, (int) port); @@ -227,8 +227,7 @@ PconnPool::PconnPool(const char *aDescr) : table(NULL), descr(aDescr) } void - -PconnPool::push(int fd, const char *host, u_short port, const char *domain, struct IN_ADDR *client_address) +PconnPool::push(int fd, const char *host, u_short port, const char *domain, IPAddress &client_address) { IdleConnList *list; @@ -275,7 +274,7 @@ PconnPool::push(int fd, const char *host, u_short port, const char *domain, stru */ int -PconnPool::pop(const char *host, u_short port, const char *domain, struct IN_ADDR *client_address, bool isRetriable) +PconnPool::pop(const char *host, u_short port, const char *domain, IPAddress &client_address, bool isRetriable) { IdleConnList *list; const char * aKey = key(host, port, domain, client_address); diff --git a/src/pconn.h b/src/pconn.h index a2d4df6ec5..6629c72249 100644 --- a/src/pconn.h +++ b/src/pconn.h @@ -48,15 +48,15 @@ public: PconnPool(const char *); void moduleInit(); - void push(int fd, const char *host, u_short port, const char *domain, struct IN_ADDR *client_address); - int pop(const char *host, u_short port, const char *domain, struct IN_ADDR *client_address, bool retriable); + void push(int fd, const char *host, u_short port, const char *domain, IPAddress &client_address); + int pop(const char *host, u_short port, const char *domain, IPAddress &client_address, bool retriable); void count(int uses); void dumpHist(StoreEntry *e); void unlinkList(IdleConnList *list) const; private: - static const char *key(const char *host, u_short port, const char *domain, struct IN_ADDR *client_address); + static const char *key(const char *host, u_short port, const char *domain, IPAddress &client_address); int hist[PCONN_HIST_SZ]; hash_table *table; diff --git a/src/peer_digest.cc b/src/peer_digest.cc index 602a0162f1..ecebc907b3 100644 --- a/src/peer_digest.cc +++ b/src/peer_digest.cc @@ -1,6 +1,6 @@ /* - * $Id: peer_digest.cc,v 1.127 2007/08/27 12:50:43 hno Exp $ + * $Id: peer_digest.cc,v 1.128 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 72 Peer Digest Routines * AUTHOR: Alex Rousskov @@ -257,6 +257,7 @@ peerDigestCheck(void *data) { PeerDigest *pd = (PeerDigest *)data; time_t req_time; + char buf[MAX_IPSTRLEN]; assert(!pd->flags.requested); @@ -267,7 +268,7 @@ peerDigestCheck(void *data) return; } - debugs(72, 3, "peerDigestCheck: peer " << pd->peer->host << ":" << pd->peer->http_port); + debugs(72, 3, "peerDigestCheck: peer " << pd->peer->host << ":" << pd->peer->http_port); debugs(72, 3, "peerDigestCheck: time: " << squid_curtime << ", last received: " << (long int) pd->times.received << " (" << std::showpos << (int) (squid_curtime - pd->times.received) << ")"); diff --git a/src/peer_select.cc b/src/peer_select.cc index 6ffd0e2173..76a65aca57 100644 --- a/src/peer_select.cc +++ b/src/peer_select.cc @@ -1,6 +1,5 @@ - /* - * $Id: peer_select.cc,v 1.147 2007/04/30 16:56:09 wessels Exp $ + * $Id: peer_select.cc,v 1.148 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 44 Peer Selection Algorithm * AUTHOR: Duane Wessels @@ -42,6 +41,7 @@ #include "ACLChecklist.h" #include "htcp.h" #include "forward.h" +#include "SquidTime.h" const char *hier_strings[] = { @@ -180,9 +180,7 @@ peerSelect(HttpRequest * request, #endif if (psstate->entry) - psstate->entry->lock() - - ; + psstate->entry->lock(); peerSelectFoo(psstate); } @@ -254,7 +252,7 @@ peerCheckNetdbDirect(ps_state * psstate) if (psstate->direct == DIRECT_NO) return 0; - myrtt = netdbHostRtt(psstate->request->host); + myrtt = netdbHostRtt(psstate->request->GetHost()); debugs(44, 3, "peerCheckNetdbDirect: MY RTT = " << myrtt << " msec"); debugs(44, 3, "peerCheckNetdbDirect: minimum_direct_rtt = " << Config.minDirectRtt << " msec"); @@ -263,7 +261,7 @@ peerCheckNetdbDirect(ps_state * psstate) if (myrtt && myrtt <= Config.minDirectRtt) return 1; - myhops = netdbHostHops(psstate->request->host); + myhops = netdbHostHops(psstate->request->GetHost()); debugs(44, 3, "peerCheckNetdbDirect: MY hops = " << myhops); debugs(44, 3, "peerCheckNetdbDirect: minimum_direct_hops = " << Config.minDirectHops); @@ -272,7 +270,7 @@ peerCheckNetdbDirect(ps_state * psstate) if (myhops && myhops <= Config.minDirectHops) return 1; - p = whichPeer(&psstate->closest_parent_miss); + p = whichPeer(psstate->closest_parent_miss); if (p == NULL) return 0; @@ -290,7 +288,7 @@ peerSelectFoo(ps_state * ps) { StoreEntry *entry = ps->entry; HttpRequest *request = ps->request; - debugs(44, 3, "peerSelectFoo: '" << RequestMethodStr[request->method] << " " << request->host << "'"); + debugs(44, 3, "peerSelectFoo: '" << RequestMethodStr[request->method] << " " << request->GetHost() << "'"); if (ps->direct == DIRECT_UNKNOWN) { if (ps->always_direct == 0 && Config.accessList.AlwaysDirect) { @@ -453,7 +451,7 @@ peerGetSomeNeighborReplies(ps_state * ps) if (peerCheckNetdbDirect(ps)) { code = CLOSEST_DIRECT; - debugs(44, 3, "peerSelect: " << hier_strings[code] << "/" << request->host); + debugs(44, 3, "peerSelect: " << hier_strings[code] << "/" << request->GetHost()); peerAddFwdServer(&ps->servers, NULL, code); return; } @@ -461,19 +459,15 @@ peerGetSomeNeighborReplies(ps_state * ps) 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; - } 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 (!ps->closest_parent_miss.IsAnyAddr()) { + p = whichPeer(ps->closest_parent_miss); + code = CLOSEST_PARENT_MISS; + } else if (!ps->first_parent_miss.IsAnyAddr()) { + p = whichPeer(ps->first_parent_miss); + code = FIRST_PARENT_MISS; + } + } if (p && code != HIER_NONE) { debugs(44, 3, "peerSelect: " << hier_strings[code] << "/" << p->host); peerAddFwdServer(&ps->servers, p, code); @@ -506,7 +500,7 @@ peerGetSomeParent(ps_state * ps) peer *p; HttpRequest *request = ps->request; hier_code code = HIER_NONE; - debugs(44, 3, "peerGetSomeParent: " << RequestMethodStr[request->method] << " " << request->host); + debugs(44, 3, "peerGetSomeParent: " << RequestMethodStr[request->method] << " " << request->GetHost()); if (ps->direct == DIRECT_YES) return; @@ -625,7 +619,7 @@ peerIcpParentMiss(peer * p, icp_common_t * header, ps_state * ps) return; /* set FIRST_MISS if there is no CLOSEST parent */ - if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) + if (!ps->closest_parent_miss.IsAnyAddr()) return; rtt = (tvSubMsec(ps->ping.start, current_time) - p->basetime) / p->weight; @@ -633,8 +627,7 @@ peerIcpParentMiss(peer * p, icp_common_t * header, ps_state * ps) if (rtt < 1) rtt = 1; - if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr || - rtt < ps->ping.w_rtt) { + if (ps->first_parent_miss.IsAnyAddr() || rtt < ps->ping.w_rtt) { ps->first_parent_miss = p->in_addr; ps->ping.w_rtt = rtt; } @@ -667,14 +660,6 @@ peerHandleIcpReply(peer * p, peer_t type, icp_common_t * header, void *data) 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; @@ -731,7 +716,7 @@ peerHtcpParentMiss(peer * p, htcpReplyData * htcp, ps_state * ps) return; /* set FIRST_MISS if there is no CLOSEST parent */ - if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr) + if (!ps->closest_parent_miss.IsAnyAddr()) return; rtt = (tvSubMsec(ps->ping.start, current_time) - p->basetime) / p->weight; @@ -739,8 +724,7 @@ peerHtcpParentMiss(peer * p, htcpReplyData * htcp, ps_state * ps) if (rtt < 1) rtt = 1; - if (ps->first_parent_miss.sin_addr.s_addr == any_addr.s_addr || - rtt < ps->ping.w_rtt) { + if (ps->first_parent_miss.IsAnyAddr() || rtt < ps->ping.w_rtt) { ps->first_parent_miss = p->in_addr; ps->ping.w_rtt = rtt; } @@ -796,16 +780,13 @@ ps_state::ps_state() : request (NULL), callback (NULL), callback_data (NULL), servers (NULL), + first_parent_miss(), + closest_parent_miss(), hit(NULL), hit_type(PEER_NONE), -#if ALLOW_SOURCE_PING - - secho( NULL), -#endif acl_checklist (NULL) { - memset(&first_parent_miss, '\0', sizeof(first_parent_miss)); - memset(&closest_parent_miss, '\0', sizeof(closest_parent_miss)); + ; // no local defaults. } ping_data::ping_data() : diff --git a/src/pinger.cc b/src/pinger.cc index f906f3fd83..bd8feba706 100644 --- a/src/pinger.cc +++ b/src/pinger.cc @@ -1,6 +1,5 @@ - /* - * $Id: pinger.cc,v 1.59 2007/04/30 16:56:09 wessels Exp $ + * $Id: pinger.cc,v 1.60 2007/12/14 23:11:47 amosjeffries Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels @@ -40,618 +39,160 @@ #if USE_ICMP -/* Native Windows port doesn't have netinet support, so we emulate it. - At this time, Cygwin lacks icmp support in its include files, so we need - to use the native Windows port definitions. - */ - -#ifndef _SQUID_WIN32_ - -#include -#include -#include -#include - -#define PINGER_TIMEOUT 10 - -static int socket_from_squid = 0; -static int socket_to_squid = 1; - -#else /* _SQUID_WIN32_ */ - -#include "fde.h" +#include "ICMPv4.h" +#include "ICMPv6.h" +#include "ICMPPinger.h" #ifdef _SQUID_MSWIN_ #include #include +#include "fde.h" #define PINGER_TIMEOUT 5 -static int socket_to_squid = -1; -#define socket_from_squid socket_to_squid - -#else /* _SQUID_CYGWIN_ */ -#include -#include -#include -#include - -#define PINGER_TIMEOUT 10 - -static int socket_from_squid = 0; -static int socket_to_squid = 1; - -#endif +/* windows uses the control socket for feedback to squid */ +#define LINK_TO_SQUID squid_link -#define ICMP_ECHO 8 -#define ICMP_ECHOREPLY 0 +// windows still requires WSAFD but there are too many dependancy problems +// to just link to win32.cc where it is normally defined. -typedef struct iphdr +int +Win32__WSAFDIsSet(int fd, fd_set FAR * set) { + fde *F = &fd_table[fd]; + SOCKET s = F->win32.handle; -u_int8_t ip_vhl: - 4; /* Length of the header in dwords */ - -u_int8_t version: - 4; /* Version of IP */ - u_int8_t tos; /* Type of service */ - u_int16_t total_len; /* Length of the packet in dwords */ - u_int16_t ident; /* unique identifier */ - u_int16_t flags; /* Flags */ - u_int8_t ip_ttl; /* Time to live */ - u_int8_t proto; /* Protocol number (TCP, UDP etc) */ - u_int16_t checksum; /* IP checksum */ - u_int32_t source_ip; - u_int32_t dest_ip; + return __WSAFDIsSet(s, set); } -iphdr; - -/* ICMP header */ +#else -typedef struct icmphdr -{ - u_int8_t icmp_type; /* ICMP packet type */ - u_int8_t icmp_code; /* Type sub code */ - u_int16_t icmp_cksum; - u_int16_t icmp_id; - u_int16_t icmp_seq; - u_int32_t timestamp; /* not part of ICMP, but we need it */ -} +#define PINGER_TIMEOUT 10 -icmphdr; +/* non-windows use STDOUT for feedback to squid */ +#define LINK_TO_SQUID 1 #endif /* _SQUID_MSWIN_ */ -#ifndef _SQUID_LINUX_ -#ifndef _SQUID_CYGWIN_ -#ifndef _SQUID_MSWIN_ -#define icmphdr icmp -#define iphdr ip -#endif -#endif -#endif - -#if defined (_SQUID_LINUX_) -#ifdef icmp_id -#undef icmp_id -#endif -#ifdef icmp_seq -#undef icmp_seq +// ICMP Engines are declared global here so they can call each other easily. +ICMPPinger control; +ICMPv4 icmp4; +#if USE_IPV6 +ICMPv6 icmp6; #endif -#define icmp_type type -#define icmp_code code -#define icmp_cksum checksum -#define icmp_id un.echo.id -#define icmp_seq un.echo.sequence -#define ip_hl ihl -#define ip_v version -#define ip_tos tos -#define ip_len tot_len -#define ip_id id -#define ip_off frag_off -#define ip_ttl ttl -#define ip_p protocol -#define ip_sum check -#define ip_src saddr -#define ip_dst daddr -#endif - -#if ALLOW_SOURCE_PING -#define MAX_PKT_SZ 8192 -#define MAX_PAYLOAD (MAX_PKT_SZ - sizeof(struct icmphdr) - sizeof (char) - sizeof(struct timeval) - 1) -#else -#define MAX_PAYLOAD SQUIDHOSTNAMELEN -#define MAX_PKT_SZ (MAX_PAYLOAD + sizeof(struct timeval) + sizeof (char) + sizeof(struct icmphdr) + 1) -#endif - -typedef struct -{ - - struct timeval tv; - unsigned char opcode; - char payload[MAX_PAYLOAD]; -} -icmpEchoData; - -int icmp_ident = -1; int icmp_pkts_sent = 0; -static const char *icmpPktStr[] = - { - "Echo Reply", - "ICMP 1", - "ICMP 2", - "Destination Unreachable", - "Source Quench", - "Redirect", - "ICMP 6", - "ICMP 7", - "Echo", - "ICMP 9", - "ICMP 10", - "Time Exceeded", - "Parameter Problem", - "Timestamp", - "Timestamp Reply", - "Info Request", - "Info Reply", - "Out of Range Type" - }; - -static int in_cksum(unsigned short *ptr, int size); -static void pingerRecv(void); - -static void pingerLog(struct icmphdr *, struct IN_ADDR, int, int); -static int ipHops(int ttl); -static void pingerSendtoSquid(pingerReplyData * preply); -static void pingerOpen(void); -static void pingerClose(void); - -#ifdef _SQUID_MSWIN_ - -int Win32__WSAFDIsSet(int fd, fd_set FAR * set - ) -{ - fde *F = &fd_table[fd]; - SOCKET s = F->win32.handle; - - return __WSAFDIsSet(s, set - ); -} - -#endif - -void -pingerOpen(void) +int +main(int argc, char *argv[]) { - - struct protoent *proto = NULL; -#ifdef _SQUID_MSWIN_ - - WSADATA wsaData; - WSAPROTOCOL_INFO wpi; - char buf[sizeof(wpi)]; + fd_set R; int x; + int max_fd = 0; - struct sockaddr_in PS; - - WSAStartup(2, &wsaData); - - getCurrentTime(); - _db_init(NULL, "ALL,1"); - setmode(0, O_BINARY); - setmode(1, O_BINARY); - x = read(0, buf, sizeof(wpi)); - - if (x < (int)sizeof(wpi)) { - getCurrentTime(); - debugs(42, 0, "pingerOpen: read: FD 0: " << xstrerror()); - write(1, "ERR\n", 4); - exit(1); - } - - xmemcpy(&wpi, buf, sizeof(wpi)); - - write(1, "OK\n", 3); - x = read(0, buf, sizeof(PS)); - - if (x < (int)sizeof(PS)) { - getCurrentTime(); - debugs(42, 0, "pingerOpen: read: FD 0: " << xstrerror()); - write(1, "ERR\n", 4); - exit(1); - } + struct timeval tv; + const char *debug_args = "ALL,10"; + char *t; + time_t last_check_time = 0; - xmemcpy(&PS, buf, sizeof(PS)); + /* + * cevans - do this first. It grabs a raw socket. After this we can + * drop privs + */ + int icmp4_worker = -1; +#if USE_IPV6 + int icmp6_worker = -1; #endif + int squid_link = -1; - if ((proto = getprotobyname("icmp")) == 0) { - debugs(42, 0, "pingerOpen: unknown protocol: icmp"); - exit(1); - } - - icmp_sock = socket(PF_INET, SOCK_RAW, proto->p_proto); - - if (icmp_sock < 0) { - debugs(50, 0, "pingerOpen: icmp_sock: " << xstrerror()); - exit(1); - } - - icmp_ident = getpid() & 0xffff; - debugs(42, 0, "pinger: ICMP socket opened"); -#ifdef _SQUID_MSWIN_ - - socket_to_squid = - WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, - &wpi, 0, 0); - - if (socket_to_squid == -1) { - getCurrentTime(); - debugs(42, 0, "pingerOpen: WSASocket: " << xstrerror()); - write(1, "ERR\n", 4); - exit(1); - } - - x = connect(socket_to_squid, (struct sockaddr *) &PS, sizeof(PS)); - - if (SOCKET_ERROR == x) { - getCurrentTime(); - debugs(42, 0, "pingerOpen: connect: " << xstrerror()); - write(1, "ERR\n", 4); - exit(1); - } - - write(1, "OK\n", 3); - memset(buf, 0, sizeof(buf)); - x = recv(socket_to_squid, (void *) buf, sizeof(buf), 0); - - if (x < 3) { - debugs(42, 0, "icmpOpen: recv: " << xstrerror()); - exit(1); - } - - x = send(socket_to_squid, (const void *) buf, strlen(buf), 0); - - if (x < 3 || strncmp("OK\n", buf, 3)) { - debugs(42, 0, "icmpOpen: recv: " << xstrerror()); - exit(1); - } + /* start by initializing the pinger debug cache.log-pinger */ + if ((t = getenv("SQUID_DEBUG"))) + debug_args = xstrdup(t); getCurrentTime(); - debugs(42, 0, "pinger: Squid socket opened"); -#endif -} - -void -pingerClose(void) -{ - close(icmp_sock); -#ifdef _SQUID_MSWIN_ - - shutdown(socket_to_squid, SD_BOTH); - close(socket_to_squid); - socket_to_squid = -1; -#endif - - icmp_sock = -1; - icmp_ident = 0; -} - -static void - -pingerSendEcho(struct IN_ADDR to, int opcode, char *payload, int len) -{ - LOCAL_ARRAY(char, pkt, MAX_PKT_SZ); - - struct icmphdr *icmp = NULL; - icmpEchoData *echo; - - size_t icmp_pktsize = sizeof(struct icmphdr); - - struct sockaddr_in S; - memset(pkt, '\0', MAX_PKT_SZ); - icmp = (struct icmphdr *) (void *) pkt; + _db_init(NULL, debug_args); - /* - * cevans - beware signed/unsigned issues in untrusted data from - * the network!! - */ + debugs(42, 0, "pinger: Initialising ICMP pinger ..."); - if (len < 0) - { - len = 0; + icmp4_worker = icmp4.Open(); + if(icmp4_worker < 0) { + debugs(42, 0, "pinger: Unable to start ICMP pinger."); } + max_fd = max(max_fd, icmp4_worker); - icmp->icmp_type = ICMP_ECHO; - icmp->icmp_code = 0; - icmp->icmp_cksum = 0; - icmp->icmp_id = icmp_ident; - icmp->icmp_seq = (u_short) icmp_pkts_sent++; - echo = (icmpEchoData *) (icmp + 1); - echo->opcode = (unsigned char) opcode; - echo->tv = current_time; - - icmp_pktsize += sizeof(struct timeval) + sizeof(char); - - if (payload) - { - if (len > MAX_PAYLOAD) - len = MAX_PAYLOAD; - - xmemcpy(echo->payload, payload, len); - - icmp_pktsize += len; +#if USE_IPV6 + icmp6_worker = icmp6.Open(); + if(icmp6_worker <0 ) { + debugs(42, 0, "pinger: Unable to start ICMPv6 pinger."); } - - 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); - sendto(icmp_sock, - (const void *) pkt, - icmp_pktsize, - 0, - - (struct sockaddr *) &S, - - sizeof(struct sockaddr_in)); - pingerLog(icmp, to, 0, 0); -} - -static void -pingerRecv(void) -{ - int n; - socklen_t fromlen; - - struct sockaddr_in from; - int iphdrlen = 20; - - struct iphdr *ip = NULL; - - struct icmphdr *icmp = NULL; - static char *pkt = NULL; - - struct timeval now; - icmpEchoData *echo; - static pingerReplyData preply; - - if (pkt == NULL) - pkt = (char *)xmalloc(MAX_PKT_SZ); - - fromlen = sizeof(from); - - n = recvfrom(icmp_sock, - (void *)pkt, - MAX_PKT_SZ, - 0, - - (struct sockaddr *) &from, - &fromlen); - -#if GETTIMEOFDAY_NO_TZP - - gettimeofday(&now); - -#else - - gettimeofday(&now, NULL); - + max_fd = max(max_fd, icmp6_worker); #endif - debugs(42, 9, "pingerRecv: " << n << " bytes from " << - inet_ntoa(from.sin_addr)); - - ip = (struct iphdr *) (void *) pkt; - -#if HAVE_STRUCT_IPHDR_IP_HL - - iphdrlen = ip->ip_hl << 2; - -#else /* HAVE_STRUCT_IPHDR_IP_HL */ -#if WORDS_BIGENDIAN - - iphdrlen = (ip->ip_vhl >> 4) << 2; - -#else - - iphdrlen = (ip->ip_vhl & 0xF) << 2; - + // abort if neither worker could open a socket. + if(icmp4_worker == -1) { +#if USE_IPV6 + if(icmp6_worker == -1) #endif -#endif /* HAVE_STRUCT_IPHDR_IP_HL */ - - icmp = (struct icmphdr *) (void *) (pkt + iphdrlen); - - if (icmp->icmp_type != ICMP_ECHOREPLY) - return; - - if (icmp->icmp_id != icmp_ident) - return; - - echo = (icmpEchoData *) (void *) (icmp + 1); - - preply.from = from.sin_addr; - - preply.opcode = echo->opcode; - - preply.hops = ipHops(ip->ip_ttl); - - preply.rtt = tvSubMsec(echo->tv, now); - - preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT_SZ); - - pingerSendtoSquid(&preply); - - pingerLog(icmp, from.sin_addr, preply.rtt, preply.hops); -} - - -static int -in_cksum(unsigned short *ptr, int size) -{ - long sum; - unsigned short oddbyte; - unsigned short answer; - sum = 0; - - while (size > 1) { - sum += *ptr++; - size -= 2; - } - - if (size == 1) { - oddbyte = 0; - *((unsigned char *) &oddbyte) = *(unsigned char *) ptr; - sum += oddbyte; - } - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - answer = (unsigned short) ~sum; - return (answer); -} - -static void - -pingerLog(struct icmphdr *icmp, struct IN_ADDR addr, int rtt, int hops) -{ - debugs(42, 2, "pingerLog: " << std::setw(9) << current_time.tv_sec << - "."<< std::setfill('0') << std::setw(6) << - current_time.tv_usec << " "<< std::left << std::setfill(' ')<< - std::setw(16) << inet_ntoa(addr) << " "<< icmp->icmp_type << - " " << std::setw(15) << icmpPktStr[icmp->icmp_type] << " " << rtt << - "ms " << hops << " hops"); -} - -static int -ipHops(int ttl) -{ - if (ttl < 33) - return 33 - ttl; - - if (ttl < 63) - return 63 - ttl; /* 62 = (64+60)/2 */ - - if (ttl < 65) - return 65 - ttl; /* 62 = (64+60)/2 */ - - if (ttl < 129) - return 129 - ttl; - - if (ttl < 193) - return 193 - ttl; - - return 256 - ttl; -} - -static int -pingerReadRequest(void) -{ - static pingerEchoData pecho; - int n; - int guess_size; - memset(&pecho, '\0', sizeof(pecho)); - n = recv(socket_from_squid, &pecho, sizeof(pecho), 0); - - if (n < 0) - return n; - - if (0 == n) { - /* EOF indicator */ - fprintf(stderr, "EOF encountered\n"); - errno = 0; - return -1; - } - - guess_size = n - (sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ); - - if (guess_size != pecho.psize) { - fprintf(stderr, "size mismatch, guess=%d psize=%d\n", - guess_size, pecho.psize); - /* don't process this message, but keep running */ - return 0; + debugs(42, 0, "FATAL: pinger: Unable to open any ICMP sockets."); + exit(1); } - pingerSendEcho(pecho.to, - pecho.opcode, - pecho.payload, - pecho.psize); - return n; -} - -static void -pingerSendtoSquid(pingerReplyData * preply) -{ - int len = sizeof(pingerReplyData) - MAX_PKT_SZ + preply->psize; - - if (send(socket_to_squid, preply, len, 0) < 0) { - debugs(50, 0, "pinger: send: " << xstrerror()); - pingerClose(); - exit(1); + if( (squid_link = control.Open()) < 0) { + debugs(42, 0, "FATAL: pinger: Unable to setup Pinger control sockets."); + icmp4.Close(); +#if USE_IPV6 + icmp6.Close(); +#endif + exit(1); // fatal error if the control channel fails. } -} - -int -main(int argc, char *argv[]) -{ - fd_set R; - int x; + max_fd = max(max_fd, squid_link); - struct timeval tv; - const char *debug_args = "ALL,1"; - 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); - for (;;) { tv.tv_sec = PINGER_TIMEOUT; tv.tv_usec = 0; FD_ZERO(&R); - FD_SET(socket_from_squid, &R); - FD_SET(icmp_sock, &R); - x = select(icmp_sock + 1, &R, NULL, NULL, &tv); + if(icmp4_worker >= 0) { + FD_SET(icmp4_worker, &R); + } +#if USE_IPV6 + + if(icmp6_worker >= 0) { + FD_SET(icmp6_worker, &R); + } +#endif + FD_SET(squid_link, &R); + x = select(10, &R, NULL, NULL, &tv); getCurrentTime(); if (x < 0) { - pingerClose(); + debugs(42, 0, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerror()); + control.Close(); exit(1); } - if (FD_ISSET(socket_from_squid, &R)) - if (pingerReadRequest() < 0) { - debugs(42, 0, "Pinger exiting."); - pingerClose(); - exit(1); - } + if (FD_ISSET(squid_link, &R)) { + control.Recv(); + } - if (FD_ISSET(icmp_sock, &R)) - pingerRecv(); +#if USE_IPV6 + if (icmp6_worker >= 0 && FD_ISSET(icmp6_worker, &R)) { + icmp6.Recv(); + } +#endif + + if (icmp4_worker >= 0 && FD_ISSET(icmp4_worker, &R)) { + icmp4.Recv(); + } if (PINGER_TIMEOUT + last_check_time < squid_curtime) { - if (send(socket_to_squid, &tv, 0, 0) < 0) { - pingerClose(); + if (send(LINK_TO_SQUID, &tv, 0, 0) < 0) { + debugs(42, 0, "pinger: Closing. No requests in last " << PINGER_TIMEOUT << " seconds."); + control.Close(); exit(1); } diff --git a/src/protos.h b/src/protos.h index 333463e3bc..11023aaafe 100644 --- a/src/protos.h +++ b/src/protos.h @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.550 2007/09/28 00:22:38 hno Exp $ + * $Id: protos.h,v 1.551 2007/12/14 23:11:47 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -43,6 +43,8 @@ */ #include "HttpRequestMethod.h" /* for routines still in this file that take CacheManager parameters */ +#include "IPAddress.h" +/* for routines in here that need it as a parameter. */ class CacheManager; @@ -75,7 +77,7 @@ SQUIDCEXTERN void parse_wordlist(wordlist ** list); SQUIDCEXTERN void requirePathnameExists(const char *name, const char *path); SQUIDCEXTERN void parse_time_t(time_t * var); -SQUIDCEXTERN void parse_sockaddr_in_list_token(sockaddr_in_list **, char *); +SQUIDCEXTERN void parse_IPAddress_list_token(IPAddress_list **, char *); /* client_side.c - FD related client side routines */ @@ -83,13 +85,13 @@ SQUIDCEXTERN void parse_sockaddr_in_list_token(sockaddr_in_list **, char *); SQUIDCEXTERN void clientdbInit(void); extern void clientdbRegisterWithCacheManager(CacheManager & manager); -SQUIDCEXTERN void clientdbUpdate(struct IN_ADDR, log_type, protocol_t, size_t); +SQUIDCEXTERN void clientdbUpdate(const IPAddress &, log_type, protocol_t, size_t); -SQUIDCEXTERN int clientdbCutoffDenied(struct IN_ADDR); +SQUIDCEXTERN int clientdbCutoffDenied(const IPAddress &); SQUIDCEXTERN void clientdbDump(StoreEntry *); SQUIDCEXTERN void clientdbFreeMemory(void); -SQUIDCEXTERN int clientdbEstablished(struct IN_ADDR, int); +SQUIDCEXTERN int clientdbEstablished(const IPAddress &, int); SQUIDCEXTERN void clientOpenListenSockets(void); SQUIDCEXTERN void clientHttpConnectionsClose(void); SQUIDCEXTERN void httpRequestFree(void *); @@ -142,7 +144,7 @@ SQUIDCEXTERN void idnsShutdown(void); extern void idnsRegisterWithCacheManager(CacheManager & manager); SQUIDCEXTERN void idnsALookup(const char *, IDNSCB *, void *); -SQUIDCEXTERN void idnsPTRLookup(const struct IN_ADDR, IDNSCB *, void *); +SQUIDCEXTERN void idnsPTRLookup(const IPAddress &, IDNSCB *, void *); SQUIDCEXTERN void fd_close(int fd); SQUIDCEXTERN void fd_open(int fd, unsigned int type, const char *); @@ -161,15 +163,15 @@ SQUIDCEXTERN void file_map_bit_reset(fileMap *, int); SQUIDCEXTERN void filemapFreeMemory(fileMap *); -SQUIDCEXTERN void fqdncache_nbgethostbyaddr(struct IN_ADDR, FQDNH *, void *); +SQUIDCEXTERN void fqdncache_nbgethostbyaddr(IPAddress &, FQDNH *, void *); -SQUIDCEXTERN const char *fqdncache_gethostbyaddr(struct IN_ADDR, int flags); +SQUIDCEXTERN const char *fqdncache_gethostbyaddr(IPAddress &, int flags); SQUIDCEXTERN void fqdncache_init(void); extern void fqdncacheRegisterWithCacheManager(CacheManager & manager); SQUIDCEXTERN void fqdnStats(StoreEntry *); SQUIDCEXTERN void fqdncacheReleaseInvalid(const char *); -SQUIDCEXTERN const char *fqdnFromAddr(struct IN_ADDR); +SQUIDCEXTERN const char *fqdnFromAddr(IPAddress &); SQUIDCEXTERN int fqdncacheQueueDrain(void); SQUIDCEXTERN void fqdncacheFreeMemory(void); SQUIDCEXTERN void fqdncache_restart(void); @@ -178,7 +180,7 @@ SQUIDCEXTERN void fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames); class FwdState; SQUIDCEXTERN void ftpStart(FwdState *); -SQUIDCEXTERN char *ftpUrlWith2f(const HttpRequest *); +SQUIDCEXTERN const char *ftpUrlWith2f(HttpRequest *); SQUIDCEXTERN void gopherStart(FwdState *); SQUIDCEXTERN int gopherCachable(const HttpRequest *); @@ -261,13 +263,6 @@ SQUIDCEXTERN void httpHeaderStoreReport(StoreEntry * e); SQUIDCEXTERN void httpHdrMangleList(HttpHeader *, HttpRequest *, int req_or_rep); SQUIDCEXTERN int httpReqHdrManglersConfigured(); -SQUIDCEXTERN void icmpOpen(void); -SQUIDCEXTERN void icmpClose(void); - -SQUIDCEXTERN void icmpSourcePing(struct IN_ADDR to, const icp_common_t *, const char *url); - -SQUIDCEXTERN void icmpDomainPing(struct IN_ADDR to, const char *domain); - #ifdef SQUID_SNMP SQUIDCEXTERN PF snmpHandleUdp; SQUIDCEXTERN void snmpInit(void); @@ -276,11 +271,10 @@ SQUIDCEXTERN void snmpConnectionShutdown(void); SQUIDCEXTERN void snmpConnectionClose(void); SQUIDCEXTERN void snmpDebugOid(int lvl, oid * Name, snint Len); -SQUIDCEXTERN void addr2oid(struct IN_ADDR addr, oid * Dest); +SQUIDCEXTERN void addr2oid(IPAddress &addr, oid *Dest); +SQUIDCEXTERN void oid2addr(oid *Dest, IPAddress &addr, u_int code); -SQUIDCEXTERN struct IN_ADDR *oid2addr(oid * id); - -SQUIDCEXTERN struct IN_ADDR *client_entry(struct IN_ADDR *current); +SQUIDCEXTERN IPAddress *client_entry(IPAddress *current); SQUIDCEXTERN variable_list *snmp_basicFn(variable_list *, snint *); SQUIDCEXTERN variable_list *snmp_confFn(variable_list *, snint *); SQUIDCEXTERN variable_list *snmp_sysFn(variable_list *, snint *); @@ -322,9 +316,9 @@ extern void ipcacheRegisterWithCacheManager(CacheManager & manager); SQUIDCEXTERN void stat_ipcache_get(StoreEntry *); SQUIDCEXTERN void ipcacheCycleAddr(const char *name, ipcache_addrs *); -SQUIDCEXTERN void ipcacheMarkBadAddr(const char *name, struct IN_ADDR); +SQUIDCEXTERN void ipcacheMarkBadAddr(const char *name, IPAddress &); -SQUIDCEXTERN void ipcacheMarkGoodAddr(const char *name, struct IN_ADDR); +SQUIDCEXTERN void ipcacheMarkGoodAddr(const char *name, IPAddress &); SQUIDCEXTERN void ipcacheFreeMemory(void); SQUIDCEXTERN ipcache_addrs *ipcacheCheckNumeric(const char *name); SQUIDCEXTERN void ipcache_restart(void); @@ -364,7 +358,7 @@ SQUIDCEXTERN int neighborsUdpPing(HttpRequest *, int *timeout); SQUIDCEXTERN void neighborAddAcl(const char *, const char *); -SQUIDCEXTERN void neighborsUdpAck(const cache_key *, icp_common_t *, const struct sockaddr_in *); +SQUIDCEXTERN void neighborsUdpAck(const cache_key *, icp_common_t *, const IPAddress &); SQUIDCEXTERN void neighborAdd(const char *, const char *, int, int, int, int, int); SQUIDCEXTERN void neighbors_init(void); extern void neighborsRegisterWithCacheManager(CacheManager & manager); @@ -388,26 +382,28 @@ SQUIDCEXTERN void peerConnectSucceded(peer *); SQUIDCEXTERN void dump_peer_options(StoreEntry *, peer *); SQUIDCEXTERN int peerHTTPOkay(const peer *, HttpRequest *); -SQUIDCEXTERN peer *whichPeer(const struct sockaddr_in *from); +SQUIDCEXTERN peer *whichPeer(const IPAddress &from); SQUIDCEXTERN void netdbInit(void); extern void netdbRegisterWitHCacheManager(CacheManager & manager); -SQUIDCEXTERN void netdbHandlePingReply(const struct sockaddr_in *from, int hops, int rtt); +SQUIDCEXTERN void netdbHandlePingReply(const IPAddress &from, int hops, int rtt); SQUIDCEXTERN void netdbPingSite(const char *hostname); SQUIDCEXTERN void netdbDump(StoreEntry *); -SQUIDCEXTERN int netdbHops(struct IN_ADDR); +#if 0 // AYJ: Looks to be unused now. +SQUIDCEXTERN int netdbHops(IPAddress &); +#endif SQUIDCEXTERN void netdbFreeMemory(void); SQUIDCEXTERN int netdbHostHops(const char *host); SQUIDCEXTERN int netdbHostRtt(const char *host); SQUIDCEXTERN void netdbUpdatePeer(HttpRequest *, peer * e, int rtt, int hops); -SQUIDCEXTERN void netdbDeleteAddrNetwork(struct IN_ADDR addr); +SQUIDCEXTERN void netdbDeleteAddrNetwork(IPAddress &addr); SQUIDCEXTERN void netdbBinaryExchange(StoreEntry *); SQUIDCEXTERN void netdbExchangeStart(void *); -SQUIDCEXTERN void netdbExchangeUpdatePeer(struct IN_ADDR, peer *, double, double); +SQUIDCEXTERN void netdbExchangeUpdatePeer(IPAddress &, peer *, double, double); SQUIDCEXTERN peer *netdbClosestParent(HttpRequest *); SQUIDCEXTERN void netdbHostData(const char *host, int *samp, int *rtt, int *hops); @@ -420,7 +416,7 @@ SQUIDCEXTERN void peerDigestNeeded(PeerDigest * pd); SQUIDCEXTERN void peerDigestNotePeerGone(PeerDigest * pd); SQUIDCEXTERN void peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e); -SQUIDCEXTERN struct IN_ADDR getOutgoingAddr(HttpRequest * request); +SQUIDCEXTERN IPAddress getOutgoingAddr(HttpRequest * request); unsigned long getOutgoingTOS(HttpRequest * request); SQUIDCEXTERN void urnStart(HttpRequest *, StoreEntry *); @@ -452,7 +448,7 @@ extern void waisStart(FwdState *); /* ident.c */ #if USE_IDENT -SQUIDCEXTERN void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, +SQUIDCEXTERN void identStart(IPAddress &me, IPAddress &my_peer, IDCB * callback, void *cbdata); SQUIDCEXTERN void identInit(void); #endif @@ -599,7 +595,9 @@ SQUIDCEXTERN void squid_signal(int sig, SIGHDLR *, int flags); SQUIDCEXTERN pid_t readPidFile(void); SQUIDCEXTERN void keepCapabilities(void); -SQUIDCEXTERN struct IN_ADDR inaddrFromHostent(const struct hostent *hp); +/* AYJ debugs function to show locations being reset with memset() */ +SQUIDCEXTERN void *xmemset(void *dst, int, size_t); + SQUIDCEXTERN int intAverage(int, int, int, int); SQUIDCEXTERN double doubleAverage(double, double, int, int); SQUIDCEXTERN void debug_trap(const char *); @@ -675,6 +673,7 @@ SQUIDCEXTERN pid_t ipcCreate(int type, const char *prog, const char *const args[], const char *name, + IPAddress &local_addr, int *rfd, int *wfd, void **hIpc); diff --git a/src/redirect.cc b/src/redirect.cc index f9142a303e..cba04a10ad 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -1,6 +1,6 @@ /* - * $Id: redirect.cc,v 1.122 2007/11/06 21:19:31 wessels Exp $ + * $Id: redirect.cc,v 1.123 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 61 Redirector * AUTHOR: Duane Wessels @@ -49,7 +49,7 @@ typedef struct void *data; char *orig_url; - struct IN_ADDR client_addr; + IPAddress client_addr; const char *client_ident; const char *method_s; RH *handler; @@ -117,8 +117,8 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) redirectStateData *r = NULL; const char *fqdn; char buf[8192]; - char claddr[20]; - char myaddr[20]; + char claddr[MAX_IPSTRLEN]; + char myaddr[MAX_IPSTRLEN]; assert(http); assert(handler); debugs(61, 5, "redirectStart: '" << http->uri << "'"); @@ -132,7 +132,10 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) r = cbdataAlloc(redirectStateData); r->orig_url = xstrdup(http->uri); - r->client_addr = conn != NULL ? conn->log_addr : no_addr; + if(conn != NULL) + r->client_addr = conn->log_addr; + else + r->client_addr.SetNoAddr(); r->client_ident = NULL; if (http->request->auth_user_request) @@ -163,16 +166,14 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL) fqdn = dash_str; - xstrncpy(claddr, inet_ntoa(r->client_addr), 20); - xstrncpy(myaddr, inet_ntoa(http->request->my_addr), 20); snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n", r->orig_url, - claddr, + r->client_addr.NtoA(claddr,MAX_IPSTRLEN), fqdn, r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str, r->method_s, - myaddr, - http->request->my_port); + http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN), + http->request->my_addr.GetPort()); helperSubmit(redirectors, buf, redirectHandleReply, r); } diff --git a/src/send-announce.cc b/src/send-announce.cc index 5e9a45d457..2914fbf5a8 100644 --- a/src/send-announce.cc +++ b/src/send-announce.cc @@ -1,6 +1,6 @@ /* - * $Id: send-announce.cc,v 1.68 2007/04/28 22:26:37 hno Exp $ + * $Id: send-announce.cc,v 1.69 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 27 Cache Announcer * AUTHOR: Duane Wessels @@ -60,7 +60,7 @@ send_announce(const ipcache_addrs * ia, void *junk) LOCAL_ARRAY(char, tbuf, 256); LOCAL_ARRAY(char, sndbuf, BUFSIZ); - struct sockaddr_in S; + IPAddress S; char *host = Config.Announce.host; char *file = NULL; u_short port = Config.Announce.port; @@ -109,14 +109,10 @@ send_announce(const ipcache_addrs * ia, void *junk) } } - memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; - S.sin_port = htons(port); - S.sin_addr = ia->in_addrs[0]; + S.SetPort(port); + S = ia->in_addrs[0]; assert(theOutIcpConnection > 0); - x = comm_udp_sendto(theOutIcpConnection, - &S, sizeof(S), - sndbuf, strlen(sndbuf) + 1); + x = comm_udp_sendto(theOutIcpConnection, S, sndbuf, strlen(sndbuf) + 1); if (x < 0) debugs(27, 1, "send_announce: FD " << theOutIcpConnection << ": " << xstrerror()); diff --git a/src/snmp_agent.cc b/src/snmp_agent.cc index d57bc55e81..90ba56d010 100644 --- a/src/snmp_agent.cc +++ b/src/snmp_agent.cc @@ -1,6 +1,5 @@ - /* - * $Id: snmp_agent.cc,v 1.96 2007/04/28 22:26:37 hno Exp $ + * $Id: snmp_agent.cc,v 1.97 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 49 SNMP Interface * AUTHOR: Kostas Anagnostakis @@ -33,11 +32,11 @@ * */ - #include "squid.h" #include "cache_snmp.h" #include "Store.h" #include "mem_node.h" +#include "SquidTime.h" /************************************************************************ @@ -45,6 +44,10 @@ ************************************************************************/ +/* + * cacheSystem group + */ + variable_list * snmp_sysFn(variable_list * Var, snint * ErrP) { @@ -81,6 +84,9 @@ snmp_sysFn(variable_list * Var, snint * ErrP) return Answer; } +/* + * cacheConfig group + */ variable_list * snmp_confFn(variable_list * Var, snint * ErrP) { @@ -183,29 +189,47 @@ snmp_confFn(variable_list * Var, snint * ErrP) return Answer; } + +/* + * cacheMesh group + * - cachePeerTable + */ variable_list * snmp_meshPtblFn(variable_list * Var, snint * ErrP) { variable_list *Answer = NULL; - struct IN_ADDR *laddr; + IPAddress laddr; char *cp = NULL; peer *p = NULL; int cnt = 0; debugs(49, 5, "snmp_meshPtblFn: peer " << Var->name[LEN_SQ_MESH + 3] << " requested!"); *ErrP = SNMP_ERR_NOERROR; - laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]); + u_int index = Var->name[LEN_SQ_MESH + 3] ; for (p = Config.peers; p != NULL; p = p->next, cnt++) - if (p->in_addr.sin_addr.s_addr == laddr->s_addr) - break; + { + if (p->index == index) + { + laddr = p->in_addr ; + break; + } + } if (p == NULL) { - *ErrP = SNMP_ERR_NOSUCHNAME; - return NULL; + *ErrP = SNMP_ERR_NOSUCHNAME; + return NULL; } + switch (Var->name[LEN_SQ_MESH + 2]) { + case MESH_PTBL_INDEX: // FIXME INET6: Should be visible? + { + Answer = snmp_var_new_integer(Var->name, Var->name_length, + (snint)p->index, SMI_INTEGER); + } + break; + case MESH_PTBL_NAME: cp = p->host; @@ -213,12 +237,29 @@ snmp_meshPtblFn(variable_list * Var, snint * ErrP) Answer->type = ASN_OCTET_STR; Answer->val_len = strlen(cp); Answer->val.string = (u_char *) xstrdup(cp); + break; - case MESH_PTBL_IP: - Answer = snmp_var_new_integer(Var->name, Var->name_length, - (snint) p->in_addr.sin_addr.s_addr, - SMI_IPADDRESS); + case MESH_PTBL_ADDR_TYPE: + { + int ival; + ival = laddr.IsIPv4() ? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; + Answer = snmp_var_new_integer(Var->name, Var->name_length, + ival, SMI_INTEGER); + } + break; + case MESH_PTBL_ADDR: + { + Answer = snmp_var_new(Var->name, Var->name_length); + // InetAddress doesn't have its own ASN.1 type, + // like IpAddr does (SMI_IPADDRESS) + // See: rfc4001.txt + Answer->type = ASN_OCTET_STR; + char host[MAX_IPSTRLEN]; + laddr.NtoA(host,MAX_IPSTRLEN); + Answer->val_len = strlen(host); + Answer->val.string = (u_char *) xstrdup(host); + } break; case MESH_PTBL_HTTP: diff --git a/src/snmp_core.cc b/src/snmp_core.cc index 2e006cacca..401a8edd84 100644 --- a/src/snmp_core.cc +++ b/src/snmp_core.cc @@ -1,6 +1,6 @@ /* - * $Id: snmp_core.cc,v 1.79 2007/07/06 11:30:45 amosjeffries Exp $ + * $Id: snmp_core.cc,v 1.80 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 49 SNMP support * AUTHOR: Glenn Chisholm @@ -81,7 +81,6 @@ static mib_tree_entry *snmpTreeEntry(oid entry, snint len, mib_tree_entry * curr static mib_tree_entry *snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current); static void snmpSnmplibDebug(int lvl, char *buf); - /* * The functions used during startup: * snmpInit @@ -150,91 +149,91 @@ snmpInit(void) LEN_SQ_PRF, NULL, NULL, 2, snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, PERF_SYS), LEN_SQ_PRF + 1, NULL, NULL, 13, - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 1), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_PF), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_NUMR), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 3), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_MEMUSAGE), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 4), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CPUTIME), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 5), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CPUUSAGE), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 6), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_MAXRESSZ), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 7), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_NUMOBJCNT), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 8), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURLRUEXP), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 9), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUNLREQ), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 10), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUNUSED_FD), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 11), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURRESERVED_FD), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 12), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURUSED_FD), LEN_SQ_PRF + 2, snmp_prfSysFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, 13), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_SYS, PERF_SYS_CURMAX_FD), 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), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR), LEN_SQ_PRF + 2, NULL, NULL, 15, - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 1), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_REQ), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_HITS), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 3), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_ERRORS), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 4), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_IN), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 5), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_HTTP_KBYTES_OUT), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 6), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_S), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 7), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_R), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 8), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_SKB), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 9), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ICP_RKB), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 10), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_REQ), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 11), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_ERRORS), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 12), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_KBYTES_IN), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 13), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_KBYTES_OUT), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 14), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_CURSWAP), LEN_SQ_PRF + 3, snmp_prfProtoFn, static_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, 1, 15), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_AGGR, PERF_PROTOSTAT_AGGR_CLIENTS), 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), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1), LEN_SQ_PRF + 3, NULL, NULL, 11, - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 1), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_TIME), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_ALL), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 3), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_MISS), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 4), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_NM), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 5), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_HIT), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 6), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_QUERY), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 7), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_ICP_REPLY), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 8), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_DNS), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 9), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_RHR), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 10), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_BHR), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, 2, 1, 11), + snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, PERF_PROTO, PERF_PROTOSTAT_MEDIAN, 1, PERF_MEDIAN_HTTP_NH), LEN_SQ_PRF + 4, snmp_prfProtoFn, time_Inst, 0))))), snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET), LEN_SQ_NET, NULL, NULL, 3, @@ -291,57 +290,63 @@ snmpInit(void) #endif snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH), LEN_SQ_MESH, NULL, NULL, 2, - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, MESH_PTBL), 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 + 2, NULL, NULL, 15, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_INDEX), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_NAME), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ADDR_TYPE), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ADDR), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_HTTP), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_ICP), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_TYPE), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_STATE), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_SENT), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_PACKED), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_FETCHES), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_RTT), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_IGN), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_KEEPAL_S), + LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_PTBL, 1, MESH_PTBL_KEEPAL_R), LEN_SQ_MESH + 3, snmp_meshPtblFn, peer_Inst, 0))), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, MESH_CTBL), 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), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, MESH_CTBL, 1), + LEN_SQ_MESH + 2, NULL, NULL, 10, + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ADDR_TYPE), + LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ADDR), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTREQ), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTBYTES), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTHITS), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_HTHITBYTES), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPREQ), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPBYTES), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8), + snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPHITS), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0), - (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9), + (mib_tree_last = snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, MESH_CTBL, 1, MESH_CTBL_ICPHITBYTES), LEN_SQ_MESH + 3, snmp_meshCtblFn, client_Inst, 0))))) ) ) @@ -358,20 +363,17 @@ snmpInit(void) void snmpConnectionOpen(void) { - u_short port; - - struct sockaddr_in xaddr; - socklen_t len; + struct addrinfo *xaddr = NULL; int x; debugs(49, 5, "snmpConnectionOpen: Called"); - if ((port = Config.Port.snmp) > (u_short) 0) { + if (Config.Port.snmp > 0) { + Config.Addrs.snmp_incoming.SetPort(Config.Port.snmp); enter_suid(); theInSnmpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, Config.Addrs.snmp_incoming, - port, COMM_NONBLOCKING, "SNMP Port"); leave_suid(); @@ -381,14 +383,14 @@ snmpConnectionOpen(void) commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); - debugs(1, 1, "Accepting SNMP messages on port " << port << ", FD " << theInSnmpConnection << "."); + debugs(1, 1, "Accepting SNMP messages on " << Config.Addrs.snmp_incoming << ", FD " << theInSnmpConnection << "."); - if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) { + if (!Config.Addrs.snmp_outgoing.IsNoAddr()) { + Config.Addrs.snmp_outgoing.SetPort(Config.Port.snmp); enter_suid(); theOutSnmpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, Config.Addrs.snmp_outgoing, - port, COMM_NONBLOCKING, "SNMP Port"); leave_suid(); @@ -401,7 +403,7 @@ snmpConnectionOpen(void) snmpHandleUdp, NULL, 0); - debugs(1, 1, "Outgoing SNMP messages on port " << port << ", FD " << theOutSnmpConnection << "."); + debugs(1, 1, "Outgoing SNMP messages on " << Config.Addrs.snmp_outgoing << ", FD " << theOutSnmpConnection << "."); fd_note(theOutSnmpConnection, "Outgoing SNMP socket"); @@ -410,18 +412,18 @@ snmpConnectionOpen(void) theOutSnmpConnection = theInSnmpConnection; } - memset(&theOutSNMPAddr, '\0', sizeof(struct IN_ADDR)); + theOutSNMPAddr.SetEmpty(); - len = sizeof(struct sockaddr_in); - memset(&xaddr, '\0', len); - x = getsockname(theOutSnmpConnection, + theOutSNMPAddr.InitAddrInfo(xaddr); - (struct sockaddr *) &xaddr, &len); + x = getsockname(theOutSnmpConnection, xaddr->ai_addr, &xaddr->ai_addrlen); if (x < 0) debugs(51, 1, "theOutSnmpConnection FD " << theOutSnmpConnection << ": getsockname: " << xstrerror()); else - theOutSNMPAddr = xaddr.sin_addr; + theOutSNMPAddr = *xaddr; + + theOutSNMPAddr.FreeAddrInfo(xaddr); } } @@ -476,9 +478,7 @@ void snmpHandleUdp(int sock, void *not_used) { LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); - - struct sockaddr_in from; - socklen_t from_len; + IPAddress from; snmp_request_t *snmp_rq; int len; @@ -486,29 +486,24 @@ snmpHandleUdp(int sock, void *not_used) 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); len = comm_udp_recvfrom(sock, buf, SNMP_REQUEST_SIZE, 0, - - (struct sockaddr *) &from, - &from_len); + from); if (len > 0) { buf[len] = '\0'; - debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << inet_ntoa(from.sin_addr) << "."); + debugs(49, 3, "snmpHandleUdp: FD " << sock << ": received " << len << " bytes from " << from << "."); snmp_rq = (snmp_request_t *)xcalloc(1, sizeof(snmp_request_t)); snmp_rq->buf = (u_char *) buf; snmp_rq->len = len; snmp_rq->sock = sock; snmp_rq->outbuf = (unsigned char *)xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE); - - xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in)); + snmp_rq->from = from; snmpDecodePacket(snmp_rq); xfree(snmp_rq->outbuf); xfree(snmp_rq); @@ -523,36 +518,39 @@ snmpHandleUdp(int sock, void *not_used) static void snmpDecodePacket(snmp_request_t * rq) { - struct snmp_pdu *PDU; - u_char *Community; u_char *buf = rq->buf; int len = rq->len; int allow = 0; - debugs(49, 5, "snmpDecodePacket: Called."); - /* Now that we have the data, turn it into a PDU */ + debugs(49, 5, HERE << "Called."); PDU = snmp_pdu_create(0); + /* Allways answer on SNMPv1 */ rq->session.Version = SNMP_VERSION_1; Community = snmp_parse(&rq->session, PDU, buf, len); if (Community) { ACLChecklist checklist; checklist.accessList = cbdataReference(Config.accessList.snmp); - checklist.src_addr = rq->from.sin_addr; + checklist.src_addr = rq->from; checklist.snmp_community = (char *) Community; /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ allow = checklist.fastCheck(); } +#if 1 /* FIXME INET6 : Kill this block before committing to HEAD. */ + /* RAFA, Amos, DO NOT COMMIT INTO AHEAD with this !!! */ + allow = 1 ; + /* allow */ +#endif /* KILL */ if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) { rq->community = Community; rq->PDU = PDU; debugs(49, 5, "snmpAgentParse: reqid=[" << PDU->reqid << "]"); snmpConstructReponse(rq); } else { - debugs(49, 1, "Failed SNMP agent query from : " << inet_ntoa(rq->from.sin_addr) << "."); + debugs(49, 1, HERE << "Failed SNMP agent query from : " << rq->from); snmp_free_pdu(PDU); } @@ -575,7 +573,7 @@ snmpConstructReponse(snmp_request_t * rq) if (RespPDU != NULL) { snmp_build(&rq->session, RespPDU, rq->outbuf, &rq->outlen); - comm_udp_sendto(rq->sock, &rq->from, sizeof(rq->from), rq->outbuf, rq->outlen); + comm_udp_sendto(rq->sock, rq->from, rq->outbuf, rq->outlen); snmp_free_pdu(RespPDU); } } @@ -600,6 +598,7 @@ static struct snmp_pdu * Answer->errindex = 0; if (PDU->command == SNMP_PDU_GET || PDU->command == SNMP_PDU_GETNEXT) { + /* Indirect way */ int get_next = (PDU->command == SNMP_PDU_GETNEXT); variable_list *VarPtr_; variable_list **RespVars = &(Answer->variables); @@ -615,8 +614,6 @@ static struct snmp_pdu * index++; - /* Find the parsing function for this variable */ - if (get_next) ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen); else @@ -639,7 +636,6 @@ static struct snmp_pdu * snmp_var_free(VarPtr); } - /* Was there an error? */ if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) { Answer->errindex = index; debugs(49, 5, "snmpAgentResponse: error."); @@ -647,7 +643,6 @@ static struct snmp_pdu * if (VarNew) snmp_var_free(VarNew); - /* Free the already processed results, if any */ while ((VarPtr = Answer->variables) != NULL) { Answer->variables = VarPtr->next_variable; snmp_var_free(VarPtr); @@ -666,8 +661,8 @@ static struct snmp_pdu * *RespVars = VarNew; RespVars = &(VarNew->next_variable); - } - } + } + } } return (Answer); @@ -724,14 +719,13 @@ snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen) while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { mib_tree_entry *nextmibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); - if (!nextmibTreeEntry) + if (!nextmibTreeEntry) break; else mibTreeEntry = nextmibTreeEntry; count++; } - debugs(49, 5, "snmpTreeNext: Recursed down to requested object"); } else { return NULL; @@ -740,20 +734,23 @@ snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen) 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)) { + *NextLen = CurrentLen; + *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn); + if (*Next) + { + debugs(49, 6, "snmpTreeNext: Next : "); + snmpDebugOid(6, *Next, *NextLen); + return (Fn); + } } if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { count--; nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent); - if (nextoid) { - debugs(49, 5, "snmpTreeNext: Next OID found for sibling"); + debugs(49, 5, "snmpTreeNext: Next OID found for sibling" << nextoid ); mibTreeEntry = nextoid; count++; } else { @@ -777,7 +774,6 @@ snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen) } } } - while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) { mibTreeEntry = mibTreeEntry->leaves[0]; } @@ -788,7 +784,11 @@ snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen) } if (*Next) - return (Fn); + { + debugs(49, 6, "snmpTreeNext: Next : "); + snmpDebugOid(6, *Next, *NextLen); + return (Fn); + } else return NULL; } @@ -797,14 +797,12 @@ static oid * static_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) { oid *instance = NULL; - if (*len <= current->len) { instance = (oid *)xmalloc(sizeof(name) * (*len + 1)); xmemcpy(instance, name, (sizeof(name) * *len)); instance[*len] = 0; *len += 1; } - *Fn = current->parsefunction; return (instance); } @@ -814,8 +812,7 @@ 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}; + int index[TIME_INDEX_LEN] = {TIME_INDEX}; if (*len <= current->len) { instance = (oid *)xmalloc(sizeof(name) * (*len + 1)); @@ -828,7 +825,7 @@ time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) while ((loop < TIME_INDEX_LEN) && (identifier != index[loop])) loop++; - if (loop < TIME_INDEX_LEN - 1) { + if (loop < (TIME_INDEX_LEN - 1)) { instance = (oid *)xmalloc(sizeof(name) * (*len)); xmemcpy(instance, name, (sizeof(name) * *len)); instance[*len - 1] = index[++loop]; @@ -839,68 +836,38 @@ time_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) return (instance); } + static oid * peer_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn) { 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 = (oid *)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 if (*len <= current->len) { + instance = (oid *)xmalloc(sizeof(name) * ( *len + 1)); + xmemcpy(instance, name, (sizeof(name) * *len)); + instance[*len] = 1 ; + *len += 1; } else { - laddr = oid2addr(&name[*len - 4]); - host_addr = inet_ntoa(*laddr); - last_addr = (char *)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 = (oid *)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); - } + int no = name[current->len] ; + int i ; // Note: This works because the Confifg.peers + // keep its index acording to its position. + for ( i=0 ; peers && (i < no) ; peers = peers->next , i++ ) ; + + if (peers) { + instance = (oid *)xmalloc(sizeof(name) * (current->len + 1 )); + xmemcpy(instance, name, (sizeof(name) * current->len )); + instance[current->len] = no + 1 ; // i.e. the next index on cache_peeer table. + } else { + return (instance); + } } - *Fn = current->parsefunction; return (instance); } @@ -909,38 +876,50 @@ static 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; + IPAddress laddr; + IPAddress *aux; if (*len <= current->len) { - instance = (oid *)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); + aux = client_entry(NULL); + // FIXME INET6 . is this good C++ style ? + // What otherwise ? + if (aux) laddr = *aux ; else laddr.SetAnyAddr(); + +#if USE_IPV6 + int size = laddr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; +#else + int size = sizeof(in_addr); +#endif - if (laddr) { - instance = (oid *)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++; - } - } + instance = (oid *)xmalloc(sizeof(name) * (*len + size )); + xmemcpy(instance, name, (sizeof(name) * (*len))); + if ( !laddr.IsAnyAddr() ) { + addr2oid(laddr, &instance[ *len]); // the addr + *len += size ; + } + } else { + int shift = *len - current->len ; // i.e 4 or 16 + oid2addr(&name[*len - shift], laddr,shift); + aux = client_entry(&laddr); + // FIXME INET6 . is this good C++ style ? + // What otherwise ? + if (aux) laddr = *aux ; else laddr.SetAnyAddr(); + + + if (!laddr.IsAnyAddr()) { +#if USE_IPV6 + int newshift = laddr.IsIPv4()? sizeof(in_addr) : sizeof(in6_addr) ; +#else + int newshift = sizeof(in_addr) ; +#endif + instance = (oid *)xmalloc(sizeof(name) * (current->len + newshift)); + xmemcpy(instance, name, (sizeof(name) * (current->len))); + addr2oid(laddr, &instance[current->len]); // the addr. + *len = current->len + newshift ; + } + } + *Fn = current->parsefunction; return (instance); } @@ -955,7 +934,8 @@ client_Inst(oid * name, snint * len, mib_tree_entry * current, oid_ParseFn ** Fn */ /* - * Returns a the sibling object in the tree + * Returns a sibling object for the requested child object or NULL + * if it does not exit */ static mib_tree_entry * snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current) @@ -971,6 +951,7 @@ snmpTreeSiblingEntry(oid entry, snint len, mib_tree_entry * current) count++; } + /* Exactly the sibling on rigth */ if (count < current->children) { next = current->leaves[count]; } else { @@ -1118,30 +1099,86 @@ snmpSnmplibDebug(int lvl, char *buf) debug(49, lvl) ("%s", buf); } -void -addr2oid(struct IN_ADDR addr, oid * Dest) + +/* + IPv4 address: 10.10.0.9 ==> + oid == 10.10.0.9 + IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 ==> + oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 +*/ +void +addr2oid(IPAddress &addr, oid * Dest) { - u_char *cp; - cp = (u_char *) & (addr.s_addr); - Dest[0] = *cp++; - Dest[1] = *cp++; - Dest[2] = *cp++; - Dest[3] = *cp++; + u_int i ; + u_char *cp = NULL; + struct in_addr iaddr; +#if USE_IPV6 + struct in6_addr i6addr; + oid code = addr.IsIPv4()? INETADDRESSTYPE_IPV4 : INETADDRESSTYPE_IPV6 ; + u_int size = (code == INETADDRESSTYPE_IPV4) ? sizeof(struct in_addr):sizeof(struct in6_addr); +#else + oid code = INETADDRESSTYPE_IPV4 ; + u_int size = sizeof(struct in_addr) ; +#endif /* USE_IPV6 */ + // Dest[0] = code ; + if ( code == INETADDRESSTYPE_IPV4 ) { + addr.GetInAddr(iaddr); + cp = (u_char *) &(iaddr.s_addr); + } +#if USE_IPV6 + else + { + addr.GetInAddr(i6addr); + cp = (u_char *) &i6addr; + } +#endif + for ( i=0 ; i < size ; i++) + { + // OID's are in network order + Dest[i] = *cp++; + } + debugs(49, 7, "addr2oid: Dest : "); + snmpDebugOid(7, Dest, size ); + } -struct IN_ADDR - * - oid2addr(oid * id) +/* + oid == 10.10.0.9 ==> + IPv4 address: 10.10.0.9 + oid == 32.1.50.239.162.33.251.20.50.0.0.0.0.0.0.0.0.0.1 ==> + IPv6 adress : 20:01:32:ef:a2:21:fb:32:00:00:00:00:00:00:00:00:OO:01 +*/ +void +oid2addr(oid * id, IPAddress &addr, u_int size) { + struct in_addr iaddr; + u_int i; + u_char *cp; +#if USE_IPV6 + struct in6_addr i6addr; + if ( size == sizeof(struct in_addr) ) +#endif /* USE_IPV6 */ + cp = (u_char *) &(iaddr.s_addr); +#if USE_IPV6 + else + cp = (u_char *) &(i6addr); +#endif /* USE_IPV6 */ + debugs(49, 7, "oid2addr: id : "); + snmpDebugOid(7, id, size ); + for(i=0 ; inext) { const char *p = NULL; @@ -1660,11 +1662,11 @@ statClientRequests(StoreEntry * s) storeAppendPrintf(s, "\tin: buf %p, offset %ld, size %ld\n", conn->in.buf, (long int) conn->in.notYetUsed, (long int) conn->in.allocatedSize); storeAppendPrintf(s, "\tpeer: %s:%d\n", - inet_ntoa(conn->peer.sin_addr), - ntohs(conn->peer.sin_port)); + conn->peer.NtoA(buf,MAX_IPSTRLEN), + conn->peer.GetPort()); storeAppendPrintf(s, "\tme: %s:%d\n", - inet_ntoa(conn->me.sin_addr), - ntohs(conn->me.sin_port)); + conn->me.NtoA(buf,MAX_IPSTRLEN), + conn->me.GetPort()); storeAppendPrintf(s, "\tnrequests: %d\n", conn->nrequests); } diff --git a/src/store_log.cc b/src/store_log.cc index 2d1be05e20..7a0a992e1b 100644 --- a/src/store_log.cc +++ b/src/store_log.cc @@ -1,6 +1,5 @@ - /* - * $Id: store_log.cc,v 1.35 2007/08/13 17:20:51 hno Exp $ + * $Id: store_log.cc,v 1.36 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 20 Storage Manager Logging Functions * AUTHOR: Duane Wessels @@ -38,6 +37,7 @@ #include "MemObject.h" #include "HttpReply.h" #include "CacheManager.h" +#include "SquidTime.h" static const char *storeLogTags[] = { diff --git a/src/structs.h b/src/structs.h index ce2a077bf3..625fbd69de 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.568 2007/12/02 08:23:56 amosjeffries Exp $ + * $Id: structs.h,v 1.569 2007/12/14 23:11:48 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -76,7 +76,7 @@ struct _snmp_request_t long reqid; int outlen; - struct sockaddr_in from; + IPAddress from; struct snmp_pdu *PDU; ACLChecklist *acl_checklist; @@ -93,7 +93,7 @@ struct _acl_address acl_address *next; ACLList *aclList; - struct IN_ADDR addr; + IPAddress addr; }; struct _acl_tos @@ -123,18 +123,11 @@ struct _relist relist *next; }; -struct _sockaddr_in_list -{ - - struct sockaddr_in s; - sockaddr_in_list *next; -}; - struct _http_port_list { http_port_list *next; - struct sockaddr_in s; + IPAddress s; char *protocol; /* protocol name */ char *name; /* visible name */ char *defaultsite; /* default web site */ @@ -183,6 +176,10 @@ struct _https_port_list #include "DelayConfig.h" #endif +#if USE_ICMP +#include "ICMPConfig.h" +#endif + /* forward decl for SquidConfig, see RemovalPolicy.h */ class RemovalPolicySettings; @@ -300,9 +297,9 @@ struct _SquidConfig struct { - struct IN_ADDR router; + IPAddress router; - struct IN_ADDR address; + IPAddress address; int version; } @@ -312,9 +309,9 @@ struct _SquidConfig struct { - sockaddr_in_list *router; + IPAddress_list *router; - struct IN_ADDR address; + IPAddress address; int forwarding_method; int return_method; int assignment_method; @@ -326,6 +323,10 @@ struct _SquidConfig Wccp2; #endif +#if USE_ICMP + ICMPConfig pinger; +#endif + char *as_whois_server; struct @@ -368,10 +369,6 @@ struct _SquidConfig #endif wordlist *redirect; -#if USE_ICMP - - char *pinger; -#endif #if USE_UNLINKD char *unlinkd; @@ -430,17 +427,17 @@ struct _SquidConfig struct { - struct IN_ADDR udp_incoming; + IPAddress udp_incoming; - struct IN_ADDR udp_outgoing; + IPAddress udp_outgoing; #if SQUID_SNMP - struct IN_ADDR snmp_incoming; + IPAddress snmp_incoming; - struct IN_ADDR snmp_outgoing; + IPAddress snmp_outgoing; #endif - - struct IN_ADDR client_netmask; + /* FIXME INET6 : this should really be a CIDR value */ + IPAddress client_netmask; } Addrs; @@ -501,11 +498,6 @@ struct _SquidConfig int query_icmp; int icp_hit_stale; int buffered_logs; -#if ALLOW_SOURCE_PING - - int source_ping; -#endif - int common_log; int log_mime_hdrs; int log_fqdn; @@ -553,6 +545,7 @@ struct _SquidConfig int emailErrData; int httpd_suppress_version_string; int global_internal_static; + int dns_require_A; int debug_override_X; } @@ -667,7 +660,7 @@ struct _SquidConfig struct { - struct IN_ADDR addr; + IPAddress addr; int ttl; unsigned short port; char *encode_key; @@ -940,8 +933,7 @@ unsigned int consume_body_data: struct _ipcache_addrs { - - struct IN_ADDR *in_addrs; + IPAddress *in_addrs; unsigned char *bad_mask; unsigned char count; unsigned char cur; @@ -980,11 +972,12 @@ struct _cd_guess_stats struct _peer { + u_int index; char *name; char *host; peer_t type; - struct sockaddr_in in_addr; + IPAddress in_addr; struct { @@ -1123,7 +1116,7 @@ unsigned int counting: int tcp_up; /* 0 if a connect() fails */ - struct IN_ADDR addresses[10]; + IPAddress addresses[10]; int n_addresses; int rr_count; int rr_lastcount; @@ -1183,7 +1176,7 @@ struct _net_db_peer struct _netdbEntry { hash_link hash; /* must be first */ - char network[16]; + char network[MAX_IPSTRLEN]; int pings_sent; int pings_recv; double hops; @@ -1198,30 +1191,6 @@ struct _netdbEntry }; -#if USE_ICMP - -struct _pingerEchoData -{ - - struct IN_ADDR to; - unsigned char opcode; - int psize; - char payload[PINGER_PAYLOAD_SZ]; -}; - -struct _pingerReplyData -{ - - struct IN_ADDR from; - unsigned char opcode; - int rtt; - int hops; - int psize; - char payload[PINGER_PAYLOAD_SZ]; -}; - -#endif - struct _iostats { @@ -1608,7 +1577,7 @@ struct _ClientInfo { hash_link hash; /* must be first */ - struct IN_ADDR addr; + IPAddress addr; struct { diff --git a/src/tests/stub_comm.cc b/src/tests/stub_comm.cc index 018d453a75..69d8580fb3 100644 --- a/src/tests/stub_comm.cc +++ b/src/tests/stub_comm.cc @@ -1,5 +1,5 @@ /* - * $Id: stub_comm.cc,v 1.5 2006/09/14 20:13:23 serassio Exp $ + * $Id: stub_comm.cc,v 1.6 2007/12/14 23:11:53 amosjeffries Exp $ * * DEBUG: section 84 Helper process maintenance * AUTHOR: Robert Collins @@ -114,7 +114,7 @@ commUnsetNonBlocking(int fd) /* bah, cheating on stub count */ pid_t -ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) +ipcCreate(int type, const char *prog, const char *const args[], const char *name, IPAddress &local_addr, int *rfd, int *wfd, void **hIpc) { fatal ("Not implemented"); return -1; diff --git a/src/tests/testEvent.cc b/src/tests/testEvent.cc index d91db9fb32..290024846b 100644 --- a/src/tests/testEvent.cc +++ b/src/tests/testEvent.cc @@ -93,20 +93,44 @@ testEvent::testDump() CalledEvent event; CalledEvent event2; CapturingStoreEntry * anEntry = new CapturingStoreEntry(); + String expect = "Last event to run: last event\n" + "\n" + "Operation \tNext Execution \tWeight\tCallback Valid?\n" + "test event \t0.000 sec\t 0\t N/A\n" + "test event2 \t0.000 sec\t 0\t N/A\n" + ; + scheduler.schedule("last event", CalledEvent::Handler, &event, 0, 0, false); + /* schedule and dispatch to set the last run event */ scheduler.checkEvents(0); dispatcher.dispatch(); scheduler.schedule("test event", CalledEvent::Handler, &event, 0, 0, false); scheduler.schedule("test event2", CalledEvent::Handler, &event2, 0, 0, false); scheduler.dump(anEntry); - CPPUNIT_ASSERT_EQUAL(String( - "Last event to run: last event\n" - "\n" - "Operation\tNext Execution\tWeight\tCallback Valid?\n" - "test event\t0.000000 seconds\t0\tN/A\n" - "test event2\t0.000000 seconds\t0\tN/A\n" - ), anEntry->_appended_text); + + /* loop over the strings, showing exactly where they differ (if at all) */ + printf("Actual Text:\n"); + /* TODO: these should really be just [] lookups, but String doesn't have those here yet. */ + for( int i = 0; i < anEntry->_appended_text.size(); i++) { + CPPUNIT_ASSERT( expect.buf()[i] ); + CPPUNIT_ASSERT( anEntry->_appended_text.buf()[i] ); + + /* slight hack to make special chars visible */ + switch(anEntry->_appended_text.buf()[i]) + { + case '\t': + printf("\\t"); break; + default: + printf("%c", anEntry->_appended_text.buf()[i] ); + } + /* make this an int comparison, so that we can see the ASCII code at failure */ + CPPUNIT_ASSERT_EQUAL( (int)expect.buf()[i], (int)anEntry->_appended_text.buf()[i] ); + } + printf("\n"); + CPPUNIT_ASSERT_EQUAL( expect, anEntry->_appended_text); + + /* cleanup */ delete anEntry; } diff --git a/src/tests/testHttpRequest.cc b/src/tests/testHttpRequest.cc index d0840cca6a..d0864a0e8b 100644 --- a/src/tests/testHttpRequest.cc +++ b/src/tests/testHttpRequest.cc @@ -37,33 +37,36 @@ testHttpRequest::testCreateFromUrlAndMethod() HttpRequest *nullRequest = NULL; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); CPPUNIT_ASSERT_EQUAL(METHOD_GET, aRequest->method); - CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->host)); + CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); xfree(url); + /* vanilla url, different method */ url = xstrdup("http://foo/bar"); aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_PUT); expected_port = 80; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); CPPUNIT_ASSERT_EQUAL(METHOD_PUT, aRequest->method); - CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->host)); + CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url)); + /* a connect url with non-CONNECT data */ url = xstrdup(":foo/bar"); aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_CONNECT); xfree(url); CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest); + /* a CONNECT url with CONNECT data */ url = xstrdup("foo:45"); aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_CONNECT); expected_port = 45; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); CPPUNIT_ASSERT_EQUAL(METHOD_CONNECT, aRequest->method); - CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->host)); + CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String(""), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(PROTO_NONE, aRequest->protocol); CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url)); @@ -83,9 +86,62 @@ testHttpRequest::testCreateFromUrl() expected_port = 90; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); CPPUNIT_ASSERT_EQUAL(METHOD_GET, aRequest->method); - CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->host)); + CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); xfree(url); } + +/* + * Test BUG: URL '2000:800:45' opens host 2000 port 800 !! + */ +void +testHttpRequest::testIPv6HostColonBug() +{ + ushort expected_port; + char * url = NULL; + HttpRequest *aRequest = NULL; + + /* valid IPv6 address without port */ + url = xstrdup("http://[2000:800::45]/foo"); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + expected_port = 80; + CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); + CPPUNIT_ASSERT_EQUAL(METHOD_GET, aRequest->method); + CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); + CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); + CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); + CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url)); + xfree(url); + + /* valid IPv6 address with port */ + url = xstrdup("http://[2000:800::45]:90/foo"); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + expected_port = 90; + CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); + CPPUNIT_ASSERT_EQUAL(METHOD_GET, aRequest->method); + CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); + CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); + CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); + CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url)); + xfree(url); + + /* IPv6 address as invalid (bug trigger) */ + url = xstrdup("http://2000:800::45/foo"); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + expected_port = 80; + CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); + CPPUNIT_ASSERT_EQUAL(METHOD_GET, aRequest->method); +#if USE_IPV6 + /* We hasve fixed this in IPv6 build. */ + CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); +#else + /* NO fix is possible in IPv4-pure build. */ + CPPUNIT_ASSERT_EQUAL(String("2000:800::45"), String(aRequest->GetHost())); +#endif + CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); + CPPUNIT_ASSERT_EQUAL(PROTO_HTTP, aRequest->protocol); + CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url)); + xfree(url); +} diff --git a/src/tests/testHttpRequest.h b/src/tests/testHttpRequest.h index e81c73a7d8..9e0735f34f 100644 --- a/src/tests/testHttpRequest.h +++ b/src/tests/testHttpRequest.h @@ -13,6 +13,7 @@ class testHttpRequest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST_SUITE( testHttpRequest ); CPPUNIT_TEST( testCreateFromUrlAndMethod ); CPPUNIT_TEST( testCreateFromUrl ); + CPPUNIT_TEST( testIPv6HostColonBug ); CPPUNIT_TEST_SUITE_END(); public: @@ -21,6 +22,7 @@ public: protected: void testCreateFromUrlAndMethod(); void testCreateFromUrl(); + void testIPv6HostColonBug(); }; #endif diff --git a/src/tests/testICMP.cc b/src/tests/testICMP.cc new file mode 100644 index 0000000000..5d223c637d --- /dev/null +++ b/src/tests/testICMP.cc @@ -0,0 +1,84 @@ + +#define SQUID_HELPER 1 +#include "squid.h" + +#include + +#include "testICMP.h" + +CPPUNIT_TEST_SUITE_REGISTRATION( testICMP ); + +#if USE_ICMP + +void +testICMP::testChecksum() +{ + stubICMP icmp; + short unsigned int buf[10] = {1,2,3,4,5,6,7,8,9}; + + // NULL data + CPPUNIT_ASSERT_EQUAL(65535, icmp.testChecksum(NULL,0)); + + // NULL data with length!! + CPPUNIT_ASSERT_EQUAL(65535, icmp.testChecksum(NULL,1)); + + // data with 0 length + CPPUNIT_ASSERT_EQUAL(65535, icmp.testChecksum(buf,0)); + + // data with invalid length (low) + CPPUNIT_ASSERT_EQUAL(65534, icmp.testChecksum(buf,1)); + + // data with invalid length (max-low) + CPPUNIT_ASSERT_EQUAL(65520, icmp.testChecksum(buf,9)); + + // data with accurate length + CPPUNIT_ASSERT_EQUAL(65520, icmp.testChecksum(buf,10)); + + // data with invalid length (overrun) + CPPUNIT_ASSERT_EQUAL(65514, icmp.testChecksum(buf,11)); +} + +void +testICMP::testHops() +{ + stubICMP icmp; + + /* test invalid -(under values) */ + // negative : n > 33 + CPPUNIT_ASSERT_EQUAL(34, icmp.testHops(-1)); + // zero + CPPUNIT_ASSERT_EQUAL(33, icmp.testHops(0)); + + /* test each valid case boundary */ + // n(1...32) : 32 >= n >= 1 + CPPUNIT_ASSERT_EQUAL(32, icmp.testHops(1)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(32)); + + // n(33...62) : 30 >= n >= 1 + CPPUNIT_ASSERT_EQUAL(30, icmp.testHops(33)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(62)); + + // n(63...64) : 2 >= n >= 1 + CPPUNIT_ASSERT_EQUAL(2, icmp.testHops(63)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(64)); + + // n(65...128) : 64 >= n >= 1 + CPPUNIT_ASSERT_EQUAL(64, icmp.testHops(65)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(128)); + + // n(129...192) : 64 >= n >= 1 + CPPUNIT_ASSERT_EQUAL(64, icmp.testHops(129)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(192)); + + // n(193...) : n < 63 + CPPUNIT_ASSERT_EQUAL(63, icmp.testHops(193)); + CPPUNIT_ASSERT_EQUAL(1, icmp.testHops(255)); + + /* test invalid (over values) */ + // 256 - produces zero + CPPUNIT_ASSERT_EQUAL(0, icmp.testHops(256)); + // 257 - produces negative hops + CPPUNIT_ASSERT_EQUAL(-1, icmp.testHops(257)); +} + +#endif /* USE_ICMP */ diff --git a/src/tests/testICMP.h b/src/tests/testICMP.h new file mode 100644 index 0000000000..da50d6722c --- /dev/null +++ b/src/tests/testICMP.h @@ -0,0 +1,50 @@ +#ifndef SQUID_SRC_TEST_URL_H +#define SQUID_SRC_TEST_URL_H + +#include + +#include "ICMP.h" + +#if USE_ICMP + +class stubICMP : public ICMP +{ +public: + stubICMP() {}; + virtual ~stubICMP() {}; + virtual int Open() { return 0; }; + virtual void Close() {}; + + /// Construct ECHO request + virtual void SendEcho(IPAddress &to, int opcode, const char *payload, int len) {}; + + /// Handle ICMP responses. + virtual void Recv(void) {}; + +/* methods to relay test data from tester to private methods being tested */ + int testChecksum(unsigned short *ptr, int size) { return CheckSum(ptr,size); }; + int testHops(int ttl) { return ipHops(ttl); }; +}; + +#endif /* USE_ICMP */ + +/** + * test the ICMP base class. + */ +class testICMP : public CPPUNIT_NS::TestFixture +{ + CPPUNIT_TEST_SUITE( testICMP ); +#if USE_ICMP + CPPUNIT_TEST( testChecksum ); + CPPUNIT_TEST( testHops ); +#endif /* USE_ICMP */ + CPPUNIT_TEST_SUITE_END(); + +protected: +#if USE_ICMP + void testChecksum(); + void testHops(); +#endif /* USE_ICMP */ +}; + +#endif diff --git a/src/time.cc b/src/time.cc index 75101b5de0..2b15c5872a 100644 --- a/src/time.cc +++ b/src/time.cc @@ -1,6 +1,5 @@ - /* - * $Id: time.cc,v 1.3 2006/08/12 01:43:11 robertc Exp $ + * $Id: time.cc,v 1.4 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 21 Time Functions * AUTHOR: Harvest Derived @@ -35,6 +34,9 @@ #include "SquidTime.h" +struct timeval current_time; +double current_dtime; + time_t squid_curtime = 0; time_t diff --git a/src/tools.cc b/src/tools.cc index 9f890a52c9..d2eb3260b3 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -1,6 +1,6 @@ /* - * $Id: tools.cc,v 1.279 2007/09/23 09:18:10 serassio Exp $ + * $Id: tools.cc,v 1.280 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -595,10 +595,8 @@ getMyHostname(void) { LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1); static int present = 0; - - const struct hostent *h = NULL; - - struct IN_ADDR sa; + struct addrinfo *AI = NULL; + IPAddress sa; if (Config.visibleHostname != NULL) return Config.visibleHostname; @@ -608,59 +606,72 @@ getMyHostname(void) host[0] = '\0'; - memcpy(&sa, &any_addr, sizeof(sa)); - - if (Config.Sockaddr.http && sa.s_addr == any_addr.s_addr) - memcpy(&sa, &Config.Sockaddr.http->s.sin_addr, sizeof(sa)); + if (Config.Sockaddr.http && sa.IsAnyAddr()) + sa = Config.Sockaddr.http->s; #if USE_SSL - if (Config.Sockaddr.https && sa.s_addr == any_addr.s_addr) - memcpy(&sa, &Config.Sockaddr.https->http.s.sin_addr, sizeof(sa)); + if (Config.Sockaddr.https && sa.IsAnyAddr()) + sa = Config.Sockaddr.https->http.s; #endif + /* * If the first http_port address has a specific address, try a * reverse DNS lookup on it. */ - if (sa.s_addr != any_addr.s_addr) { - h = gethostbyaddr((char *) &sa, - sizeof(sa), AF_INET); + if( !sa.IsAnyAddr() ) { - if (h != NULL) { + sa.GetAddrInfo(AI); + /* we are looking for a name. */ + if(xgetnameinfo(AI->ai_addr, AI->ai_addrlen, host, SQUIDHOSTNAMELEN, NULL, 0, NI_NAMEREQD ) == 0) { /* DNS lookup successful */ /* use the official name from DNS lookup */ - xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN); - debugs(50, 4, "getMyHostname: resolved " << inet_ntoa(sa) << " to '" << host << "'"); + debugs(50, 4, "getMyHostname: resolved " << sa << " to '" << host << "'"); present = 1; + sa.FreeAddrInfo(AI); + if (strchr(host, '.')) return host; - } - debugs(50, 1, "WARNING: failed to resolve " << inet_ntoa(sa) << " to a fully qualified hostname"); + sa.FreeAddrInfo(AI); + debugs(50, 1, "WARNING: failed to resolve " << sa << " to a fully qualified hostname"); } + else { + if (gethostname(host, SQUIDHOSTNAMELEN) < 0) { + debugs(50, 1, "WARNING: gethostname failed: " << xstrerror()); + } + else { + /* Verify that the hostname given resolves properly */ + struct addrinfo hints; + memset(&hints, 0, sizeof(addrinfo)); + hints.ai_flags = AI_CANONNAME; + + if(xgetaddrinfo(host, NULL, NULL, &AI) == 0) { + /* DNS lookup successful */ + /* use the official name from DNS lookup */ + debugs(50, 6, "getMyHostname: '" << host << "' resolved into '" << AI->ai_canonname << "'"); + xstrncpy(host, AI->ai_canonname, SQUIDHOSTNAMELEN); + present = 1; + + /* AYJ: do we want to flag AI_ALL and cache the result anywhere. ie as our local host IPs? */ + if(AI) { + xfreeaddrinfo(AI); + AI = NULL; + } - /* - * Get the host name and store it in host to return - */ - if (gethostname(host, SQUIDHOSTNAMELEN) < 0) { - debugs(50, 1, "WARNING: gethostname failed: " << xstrerror()); - } else if ((h = gethostbyname(host)) == NULL) { - debugs(50, 1, "WARNING: gethostbyname failed for " << host); - } else { - debugs(50, 6, "getMyHostname: '" << host << "' resolved into '" << h->h_name << "'"); - /* DNS lookup successful */ - /* use the official name from DNS lookup */ - xstrncpy(host, h->h_name, SQUIDHOSTNAMELEN); - present = 1; - - if (strchr(host, '.')) - return host; + return host; + } + + if(AI) xfreeaddrinfo(AI); + debugs(50, 1, "WARNING: getaddrinfo('" << host << "') failed: " << xstrerror()); + } } + /* throw a fatal configuration error when the Host/IP given has bad DNS/rDNS. */ if (opt_send_signal == -1) fatal("Could not determine fully qualified hostname. Please set 'visible_hostname'\n"); else @@ -1019,16 +1030,6 @@ squid_signal(int sig, SIGHDLR * func, int flags) #endif } -struct IN_ADDR - - inaddrFromHostent(const struct hostent *hp) -{ - - struct IN_ADDR s; - xmemcpy(&s.s_addr, hp->h_addr, sizeof(s.s_addr)); - return s; -} - double doubleAverage(double cur, double newD, int N, int max) { @@ -1258,12 +1259,12 @@ int getMyPort(void) { if (Config.Sockaddr.http) - return ntohs(Config.Sockaddr.http->s.sin_port); + return Config.Sockaddr.http->s.GetPort(); #if USE_SSL if (Config.Sockaddr.https) - return ntohs(Config.Sockaddr.https->http.s.sin_port); + return Config.Sockaddr.https->http.s.GetPort(); #endif @@ -1400,3 +1401,13 @@ nocap: #endif } + +void * +xmemset(void *dst, int val, size_t sz) +{ + // do debugs output + debugs(63, 9, "memset: dst=" << dst << ", val=" << val << ", bytes=" << sz); + + // call the system one to do the actual work ~safely. + return memset(dst, val, sz); +} diff --git a/src/tunnel.cc b/src/tunnel.cc index da4fdcb6d8..ed3a1a7582 100644 --- a/src/tunnel.cc +++ b/src/tunnel.cc @@ -1,6 +1,6 @@ /* - * $Id: tunnel.cc,v 1.175 2007/10/16 14:38:18 rousskov Exp $ + * $Id: tunnel.cc,v 1.176 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 26 Secure Sockets Layer Proxy * AUTHOR: Duane Wessels @@ -604,19 +604,18 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr) HttpRequest *request = http->request; char *url = http->uri; /* - * client_addr == no_addr indicates this is an "internal" request + * client_addr.IsNoAddr() indicates this is an "internal" request * from peer_digest.c, asn.c, netdb.c, etc and should always * be allowed. yuck, I know. */ - if (request->client_addr.s_addr != no_addr.s_addr) { + if (!request->client_addr.IsNoAddr()) { /* * Check if this host is allowed to fetch MISSES from us (miss_access) */ ACLChecklist ch; ch.src_addr = request->client_addr; ch.my_addr = request->my_addr; - ch.my_port = request->my_port; ch.request = HTTPMSGLOCK(request); ch.accessList = cbdataReference(Config.accessList.miss); /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */ @@ -634,10 +633,10 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr) statCounter.server.all.requests++; statCounter.server.other.requests++; /* Create socket. */ + IPAddress temp = getOutgoingAddr(request); sock = comm_openex(SOCK_STREAM, IPPROTO_TCP, - getOutgoingAddr(request), - 0, + temp, COMM_NONBLOCKING, getOutgoingTOS(request), url); @@ -734,7 +733,7 @@ tunnelPeerSelectComplete(FwdServer * fs, void *data) } tunnelState->servers = fs; - tunnelState->host = fs->_peer ? fs->_peer->host : request->host; + tunnelState->host = fs->_peer ? fs->_peer->host : xstrdup(request->GetHost()); if (fs->_peer == NULL) { tunnelState->port = request->port; diff --git a/src/typedefs.h b/src/typedefs.h index 2246ba0ba6..82c11b6356 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -1,6 +1,6 @@ /* - * $Id: typedefs.h,v 1.190 2007/05/09 07:45:58 wessels Exp $ + * $Id: typedefs.h,v 1.191 2007/12/14 23:11:48 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -84,8 +84,6 @@ typedef struct _ushortlist ushortlist; typedef struct _relist relist; -typedef struct _sockaddr_in_list sockaddr_in_list; - typedef struct _http_port_list http_port_list; typedef struct _https_port_list https_port_list; @@ -148,10 +146,6 @@ typedef struct _net_db_peer net_db_peer; typedef struct _netdbEntry netdbEntry; -typedef struct _pingerEchoData pingerEchoData; - -typedef struct _pingerReplyData pingerReplyData; - typedef struct _icp_common_t icp_common_t; typedef struct _Meta_data Meta_data; diff --git a/src/unlinkd.cc b/src/unlinkd.cc index 3f8f5e18a0..61e26baaf4 100644 --- a/src/unlinkd.cc +++ b/src/unlinkd.cc @@ -1,6 +1,6 @@ /* - * $Id: unlinkd.cc,v 1.64 2007/04/30 16:56:09 wessels Exp $ + * $Id: unlinkd.cc,v 1.65 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 2 Unlink Daemon * AUTHOR: Duane Wessels @@ -194,9 +194,12 @@ void unlinkdInit(void) { const char *args[2]; + IPAddress localhost; args[0] = "(unlinkd)"; args[1] = NULL; + localhost.SetLocalhost(); + pid = ipcCreate( #if USE_POLL && defined(_SQUID_OSF_) /* pipes and poll() don't get along on DUNIX -DW */ @@ -211,6 +214,7 @@ IPC_FIFO, Config.Program.unlinkd, args, "unlinkd", + localhost, &unlinkd_rfd, &unlinkd_wfd, &hIpc); diff --git a/src/url.cc b/src/url.cc index af21d6dd3d..c747eeed8b 100644 --- a/src/url.cc +++ b/src/url.cc @@ -1,6 +1,6 @@ /* - * $Id: url.cc,v 1.162 2007/05/29 13:31:41 amosjeffries Exp $ + * $Id: url.cc,v 1.163 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 23 URL Parsing * AUTHOR: Duane Wessels @@ -42,11 +42,17 @@ static const char valid_hostname_chars_u[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789-._" +#if USE_IPV6 + "[:]" +#endif ; static const char valid_hostname_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789-." +#if USE_IPV6 + "[:]" +#endif ; void @@ -81,7 +87,7 @@ urlInitialize(void) /* more cases? */ } -/* +/** * urlParseProtocol() takes begin (b) and end (e) pointers, but for * backwards compatibility, e defaults to NULL, in which case we * assume b is NULL-terminated. @@ -181,6 +187,14 @@ urlDefaultPort(protocol_t p) * looked for. * The url is non const so that if its too long we can NULL-terminate it in place. */ + +/* + * This routine parses a URL. Its assumed that the URL is complete - + * ie, the end of the string is the end of the URL. Don't pass a partial + * URL here as this routine doesn't have any way of knowing whether + * its partial or not (ie, it handles the case of no trailing slash as + * being "end of host with implied path of /". + */ HttpRequest * urlParse(method_t method, char *url, HttpRequest *request) { @@ -193,6 +207,9 @@ urlParse(method_t method, char *url, HttpRequest *request) int port; protocol_t protocol = PROTO_NONE; int l; + int i; + const char *src; + char *dst; proto[0] = host[0] = urlpath[0] = login[0] = '\0'; if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) { @@ -201,23 +218,67 @@ urlParse(method_t method, char *url, HttpRequest *request) debugs(23, 1, "urlParse: URL too large (" << l << " bytes)"); return NULL; } - if (method == METHOD_CONNECT) { port = CONNECT_PORT; - if (sscanf(url, "%[^:]:%d", host, &port) < 1) - return NULL; + if (sscanf(url, "[%[^:]]:%d", host, &port) < 1) + if (sscanf(url, "%[^:]:%d", host, &port) < 1) + return NULL; + } else if (!strncmp(url, "urn:", 4)) { return urnParse(method, url); } else { - if (sscanf(url, "%[^:]://%[^/]%[^\r\n]", proto, host, urlpath) < 2) + /* Parse the URL: */ + src = url; + i = 0; + /* Find first : - everything before is protocol */ + for (i = 0, dst = proto; i < l && *src != ':'; i++, src++, dst++) { + *dst = *src; + } + if (i >= l) + return NULL; + *dst = '\0'; + + /* Then its :// */ + /* (XXX yah, I'm not checking we've got enough data left before checking the array..) */ + if (*src != ':' || *(src + 1) != '/' || *(src + 2) != '/') return NULL; + i += 3; + src += 3; - protocol = urlParseProtocol(proto); + /* Then everything until first /; thats host (and port; which we'll look for here later) */ + /* bug 1881: If we don't get a "/" then we imply it was there */ + for (dst = host; i < l && *src != '/' && src != '\0'; i++, src++, dst++) { + *dst = *src; + } + + /* + * We can't check for "i >= l" here because we could be at the end of the line + * and have a perfectly valid URL w/ no trailing '/'. In this case we assume we've + * been -given- a valid URL and the path is just '/'. + */ + if (i > l) + return NULL; + *dst = '\0'; + + /* Then everything from / (inclusive) until \r\n or \0 - thats urlpath */ + for (dst = urlpath; i < l && *src != '\r' && *src != '\n' && *src != '\0'; i++, src++, dst++) { + *dst = *src; + } + /* We -could- be at the end of the buffer here */ + if (i > l) + return NULL; + /* If the URL path is empty we set it to be "/" */ + if (dst == urlpath) { + *(dst++) = '/'; + } + *dst = '\0'; + + protocol = urlParseProtocol(proto); port = urlDefaultPort(protocol); - /* Is there any login informaiton? */ + /* Is there any login information? (we should eventually parse it above) */ if ((t = strrchr(host, '@'))) { strcpy((char *) login, (char *) host); t = strrchr(login, '@'); @@ -225,11 +286,43 @@ urlParse(method_t method, char *url, HttpRequest *request) strcpy((char *) host, t + 1); } - if ((t = strrchr(host, ':'))) { - *t++ = '\0'; + /* Is there any host information? (we should eventually parse it above) */ + if(*host == '[') { + /* strip any IPA brackets. valid under IPv6. */ + dst = host; +#if USE_IPV6 + /* only for IPv6 sadly, pre-IPv6/URL code can't handle the clean result properly anyway. */ + src = host; src++; + l = strlen(host); + i = 1; + for (; i < l && *src != ']' && *src != '\0'; i++, src++, dst++) { + *dst = *src; + } + + /* we moved in-place, so truncate the actual hostname found */ + *(dst++) = '\0'; +#else + /* IPv4-pure needs to skip the whole hostname to ']' inclusive for now */ + while(*dst != '\0' && *dst != ']') dst++; +#endif + + /* skip ahead to either start of port, or original EOS */ + while(*dst != '\0' && *dst != ':') dst++; + t = dst; + } else { + t = strrchr(host, ':'); + + if(t != strchr(host,':') ) { + /* RFC 2732 states IPv6 "SHOULD" be bracketed. allowing for times when its not. */ + /* RFC 3986 'update' simply modifies this to an "is" with no emphasis at all! */ + /* therefore we MUST accept the case where they are not bracketed at all. */ + t = NULL; + } + } - if (*t != '\0') - port = atoi(t); + if (t && *t == ':') { + *t = '\0'; t++; + port = atoi(t); } } @@ -239,36 +332,34 @@ urlParse(method_t method, char *url, HttpRequest *request) if (stringHasWhitespace(host)) { if (URI_WHITESPACE_STRIP == Config.uri_whitespace) { t = q = host; - while (*t) { if (!xisspace(*t)) *q++ = *t; - t++; } - *q = '\0'; } } + debugs(23, 3, "urlParse: Split URL '" << url << "' into proto='" << proto << "', host='" << host << "', port='" << port << "', path='" << urlpath << "'"); + if (Config.onoff.check_hostnames && strspn(host, Config.onoff.allow_underscore ? valid_hostname_chars_u : valid_hostname_chars) != strlen(host)) { debugs(23, 1, "urlParse: Illegal character in hostname '" << host << "'"); return NULL; } -#if DONT_DO_THIS_IT_BREAKS_SEMANTIC_TRANSPARENCY + if (Config.appendDomain && !strchr(host, '.')) + strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(host) - 1); + /* remove trailing dots from hostnames */ while ((l = strlen(host)) > 0 && host[--l] == '.') host[l] = '\0'; - /* remove duplicate dots */ - while ((t = strstr(host, ".."))) - xmemmove(t, t + 1, strlen(t)); - -#endif - - if (Config.appendDomain && !strchr(host, '.')) - strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(host) - 1); + /* reject duplicate or leading dots */ + if (strstr(host, "..") || *host == '.') { + debug(23, 1) ("urlParse: Illegal hostname '%s'\n", host); + return NULL; + } if (port < 1 || port > 65535) { debugs(23, 3, "urlParse: Invalid port '" << port << "'"); @@ -282,8 +373,8 @@ urlParse(method_t method, char *url, HttpRequest *request) debugs(23, 0, "urlParse: Deny access to port " << port); return NULL; } - #endif + if (stringHasWhitespace(urlpath)) { debugs(23, 2, "urlParse: URI has whitespace: {" << url << "}"); @@ -305,17 +396,13 @@ urlParse(method_t method, char *url, HttpRequest *request) break; case URI_WHITESPACE_STRIP: - default: t = q = urlpath; - while (*t) { if (!xisspace(*t)) *q++ = *t; - t++; } - *q = '\0'; } } @@ -326,7 +413,7 @@ urlParse(method_t method, char *url, HttpRequest *request) request->initHTTP(method, protocol, urlpath); } - xstrncpy(request->host, host, SQUIDHOSTNAMELEN); + request->SetHost(host); xstrncpy(request->login, login, MAX_LOGIN_SZ); request->port = (u_short) port; return request; @@ -354,7 +441,7 @@ urlCanonical(HttpRequest * request) switch (request->method) { case METHOD_CONNECT: - snprintf(urlbuf, MAX_URL, "%s:%d", request->host, request->port); + snprintf(urlbuf, MAX_URL, "%s:%d", request->GetHost(), request->port); break; default: @@ -367,7 +454,7 @@ urlCanonical(HttpRequest * request) ProtocolStr[request->protocol], request->login, *request->login ? "@" : null_string, - request->host, + request->GetHost(), portbuf, request->urlpath.buf()); @@ -392,7 +479,9 @@ urlCanonicalClean(const HttpRequest * request) switch (request->method) { case METHOD_CONNECT: - snprintf(buf, MAX_URL, "%s:%d", request->host, request->port); + snprintf(buf, MAX_URL, "%s:%d", + request->GetHost(), + request->port); break; default: @@ -415,7 +504,7 @@ urlCanonicalClean(const HttpRequest * request) snprintf(buf, MAX_URL, "%s://%s%s%s%s", ProtocolStr[request->protocol], loginbuf, - request->host, + request->GetHost(), portbuf, request->urlpath.buf()); /* @@ -660,6 +749,12 @@ URLHostName::findHostStart() while (*hostStart != '\0' && *hostStart == '/') ++hostStart; + +#if USE_IPV6 + if (*hostStart == ']') + ++hostStart; +#endif + } void @@ -670,8 +765,14 @@ URLHostName::trimTrailingChars() if ((t = strchr(Host, '/'))) *t = '\0'; - if ((t = strchr(Host, ':'))) + if ((t = strrchr(Host, ':'))) *t = '\0'; + +#if USE_IPV6 + if ((t = strchr(Host, ']'))) + *t = '\0'; +#endif + } void diff --git a/src/urn.cc b/src/urn.cc index d1d9c34923..d8db3baf49 100644 --- a/src/urn.cc +++ b/src/urn.cc @@ -1,6 +1,6 @@ /* - * $Id: urn.cc,v 1.107 2007/05/29 13:31:41 amosjeffries Exp $ + * $Id: urn.cc,v 1.108 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 52 URN Parsing * AUTHOR: Kostas Anagnostakis @@ -179,6 +179,9 @@ UrnState::getHost (String &urlpath) char * result; char const *t; +/* FIXME: this appears to be parsing the URL. *very* badly. */ +/* FIXME: a proper encapsulated URI/URL type needs to clear this up. */ + if ((t = urlpath.pos(':')) != NULL) { urlpath.set(t, '\0'); result = xstrdup(urlpath.buf()); diff --git a/src/wccp.cc b/src/wccp.cc index 4c87569412..c99e9f7440 100644 --- a/src/wccp.cc +++ b/src/wccp.cc @@ -1,6 +1,6 @@ /* - * $Id: wccp.cc,v 1.44 2007/08/08 14:47:41 rousskov Exp $ + * $Id: wccp.cc,v 1.45 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 80 WCCP Support * AUTHOR: Glenn Chisholm @@ -61,8 +61,7 @@ struct wccp_here_i_am_t struct wccp_cache_entry_t { - - struct IN_ADDR ip_addr; + IPAddress ip_addr; int revision; char hash[WCCP_HASH_SIZE]; int reserved; @@ -96,7 +95,7 @@ static int last_id; static int last_assign_buckets_change; static unsigned int number_caches; -static struct IN_ADDR local_ip; +static IPAddress local_ip; static PF wccpHandleUdp; static int wccpLowestIP(void); @@ -124,7 +123,7 @@ wccpInit(void) last_assign_buckets_change = 0; number_caches = 0; - if (Config.Wccp.router.s_addr != any_addr.s_addr) + if (!Config.Wccp.router.IsAnyAddr()) if (!eventFind(wccpHereIam, NULL)) eventAdd("wccpHereIam", wccpHereIam, NULL, 5.0, 1); } @@ -132,21 +131,29 @@ wccpInit(void) void wccpConnectionOpen(void) { - u_short port = WCCP_PORT; - - struct sockaddr_in router, local; - socklen_t local_len, router_len; + struct addrinfo *router = NULL, *local = NULL; debugs(80, 5, "wccpConnectionOpen: Called"); - if (Config.Wccp.router.s_addr == any_addr.s_addr) { + if (Config.Wccp.router.IsAnyAddr()) { debugs(80, 2, "WCCPv1 disabled."); return; } + if ( !Config.Wccp.router.SetIPv4() ) { + debugs(1, 1, "WCCPv1 Disabled. Router " << Config.Wccp.router << " is not IPv4."); + return; + } + + if ( !Config.Wccp.address.SetIPv4() ) { + debugs(1, 1, "WCCPv1 Disabled. Local address " << Config.Wccp.address << " is not IPv4."); + return; + } + + Config.Wccp.address.SetPort(WCCP_PORT); + theWccpConnection = comm_open(SOCK_DGRAM, IPPROTO_UDP, Config.Wccp.address, - port, COMM_NONBLOCKING, "WCCP Socket"); @@ -159,30 +166,23 @@ wccpConnectionOpen(void) NULL, 0); - debugs(80, 1, "Accepting WCCPv1 messages on port " << port << ", FD " << theWccpConnection << "."); - - - router_len = sizeof(router); - - memset(&router, '\0', router_len); + debugs(80, 1, "Accepting WCCPv1 messages on " << Config.Wccp.address << ", FD " << theWccpConnection << "."); - router.sin_family = AF_INET; + Config.Wccp.router.GetAddrInfo(router,AF_INET); - router.sin_port = htons(port); - - router.sin_addr = Config.Wccp.router; - - if (connect(theWccpConnection, (struct sockaddr *) &router, router_len)) + if (connect(theWccpConnection, router->ai_addr, router->ai_addrlen)) fatal("Unable to connect WCCP out socket"); - local_len = sizeof(local); + Config.Wccp.router.FreeAddrInfo(router); - memset(&local, '\0', local_len); + Config.Wccp.address.InitAddrInfo(local); - if (getsockname(theWccpConnection, (struct sockaddr *) &local, &local_len)) + if (getsockname(theWccpConnection, local->ai_addr, &local->ai_addrlen)) fatal("Unable to getsockname on WCCP out socket"); - local_ip.s_addr = local.sin_addr.s_addr; + local_ip = *local; + + Config.Wccp.address.FreeAddrInfo(local); } @@ -207,27 +207,22 @@ static void wccpHandleUdp(int sock, void *not_used) { - struct sockaddr_in from; - socklen_t from_len; + IPAddress from; int len; debugs(80, 6, "wccpHandleUdp: Called."); commSetSelect(sock, COMM_SELECT_READ, wccpHandleUdp, NULL, 0); - from_len = sizeof(struct sockaddr_in); - memset(&from, '\0', from_len); memset(&wccp_i_see_you, '\0', sizeof(wccp_i_see_you)); len = comm_udp_recvfrom(sock, (void *) &wccp_i_see_you, sizeof(wccp_i_see_you), 0, - - (struct sockaddr *) &from, - &from_len); - debugs(80, 3, "wccpHandleUdp: " << len << " bytes WCCP pkt from " << - inet_ntoa(from.sin_addr) << ": type=" << + from); + debugs(80, 3, "wccpHandleUdp: " << len << " bytes WCCP pkt from " << from << + ": type=" << (unsigned) ntohl(wccp_i_see_you.type) << ", version=" << (unsigned) ntohl(wccp_i_see_you.version) << ", change=" << (unsigned) ntohl(wccp_i_see_you.change) << ", id=" << @@ -237,7 +232,7 @@ wccpHandleUdp(int sock, void *not_used) if (len < 0) return; - if (Config.Wccp.router.s_addr != from.sin_addr.s_addr) + if (from != Config.Wccp.router) return; if ((unsigned) ntohl(wccp_i_see_you.version) != (unsigned) Config.Wccp.version) @@ -248,7 +243,7 @@ wccpHandleUdp(int sock, void *not_used) if (ntohl(wccp_i_see_you.number) > WCCP_ACTIVE_CACHES) { debugs(80, 1, "Ignoring WCCP_I_SEE_YOU from " << - inet_ntoa(from.sin_addr) << " with number of caches set to " << + from << " with number of caches set to " << (int) ntohl(wccp_i_see_you.number)); return; @@ -296,10 +291,10 @@ wccpLowestIP(void) for (loop = 0; loop < (unsigned) ntohl(wccp_i_see_you.number); loop++) { assert(loop < WCCP_ACTIVE_CACHES); - if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr < local_ip.s_addr) + if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr < local_ip) return 0; - if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr == local_ip.s_addr) + if (wccp_i_see_you.wccp_cache_entry[loop].ip_addr == local_ip) found = 1; } @@ -364,7 +359,7 @@ wccpAssignBuckets(void) for (loop = 0; loop < number_caches; loop++) { int i; xmemcpy(&caches[loop], - &wccp_i_see_you.wccp_cache_entry[loop].ip_addr.s_addr, + &wccp_i_see_you.wccp_cache_entry[loop].ip_addr, sizeof(*caches)); for (i = 0; i < buckets_per_cache; i++) { diff --git a/src/wccp2.cc b/src/wccp2.cc index 98e214195b..f579d910ad 100644 --- a/src/wccp2.cc +++ b/src/wccp2.cc @@ -1,6 +1,6 @@ /* - * $Id: wccp2.cc,v 1.19 2007/11/15 16:47:35 wessels Exp $ + * $Id: wccp2.cc,v 1.20 2007/12/14 23:11:48 amosjeffries Exp $ * * DEBUG: section 80 WCCP Support * AUTHOR: Steven Wilton @@ -39,6 +39,7 @@ #include "Parsing.h" #include "Store.h" #include "SwapDir.h" +#include "IPAddress.h" #if USE_WCCPv2 #include @@ -127,6 +128,7 @@ static EVH wccp2AssignBuckets; /* WCCP v2 packet header */ +/// \interface WCCPv2 Protocol struct wccp2_here_i_am_header_t { uint32_t type; @@ -145,6 +147,7 @@ struct wccp2_security_none_t uint32_t security_option; }; +/// \interface WCCPv2 Protocol struct wccp2_security_md5_t { uint16_t security_type; @@ -155,6 +158,7 @@ struct wccp2_security_md5_t /* Service info struct */ +/// \interface WCCPv2 Protocol struct wccp2_service_info_t { uint16_t service_type; @@ -174,10 +178,10 @@ struct wccp2_service_info_t uint16_t port7; }; +/// \interface WCCPv2 Protocol struct wccp2_cache_identity_info_t { - - struct IN_ADDR addr; + struct in_addr addr; uint16_t hash_revision; char bits[2]; char buckets[32]; @@ -187,6 +191,7 @@ struct wccp2_cache_identity_info_t /* Web Cache identity info */ +/// \interface WCCPv2 Protocol struct wccp2_identity_info_t { uint16_t cache_identity_type; @@ -197,10 +202,10 @@ struct wccp2_identity_info_t static struct wccp2_identity_info_t wccp2_identity_info; +/// \interface WCCPv2 Protocol struct wccp2_cache_mask_identity_info_t { - - struct IN_ADDR addr; + struct in_addr addr; uint32_t num1; uint32_t num2; uint32_t source_ip_mask; @@ -213,6 +218,7 @@ struct wccp2_cache_mask_identity_info_t /* Web Cache identity info */ +/// \interface WCCPv2 Protocol struct wccp2_mask_identity_info_t { uint16_t cache_identity_type; @@ -225,6 +231,7 @@ static struct wccp2_mask_identity_info_t wccp2_mask_identity_info; /* View header */ +/// \interface WCCPv2 Protocol struct wccp2_cache_view_header_t { uint16_t cache_view_type; @@ -236,6 +243,7 @@ static struct wccp2_cache_view_header_t wccp2_cache_view_header; /* View info */ +/// \interface WCCPv2 Protocol struct wccp2_cache_view_info_t { uint32_t num_routers; @@ -246,10 +254,10 @@ static struct wccp2_cache_view_info_t wccp2_cache_view_info; /* Router ID element */ +/// \interface WCCPv2 Protocol struct wccp2_router_id_element_t { - - struct IN_ADDR router_address; + struct in_addr router_address; uint32_t received_id; }; @@ -257,6 +265,7 @@ static struct wccp2_router_id_element_t wccp2_router_id_element; /* Capability info header */ +/// \interface WCCpv2 Protocol struct wccp2_capability_info_header_t { uint16_t capability_info_type; @@ -267,6 +276,7 @@ static struct wccp2_capability_info_header_t wccp2_capability_info_header; /* Capability element header */ +/// \interface WCCPv2 Protocol struct wccp2_capability_element_header_t { uint16_t capability_type; @@ -275,6 +285,7 @@ struct wccp2_capability_element_header_t /* Capability element */ +/// \interface WCCPv2 Protocol struct wccp2_capability_element_t { uint16_t capability_type; @@ -286,6 +297,7 @@ static struct wccp2_capability_element_t wccp2_capability_element; /* Mask Element */ +/// \interface WCCPv2 Protocol struct wccp2_mask_element_t { uint32_t source_ip_mask; @@ -297,6 +309,7 @@ struct wccp2_mask_element_t /* Value Element */ +/// \interface WCCPv2 Protocol struct wccp2_value_element_t { uint32_t source_ip_value; @@ -304,11 +317,12 @@ struct wccp2_value_element_t uint16_t source_port_value; uint16_t dest_port_value; - struct IN_ADDR cache_ip; + struct in_addr cache_ip; }; /* RECEIVED PACKET STRUCTURE */ +/// \interface WCCPv2 Protocol struct wccp2_i_see_you_t { uint32_t type; @@ -321,16 +335,17 @@ static struct wccp2_i_see_you_t wccp2_i_see_you; /* Router ID element */ +/// \interface WCCPv2 Protocol struct wccp2_router_assign_element_t { - - struct IN_ADDR router_address; + struct in_addr router_address; uint32_t received_id; uint32_t change_number; }; /* Generic header struct */ +/// \interface WCCPv2 Protocol struct wccp2_item_header_t { uint16_t type; @@ -339,6 +354,7 @@ struct wccp2_item_header_t /* Router identity struct */ +/// \interface WCCPv2 Protocol struct router_identity_info_t { @@ -352,10 +368,10 @@ struct router_identity_info_t /* The received packet for a mask assignment is unusual */ +/// \interface WCCPv2 Protocol struct cache_mask_info_t { - - struct IN_ADDR addr; + struct in_addr addr; uint32_t num1; uint32_t num2; uint32_t num3; @@ -363,15 +379,16 @@ struct cache_mask_info_t /* assigment key */ +/// \interface WCCPv2 Protocol struct assignment_key_t { - - struct IN_ADDR master_ip; + struct in_addr master_ip; uint32_t master_number; }; /* Router view of WCCP */ +/// \interface WCCPv2 Protocol struct router_view_t { @@ -383,24 +400,26 @@ struct router_view_t /* Lists used to keep track of caches, routers and services */ +/// \interface WCCPv2 Protocol struct wccp2_cache_list_t { - struct IN_ADDR cache_ip; + struct in_addr cache_ip; int weight; struct wccp2_cache_list_t *next; }; +/// \interface WCCPv2 Protocol struct wccp2_router_list_t { struct wccp2_router_id_element_t *info; - struct IN_ADDR local_ip; + struct in_addr local_ip; - struct IN_ADDR router_sendto_address; + struct in_addr router_sendto_address; uint32_t member_change; uint32_t num_caches; @@ -411,6 +430,7 @@ struct wccp2_router_list_t static int wccp2_numrouters; +/// \interface WCCPv2 Protocol struct wccp2_service_list_t { @@ -638,7 +658,7 @@ wccp2_check_security(struct wccp2_service_list_t *srv, char *security, char *pac void wccp2Init(void) { - sockaddr_in_list *s; + IPAddress_list *s; char *ptr; uint32_t service_flags; @@ -657,7 +677,7 @@ wccp2Init(void) /* Calculate the number of routers configured in the config file */ for (s = Config.Wccp2.router; s; s = s->next) { - if (s->s.sin_addr.s_addr != any_addr.s_addr) { + if (!s->s.IsAnyAddr()) { /* Increment the counter */ wccp2_numrouters++; } @@ -736,7 +756,7 @@ wccp2Init(void) assert(wccp2_here_i_am_header.length <= WCCP_RESPONSE_SIZE); wccp2_identity_info.cache_identity_type = htons(WCCP2_WC_ID_INFO); wccp2_identity_info.cache_identity_length = htons(sizeof(wccp2_identity_info.cache_identity)); - memset(&wccp2_identity_info.cache_identity.addr, '\0', sizeof(wccp2_identity_info.cache_identity.addr)); + memset(&wccp2_identity_info.cache_identity.addr, '\0', sizeof(struct in_addr)); memset(&wccp2_identity_info.cache_identity.hash_revision, '\0', sizeof(wccp2_identity_info.cache_identity.hash_revision)); memset(&wccp2_identity_info.cache_identity.bits, '\0', sizeof(wccp2_identity_info.cache_identity.bits)); memset(&wccp2_identity_info.cache_identity.buckets, '\0', sizeof(wccp2_identity_info.cache_identity.buckets)); @@ -755,7 +775,7 @@ wccp2Init(void) assert(wccp2_here_i_am_header.length <= WCCP_RESPONSE_SIZE); wccp2_mask_identity_info.cache_identity_type = htons(WCCP2_WC_ID_INFO); wccp2_mask_identity_info.cache_identity_length = htons(sizeof(wccp2_mask_identity_info.cache_identity)); - memset(&wccp2_mask_identity_info.cache_identity.addr, '\0', sizeof(wccp2_mask_identity_info.cache_identity.addr)); + memset(&wccp2_mask_identity_info.cache_identity.addr, '\0', sizeof(struct in_addr)); wccp2_mask_identity_info.cache_identity.num1 = htonl(2); wccp2_mask_identity_info.cache_identity.num2 = htonl(1); service_flags = ntohl(service_list_ptr->service_info->service_flags); @@ -826,7 +846,7 @@ wccp2Init(void) /* Add each router. Keep this functionality here to make sure the received_id can be updated in the packet */ for (s = Config.Wccp2.router; s; s = s->next) { - if (s->s.sin_addr.s_addr != any_addr.s_addr) { + if (!s->s.IsAnyAddr()) { wccp2_here_i_am_header.length += sizeof(struct wccp2_router_id_element_t); assert(wccp2_here_i_am_header.length <= WCCP_RESPONSE_SIZE); @@ -834,9 +854,9 @@ wccp2Init(void) /* Add a pointer to the router list for this router */ router_list_ptr->info = (struct wccp2_router_id_element_t *) ptr; - router_list_ptr->info->router_address = s->s.sin_addr; + s->s.GetInAddr(router_list_ptr->info->router_address); router_list_ptr->info->received_id = htonl(0); - router_list_ptr->router_sendto_address = s->s.sin_addr; + s->s.GetInAddr(router_list_ptr->router_sendto_address); router_list_ptr->member_change = htonl(0); /* Build the next struct */ @@ -943,8 +963,6 @@ wccp2Init(void) void wccp2ConnectionOpen(void) { - u_short port = WCCP_PORT; - struct sockaddr_in router, local, null; socklen_t local_len, router_len; @@ -959,10 +977,15 @@ wccp2ConnectionOpen(void) return; } + if( !Config.Wccp2.address.SetIPv4() ) { + debugs(80, 0, "WCCPv2 Disabled. " << Config.Wccp2.address << " is not an IPv4 address."); + return; + } + + Config.Wccp2.address.SetPort(WCCP_PORT); theWccp2Connection = comm_open(SOCK_DGRAM, 0, Config.Wccp2.address, - port, COMM_NONBLOCKING, "WCCPv2 Socket"); @@ -982,7 +1005,7 @@ wccp2ConnectionOpen(void) NULL, 0); - debugs(80, 1, "Accepting WCCPv2 messages on port " << port << ", FD " << theWccp2Connection << "."); + debugs(80, 1, "Accepting WCCPv2 messages on port " << WCCP_PORT << ", FD " << theWccp2Connection << "."); debugs(80, 1, "Initialising all WCCPv2 lists"); /* Initialise all routers on all services */ @@ -997,7 +1020,7 @@ wccp2ConnectionOpen(void) router_len = sizeof(router); memset(&router, '\0', router_len); router.sin_family = AF_INET; - router.sin_port = htons(port); + router.sin_port = htons(WCCP_PORT); router.sin_addr = router_list_ptr->router_sendto_address; if (connect(theWccp2Connection, (struct sockaddr *) &router, router_len)) @@ -1016,7 +1039,6 @@ wccp2ConnectionOpen(void) * but disconnects anyway so we have to just assume it worked */ if (wccp2_numrouters > 1) - connect(theWccp2Connection, (struct sockaddr *) &null, router_len); } @@ -1134,7 +1156,6 @@ wccp2HandleUdp(int sock, void *not_used) struct sockaddr_in from; struct IN_ADDR cache_address; - socklen_t from_len; int len, found; short int data_length, offset; uint32_t tmp; @@ -1145,16 +1166,14 @@ wccp2HandleUdp(int sock, void *not_used) commSetSelect(sock, COMM_SELECT_READ, wccp2HandleUdp, NULL, 0); - from_len = sizeof(struct sockaddr_in); - memset(&from, '\0', from_len); +/* FIXME INET6 : drop conversion boundary */ IPAddress from_tmp; len = comm_udp_recvfrom(sock, &wccp2_i_see_you, WCCP_RESPONSE_SIZE, 0, - - (struct sockaddr *) &from, - &from_len); + from_tmp); +/* FIXME INET6 : drop conversion boundary */ from_tmp.GetSockAddr(from); if (len < 0) return; @@ -1505,9 +1524,7 @@ wccp2HereIam(void *voidnotused) struct wccp2_mask_identity_info_t *wccp2_mask_identity_info_ptr; - struct sockaddr_in router; - int router_len; - u_short port = WCCP_PORT; + IPAddress router; debugs(80, 6, "wccp2HereIam: Called"); @@ -1522,10 +1539,7 @@ wccp2HereIam(void *voidnotused) return; } - router_len = sizeof(router); - memset(&router, '\0', router_len); - router.sin_family = AF_INET; - router.sin_port = htons(port); + router.SetPort(WCCP_PORT); /* for each router on each service send a packet */ service_list_ptr = wccp2_service_list_head; @@ -1534,7 +1548,7 @@ wccp2HereIam(void *voidnotused) debugs(80, 5, "wccp2HereIam: sending to service id " << service_list_ptr->info.service_id); for (router_list_ptr = &service_list_ptr->router_list_head; router_list_ptr->next != NULL; router_list_ptr = router_list_ptr->next) { - router.sin_addr = router_list_ptr->router_sendto_address; + router = router_list_ptr->router_sendto_address; /* Set the cache id (ip) */ @@ -1567,8 +1581,7 @@ wccp2HereIam(void *voidnotused) if (wccp2_numrouters > 1) { comm_udp_sendto(theWccp2Connection, - &router, - router_len, + router, &service_list_ptr->wccp_packet, service_list_ptr->wccp_packet_size); } else { @@ -1950,9 +1963,9 @@ wccp2AssignBuckets(void *voidnotused) /* send packet */ if (wccp2_numrouters > 1) { +/* FIXME INET6 : drop temp conversion */ IPAddress tmp_rtr(router); comm_udp_sendto(theWccp2Connection, - &router, - router_len, + tmp_rtr, &wccp_packet, offset); } else { diff --git a/src/win32.cc b/src/win32.cc index 68cfb23615..eeb085bf96 100644 --- a/src/win32.cc +++ b/src/win32.cc @@ -1,6 +1,5 @@ - /* - * $Id: win32.cc,v 1.25 2006/09/13 19:05:11 serassio Exp $ + * $Id: win32.cc,v 1.26 2007/12/14 23:11:48 amosjeffries Exp $ * * Windows support * AUTHOR: Guido Serassio @@ -56,36 +55,46 @@ int WIN32_pipe(int handles[2]) int new_socket; fde *F = NULL; - struct sockaddr_in serv_addr; - int len = sizeof(serv_addr); - u_short handle1_port; + IPAddress localhost; + IPAddress handle0; + IPAddress handle1; + struct addrinfo *AI = NULL; - handles[0] = handles[1] = -1; + localhost.SetLocalhost; - statCounter.syscalls.sock.sockets++; - - if ((new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - return -1; +#if !IPV6_SPECIAL_LOCALHOST + /* INET6: back-compatible: localhost pipes default to IPv4 unless set otherwise. + * it is blocked by untested helpers on many admins configs + * if this proves to be wrong it can die easily. + */ + localhost.SetIPv4(); +#endif - memset((void *) &serv_addr, 0, sizeof(serv_addr)); + handles[0] = handles[1] = -1; - serv_addr.sin_family = AF_INET; + statCounter.syscalls.sock.sockets++; - serv_addr.sin_port = htons(0); + handle0 = localhost; + handle0.SetPort(0); + handle0.GetAddrInfo(AI); - serv_addr.sin_addr = local_addr; + if ((new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) + return -1; - if (bind(new_socket, (SOCKADDR *) & serv_addr, len) < 0 || - listen(new_socket, 1) < 0 || getsockname(new_socket, (SOCKADDR *) & serv_addr, &len) < 0 || - (handles[1] = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + if (bind(new_socket, AI->ai_addr, AI->ai_addrlen) < 0 || + listen(new_socket, 1) < 0 || getsockname(new_socket, AI->ai_addr, &(AI->ai_addrlen) ) < 0 || + (handles[1] = socket(AI->ai_family, AI->ai_socktype, 0)) < 0) { closesocket(new_socket); return -1; } - handle1_port = ntohs(serv_addr.sin_port); + handle0 = *AI; // retrieve the new details returned by connect() + + handle1.SetPort(handle1.GetPort()); + handle1.GetAddrInfo(AI); - if (connect(handles[1], (SOCKADDR *) & serv_addr, len) < 0 || - (handles[0] = accept(new_socket, (SOCKADDR *) & serv_addr, &len)) < 0) { + if (connect(handles[1], AI->ai_addr, AI->ai_addrlen) < 0 || + (handles[0] = accept(new_socket, AI->ai_addr, &(AI->ai_addrlen)) ) < 0) { closesocket(handles[1]); handles[1] = -1; closesocket(new_socket); @@ -95,13 +104,12 @@ int WIN32_pipe(int handles[2]) closesocket(new_socket); F = &fd_table[handles[0]]; - F->local_addr = local_addr; - F->local_port = ntohs(serv_addr.sin_port); + F->local_addr = handle0; F = &fd_table[handles[1]]; - F->local_addr = local_addr; - xstrncpy(F->ipaddr, inet_ntoa(local_addr), 16); - F->remote_port = handle1_port; + F->local_addr = localhost; + handle1.NtoA(F->ipaddr, MAX_IPSTRLEN); + F->remote_port = handle1.GetPort(); return 0; } @@ -160,8 +168,7 @@ int Win32__WSAFDIsSet(int fd, fd_set FAR * set fde *F = &fd_table[fd]; SOCKET s = F->win32.handle; - return __WSAFDIsSet(s, set - ); + return __WSAFDIsSet(s, set); } LONG CALLBACK WIN32_ExceptionHandler(EXCEPTION_POINTERS* ep) diff --git a/test-suite/hash.h b/test-suite/hash.h index f24588067a..b2c13c42a1 100644 --- a/test-suite/hash.h +++ b/test-suite/hash.h @@ -22,8 +22,9 @@ struct _hash_table { typedef struct _hash_table hash_table; extern int hash_links_allocated; -extern int store_hash_buckets; /* 0 */ -extern hash_table *store_table; /* NULL */ +/* AYJ: defined by globals.h */ +//extern int store_hash_buckets; /* 0 */ +//extern hash_table *store_table; /* NULL */ extern hash_table *hash_create(HASHCMP *, int, HASHHASH *); extern void hash_insert(hash_table *, const char *, void *); extern int hash_delete(hash_table *, const char *); diff --git a/test-suite/pconn-banger.c b/test-suite/pconn-banger.c index 7e07544540..14578088f6 100644 --- a/test-suite/pconn-banger.c +++ b/test-suite/pconn-banger.c @@ -90,7 +90,9 @@ #include #endif -#define PROXY_PORT 3128 +#include "getaddrinfo.h" + +#define PROXY_PORT "3128" #define PROXY_ADDR "127.0.0.1" #define MAX_FDS 1024 #define READ_BUF_SZ 4096 @@ -170,20 +172,30 @@ int open_http_socket(void) { int s; - struct sockaddr_in S; - if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + struct addrinfo *AI = NULL; + struct addrinfo hints; + + memset(&hints, '\0', sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + xgetaddrinfo(proxy_addr, proxy_port, &hints, AI); + + if ((s = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) { perror("socket"); + xfreeaddrinfo(AI); return -1; } - memset(&S, '\0', sizeof(struct sockaddr_in)); - S.sin_family = AF_INET; - S.sin_port = htons(proxy_port); - S.sin_addr.s_addr = inet_addr(proxy_addr); - if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) { + + if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) { close(s); perror("connect"); + xfreeaddrinfo(AI); return -1; } + + xfreeaddrinfo(AI); return s; } diff --git a/tools/cachemgr.cc b/tools/cachemgr.cc index 277524d061..966e401f10 100644 --- a/tools/cachemgr.cc +++ b/tools/cachemgr.cc @@ -1,6 +1,6 @@ /* - * $Id: cachemgr.cc,v 1.5 2007/12/06 02:37:17 amosjeffries Exp $ + * $Id: cachemgr.cc,v 1.6 2007/12/14 23:11:53 amosjeffries Exp $ * * DEBUG: section 0 CGI Cache Manager * AUTHOR: Duane Wessels @@ -134,6 +134,7 @@ extern "C" #include "assert.h" #include "util.h" +#include "IPAddress.h" #ifndef DEFAULT_CACHEMGR_CONFIG #define DEFAULT_CACHEMGR_CONFIG "/etc/squid/cachemgr.conf" @@ -171,8 +172,6 @@ static const char *script_name = "/cgi-bin/cachemgr.cgi"; static const char *progname = NULL; static time_t now; -static struct IN_ADDR no_addr; - /* * Function prototypes */ @@ -764,9 +763,9 @@ static int process_request(cachemgr_request * req) { - const struct hostent *hp; - - static struct sockaddr_in S; + char ipbuf[MAX_IPSTRLEN]; + struct addrinfo *AI = NULL; + IPAddress S; int s; int l; @@ -800,19 +799,21 @@ process_request(cachemgr_request * req) return 1; } +#if USE_IPV6 + if ((s = socket(PF_INET6, SOCK_STREAM, 0)) < 0) { +#else if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { +#endif snprintf(buf, 1024, "socket: %s\n", xstrerror()); error_html(buf); return 1; } - memset(&S, '\0', sizeof(S)); - S.sin_family = AF_INET; + S = *gethostbyname(req->hostname); - if ((hp = gethostbyname(req->hostname)) != NULL) { - assert(hp->h_length >= 0 && (size_t)hp->h_length <= sizeof(S.sin_addr.s_addr)); - xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); - } else if (safe_inet_addr(req->hostname, &S.sin_addr)) + if ( !S.IsAnyAddr() ) { + (void) 0; + } else if ( S = req->hostname) (void) 0; else { snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); @@ -820,17 +821,21 @@ process_request(cachemgr_request * req) return 1; } - S.sin_port = htons(req->port); + S.SetPort(req->port); + + S.GetAddrInfo(AI); - if (connect(s, (struct sockaddr *) &S, sizeof(S)) < 0) { - snprintf(buf, 1024, "connect %s:%d: %s\n", - inet_ntoa(S.sin_addr), - ntohs(S.sin_port), + if (connect(s, AI->ai_addr, AI->ai_addrlen) < 0) { + snprintf(buf, 1024, "connect %s: %s\n", + S.ToURL(ipbuf,MAX_IPSTRLEN), xstrerror()); error_html(buf); + S.FreeAddrInfo(AI); return 1; } + S.FreeAddrInfo(AI); + l = snprintf(buf, sizeof(buf), "GET cache_object://%s/%s HTTP/1.0\r\n" "Accept: */*\r\n" @@ -850,7 +855,6 @@ main(int argc, char *argv[]) char *s; cachemgr_request *req; - safe_inet_addr("255.255.255.255", &no_addr); now = time(NULL); #ifdef _SQUID_MSWIN_ diff --git a/tools/squidclient.cc b/tools/squidclient.cc index 279bfb7cea..8fc683b85f 100644 --- a/tools/squidclient.cc +++ b/tools/squidclient.cc @@ -1,6 +1,6 @@ /* - * $Id: squidclient.cc,v 1.9 2007/09/01 19:51:30 hno Exp $ + * $Id: squidclient.cc,v 1.10 2007/12/14 23:11:53 amosjeffries Exp $ * * DEBUG: section 0 WWW Client * AUTHOR: Harvest Derived @@ -84,6 +84,7 @@ using namespace Squid; #endif #include "util.h" +#include "IPAddress.h" #ifndef BUFSIZ #define BUFSIZ 8192 @@ -92,9 +93,9 @@ using namespace Squid; typedef void SIGHDLR(int sig); /* Local functions */ -static int client_comm_bind(int, const char *); +static int client_comm_bind(int, const IPAddress &); -static int client_comm_connect(int, const char *, u_short, struct timeval *); +static int client_comm_connect(int, const IPAddress &, struct timeval *); static void usage(const char *progname); static int Now(struct timeval *); @@ -151,6 +152,7 @@ main(int argc, char *argv[]) int opt_noaccept = 0; int opt_verbose = 0; const char *hostname, *localhost; + IPAddress iaddr; char url[BUFSIZ], msg[49152], buf[BUFSIZ]; char extra_hdrs[32768]; const char *method = "GET"; @@ -434,28 +436,59 @@ main(int argc, char *argv[]) for (i = 0; loops == 0 || i < loops; i++) { int fsize = 0; + struct addrinfo *AI = NULL; + /* Connect to the server */ - if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - perror("client: socket"); - exit(1); - } - if (localhost && client_comm_bind(conn, localhost) < 0) { - perror("client: bind"); - exit(1); - } - if (client_comm_connect(conn, hostname, port, ping ? &tv1 : NULL) < 0) { - if (errno == 0) { - fprintf(stderr, "client: ERROR: Cannot connect to %s:%d: Host unknown.\n", hostname, port); - } else { - char tbuf[BUFSIZ]; - snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s:%d", - hostname, port); - perror(tbuf); - } + if(localhost) { + if( !iaddr.GetHostByName(localhost) ) { + fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", localhost); + exit(1); + } + } + else { + /* Process the remote host name to locate the Protocol required + in case we are being asked to link to another version of squid */ + if( !iaddr.GetHostByName(hostname) ) { + fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname); + exit(1); + } + } + + iaddr.GetAddrInfo(AI); + if ((conn = socket(AI->ai_family, AI->ai_socktype, 0)) < 0) { + perror("client: socket"); + iaddr.FreeAddrInfo(AI); + exit(1); + } + iaddr.FreeAddrInfo(AI); + + if (localhost && client_comm_bind(conn, iaddr) < 0) { + perror("client: bind"); + exit(1); + } + + iaddr.SetEmpty(); + if( !iaddr.GetHostByName(hostname) ) { + fprintf(stderr, "client: ERROR: Cannot resolve %s: Host unknown.\n", hostname); + exit(1); + } + + iaddr.SetPort(port); + + if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) { + char buf[MAX_IPSTRLEN]; + iaddr.ToURL(buf, MAX_IPSTRLEN); + if (errno == 0) { + fprintf(stderr, "client: ERROR: Cannot connect to %s: Host unknown.\n", buf); + } else { + char tbuf[BUFSIZ]; + snprintf(tbuf, BUFSIZ, "client: ERROR: Cannot connect to %s", buf); + perror(tbuf); + } + exit(1); + } - exit(1); - } /* Send the HTTP request */ bytesWritten = mywrite(conn, msg, strlen(msg)); @@ -466,6 +499,7 @@ main(int argc, char *argv[]) fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg); exit(1); } + if (put_file) { int x; lseek(put_fd, 0, SEEK_SET); @@ -561,50 +595,42 @@ main(int argc, char *argv[]) } static int -client_comm_bind(int sock, const char *local_host) +client_comm_bind(int sock, const IPAddress &addr) { - static const struct hostent *hp = NULL; + int res; - static struct sockaddr_in from_addr; + static struct addrinfo *AI = NULL; /* Set up the source socket address from which to send. */ - if (hp == NULL) { - from_addr.sin_family = AF_INET; + addr.GetAddrInfo(AI); - if ((hp = gethostbyname(local_host)) == 0) { - return (-1); - } - xmemcpy(&from_addr.sin_addr, hp->h_addr, hp->h_length); - from_addr.sin_port = 0; - } - return bind(sock, (struct sockaddr *) &from_addr, sizeof(struct sockaddr_in)); + res = bind(sock, AI->ai_addr, AI->ai_addrlen); + + addr.FreeAddrInfo(AI); + + return res; } static int -client_comm_connect(int sock, const char *dest_host, u_short dest_port, struct timeval *tvp) +client_comm_connect(int sock, const IPAddress &addr, struct timeval *tvp) { + int res; + static struct addrinfo *AI = NULL; - static const struct hostent *hp = NULL; + /* Set up the destination socket address for message to send to. */ - static struct sockaddr_in to_addr; + addr.GetAddrInfo(AI); - /* Set up the destination socket address for message to send to. */ + res = connect(sock, AI->ai_addr, AI->ai_addrlen); - if (hp == NULL) { - to_addr.sin_family = AF_INET; + addr.FreeAddrInfo(AI); - if ((hp = gethostbyname(dest_host)) == 0) { - return (-1); - } - xmemcpy(&to_addr.sin_addr, hp->h_addr, hp->h_length); - to_addr.sin_port = htons(dest_port); - } if (tvp) - (void) Now(tvp); + (void) Now(tvp); - return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); + return res; } static int -- 2.39.5