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
[ 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
])
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 <sys/types.h>
+# include <sys/socket.h>
+ 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],
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 \
dnl ... and some we provide local replacements for
AC_REPLACE_FUNCS(\
drand48 \
+ inet_ntop \
+ inet_pton \
initgroups \
+ getaddrinfo \
+ getnameinfo \
strerror \
tempnam \
)
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 <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#if HAVE_RESOLV_H
+#include <resolv.h>
+#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 <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#if HAVE_RESOLV_H
+#include <resolv.h>
+#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
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
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
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;
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;
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));
}
struct redirect_addr {
- struct IN_ADDR ip_addr;
+ struct in_addr ip_addr;
int port;
redirect_ptr next;
/*
- * $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
/* 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
};
#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
};
#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 */
/*
- * $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
*
#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"
/*
- * $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
*
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;
*
* Author: Ryan Troll <ryan+@andrew.cmu.edu>
*
- * $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 $
*
**********************************************************************/
#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;
/*
- * $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 <tolsty@tushino.com>
* AUTHOR: Guido Serassio <serassio@squid-cache.org>
#include <stddef.h>
#include <process.h>
#include <errno.h>
+#include <ws2tcpip.h>
#if defined(_MSC_VER) /* Microsoft C Compiler ONLY */
/* Hack to suppress compiler warnings on FD_SET() & FD_CLR() */
#pragma warning (push)
#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 */
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;
#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;
}
}
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;
}
/*
- * $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
*
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
#if !defined(SQUIDHOSTNAMELEN)
#define SQUIDHOSTNAMELEN 256
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);
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;
/*
- * $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,
#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
\f
## 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
rfc1738.c \
rfc2617.c \
rfc3596.c \
- safe_inet_addr.c \
$(SNPRINTFSOURCE) \
Splay.cc \
$(STRSEPSOURCE) \
tests/testArray.cc \
tests/testIPAddress.h \
tests/testIPAddress.cc \
+ IPAddress.cc \
+ tests/testRFC1035.h \
+ tests/testRFC1035.cc \
tests/testMain.cc \
$(XPROF_STATS_SOURCE) \
$(WIN32SRC) \
/*
- * $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
}
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;
}
/*
}
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;
}
/*
if (rfc1035QueryUnpack(buf, sz, &off, &querys[j])) {
RFC1035_UNPACK_DEBUG;
rfc1035SetErrno(rfc1035_unpack_error);
- rfc1035MessageDestroy(msg);
+ rfc1035MessageDestroy(&msg);
return -rfc1035_unpack_error;
}
}
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;
* 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;
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) {
-
-/*
- * $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 <stdio.h>
-#endif
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#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 <mijosxi@ike.tottori-u.ac.jp> 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;
-}
--- /dev/null
+#include "config.h"
+
+#if HAVE_ASSERT_H
+#include <assert.h>
+#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);
+}
--- /dev/null
+#ifndef SQUID_SRC_TEST_RFC1035_H
+#define SQUID_SRC_TEST_RFC1035_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+/*
+ * 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 */
+
/*
- * $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
#include <squid_windows.h>
#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 */
#endif
static void aclParseArpList(SplayNode<acl_arp_data *> **curlist);
static int decode_eth(const char *asc, char *eth);
-static int aclMatchArp(SplayNode<acl_arp_data *> **dataptr, struct IN_ADDR c);
+static int aclMatchArp(SplayNode<acl_arp_data *> **dataptr, IPAddress &c);
static SplayNode<acl_arp_data *>::SPLAYCMP aclArpCompare;
static SplayNode<acl_arp_data *>::SPLAYWALKEE aclDumpArpListWalkee;
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);
}
/* aclMatchArp */
/***************/
int
-aclMatchArp(SplayNode<acl_arp_data *> **dataptr, struct IN_ADDR c)
+aclMatchArp(SplayNode<acl_arp_data *> **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];
* 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) {
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);
}
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);
/* 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;
}
#elif defined(_SQUID_SOLARIS_)
- struct arpreq arpReq;
-
- struct sockaddr_in ipAddr;
-
SplayNode<acl_arp_data *> **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) {
/* 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<acl_arp_data *> **Top = dataptr;
int mib[6];
/*
* 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;
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);
/* 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);
SplayNode<acl_arp_data *> **Top = dataptr;
- struct arpreq arpReq;
-
memset(&arpReq, '\0', sizeof(arpReq));
/* Get size of Windows ARP table */
/* 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);
}
/* 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);
/*
* 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;
}
/*
- * $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/
#include "List.h"
#include "ACLStrategised.h"
#include "ACLChecklist.h"
+#include "IPAddress.h"
/* forward decls */
class CacheManager;
-SQUIDCEXTERN int asnMatchIp(List<int> *, struct IN_ADDR);
+SQUIDCEXTERN int asnMatchIp(List<int> *, IPAddress &);
SQUIDCEXTERN void asnInit(void);
extern void asnRegisterWithCacheManager(CacheManager & manager);
SQUIDCEXTERN void asnFreeMemory(void);
-class ACLASN : public ACLData<struct IN_ADDR>
+class ACLASN : public ACLData<IPAddress>
{
public:
virtual ~ACLASN();
- virtual bool match(struct IN_ADDR);
+ virtual bool match(IPAddress);
virtual wordlist *dump();
virtual void parse();
bool empty() const;
- virtual ACLData<struct IN_ADDR> *clone() const;
+ virtual ACLData<IPAddress> *clone() const;
virtual void prepareForUse();
private:
static ACL::Prototype SourceRegistryProtoype;
- static ACLStrategised<struct IN_ADDR> SourceRegistryEntry_;
+ static ACLStrategised<IPAddress> SourceRegistryEntry_;
static ACL::Prototype DestinationRegistryProtoype;
- static ACLStrategised<struct IN_ADDR> DestinationRegistryEntry_;
+ static ACLStrategised<IPAddress> DestinationRegistryEntry_;
List<int> *data;
};
/*
- * $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
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
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';
}
* 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;
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
/*
- * $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/
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;
/*
- * $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/
#define SQUID_ACLDESTINATIONASN_H
#include "ACLASN.h"
#include "ACLStrategy.h"
+#include "IPAddress.h"
-class ACLDestinationASNStrategy : public ACLStrategy<struct IN_ADDR>
+class ACLDestinationASNStrategy : public ACLStrategy<IPAddress>
{
public:
/*
- * $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
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];
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;
}
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 */
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 {
DestinationIPLookup::checkForAsync(ACLChecklist *checklist)const
{
checklist->asyncInProgress(true);
- ipcache_nbgethostbyname(checklist->request->host, LookupDone, checklist);
+ ipcache_nbgethostbyname(checklist->request->GetHost(), LookupDone, checklist);
}
void
void
ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state)
{
+ char tmpbuf[MAX_IPSTRLEN];
MemBuf mb;
wordlist **W = static_cast<wordlist **>(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);
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);
}
/*
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' */
}
}
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;
* 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;
}
}
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){}
#define SQUID_ACLIP_H
#include "ACL.h"
#include "splay.h"
+#include "IPAddress.h"
class acl_ip_data
{
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)
protected:
- int match(struct IN_ADDR &);
+ int match(IPAddress &);
IPSplay *data;
private:
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" );
/*
- * $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
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
/*
- * $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/
static Prototype RegistryProtoype;
static ACLMaxUserIP RegistryEntry_;
- int match(AuthUserRequest *, struct IN_ADDR const &);
+ int match(AuthUserRequest *, IPAddress const &);
char const *class_;
int maximum;
/*
- * $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/
int
ACLMyPortStrategy::match (ACLData<MatchType> * &data, ACLChecklist *checklist)
{
- return data->match (checklist->my_port);
+ return data->match (checklist->my_addr.GetPort());
}
ACLMyPortStrategy *
/*
- * $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/
#define SQUID_ACLSOURCEASN_H
#include "ACLASN.h"
#include "ACLStrategy.h"
+#include "IPAddress.h"
-class ACLSourceASNStrategy : public ACLStrategy<struct IN_ADDR>
+class ACLSourceASNStrategy : public ACLStrategy<IPAddress>
{
public:
/*
- * $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
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;
}
/*
- * $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/
#include "HttpVersion.h"
#include "HierarchyLogEntry.h"
+#include "IPAddress.h"
/* forward decls */
{
public:
- CacheDetails() : size(0),
+ CacheDetails() : caddr(),
+ size(0),
highOffset(0),
objectSize(0),
code (LOG_TAG_NONE),
,ssluser(NULL)
#endif
{
- memset(&caddr, '\0', sizeof(caddr));
+ ;
}
- struct IN_ADDR caddr;
+ IPAddress caddr;
int64_t size;
int64_t highOffset;
int64_t objectSize;
/*
- * $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
}
void
-AuthUser::removeIp(struct IN_ADDR ipaddr)
+AuthUser::removeIp(IPAddress ipaddr)
{
auth_user_ip_t *ipdata = (auth_user_ip_t *) ip_list.head;
{
/* 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);
}
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);
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;
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 << ")");
}
/*
- * $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/
#ifndef SQUID_AUTHUSER_H
#define SQUID_AUTHUSER_H
+#include "IPAddress.h"
+
class AuthUserRequest;
class AuthUser
_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()
/*
- * $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
}
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();
}
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();
*/
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);
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;
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);
/*
- * $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
dlink_node node;
/* IP addr this user authenticated from */
- struct IN_ADDR ipaddr;
+ IPAddress ipaddr;
time_t ip_expiretime;
};
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();
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;
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 *);
/*
- * $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 <robertc@squid-cache.org>
#include "DelayPools.h"
#include "DelayIdComposite.h"
#include "CommRead.h"
+#include "IPAddress.h"
class StoreEntry;
public:
CompositeSelectionDetails() {}
- struct IN_ADDR src_addr;
+ IPAddress src_addr;
AuthUserRequest *user;
String tag;
};
/*
- * $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
#ifndef _SQUIDCONNECTIONDETAIL_H_
#define _SQUIDCONNECTIONDETAIL_H_
+#include "IPAddress.h"
+
class ConnectionDetail
{
ConnectionDetail();
- struct sockaddr_in me;
+ IPAddress me;
- struct sockaddr_in peer;
+ IPAddress peer;
};
#endif
-
/*
- * $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
*
* 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);
}
-
/*
- * $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/
* ----------------------------------------------------------
/*
- * $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 <robertc@squid-cache.org>
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();
}
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());
-
/*
- * $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
char skey1[32];
char skey2[32];
char skey3[32];
+ IPAddress localhost;
ikey = (getpid() << 10) + (instanceID << 2);
ikey &= 0x7fffffff;
args[2] = skey2;
args[3] = skey3;
args[4] = NULL;
+ localhost.SetLocalhost();
pid = ipcCreate(IPC_STREAM,
Config.Program.diskd,
args,
"diskd",
+ localhost,
&rfd,
&wfd,
&hIpc);
/*
- * $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
#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
/* 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 */
/* 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);
/*
- * $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
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;
/*
- * $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/
/* 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();
char login[MAX_LOGIN_SZ];
- char host[SQUIDHOSTNAMELEN + 1];
+private:
+ char host[SQUIDHOSTNAMELEN];
+
+public:
+ IPAddress host_addr;
AuthUserRequest *auth_user_request;
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;
void ICAPModXact::makeRequestHeaders(MemBuf &buf)
{
+ char ntoabuf[MAX_IPSTRLEN];
/*
* XXX These should use HttpHdr interfaces instead of Printfs
*/
}
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);
--- /dev/null
+/*
+ * $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
--- /dev/null
+/*
+ * $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 <stdlib.h>
+#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 */
--- /dev/null
+/*
+ * $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 */
--- /dev/null
+/*
+ * $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
--- /dev/null
+/*
+ * $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
+}
--- /dev/null
+/*
+ * $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 */
--- /dev/null
+/*
+ * $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 */
--- /dev/null
+/*
+ * $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 <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_IP_ICMP_H
+#include <netinet/ip_icmp.h>
+#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 <winsock2.h>
+#include <process.h>
+
+#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
--- /dev/null
+/*
+ * $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 <netinet/ip6.h>
+#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 */
--- /dev/null
+/*
+ * $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 <netinet/in.h>
+#endif
+#if HAVE_NETINET_ICMP6_H
+#include <netinet/icmp6.h>
+#endif
+#if HAVE_NETINET_IP6_H
+#include <netinet/ip6.h>
+#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 */
/*
- * $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/
_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
HttpRequest *request;
int fd;
- struct sockaddr_in from;
+ IPAddress from;
char *url;
};
struct icpUdpData
{
-
- struct sockaddr_in address;
+ IPAddress address;
void *msg;
size_t len;
icpUdpData *next;
};
-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);
/*
- * $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
#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)
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)
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;
}
#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;
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;
#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);
}
- 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;
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;
#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
/*
- * $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/
#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 */
#
# 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:
#
PINGER =
endif
+# Squid Internal ICMP sources
+ICMPSOURCE = \
+ ICMP.h \
+ icmp.cc \
+ ICMPConfig.h \
+ ICMPSquid.h \
+ ICMPSquid.cc
+
SSL_ALL_SOURCE = \
ACLCertificateData.cc \
ACLCertificateData.h \
ACLCertificate.h \
ssl_support.cc \
ssl_support.h
+
if ENABLE_SSL
SSL_SOURCE = $(SSL_ALL_SOURCE)
else
HttpRequestMethod.cc \
HttpRequestMethod.h \
HttpVersion.h \
- icmp.cc \
+ $(ICMPSOURCE) \
ICP.h \
icp_v2.cc \
icp_v3.cc \
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 \
HttpReply.cc \
HttpRequest.cc \
HttpRequestMethod.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
tests/testHeaders \
tests/test_http_range \
tests/testHttpRequest \
+ tests/testICMP \
tests/testStore \
tests/testString \
tests/testURL \
HttpMsg.cc \
HttpReply.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
HttpMsg.cc \
HttpReply.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
HttpMsg.cc \
HttpReply.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
HttpRequest.cc \
HttpRequestMethod.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
HttpMsg.cc \
HttpReply.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
@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
HttpMsg.cc \
HttpReply.cc \
HttpStatusLine.cc \
- icmp.cc \
+ $(ICMPSOURCE) \
icp_v2.cc \
icp_v3.cc \
$(IDENT_SOURCE) \
/*
- * $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
*
#include "cbdata.h"
#include "PingData.h"
+#include "IPAddress.h"
class ps_state
{
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:
/*
- * $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
#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);
/*
- * $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
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;
/* 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;
}
{
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);
{
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);
/*
- * $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
/* 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 */
{
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);
/* PUBLIC */
int
-asnMatchIp(List<int> *data, struct IN_ADDR addr)
+asnMatchIp(List<int> *data, IPAddress &addr)
{
- unsigned long lh;
-
struct squid_radix_node *rn;
as_info *e;
- m_int m_addr;
+ m_ADDR m_addr;
List<int> *a = NULL;
List<int> *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);
rtentry_t *e;
struct squid_radix_node *rn;
- char dbg1[32], dbg2[32];
List<int> **Tail = NULL;
List<int> *q = NULL;
as_info *asinfo = NULL;
- struct IN_ADDR in_a, in_m;
- long mask, addr;
+ IPAddress mask;
+ IPAddress addr;
char *t;
int bitl;
}
*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);
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!");
}
static int
-
destroyRadixNode(struct squid_radix_node *rn, void *w)
{
}
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<int> *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);
bool
-ACLASN::match(struct IN_ADDR toMatch)
+ACLASN::match(IPAddress toMatch)
{
return asnMatchIp(data, toMatch);
}
}
}
-ACLData<struct IN_ADDR> *
+ACLData<IPAddress> *
ACLASN::clone() const
{
if (data)
/* explicit template instantiation required for some systems */
-template class ACLStrategised<struct IN_ADDR>
+template class ACLStrategised<IPAddress>
;
ACL::Prototype ACLASN::SourceRegistryProtoype(&ACLASN::SourceRegistryEntry_, "src_as");
-ACLStrategised<struct IN_ADDR> ACLASN::SourceRegistryEntry_(new ACLASN, ACLSourceASNStrategy::Instance(), "src_as");
+ACLStrategised<IPAddress> ACLASN::SourceRegistryEntry_(new ACLASN, ACLSourceASNStrategy::Instance(), "src_as");
ACL::Prototype ACLASN::DestinationRegistryProtoype(&ACLASN::DestinationRegistryEntry_, "dst_as");
-ACLStrategised<struct IN_ADDR> ACLASN::DestinationRegistryEntry_(new ACLASN, ACLDestinationASNStrategy::Instance(), "dst_as");
+ACLStrategised<IPAddress> ACLASN::DestinationRegistryEntry_(new ACLASN, ACLDestinationASNStrategy::Instance(), "dst_as");
int
-ACLSourceASNStrategy::match (ACLData<MatchType> * &data, ACLChecklist *checklist)
+ACLSourceASNStrategy::match (ACLData<IPAddress> * &data, ACLChecklist *checklist)
{
return data->match(checklist->src_addr);
}
int
ACLDestinationASNStrategy::match (ACLData<MatchType> * &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++) {
}
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;
-
/*
- * $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
#include "HttpRequest.h"
#include "HttpReply.h"
#include "wordlist.h"
+#include "SquidTime.h"
/* TODO don't include this */
#include "digestScheme.h"
} 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.");
-
/*
- * $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
#include "client_side.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "SquidTime.h"
/* TODO remove this include */
#include "negotiateScheme.h"
#include "wordlist.h"
-
/*
- * $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
/* TODO remove this include */
#include "ntlmScheme.h"
#include "wordlist.h"
+#include "SquidTime.h"
static void
authenticateNTLMReleaseServer(AuthUserRequest * auth_user_request);
/*
- * $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
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 */
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);
}
}
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) {
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);
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);
self_destruct();
p->host = xstrdup(token);
-
+
p->name = xstrdup(token);
if ((token = strtok(NULL, w_space)) == NULL)
}
#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);
}
#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;
port = 0;
}
- s = static_cast<sockaddr_in_list *>(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<IPAddress_list *>(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
* 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;
}
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
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;
} 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();
}
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);
refreshpattern
removalpolicy
size_t
-sockaddr_in_list
+IPAddress_list
string
string
time_t
#
-# $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/
# ----------------------------------------------------------
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
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
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
-----------------------------------------------------------------------------
IFDEF: USE_WCCP
DOC_NONE
NAME: wccp2_router
-TYPE: sockaddr_in_list
+TYPE: IPAddress_list
LOC: Config.Wccp2.router
DEFAULT: none
IFDEF: USE_WCCPv2
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
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
/*
- * $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
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 *);
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++;
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);
* -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");
#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;
if (!Config.onoff.client_db)
return 0;
- key = inet_ntoa(addr);
+ addr.NtoA(key,MAX_IPSTRLEN);
c = (ClientInfo *) hash_lookup(client_table, key);
#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 *
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!");
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,
/*
- * $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
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
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;
updateCounters();
if (getConn() != NULL)
- clientdbUpdate(getConn()->peer.sin_addr, logType, PROTO_HTTP, out.size);
+ clientdbUpdate(getConn()->peer, logType, PROTO_HTTP, out.size);
}
delete checklist;
openReference = NULL;
fd = -1;
flags.readMoreRequests = false;
- clientdbEstablished(peer.sin_addr, -1); /* decrement */
+ clientdbEstablished(peer, -1); /* decrement */
assert(areAllContextsForThisConnection());
freeAllContexts();
int vhost = conn->port->vhost;
int vport = conn->port->vport;
char *host;
+ char ntoabuf[MAX_IPSTRLEN];
http->flags.accel = 1;
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 */
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 << "'");
}
prepareTransparentURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, const char *req_hdr)
{
char *host;
+ char ntoabuf[MAX_IPSTRLEN];
http->flags.transparent = 1;
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 << "'");
}
}
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();
}
debugs(33, 1, "clientProcessRequest: Invalid Request");
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(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;
debugs(33, 5, "Invalid URL: " << http->uri);
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(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;
debugs(33, 5, "Failed to parse request headers:\n" << HttpParserHdrBuf(hp));
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(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;
#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;
}
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) ||
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;
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;
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;
/* 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;
}
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);
}
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);
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);
}
}
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);
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++;
}
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);
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++;
}
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) {
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)
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;
}
}
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)
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;
}
/*
- * $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/
*/
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;
/*
- * $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)
/* 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 */
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 =
*/
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();
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);
}
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;
}
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();
#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;
#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;
#if USE_DNSSERVERS
- ipcacheInvalidate(r->host);
+ ipcacheInvalidate(r->GetHost());
#else
- ipcacheInvalidateNegative(r->host);
+ ipcacheInvalidateNegative(r->GetHost());
#endif /* USE_DNSSERVERS */
#if USE_DNSSERVERS
- ipcacheInvalidate(r->host);
+ ipcacheInvalidate(r->GetHost());
#else
- ipcacheInvalidateNegative(r->host);
+ ipcacheInvalidateNegative(r->GetHost());
#endif /* USE_DNSSERVERS */
}
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);
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);
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);
/*
- * $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/
#include "clientStream.h"
#include "StoreClient.h"
#include "client_side_request.h"
-
+#include "IPAddress.h"
class ErrorState;
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);
/*
- * $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)
/* 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;
clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data;
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(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;
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;
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)
+
/*
- * $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
#include "MemBuf.h"
#include "pconn.h"
#include "SquidTime.h"
+#include "IPAddress.h"
#if defined(_SQUID_CYGWIN_)
#include <sys/ioctl.h>
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<CNCB> callback;
- struct IN_ADDR in_addr;
int fd;
int tries;
int addrcount;
/* 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
/* 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
}
* 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
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 */
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;
}
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
#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
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
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");
F->local_addr = addr;
- F->tos = tos;
+ F->tos = TOS;
+
+ F->sock_family = AI->ai_family;
if (!(flags & COMM_NOCLOEXEC))
commSetCloseOnExec(new_socket);
if ((flags & COMM_REUSEADDR))
commSetReuseAddr(new_socket);
- if (port > (u_short) 0)
+ if (addr.GetPort() > (u_short) 0)
{
#ifdef _SQUID_MSWIN_
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)
cs = new ConnectStateData;
cs->fd = fd;
cs->host = xstrdup(host);
- cs->port = port;
+ cs->default_port = port;
cs->callback = CallBack<CNCB>(callback, data);
comm_add_close_handler(fd, commConnectFree, cs);
ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
}
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);
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<CNCB> aCallback = callback;
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());
* 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;
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");
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);
}
}
}
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;
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 <matusita@ics.es.osaka-u.ac.jp> */
- connect(sock, (struct sockaddr *) address, sizeof(*address));
+ connect(sock, AI->ai_addr, AI->ai_addrlen);
if (errno == EINVAL) {
errlen = sizeof(err);
}
+#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)
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");
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))
}
}
- 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;
}
/* 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)
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;
}
cancelled = true;
}
-ConnectionDetail::ConnectionDetail() {
- memset(&me, 0, sizeof(me));
- memset(&peer, 0, sizeof(peer));
+ConnectionDetail::ConnectionDetail() : me(), peer() {
}
bool
#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)
#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);
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);
/*
- * $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
*
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;
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++;
else
continue;
+#if USE_POLL
+ statCounter.syscalls.polls++;
+#else
statCounter.syscalls.selects++;
+#endif
errno = 0;
/*
- * $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
vfprintf(debug_log, format, args);
- if (!Config.onoff.buffered_logs)
+//*AYJ:*/ if (!Config.onoff.buffered_logs)
fflush(debug_log);
}
/*
- * $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/
#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)
/*
- * $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 <robertc@squid-cache.org>
#include "DelayBucket.h"
#include "DelayUser.h"
#include "DelayTagged.h"
+#include "IPAddress.h"
long DelayPools::MemoryUsed = 0;
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;
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;
};
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 */
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<unsigned char, ClassCBucket> buckets;
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 *
}
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);
}
}
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
/*
- * $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
idns_query *queue;
unsigned short domain;
unsigned short do_searchpath;
+ bool need_A;
};
struct _nsvc
struct _ns
{
-
- struct sockaddr_in S;
+ IPAddress S;
int nqueries;
int nreplies;
nsvc *vc;
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;
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) {
}
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++;
}
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");
}
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);
}
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;
vc->fd = comm_open(SOCK_STREAM,
IPPROTO_TCP,
addr,
- 0,
COMM_NONBLOCKING,
"DNS TCP Socket");
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
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);
x = 0;
} else
x = comm_udp_sendto(DnsSocket,
- &nameservers[ns].S,
- sizeof(nameservers[ns].S),
+ nameservers[ns].S,
q->buf,
q->sz);
}
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;
}
}
+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)
{
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;
* 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);
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);
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);
}
{
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;
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++;
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;
}
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();
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;
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");
*/
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);
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 */
}
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)
{
/*
- * $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
#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);
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)
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");
/*
- * $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
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));
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);
static MemBuf mb;
const char *p = NULL; /* takes priority over mb if set */
int do_quote = 1;
+ char ntoabuf[MAX_IPSTRLEN];
mb.reset();
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;
/*
- * $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/
#include "squid.h"
#include "cbdata.h"
+#include "IPAddress.h"
class AuthUserRequest;
char *dnsserver_msg;
time_t ttl;
- struct IN_ADDR src_addr;
+ IPAddress src_addr;
char *redirect_url;
ERCB *callback;
void *callback_data;
-
/*
- * $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
#include "event.h"
#include "CacheManager.h"
#include "Store.h"
+#include "SquidTime.h"
/* The list of event processes */
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;
/*
- * $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
}
quote;
+
+ IPAddress local_addr;
};
struct _external_acl_format
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);
token = strtok(NULL, w_space);
- a->quote = external_acl::QUOTE_METHOD_URL;
-
/* Parse options */
while (token) {
if (strncmp(token, "ttl=", 4) == 0) {
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;
}
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);
#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;
break;
case _external_acl_format::EXT_ACL_DST:
- str = request->host;
+ str = request->GetHost();
break;
case _external_acl_format::EXT_ACL_PROTO:
p->theHelper->ipc_type = IPC_TCP_SOCKET;
+ p->theHelper->addr = p->local_addr;
+
helperOpenServers(p->theHelper);
}
/*
- * $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
F->flags.open = 0;
fdUpdateBiggest(fd, 0);
Number_FD--;
- memset(F, '\0', sizeof(fde));
+ F->clear();
F->timeout = 0;
}
}
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;
/*
- * $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/
#ifndef SQUID_FDE_H
#define SQUID_FDE_H
+
#include "comm.h"
+#include "IPAddress.h"
class PconnPool;
{
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 *);
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
/*
- * $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
* 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 */
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);
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;
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);
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);
: 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
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);
#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;
*/
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 {
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;
}
}
#endif
- hierarchyNote(&request->hier, fs->code, request->host);
+ hierarchyNote(&request->hier, fs->code, request->GetHost());
}
commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
EBIT_SET(entry->flags, ENTRY_DISPATCHED);
- netdbPingSite(request->host);
+ netdbPingSite(request->GetHost());
if (servers && (p = servers->_peer)) {
p->stats.fetches++;
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);
}
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)
{
return l->addr;
}
- addr.s_addr = INADDR_ANY;
+ addr.SetAnyAddr();
return addr;
}
return 0;
}
-struct IN_ADDR
- getOutgoingAddr(HttpRequest * request)
+IPAddress
+getOutgoingAddr(HttpRequest * request)
{
ACLChecklist ch;
{
ch.src_addr = request->client_addr;
ch.my_addr = request->my_addr;
- ch.my_port = request->my_port;
ch.request = HTTPMSGLOCK(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);
}
class ErrorState;
#include "comm.h"
+#include "IPAddress.h"
class FwdServer
{
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; }
flags;
#if LINUX_NETFILTER
- struct sockaddr_in src;
+ IPAddress src;
#endif
};
/*
- * $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
}
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";
dnsSubmit(hashKeyStr(&f->hash), fqdncacheHandleReply, c);
#else
-
idnsPTRLookup(addr, fqdncacheHandleReply, c);
#endif
}
}
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);
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;
}
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' : ' ',
}
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;
}
/*
- * $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
SENT_TYPE,
SENT_MDTM,
SENT_SIZE,
+ SENT_EPRT,
SENT_PORT,
+ SENT_EPSV,
SENT_PASV,
SENT_CWD,
SENT_LIST,
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;
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 */
title_url.append("@");
}
- title_url.append(request->host);
+ title_url.append(request->GetHost());
if (request->port != urlDefaultPort(PROTO_FTP)) {
title_url.append(":");
base_href.append("@");
}
- base_href.append(request->host);
+ base_href.append(request->GetHost());
if (request->port != urlDefaultPort(PROTO_FTP)) {
base_href.append(":");
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);
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);
ftpReadSize(FtpStateData * ftpState)
{
int code = ftpState->ctrl.replycode;
- debugs(9, 3, "This is ftpReadSize");
+ debugs(9, 3, HERE << "ftpReadSize()");
if (code == 213) {
ftpState->unhack();
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"))
}
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());
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;
}
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;
}
fd_table[ftpState->ctrl.fd].ipaddr << ": " <<
ftpState->ctrl.last_reply);
- ftpSendPort(ftpState);
+ ftpSendEPRT(ftpState);
return;
}
fd_table[ftpState->ctrl.fd].ipaddr << ": " <<
ftpState->ctrl.last_reply);
- ftpSendPort(ftpState);
+ ftpSendEPRT(ftpState);
return;
}
}
{
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.
* 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;
}
*/
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 );
}
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;
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 */
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");
}
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);
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
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
/*
- * $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/
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 */
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 */
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;
/*
- * $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?
progname,
args,
shortname,
+ hlp->addr,
&rfd,
&wfd,
&hIpc);
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);
progname,
args,
shortname,
+ hlp->addr,
&rfd,
&wfd,
&hIpc);
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);
/*
- * $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?
#include "squid.h"
#include "cbdata.h"
+#include "IPAddress.h"
class helper_request;
int n_running;
int n_active;
int ipc_type;
+ IPAddress addr;
unsigned int concurrency;
time_t last_queue_warn;
time_t last_restart;
int n_running;
int n_active;
int ipc_type;
+ IPAddress addr;
MemAllocator *datapool;
HLPSAVAIL *IsAvailable;
HLPSONEQ *OnEmptyQueue;
{
int index;
int pid;
+ IPAddress addr;
int rfd;
int wfd;
MemBuf *wqueue;
}
stats;
+
void *hIpc;
};
{
int index;
int pid;
+ IPAddress addr;
int rfd;
int wfd;
/* MemBuf wqueue; */
/*
- * $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
void checkHit();
void checkedHit(StoreEntry *e);
- void setFrom (struct sockaddr_in *from);
+ void setFrom (IPAddress &from);
void setDataHeader (htcpDataHeader *);
char *method;
char *uri;
private:
HttpRequest *checkHitRequest;
- struct sockaddr_in *from;
+ IPAddress from; // was a ptr. return to such IFF needed. otherwise copy should do.
htcpDataHeader *dhdr;
};
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;
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)
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);
void
-htcpSpecifier::setFrom (struct sockaddr_in *aSocket)
+htcpSpecifier::setFrom (IPAddress &aSocket)
{
from = aSocket;
}
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 */
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];
static void
-htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, struct sockaddr_in *from)
+htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, IPAddress &from)
{
htcpStuff stuff;
static char pkt[8192];
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");
}
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);
}
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);
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;
}
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;
}
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;
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 */
static void
-htcpHandleData(char *buf, int sz, struct sockaddr_in *from)
+htcpHandleData(char *buf, int sz, IPAddress &from)
{
htcpDataHeader hdr;
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;
}
static void
-htcpHandle(char *buf, int sz, struct sockaddr_in *from)
+htcpHandle(char *buf, int sz, IPAddress &from)
{
htcpHeader htcpHdr;
assert (sz >= 0);
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;
}
{
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);
}
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();
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();
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);
/*
- * $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/
#if USE_HTCP
#include "HttpHeader.h"
+#include "IPAddress.h"
class HtcpReplyData
{
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);
/*
- * $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
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;
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!");
}
}
HttpStateData::processReplyBody()
{
- struct IN_ADDR *client_addr = NULL;
+ IPAddress client_addr;
if (!flags.headers_parsed) {
flags.do_next_read = 1;
#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;
/* 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", ',');
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);
}
}
/* 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);
}
}
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);
-
/*
- * $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/
* ----------------------------------------------------------
* 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 */
/*
- * $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/
#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);
/*
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)
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;
}
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;
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);
headerp->pad = htonl(pad);
- headerp->shostid = theOutICPAddr.s_addr;
+ theOutICPAddr.GetInAddr( *((struct in_addr*)&headerp->shostid) );
urloffset = buf + sizeof(icp_common_t);
int
icpUdpSend(int fd,
-
- const struct sockaddr_in *to,
+ const IPAddress &to,
icp_common_t * msg,
log_type logcode,
int delay)
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;
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);
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);
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 */
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))
{
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)
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 */
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)
{
break;
case ICP_HIT:
-#if ALLOW_SOURCE_PING
-
- case ICP_SECHO:
-#endif
case ICP_DECHO:
case ICP_DENIED:
case ICP_MISS_NOFETCH:
- header.handleReply(buf, &from);
+ header.handleReply(buf, from);
break;
case ICP_INVALID:
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;
}
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));
}
{
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;
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;
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
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);
}
}
{
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)
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)
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();
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");
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);
}
/*
/*
- * $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/
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;
}
else
codeToSend = icpGetCommonOpcode();
- icpCreateAndSend (codeToSend, 0, url, header.reqnum, 0, fd, &from);
+ icpCreateAndSend (codeToSend, 0, url, header.reqnum, 0, fd, from);
delete this;
}
/* 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)
{
{
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:
case ICP_DENIED:
case ICP_MISS_NOFETCH:
- header.handleReply(buf, &from);
+ header.handleReply(buf, from);
break;
case ICP_INVALID:
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;
}
}
/*
- * $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
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];
}
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);
}
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);
* 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)
fd = comm_open(SOCK_STREAM,
IPPROTO_TCP,
- me->sin_addr,
- 0,
+ me,
COMM_NONBLOCKING,
"ident");
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,
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);
/*
- * $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
{
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);
/* 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
/*
- * $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
#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
}
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_)
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];
}
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 );
}
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);
}
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);
}
-
/*
- * $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 <tolsty@tushino.com>
int type;
int crfd;
int cwfd;
-
- struct sockaddr_in PS;
+ IPAddress local_addr;
+ struct addrinfo PS;
const char *prog;
char **args;
};
}
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;
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);
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");
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) {
params.cwfd = cwfd;
- params.PS = PS;
+ params.PS = *aiPS;
+
+ params.local_addr = local_addr;
params.prog = prog;
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);
}
struct thread_params thread_params;
ssize_t x;
- int tmp_s, fd = -1;
+ int fd = -1;
char *str;
STARTUPINFO si;
PROCESS_INFORMATION pi;
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;
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);
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;
}
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 << ".");
}
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 << ".");
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;
}
/*
- * $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
#include "SquidTime.h"
#include "Store.h"
#include "wordlist.h"
+#include "IPAddress.h"
typedef struct _ipcache_entry ipcache_entry;
struct timeval request_time;
dlink_node lru;
unsigned short locks;
+ unsigned short cname_wait;
struct
{
#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
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;
/* 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=<NULL>");
+ 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 *
{
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);
ipcacheCallback(ipcache_entry * i)
{
IPH *callback = i->handler;
- void *cbdata;
+ void *cbdata = NULL;
i->lastref = squid_curtime;
if (!i->handler)
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 << "'");
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) {
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) {
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);
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
ipcacheHandleReply(void *data, rfc1035_rr * answers, int na, const char *error_message)
#endif
{
+ int done;
ipcache_entry *i;
static_cast<generic_cbdata *>(data)->unwrap(&i);
IpcacheStats.replies++;
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
}
if ((addrs = ipcacheCheckNumeric(name))) {
+ debugs(14, 4, "ipcache_nbgethostbyname: BYPASS for '" << name << "' (already numeric)");
dns_error_message = NULL;
IpcacheStats.numeric_hits++;
handler(addrs, handlerData);
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);
IpcacheStats.misses++;
if (flags & IP_LOOKUP_IF_MISS)
- ipcache_nbgethostbyname(name, dummy_handler, NULL);
+ ipcache_nbgethostbyname(name, ipcacheHandleCnameRecurse, NULL);
return NULL;
}
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' : ' ',
(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: <IP> '-' ('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 */
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
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;
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))
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 << ")");
}
/*
* 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;
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;
}
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);
void
-ipcacheMarkGoodAddr(const char *name, struct IN_ADDR addr)
+ipcacheMarkGoodAddr(const char *name, IPAddress &addr)
{
ipcache_entry *i;
ipcache_addrs *ia;
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;
}
ia->badcount--;
- debugs(14, 2, "ipcacheMarkGoodAddr: " << name << " [" << inet_ntoa(addr) << "]");
+ debugs(14, 2, "ipcacheMarkGoodAddr: " << name << " " << addr );
}
static void
{
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;
}
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);
/*
- * $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
#include "SwapDir.h"
#include "forward.h"
#include "MemPool.h"
+#include "ICMPSquid.h"
#if USE_WIN32_SERVICE
#endif
clientdbInit();
- icmpOpen();
+ icmpEngine.Open();
netdbInit();
asnInit();
ACL::Initialize();
htcpSocketShutdown();
#endif
- icmpClose();
+ icmpEngine.Close();
#ifdef SQUID_SNMP
snmpConnectionShutdown();
static void
mainRotate(void)
{
- icmpClose();
+ icmpEngine.Close();
#if USE_DNSSERVERS
dnsShutdown();
fwdLogRotate();
#endif
- icmpOpen();
+ icmpEngine.Open();
#if USE_DNSSERVERS
dnsInit();
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();
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);
}
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
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
"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."
--
--- cacheSystem group
+-- cacheSystem group { squid 1 }
--
cacheSysVMsize OBJECT-TYPE
::= { cacheSystem 3 }
--
--- config group
+-- cacheConfig group { squid 2 }
--
-- Contains configuration information including peers etc.
--
--
--- performance group { squid 3 }
+-- cachePerformance group { squid 3 }
--
cacheSysPerf OBJECT IDENTIFIER ::= { cachePerf 1 }
::= { 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.
::= { cacheDns 3 }
--
--- cacheMesh group
+-- cacheMesh group { squid 5 }
--
cachePeerTable OBJECT-TYPE
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,
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
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
STATUS current
DESCRIPTION
" The port the peer listens for HTTP requests "
- ::= { cachePeerEntry 3 }
+ ::= { cachePeerEntry 5 }
cachePeerPortIcp OBJECT-TYPE
SYNTAX Integer32
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
STATUS current
DESCRIPTION
" Peer Type "
- ::= { cachePeerEntry 5 }
+ ::= { cachePeerEntry 7 }
cachePeerState OBJECT-TYPE
SYNTAX INTEGER
STATUS current
DESCRIPTION
" The operational state of this peer "
- ::= { cachePeerEntry 6 }
+ ::= { cachePeerEntry 8 }
cachePeerPingsSent OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of pings sent to peer "
- ::= { cachePeerEntry 7 }
+ ::= { cachePeerEntry 9 }
cachePeerPingsAcked OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of pings received from peer "
- ::= { cachePeerEntry 8 }
+ ::= { cachePeerEntry 10 }
cachePeerFetches OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of times this peer was selected "
- ::= { cachePeerEntry 9 }
+ ::= { cachePeerEntry 11 }
cachePeerRtt OBJECT-TYPE
SYNTAX Integer32
STATUS current
DESCRIPTION
" Last known round-trip time to the peer (in ms) "
- ::= { cachePeerEntry 10 }
+ ::= { cachePeerEntry 12 }
cachePeerIgnored OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" How many times this peer was ignored "
- ::= { cachePeerEntry 11 }
+ ::= { cachePeerEntry 13 }
cachePeerKeepAlSent OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of keepalives sent "
- ::= { cachePeerEntry 12 }
+ ::= { cachePeerEntry 14 }
cachePeerKeepAlRecv OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of keepalives received "
- ::= { cachePeerEntry 13 }
+ ::= { cachePeerEntry 15 }
---
--- Table of cache's clients, with statistics. Children caches can be identified
"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,
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
STATUS current
DESCRIPTION
" Amount of total HTTP traffic to this client "
- ::= { cacheClientEntry 3 }
+ ::= { cacheClientEntry 4 }
cacheClientHttpHits OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of hits in response to this client's HTTP requests "
- ::= { cacheClientEntry 4 }
+ ::= { cacheClientEntry 5 }
cacheClientHTTPHitKb OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Amount of HTTP hit traffic in KB "
- ::= { cacheClientEntry 5 }
+ ::= { cacheClientEntry 6 }
cacheClientIcpRequests OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of ICP requests received from client "
- ::= { cacheClientEntry 6 }
+ ::= { cacheClientEntry 7 }
cacheClientIcpKb OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Amount of total ICP traffic to this client (child) "
- ::= { cacheClientEntry 7 }
+ ::= { cacheClientEntry 8 }
cacheClientIcpHits OBJECT-TYPE
SYNTAX Counter32
STATUS current
DESCRIPTION
" Number of hits in response to this client's ICP requests "
- ::= { cacheClientEntry 8 }
+ ::= { cacheClientEntry 9 }
cacheClientIcpHitKb OBJECT-TYPE
SYNTAX Counter32
/*
- * $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
}
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);
/*
- * $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
#include "PeerSelectState.h"
#include "SquidTime.h"
#include "Store.h"
+#include "IPAddress.h"
/* count mcast group peers every 15 minutes */
#define MCAST_COUNT_RATE 900
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);
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;
}
}
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;
}
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;
}
checklist.my_addr = request->my_addr;
- checklist.my_port = request->my_port;
-
checklist.request = HTTPMSGLOCK(request);
checklist.accessList = cbdataReference(p->access);
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");
"/" << thisPeer->http_port << "/" <<
thisPeer->icp.port);
-
neighborRemove(thisPeer);
}
}
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
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);
query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0);
icpUdpSend(theOutIcpConnection,
- &p->in_addr,
+ p->in_addr,
query,
LOG_ICP_QUERY,
0);
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?
*/
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;
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;
}
*/
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;
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)
{
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;
}
{
peer *p = (peer *)data;
- struct sockaddr_in *ap;
int j;
if (p->n_addresses == 0) {
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);
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;
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;
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);
dump_peers(StoreEntry * sentry, peer * peers)
{
peer *e = NULL;
-
+ char ntoabuf[MAX_IPSTRLEN];
struct _domain_ping *d = NULL;
icp_opcode op;
int i;
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",
#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;
-
/*
- * $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
#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
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);
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);
}
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;
static void
netdbSendPing(const ipcache_addrs * ia, void *data)
{
-
- struct IN_ADDR addr;
+ IPAddress addr;
char *hostname = NULL;
static_cast<generic_cbdata *>(data)->unwrap(&hostname);
netdbEntry *n;
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;
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;
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
netdbEntry *n;
netdbEntry N;
- struct IN_ADDR addr;
+ IPAddress addr;
int count = 0;
struct timeval start = current_time;
if (NULL == q)
continue;
- if (!safe_inet_addr(q, &addr))
+ if (! (addr = q) )
continue;
if (netdbLookupAddr(addr) != NULL) /* no dups! */
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;
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");
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;) {
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:
}
}
- 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);
}
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;
#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);
#endif
return 256;
}
+#endif
void
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",
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,
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;
}
}
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)
void
-netdbDeleteAddrNetwork(struct IN_ADDR addr)
+netdbDeleteAddrNetwork(IPAddress &addr)
{
#if USE_ICMP
netdbEntry *n = netdbLookupAddr(addr);
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);
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;
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]);
/*
- * $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
/* ========== 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);
}
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;
*/
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);
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;
/*
- * $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
{
PeerDigest *pd = (PeerDigest *)data;
time_t req_time;
+ char buf[MAX_IPSTRLEN];
assert(!pd->flags.requested);
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) << ")");
-
/*
- * $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
#include "ACLChecklist.h"
#include "htcp.h"
#include "forward.h"
+#include "SquidTime.h"
const char *hier_strings[] =
{
#endif
if (psstate->entry)
- psstate->entry->lock()
-
- ;
+ psstate->entry->lock();
peerSelectFoo(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");
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);
if (myhops && myhops <= Config.minDirectHops)
return 1;
- p = whichPeer(&psstate->closest_parent_miss);
+ p = whichPeer(psstate->closest_parent_miss);
if (p == NULL)
return 0;
{
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) {
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;
}
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);
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;
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;
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;
}
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;
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;
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;
}
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() :
-
/*
- * $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
#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 <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-
-#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 <winsock2.h>
#include <process.h>
+#include "fde.h"
#define PINGER_TIMEOUT 5
-static int socket_to_squid = -1;
-#define socket_from_squid socket_to_squid
-
-#else /* _SQUID_CYGWIN_ */
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-
-#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);
}
/*
- * $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/
*/
#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;
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 */
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 *);
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 *);
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);
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 *);
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);
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 *);
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);
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);
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);
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 *);
/* 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
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 *);
const char *prog,
const char *const args[],
const char *name,
+ IPAddress &local_addr,
int *rfd,
int *wfd,
void **hIpc);
/*
- * $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
void *data;
char *orig_url;
- struct IN_ADDR client_addr;
+ IPAddress client_addr;
const char *client_ident;
const char *method_s;
RH *handler;
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 << "'");
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)
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);
}
/*
- * $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
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;
}
}
- 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());
-
/*
- * $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
*
*/
-
#include "squid.h"
#include "cache_snmp.h"
#include "Store.h"
#include "mem_node.h"
+#include "SquidTime.h"
/************************************************************************
************************************************************************/
+/*
+ * cacheSystem group
+ */
+
variable_list *
snmp_sysFn(variable_list * Var, snint * ErrP)
{
return Answer;
}
+/*
+ * cacheConfig group
+ */
variable_list *
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;
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:
/*
- * $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
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
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,
#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)))))
)
)
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();
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();
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");
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);
}
}
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;
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);
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);
}
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);
}
}
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);
index++;
- /* Find the parsing function for this variable */
-
if (get_next)
ParseFn = snmpTreeNext(VarPtr->name, VarPtr->name_length, &NextOidName, &NextOidNameLen);
else
snmp_var_free(VarPtr);
}
- /* Was there an error? */
if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) {
Answer->errindex = index;
debugs(49, 5, "snmpAgentResponse: error.");
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);
*RespVars = VarNew;
RespVars = &(VarNew->next_variable);
- }
- }
+ }
+ }
}
return (Answer);
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;
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 {
}
}
}
-
while ((mibTreeEntry) && (!mibTreeEntry->parsefunction)) {
mibTreeEntry = mibTreeEntry->leaves[0];
}
}
if (*Next)
- return (Fn);
+ {
+ debugs(49, 6, "snmpTreeNext: Next : ");
+ snmpDebugOid(6, *Next, *NextLen);
+ return (Fn);
+ }
else
return NULL;
}
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);
}
{
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));
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];
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);
}
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);
}
*/
/*
- * 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)
count++;
}
+ /* Exactly the sibling on rigth */
if (count < current->children) {
next = current->leaves[count];
} else {
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 ; i<size; i++)
+ {
+ cp[i] = id[i];
+ }
+#if USE_IPV6
+ if ( size == sizeof(struct in_addr) )
+#endif
+ addr = iaddr;
+#if USE_IPV6
+ else
+ addr = i6addr;
+#endif
- static struct IN_ADDR laddr;
- u_char *cp = (u_char *) & (laddr.s_addr);
- cp[0] = id[0];
- cp[1] = id[1];
- cp[2] = id[2];
- cp[3] = id[3];
- return &laddr;
}
/* SNMP checklists */
/*
- * $Id: squid.h,v 1.268 2007/12/04 13:31:11 hno Exp $
+ * $Id: squid.h,v 1.269 2007/12/14 23:11:48 amosjeffries Exp $
*
* AUTHOR: Duane Wessels
*
#endif
#include "hash.h"
-#include "rfc1035.h"
+#include "rfc3596.h"
#include "defines.h"
#include "profiling.h"
#include "MemPool.h"
+#include "IPAddress.h"
+
#if !HAVE_TEMPNAM
#include "tempnam.h"
#endif
/*
- * $Id: stat.cc,v 1.410 2007/09/20 20:22:20 hno Exp $
+ * $Id: stat.cc,v 1.411 2007/12/14 23:11:48 amosjeffries Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
#include "client_side_request.h"
#include "client_side.h"
#include "MemBuf.h"
+#include "SquidTime.h"
/* these are included because they expose stats calls */
/* TODO: provide a self registration mechanism for those classes
ClientHttpRequest *http;
StoreEntry *e;
int fd;
+ char buf[MAX_IPSTRLEN];
for (i = ClientActiveRequests.head; i; i = i->next) {
const char *p = NULL;
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);
}
-
/*
- * $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
#include "MemObject.h"
#include "HttpReply.h"
#include "CacheManager.h"
+#include "SquidTime.h"
static const char *storeLogTags[] =
{
/*
- * $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/
long reqid;
int outlen;
- struct sockaddr_in from;
+ IPAddress from;
struct snmp_pdu *PDU;
ACLChecklist *acl_checklist;
acl_address *next;
ACLList *aclList;
- struct IN_ADDR addr;
+ IPAddress addr;
};
struct _acl_tos
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 */
#include "DelayConfig.h"
#endif
+#if USE_ICMP
+#include "ICMPConfig.h"
+#endif
+
/* forward decl for SquidConfig, see RemovalPolicy.h */
class RemovalPolicySettings;
struct
{
- struct IN_ADDR router;
+ IPAddress router;
- struct IN_ADDR address;
+ IPAddress address;
int version;
}
struct
{
- sockaddr_in_list *router;
+ IPAddress_list *router;
- struct IN_ADDR address;
+ IPAddress address;
int forwarding_method;
int return_method;
int assignment_method;
Wccp2;
#endif
+#if USE_ICMP
+ ICMPConfig pinger;
+#endif
+
char *as_whois_server;
struct
#endif
wordlist *redirect;
-#if USE_ICMP
-
- char *pinger;
-#endif
#if USE_UNLINKD
char *unlinkd;
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;
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;
int emailErrData;
int httpd_suppress_version_string;
int global_internal_static;
+ int dns_require_A;
int debug_override_X;
}
struct
{
- struct IN_ADDR addr;
+ IPAddress addr;
int ttl;
unsigned short port;
char *encode_key;
struct _ipcache_addrs
{
-
- struct IN_ADDR *in_addrs;
+ IPAddress *in_addrs;
unsigned char *bad_mask;
unsigned char count;
unsigned char cur;
struct _peer
{
+ u_int index;
char *name;
char *host;
peer_t type;
- struct sockaddr_in in_addr;
+ IPAddress in_addr;
struct
{
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;
struct _netdbEntry
{
hash_link hash; /* must be first */
- char network[16];
+ char network[MAX_IPSTRLEN];
int pings_sent;
int pings_recv;
double hops;
};
-#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
{
{
hash_link hash; /* must be first */
- struct IN_ADDR addr;
+ IPAddress addr;
struct
{
/*
- * $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
/* 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;
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;
}
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));
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);
+}
CPPUNIT_TEST_SUITE( testHttpRequest );
CPPUNIT_TEST( testCreateFromUrlAndMethod );
CPPUNIT_TEST( testCreateFromUrl );
+ CPPUNIT_TEST( testIPv6HostColonBug );
CPPUNIT_TEST_SUITE_END();
public:
protected:
void testCreateFromUrlAndMethod();
void testCreateFromUrl();
+ void testIPv6HostColonBug();
};
#endif
--- /dev/null
+
+#define SQUID_HELPER 1
+#include "squid.h"
+
+#include <cppunit/TestAssert.h>
+
+#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 */
--- /dev/null
+#ifndef SQUID_SRC_TEST_URL_H
+#define SQUID_SRC_TEST_URL_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#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
-
/*
- * $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
#include "SquidTime.h"
+struct timeval current_time;
+double current_dtime;
+
time_t squid_curtime = 0;
time_t
/*
- * $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
{
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;
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
#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)
{
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
#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);
+}
/*
- * $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
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 */
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);
}
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;
/*
- * $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/
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;
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;
/*
- * $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
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 */
Config.Program.unlinkd,
args,
"unlinkd",
+ localhost,
&unlinkd_rfd,
&unlinkd_wfd,
&hIpc);
/*
- * $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
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-._"
+#if USE_IPV6
+ "[:]"
+#endif
;
static const char valid_hostname_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789-."
+#if USE_IPV6
+ "[:]"
+#endif
;
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.
* 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)
{
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)) {
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, '@');
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);
}
}
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 << "'");
debugs(23, 0, "urlParse: Deny access to port " << port);
return NULL;
}
-
#endif
+
if (stringHasWhitespace(urlpath)) {
debugs(23, 2, "urlParse: URI has whitespace: {" << url << "}");
break;
case URI_WHITESPACE_STRIP:
-
default:
t = q = urlpath;
-
while (*t) {
if (!xisspace(*t))
*q++ = *t;
-
t++;
}
-
*q = '\0';
}
}
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;
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:
ProtocolStr[request->protocol],
request->login,
*request->login ? "@" : null_string,
- request->host,
+ request->GetHost(),
portbuf,
request->urlpath.buf());
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:
snprintf(buf, MAX_URL, "%s://%s%s%s%s",
ProtocolStr[request->protocol],
loginbuf,
- request->host,
+ request->GetHost(),
portbuf,
request->urlpath.buf());
/*
while (*hostStart != '\0' && *hostStart == '/')
++hostStart;
+
+#if USE_IPV6
+ if (*hostStart == ']')
+ ++hostStart;
+#endif
+
}
void
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
/*
- * $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
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());
/*
- * $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
struct wccp_cache_entry_t
{
-
- struct IN_ADDR ip_addr;
+ IPAddress ip_addr;
int revision;
char hash[WCCP_HASH_SIZE];
int reserved;
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);
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);
}
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");
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);
}
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=" <<
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)
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;
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;
}
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++) {
/*
- * $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
#include "Parsing.h"
#include "Store.h"
#include "SwapDir.h"
+#include "IPAddress.h"
#if USE_WCCPv2
#include <netdb.h>
/* WCCP v2 packet header */
+/// \interface WCCPv2 Protocol
struct wccp2_here_i_am_header_t
{
uint32_t type;
uint32_t security_option;
};
+/// \interface WCCPv2 Protocol
struct wccp2_security_md5_t
{
uint16_t security_type;
/* Service info struct */
+/// \interface WCCPv2 Protocol
struct wccp2_service_info_t
{
uint16_t service_type;
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];
/* Web Cache identity info */
+/// \interface WCCPv2 Protocol
struct wccp2_identity_info_t
{
uint16_t cache_identity_type;
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;
/* Web Cache identity info */
+/// \interface WCCPv2 Protocol
struct wccp2_mask_identity_info_t
{
uint16_t cache_identity_type;
/* View header */
+/// \interface WCCPv2 Protocol
struct wccp2_cache_view_header_t
{
uint16_t cache_view_type;
/* View info */
+/// \interface WCCPv2 Protocol
struct wccp2_cache_view_info_t
{
uint32_t num_routers;
/* 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;
};
/* Capability info header */
+/// \interface WCCpv2 Protocol
struct wccp2_capability_info_header_t
{
uint16_t capability_info_type;
/* Capability element header */
+/// \interface WCCPv2 Protocol
struct wccp2_capability_element_header_t
{
uint16_t capability_type;
/* Capability element */
+/// \interface WCCPv2 Protocol
struct wccp2_capability_element_t
{
uint16_t capability_type;
/* Mask Element */
+/// \interface WCCPv2 Protocol
struct wccp2_mask_element_t
{
uint32_t source_ip_mask;
/* Value Element */
+/// \interface WCCPv2 Protocol
struct wccp2_value_element_t
{
uint32_t source_ip_value;
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;
/* 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;
/* Router identity struct */
+/// \interface WCCPv2 Protocol
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;
/* 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
{
/* 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;
static int wccp2_numrouters;
+/// \interface WCCPv2 Protocol
struct wccp2_service_list_t
{
void
wccp2Init(void)
{
- sockaddr_in_list *s;
+ IPAddress_list *s;
char *ptr;
uint32_t service_flags;
/* 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++;
}
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));
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);
/* 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);
/* 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 */
void
wccp2ConnectionOpen(void)
{
- u_short port = WCCP_PORT;
-
struct sockaddr_in router, local, null;
socklen_t local_len, router_len;
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");
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 */
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))
* but disconnects anyway so we have to just assume it worked
*/
if (wccp2_numrouters > 1)
-
connect(theWccp2Connection, (struct sockaddr *) &null, router_len);
}
struct sockaddr_in from;
struct IN_ADDR cache_address;
- socklen_t from_len;
int len, found;
short int data_length, offset;
uint32_t tmp;
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;
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");
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;
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) */
if (wccp2_numrouters > 1) {
comm_udp_sendto(theWccp2Connection,
- &router,
- router_len,
+ router,
&service_list_ptr->wccp_packet,
service_list_ptr->wccp_packet_size);
} else {
/* 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 {
-
/*
- * $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 <serassio@squid-cache.org>
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);
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;
}
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)
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 *);
#include <sys/stat.h>
#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
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;
}
/*
- * $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
#include "assert.h"
#include "util.h"
+#include "IPAddress.h"
#ifndef DEFAULT_CACHEMGR_CONFIG
#define DEFAULT_CACHEMGR_CONFIG "/etc/squid/cachemgr.conf"
static const char *progname = NULL;
static time_t now;
-static struct IN_ADDR no_addr;
-
/*
* Function prototypes
*/
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;
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);
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"
char *s;
cachemgr_request *req;
- safe_inet_addr("255.255.255.255", &no_addr);
now = time(NULL);
#ifdef _SQUID_MSWIN_
/*
- * $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
#endif
#include "util.h"
+#include "IPAddress.h"
#ifndef BUFSIZ
#define BUFSIZ 8192
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 *);
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";
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));
fprintf(stderr, "client: ERROR: Cannot send request?: %s\n", msg);
exit(1);
}
+
if (put_file) {
int x;
lseek(put_fd, 0, SEEK_SET);
}
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