--------------------- PatchSet 6212 Date: 2007/12/01 02:11:37 Author: amosjeffries Branch: squid3-ipv6 Tag: (none) Log: Fix many small problems with pinger upgrade. Works now AFAICT. Members: NOTES-IPv6:1.1.2.74->1.1.2.75 configure.in:1.63.2.67->1.63.2.68 src/ICMP.h:1.1.2.10->1.1.2.11 src/ICMPPinger.cc:1.1.2.1->1.1.2.2 src/ICMPPinger.h:1.1.2.1->1.1.2.2 src/ICMPSquid.cc:1.1.2.7->1.1.2.8 src/ICMPSquid.h:1.1.2.3->1.1.2.4 src/ICMPv4.cc:1.1.2.5->1.1.2.6 src/ICMPv4.h:1.1.2.5->1.1.2.6 src/ICMPv6.cc:1.1.2.4->1.1.2.5 src/ICMPv6.h:1.1.2.2->1.1.2.3 src/Makefile.am:1.58.2.28->1.58.2.29 src/debug.cc:1.13.8.5->1.13.8.6 src/pinger.cc:1.9.8.13->1.9.8.14 Index: squid3/NOTES-IPv6 =================================================================== RCS file: /cvsroot/squid-sf//squid3/Attic/NOTES-IPv6,v retrieving revision 1.1.2.74 retrieving revision 1.1.2.75 diff -u -r1.1.2.74 -r1.1.2.75 --- squid3/NOTES-IPv6 27 Nov 2007 08:07:58 -0000 1.1.2.74 +++ squid3/NOTES-IPv6 1 Dec 2007 02:11:37 -0000 1.1.2.75 @@ -1,4 +1,4 @@ -$Id: NOTES-IPv6,v 1.1.2.74 2007/11/27 08:07:58 amosjeffries Exp $ +$Id: NOTES-IPv6,v 1.1.2.75 2007/12/01 02:11:37 amosjeffries Exp $ NP: Any problems with this version of squid please contact squid3@treenet.co.nz for assistance. @@ -7,11 +7,9 @@ Any volunteers welcome. For the rest cache_dir's should be built from an empty state in the usual manner. -NP: pinger has had major alteration. If you just want to run this branch (no testing). - I recommend --disable-icmp until its had at the very least some unit-tests created. - -NP: Same with SNMP agent. If you just want to run this branch (no testing). - I recommend --disable-snmp until its had at the very least some unit-tests created. +NP: SNMP agent has undergone major alterations. + If you just want to run this branch (no testing). + I recommend --disable-snmp until its had at the very least some unit-tests created. IPv6 NEW FEATURES: @@ -28,6 +26,11 @@ addresses to IPv6 sockets, but require the client to do all the v4-mapping itself. It is not intended to be used outside Windows Vista builds. + Pinger has been upgraded to perform both ICMP and ICMPv6 as required. + As a result of this and due to a change in the binary protocol format between them, + new builds of squid are no longer backwards-compatible with old pinger binaries. + You will need to perform "make install-pinger" again after installing squid. + IPv6 LIMITS: @@ -55,6 +58,12 @@ CURRENTLY KNOWN ISSUES: +PROBLEM: squidclient mgr:ipcache with NXDOMAIN can produce: + Hostname Flg lstref TTL N(b) + kame.net N 2 58 0( 0) www.treenet.co.nz 38 21562 1( 0) + + + PROBLEM: external helper dnsserver "-s" option requires IPv4-only structures. UPDATE: The internal resolver structure _res* proved to be a very nasty mess. I've found the time to sort it out (I think) and it appears to be going @@ -153,8 +162,8 @@ defines A6, DNAME, packet sizes 4.3 Test new ICMP* engines - - Write unit tests for ICMPv, ICMPv6, ICMPSquid, ICMPPinger classes - - still requires TTL/Hop retrieval in ICMPv6 (v6 addresses always seen as 0 hops away :-) + - Write unit tests for ICMPv*, ICMPSquid, ICMPPinger classes + - still requires Hop retrieval in ICMPv6 (v6 addresses always seen as 1 hops away :-) 4.4 Upgrade peer selection bucket sizes - currently using 32-bit buckets Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.63.2.67 retrieving revision 1.63.2.68 diff -u -r1.63.2.67 -r1.63.2.68 --- squid3/configure.in 27 Nov 2007 07:59:06 -0000 1.63.2.67 +++ squid3/configure.in 1 Dec 2007 02:11:37 -0000 1.63.2.68 @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.63.2.67 2007/11/27 07:59:06 amosjeffries Exp $ +dnl $Id: configure.in,v 1.63.2.68 2007/12/01 02:11:37 amosjeffries Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.63.2.67 $)dnl +AC_REVISION($Revision: 1.63.2.68 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -668,14 +668,8 @@ [ 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 ]) @@ -1934,6 +1928,7 @@ netinet/icmp6.h \ netinet/in_systm.h \ netinet/ip.h \ + netinet/ip6.h \ netinet/ip_icmp.h \ netinet/ip_fil_compat.h \ openssl/err.h \ Index: squid3/src/ICMP.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMP.h,v retrieving revision 1.1.2.10 retrieving revision 1.1.2.11 diff -u -r1.1.2.10 -r1.1.2.11 --- squid3/src/ICMP.h 29 Oct 2007 12:24:09 -0000 1.1.2.10 +++ squid3/src/ICMP.h 1 Dec 2007 02:11:37 -0000 1.1.2.11 @@ -1,5 +1,5 @@ /* - * $Id: ICMP.h,v 1.1.2.10 2007/10/29 12:24:09 amosjeffries Exp $ + * $Id: ICMP.h,v 1.1.2.11 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -39,7 +39,7 @@ #define PINGER_PAYLOAD_SZ 8192 -#define MAX_PAYLOAD SQUIDHOSTNAMELEN +#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) @@ -111,9 +111,9 @@ \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. + \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, int len) =0; + virtual void SendEcho(IPAddress &to, int opcode, const char *payload=NULL, int len=0) =0; /// Handle ICMP responses. virtual void Recv(void) =0; @@ -130,7 +130,8 @@ \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...128) : 64 >= 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 * Index: squid3/src/ICMPPinger.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPPinger.cc,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/ICMPPinger.cc 16 Oct 2007 13:36:15 -0000 1.1.2.1 +++ squid3/src/ICMPPinger.cc 1 Dec 2007 02:11:37 -0000 1.1.2.2 @@ -1,5 +1,5 @@ /* - * $Id: ICMPPinger.cc,v 1.1.2.1 2007/10/16 13:36:15 amosjeffries Exp $ + * $Id: ICMPPinger.cc,v 1.1.2.2 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels @@ -42,6 +42,7 @@ #include "ICMPPinger.h" #include "ICMPv4.h" #include "ICMPv6.h" +#include "Debug.h" ICMPPinger::ICMPPinger() : ICMP() { @@ -58,8 +59,6 @@ int ICMPPinger::Open(void) { - struct protoent *proto = NULL; - #ifdef _SQUID_MSWIN_ WSADATA wsaData; @@ -79,7 +78,7 @@ if (x < (int)sizeof(wpi)) { getCurrentTime(); - debugs(42, 0, "pingerOpen: read: FD 0: " << xstrerror()); + debugs(42, 0, HERE << "read: FD 0: " << xstrerror()); write(1, "ERR\n", 4); return -1; } @@ -91,26 +90,18 @@ if (x < (int)sizeof(PS)) { getCurrentTime(); - debugs(42, 0, "pingerOpen: read: FD 0: " << xstrerror()); + debugs(42, 0, HERE << "read: FD 0: " << xstrerror()); write(1, "ERR\n", 4); return -1; } xmemcpy(&PS, buf, sizeof(PS)); -#endif - - if ((proto = getprotobyname("icmp")) == 0) { - debugs(42, 0, "pingerOpen: unknown protocol: icmp"); - return -1; - } - -#ifdef _SQUID_MSWIN_ icmp_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &wpi, 0, 0); if (icmp_sock == -1) { getCurrentTime(); - debugs(42, 0, "pingerOpen: WSASocket: " << xstrerror()); + debugs(42, 0, HERE << "WSASocket: " << xstrerror()); write(1, "ERR\n", 4); return -1; } @@ -119,7 +110,7 @@ if (SOCKET_ERROR == x) { getCurrentTime(); - debugs(42, 0, "pingerOpen: connect: " << xstrerror()); + debugs(42, 0, HERE << "connect: " << xstrerror()); write(1, "ERR\n", 4); return -1; } @@ -129,19 +120,19 @@ x = recv(icmp_sock, (void *) buf, sizeof(buf), 0); if (x < 3) { - debugs(42, 0, "icmpOpen: recv: " << xstrerror()); + 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, "icmpOpen: recv: " << xstrerror()); + debugs(42, 0, HERE << "recv: " << xstrerror()); return -1; } getCurrentTime(); - debugs(42, 0, "pinger: Squid socket opened"); + debugs(42, 1, "pinger: Squid socket opened"); /* windows uses a socket stream as a dual-direction channel */ socket_to_squid = icmp_sock; @@ -149,7 +140,7 @@ return icmp_sock; -#else /* _SQUID_MSWIN_ */ +#else /* !_SQUID_MSWIN_ */ /* non-windows apps use stdin/out pipes as the squid channel(s) */ socket_from_squid = 0; // use STDIN macro ?? @@ -181,18 +172,19 @@ 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, 0, "Pinger exiting."); + debugs(42, 1, "Pinger exiting."); Close(); exit(1); } if (0 == n) { /* EOF indicator */ - fprintf(stderr, "EOF encountered. Pinger exiting.\n"); + debugs(42, 0, HERE << "EOF encountered. Pinger exiting.\n"); errno = 0; Close(); exit(1); @@ -201,8 +193,7 @@ 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); + debugs(42, 2, HERE << "size mismatch, guess=" << guess_size << ", psize=" << pecho.psize); /* don't process this message, but keep running */ return; } @@ -210,6 +201,7 @@ #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, @@ -218,19 +210,25 @@ #endif /* pass the packet for ICMP handling */ - if(pecho.to.IsIPv4()) { + 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(50, 0, "pinger: send: " << xstrerror()); + debugs(42, 0, "pinger: FATAL error on send: " << xstrerror()); Close(); exit(1); } Index: squid3/src/ICMPPinger.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPPinger.h,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- squid3/src/ICMPPinger.h 16 Oct 2007 13:36:15 -0000 1.1.2.1 +++ squid3/src/ICMPPinger.h 1 Dec 2007 02:11:37 -0000 1.1.2.2 @@ -1,5 +1,5 @@ /* - * $Id: ICMPPinger.h,v 1.1.2.1 2007/10/16 13:36:15 amosjeffries Exp $ + * $Id: ICMPPinger.h,v 1.1.2.2 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -73,7 +73,7 @@ #endif /* USE_ICMP */ }; -#if USE_ICMP && SQUID_HELPER +#if USE_ICMP /// pinger helper contains one of these as a global object. SQUIDCEXTERN ICMPPinger control; Index: squid3/src/ICMPSquid.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPSquid.cc,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -r1.1.2.7 -r1.1.2.8 --- squid3/src/ICMPSquid.cc 27 Oct 2007 06:03:44 -0000 1.1.2.7 +++ squid3/src/ICMPSquid.cc 1 Dec 2007 02:11:37 -0000 1.1.2.8 @@ -1,5 +1,5 @@ /* - * $Id: ICMPSquid.cc,v 1.1.2.7 2007/10/27 06:03:44 amosjeffries Exp $ + * $Id: ICMPSquid.cc,v 1.1.2.8 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -37,24 +37,23 @@ #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 - -#if USE_ICMP - static void * hIpc; static pid_t pid; #endif /* USE_ICMP */ + ICMPSquid::ICMPSquid() : ICMP() { ; // nothing new. @@ -74,9 +73,27 @@ static pingerEchoData pecho; int x, slen; - if (payload && len == 0) + /** \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; @@ -85,7 +102,8 @@ pecho.psize = len; - xmemcpy(pecho.payload, payload, len); + if(len > 0) + xmemcpy(pecho.payload, payload, len); slen = sizeof(pingerEchoData) - PINGER_PAYLOAD_SZ + pecho.psize; @@ -96,16 +114,20 @@ 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) { @@ -118,9 +140,7 @@ int n; static int fail_count = 0; pingerReplyData preply; - static IPAddress F; - debugs(37,0, HERE << "icmp_sock=" << icmp_sock); commSetSelect(icmp_sock, COMM_SELECT_READ, icmpSquidRecv, NULL, 0); memset(&preply, '\0', sizeof(pingerReplyData)); @@ -146,8 +166,10 @@ fail_count = 0; - if (n == 0) /* test probe from pinger */ + /** If its a test probe from the pinger. Do nothing. */ + if (n == 0) { return; + } F = preply.from; @@ -156,9 +178,11 @@ 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; @@ -174,7 +198,7 @@ ICMPSquid::DomainPing(IPAddress &to, const char *domain) { #if USE_ICMP - debugs(37, 3, HERE << "'" << domain << "'"); + debugs(37, 4, HERE << "'" << domain << "' (" << to << ")"); SendEcho(to, S_ICMP_DOM, domain, 0); #endif } @@ -187,9 +211,11 @@ int rfd; int wfd; IPAddress localhost; + 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 @@ -219,6 +245,13 @@ 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); @@ -251,7 +284,7 @@ if (hIpc) { if (WaitForSingleObject(hIpc, 12000) != WAIT_OBJECT_0) { getCurrentTime(); - debugs(37, 1, HERE << "WARNING: (pinger," << pid << ") didn't exit in 12 seconds"); + debugs(37, 0, HERE << "WARNING: (pinger," << pid << ") didn't exit in 12 seconds"); } CloseHandle(hIpc); Index: squid3/src/ICMPSquid.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPSquid.h,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -r1.1.2.3 -r1.1.2.4 --- squid3/src/ICMPSquid.h 24 Oct 2007 02:34:39 -0000 1.1.2.3 +++ squid3/src/ICMPSquid.h 1 Dec 2007 02:11:37 -0000 1.1.2.4 @@ -1,5 +1,5 @@ /* - * $Id: ICMPSquid.h,v 1.1.2.3 2007/10/24 02:34:39 amosjeffries Exp $ + * $Id: ICMPSquid.h,v 1.1.2.4 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -58,14 +58,12 @@ void DomainPing(IPAddress &to, const char *domain); #if USE_ICMP - virtual void SendEcho(IPAddress &, int, const char*, int); + virtual void SendEcho(IPAddress &to, int opcode, const char* payload=NULL, int len=0); virtual void Recv(void); #endif }; -#if !SQUID_HELPER // global engine within squid. SQUIDCEXTERN ICMPSquid icmpEngine; -#endif #endif /* _INCLUDE_ICMPSQUID_H */ Index: squid3/src/ICMPv4.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPv4.cc,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ICMPv4.cc 31 Oct 2007 04:51:38 -0000 1.1.2.5 +++ squid3/src/ICMPv4.cc 1 Dec 2007 02:11:37 -0000 1.1.2.6 @@ -1,5 +1,5 @@ /* - * $Id: ICMPv4.cc,v 1.1.2.5 2007/10/31 04:51:38 amosjeffries Exp $ + * $Id: ICMPv4.cc,v 1.1.2.6 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels, Amos Jeffries @@ -31,8 +31,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ - -#define SQUID_HELPER 1 +//#define SQUID_HELPER 1 #include "squid.h" @@ -41,6 +40,7 @@ #include "SquidTime.h" #include "ICMPv4.h" #include "ICMPPinger.h" +#include "Debug.h" const char *icmpPktStr[] = { @@ -77,14 +77,7 @@ int ICMPv4::Open(void) { - struct protoent *proto = NULL; - - if ((proto = getprotobyname("icmp")) == 0) { - debugs(42, 0, HERE << " unknown protocol: icmp"); - return -1; - } - - icmp_sock = socket(PF_INET, SOCK_RAW, proto->p_proto); + icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); if (icmp_sock < 0) { debugs(50, 0, HERE << " icmp_sock: " << xstrerror()); @@ -92,7 +85,7 @@ } icmp_ident = getpid() & 0xffff; - debugs(42, 0, "pinger: ICMP socket opened"); + debugs(42, 1, "pinger: ICMP socket opened."); return icmp_sock; } @@ -100,6 +93,7 @@ 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; @@ -149,12 +143,20 @@ to.GetAddrInfo(S); ((sockaddr_in*)S->ai_addr)->sin_port = 0; assert(icmp_pktsize <= MAX_PKT4_SZ); - sendto(icmp_sock, + + 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); } @@ -163,19 +165,18 @@ { int n; struct addrinfo *from = NULL; - int iphdrlen = 20; - + 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) + 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); @@ -200,7 +201,7 @@ #endif - debugs(42, 9, "pingerRecv: " << n << " bytes from " << preply.from); + debugs(42, 8, HERE << n << " bytes from " << preply.from); ip = (struct iphdr *) (void *) pkt; Index: squid3/src/ICMPv4.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPv4.h,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ICMPv4.h 31 Oct 2007 04:51:38 -0000 1.1.2.5 +++ squid3/src/ICMPv4.h 1 Dec 2007 02:11:37 -0000 1.1.2.6 @@ -1,5 +1,5 @@ /* - * $Id: ICMPv4.h,v 1.1.2.5 2007/10/31 04:51:38 amosjeffries Exp $ + * $Id: ICMPv4.h,v 1.1.2.6 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -137,6 +137,10 @@ #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 @@ -165,7 +169,7 @@ #endif }; -#if USE_ICMP && SQUID_HELPER +#if USE_ICMP /// pinger helper contains one of these as a global object. SQUIDCEXTERN ICMPv4 icmp4; Index: squid3/src/ICMPv6.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPv6.cc,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -r1.1.2.4 -r1.1.2.5 --- squid3/src/ICMPv6.cc 26 Nov 2007 00:24:13 -0000 1.1.2.4 +++ squid3/src/ICMPv6.cc 1 Dec 2007 02:11:37 -0000 1.1.2.5 @@ -1,5 +1,5 @@ /* - * $Id: ICMPv6.cc,v 1.1.2.4 2007/11/26 00:24:13 amosjeffries Exp $ + * $Id: ICMPv6.cc,v 1.1.2.5 2007/12/01 02:11:37 amosjeffries Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels, Amos Jeffries @@ -31,16 +31,24 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ -#define SQUID_HELPER 1 +//#define SQUID_HELPER 1 #include "squid.h" -#include "SquidTime.h" #if USE_ICMP && USE_IPV6 +#include "SquidTime.h" +#include "Debug.h" #include "ICMPv6.h" #include "ICMPPinger.h" +// Some system headers are only neeed internally here. +// They should not be included via the header. + +#if HAVE_NETINET_IP6_H +#include +#endif + // ICMPv6 OP-Codes // see http://www.iana.org/assignments/icmpv6-parameters // NP: LowPktStr is for codes 0-127 @@ -110,14 +118,7 @@ int ICMPv6::Open(void) { - struct protoent *proto = NULL; - - if ((proto = getprotobyname("icmp")) == 0) { - debugs(42, 0, HERE << " unknown protocol: icmp"); - return -1; - } - - icmp_sock = socket(PF_INET6, SOCK_RAW, proto->p_proto); + icmp_sock = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6); if (icmp_sock < 0) { debugs(50, 0, HERE << " icmp_sock: " << xstrerror()); @@ -125,7 +126,7 @@ } icmp_ident = getpid() & 0xffff; - debugs(42, 0, "pinger: ICMPv6 socket opened"); + debugs(42, 1, "pinger: ICMPv6 socket opened"); return icmp_sock; } @@ -136,6 +137,7 @@ 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; @@ -186,12 +188,21 @@ ((sockaddr_in6*)S->ai_addr)->sin6_port = 0; assert(icmp6_pktsize <= MAX_PKT6_SZ); - sendto(icmp_sock, + + 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); } @@ -202,31 +213,33 @@ ICMPv6::Recv(void) { int n; - struct addrinfo *afrom = NULL; - int iphdrlen = 20; -// struct iphdr *ip = NULL; + 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) + if(icmp_sock < 0) { + debugs(42,0, HERE << "dropping ICMPv6 read. No socket!?"); return; + } - if (pkt == NULL) + if (pkt == NULL) { pkt = (char *)xmalloc(MAX_PKT6_SZ); + } - preply.from.InitAddrInfo(afrom); + preply.from.InitAddrInfo(from); n = recvfrom(icmp_sock, (void *)pkt, MAX_PKT6_SZ, 0, - afrom->ai_addr, - &afrom->ai_addrlen); + from->ai_addr, + &from->ai_addrlen); - preply.from = *afrom; + preply.from = *from; #if GETTIMEOFDAY_NO_TZP @@ -238,35 +251,93 @@ #endif - debugs(42, 9, "pingerRecv: " << n << " bytes from " << preply.from); + debugs(42, 8, HERE << n << " bytes from " << preply.from); -// AYJ FIXME : TTL still has to come from the IP header somewhere. +// 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. - - icmp6 = (struct icmp6_hdr *) (void *) (pkt + iphdrlen); - - if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) +// 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) + 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 + iphdrlen); + echo = (icmpEchoData *) pkt; preply.opcode = echo->opcode; -/*AYJ see above preply.hops = ipHops(icmpip->ip_ttl); */ preply.hops = 0; // null it for now. - preply.rtt = tvSubMsec(echo->tv, now); - preply.psize = n - iphdrlen - (sizeof(icmpEchoData) - MAX_PKT6_SZ); +/* + * 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; - /* send results of the lookup back to squid.*/ - control.SendResult(preply, (sizeof(pingerReplyData) - MAX_PKT6_SZ + preply.psize) ); + preply.psize = n - /* sizeof(ip6_hdr) - */ sizeof(icmp6_hdr) - (sizeof(icmpEchoData) - MAX_PKT6_SZ); - Log(preply.from, preply.opcode, - ( preply.opcode&0x80 ? icmp6HighPktStr[(preply.opcode&0x7f)] : icmp6LowPktStr[(preply.opcode&0x7f)] ), - preply.rtt, preply.hops); + /* 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 */ Index: squid3/src/ICMPv6.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/ICMPv6.h,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- squid3/src/ICMPv6.h 16 Oct 2007 13:35:08 -0000 1.1.2.2 +++ squid3/src/ICMPv6.h 1 Dec 2007 02:11:38 -0000 1.1.2.3 @@ -1,5 +1,5 @@ /* - * $Id: ICMPv6.h,v 1.1.2.2 2007/10/16 13:35:08 amosjeffries Exp $ + * $Id: ICMPv6.h,v 1.1.2.3 2007/12/01 02:11:38 amosjeffries Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels, Amos Jeffries @@ -41,18 +41,29 @@ #include "ICMP.h" #include "IPAddress.h" +#if HAVE_NETINET_IN_H +#include +#endif #if HAVE_NETINET_ICMP6_H #include #endif +#include + +/* 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. @@ -72,7 +83,7 @@ #endif }; -#if USE_ICMP && SQUID_HELPER +#if USE_ICMP /// pinger helper contains one of these as a global object. SQUIDCEXTERN ICMPv6 icmp6; Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.58.2.28 retrieving revision 1.58.2.29 diff -u -r1.58.2.28 -r1.58.2.29 --- squid3/src/Makefile.am 1 Nov 2007 10:39:55 -0000 1.58.2.28 +++ squid3/src/Makefile.am 1 Dec 2007 02:11:38 -0000 1.58.2.29 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.58.2.28 2007/11/01 10:39:55 amosjeffries Exp $ +# $Id: Makefile.am,v 1.58.2.29 2007/12/01 02:11:38 amosjeffries Exp $ # # Uncomment and customize the following to suit your needs: # @@ -127,6 +127,13 @@ PINGER = endif +# Squid Internal ICMP sources +ICMPSOURCE = \ + ICMP.h \ + icmp.cc \ + ICMPSquid.h \ + ICMPSquid.cc + SSL_ALL_SOURCE = \ ACLCertificateData.cc \ ACLCertificateData.h \ @@ -134,6 +141,7 @@ ACLCertificate.h \ ssl_support.cc \ ssl_support.h + if ENABLE_SSL SSL_SOURCE = $(SSL_ALL_SOURCE) else @@ -507,10 +515,7 @@ HttpRequestMethod.cc \ HttpRequestMethod.h \ HttpVersion.h \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ ICP.h \ icp_v2.cc \ icp_v3.cc \ @@ -707,6 +712,8 @@ 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 \ @@ -823,10 +830,7 @@ HttpReply.cc \ HttpRequest.cc \ HttpRequestMethod.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1352,10 +1356,7 @@ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1521,10 +1522,7 @@ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1676,10 +1674,7 @@ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -1859,10 +1854,7 @@ HttpRequest.cc \ HttpRequestMethod.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -2017,10 +2009,7 @@ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ @@ -2376,10 +2365,7 @@ HttpMsg.cc \ HttpReply.cc \ HttpStatusLine.cc \ - ICMP.h \ - icmp.cc \ - ICMPSquid.h \ - ICMPSquid.cc \ + $(ICMPSOURCE) \ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ Index: squid3/src/debug.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/debug.cc,v retrieving revision 1.13.8.5 retrieving revision 1.13.8.6 diff -u -r1.13.8.5 -r1.13.8.6 --- squid3/src/debug.cc 29 Oct 2007 08:36:30 -0000 1.13.8.5 +++ squid3/src/debug.cc 1 Dec 2007 02:11:38 -0000 1.13.8.6 @@ -1,5 +1,5 @@ /* - * $Id: debug.cc,v 1.13.8.5 2007/10/29 08:36:30 amosjeffries Exp $ + * $Id: debug.cc,v 1.13.8.6 2007/12/01 02:11:38 amosjeffries Exp $ * * DEBUG: section 0 Debug Routines * AUTHOR: Harvest Derived @@ -173,7 +173,7 @@ vfprintf(debug_log, format, args); - if (!Config.onoff.buffered_logs) +//*AYJ:*/ if (!Config.onoff.buffered_logs) fflush(debug_log); } Index: squid3/src/pinger.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/pinger.cc,v retrieving revision 1.9.8.13 retrieving revision 1.9.8.14 diff -u -r1.9.8.13 -r1.9.8.14 --- squid3/src/pinger.cc 24 Oct 2007 01:42:04 -0000 1.9.8.13 +++ squid3/src/pinger.cc 1 Dec 2007 02:11:38 -0000 1.9.8.14 @@ -1,5 +1,5 @@ /* - * $Id: pinger.cc,v 1.9.8.13 2007/10/24 01:42:04 amosjeffries Exp $ + * $Id: pinger.cc,v 1.9.8.14 2007/12/01 02:11:38 amosjeffries Exp $ * * DEBUG: section 42 ICMP Pinger program * AUTHOR: Duane Wessels @@ -68,7 +68,7 @@ #else -#define PINGER_TIMEOUT 10 +#define PINGER_TIMEOUT 100 /* non-windows use STDOUT for feedback to squid */ #define LINK_TO_SQUID 1 @@ -80,7 +80,7 @@ ICMPv4 icmp4; #if USE_IPV6 ICMPv6 icmp6; -#endif /* USE_IPV6 */ +#endif int icmp_pkts_sent = 0; @@ -89,9 +89,10 @@ { fd_set R; int x; + int max_fd = 0; struct timeval tv; - const char *debug_args = "ALL,1 42,9"; + const char *debug_args = "ALL,10"; char *t; time_t last_check_time = 0; @@ -100,21 +101,33 @@ * drop privs */ int icmp4_worker = -1; +#if USE_IPV6 int icmp6_worker = -1; +#endif int squid_link = -1; - debugs(42, 0, "pinger: Initialising ICMP pinger ..."); + /* start by initializing the pinger debug cache.log-pinger */ + if ((t = getenv("SQUID_DEBUG"))) + debug_args = xstrdup(t); + + getCurrentTime(); + + _db_init("/tmp/squid-pinger.log", debug_args); + + debugs(42, 0, "pinger: Initialising ICMP pinger ..."); icmp4_worker = icmp4.Open(); if(icmp4_worker < 0) { debugs(42, 0, "pinger: Unable to start ICMP pinger."); } + max_fd = max(max_fd, icmp4_worker); #if USE_IPV6 icmp6_worker = icmp6.Open(); if(icmp6_worker <0 ) { debugs(42, 0, "pinger: Unable to start ICMPv6 pinger."); } + max_fd = max(max_fd, icmp6_worker); #endif // abort if neither worker could open a socket. @@ -122,28 +135,23 @@ #if USE_IPV6 if(icmp6_worker == -1) #endif + debugs(42, 0, "FATAL: pinger: Unable to open any ICMP sockets."); exit(1); } if( (squid_link = control.Open()) < 0) { - debugs(42, 0, "pinger: Unable to setup Pinger control sockets."); + 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. } + max_fd = max(max_fd, squid_link); 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; @@ -151,28 +159,35 @@ 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(squid_link + 1, &R, NULL, NULL, &tv); + x = select(10, &R, NULL, NULL, &tv); getCurrentTime(); if (x < 0) { + debugs(42, 0, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerror()); control.Close(); exit(1); } - if (FD_ISSET(squid_link, &R)) + if (FD_ISSET(squid_link, &R)) { control.Recv(); + } #if USE_IPV6 - if (icmp6_worker >= 0 && FD_ISSET(icmp6_worker, &R)) + if (icmp6_worker >= 0 && FD_ISSET(icmp6_worker, &R)) { icmp6.Recv(); + } #endif - if (icmp4_worker >= 0 && FD_ISSET(icmp4_worker, &R)) + if (icmp4_worker >= 0 && FD_ISSET(icmp4_worker, &R)) { icmp4.Recv(); + } if (PINGER_TIMEOUT + last_check_time < squid_curtime) { if (send(LINK_TO_SQUID, &tv, 0, 0) < 0) {