Sigh. For some weird reason my test machine built squid with the previous patches despite a missing #include.

Here is an updated patch set, tested on two machines.
Patch file generated Sun Apr  8 01:12:39 NZST 2007 from
CVS branch squid3-ipv6
CVS base branch HEAD
CVS repository: [EMAIL PROTECTED]:/cvsroot/squid
CVS module: squid3/include

cvs -q rdiff -u -kk -r Z-squid3-ipv6_merge_HEAD -r squid3-ipv6 squid3/include
Index: squid3/include/IPAddress.h
diff -u /dev/null squid3/include/IPAddress.h:1.1.2.12
--- /dev/null		Thu Jan  1 01:00:00 1970
+++ squid3/include/IPAddress.h	Sat Apr  7 06:06:43 2007
@@ -0,0 +1,303 @@
+
+/*
+ * $Id$
+ *
+ * DEBUG: section 14    IP Storage and Handling
+ * AUTHOR: Amos Jeffries
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  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.
+ *
+ */
+
+#ifndef _INC_IPADDRESS_H
+#define _INC_IPADDRESS_H
+
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_NETDB_H && !defined(_SQUID_NETDB_H_)   /* protect NEXTSTEP */
+#define _SQUID_NETDB_H_
+#ifdef _SQUID_NEXT_
+#include <netinet/in_systm.h>
+#endif
+#include <netdb.h>
+#endif
+
+#include <iostream>
+
+
+/// Specify the type of Address being or to be handled.
+enum IPAddressType {
+    None     =0, ///< Nothing Special. Equates to default if used as a parameter.
+    SockAddr =1, ///< Full SocketAddr Details Stored. Port and Address can be used together or seperately.
+    IPv4     =2, ///< Pure IPv4 address stored (conversion up must be done explicitly)
+    IPv6     =4, ///< Pure IPv6 address Stored (no conversion to IPv4 possible)
+    IPv64    =6  ///< Dual-Address stored (can return either IPv6 OR IPv4)
+};
+
+/// Length of buffer that needs to be allocated to old a null-terminated IP-string
+// Yuck. But there are still structures that need it to be an 'integer constant'.
+#define MAX_IPSTRLEN  75
+
+/**
+ * Holds and manipulates IPv4, IPv6, and Socket Addresses.
+ */
+
+class IPAddress
+{
+
+public:
+    /** @name Constructors and Destructor */
+    /[EMAIL PROTECTED]/
+    // default constructor.
+    IPAddress();
+    IPAddress(const IPAddress &);
+
+    IPAddress(const struct in_addr &);
+
+    IPAddress(const struct sockaddr_in &);
+#ifdef USE_IPV6
+
+    IPAddress(const struct in6_addr &);
+
+    IPAddress(const struct sockaddr_in6 &);
+#endif
+
+    IPAddress(const hostent *);
+    IPAddress(const char*);
+    /// Default destructor.
+    ~IPAddress();
+    /[EMAIL PROTECTED]/
+
+    /** @name Assignment Operators */
+    /[EMAIL PROTECTED]/
+    IPAddress& operator =(const IPAddress &s);
+
+    IPAddress& operator =(struct sockaddr_in const &s);
+
+    IPAddress& operator =(struct in_addr const &s);
+#ifdef USE_IPV6
+
+    IPAddress& operator =(struct in6_addr const &s);
+
+    IPAddress& operator =(struct sockaddr_in6 const &s);
+#endif
+
+    bool operator =(const struct hostent *s);
+    bool operator =(const char *s);
+    /[EMAIL PROTECTED]/
+
+    /** @name Boolean Operators */
+    /[EMAIL PROTECTED]/
+    bool operator ==(IPAddress const &s) const;
+    bool operator >=(IPAddress const &rhs) const;
+    bool operator <=(IPAddress const &rhs) const;
+
+public:
+    /* methods */
+
+    /** Test whether content can be used as an IPv4 address
+     *  \retval true  if content was received as an IPv4 address
+     *  \retval true  if content was received as an IPv4-Mapped address
+     *  \retval false if content was received as a non-mapped IPv6 native address.
+     */
+    inline bool IsIPv4() const { return (m_Type & IPv4); };
+
+    /** Test whether content can be used as an IPv6 address.
+     *  \retval true  if --enable-ipv6 has been compiled.
+     *  \retval false if --disable-ipv6 has been compiled.
+     *  \retval false if --with-ipv6-split-stack has been compiled AND content is IPv4-mapped.
+     */
+    inline bool IsIPv6() const
+    {
+        return (m_Type & IPv6)
+#ifdef USE_IPV6_SPLITSTACK
+               && !(m_Type & IPv4)
+#endif
+               ;
+    };
+
+    /** Test whether content can be used as a Socket address.
+     *  \retval true  if address AND port are both set
+     *  \retval true  if content was received as a Socket address
+     *  \retval false if port in unset (zero)
+     */
+    inline bool IsSockAddr() const { return (m_Type & SockAddr); };
+
+    /** Content-neutral test for whether the specific IP case ANY_ADDR is stored.
+     *  This is the default content of a new undefined IPAddress object.
+     *  \retval true IPv4 0.0.0.0
+     *  \retval true IPv6 ::
+     *  \retval false anything else.
+     */
+    bool IsAnyAddr() const;
+    /** Content-neutral test for whether the specific IP case NO_ADDR is stored.
+     *  \retval true IPv4 255.255.255.255
+     *  \retval true IPv6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+     *  \retval false anything else.
+     */
+    bool IsNoAddr() const;
+    /[EMAIL PROTECTED]/
+
+    /** Retrieve the Port if stored.
+     *  \retval 0 Port is unset or an error occured.
+     *  \retval n Port associated with this address in host native -endian.
+     */
+    u_short GetPort() const;
+    /** Set the Port value for an address.
+     *  Replaces any previously existing Port value.
+     *  \param port Port being assigned in host native -endian.
+     *  \retval 0 Port is unset or an error occured.
+     *  \retval n Port associated with this address in host native -endian.
+     */
+    u_short SetPort(u_short port);
+
+    /// Set object to contain the specific IP case ANY_ADDR (format-neutral).
+    /// see IsAnyAddr() for more detail.
+    void SetAnyAddr();
+
+    /// Set object to contain the specific IP case NO_ADDR (format-neutral).
+    /// see \link IsNoAddr() for more detail.
+    void SetNoAddr();
+
+    /// Fast reset of the stored content to what would be after default constructor.
+    void SetEmpty();
+
+    /**
+     *  Valid results IF and only IF the stored IP address is actually a network bitmask
+     * \retval N number of bits which are set in the bitmask stored.
+     */
+    int GetCIDR();
+
+    /** Apply a mask to the stored address.
+     *  \param mask Netmask format to be bit-mask-AND'd over the stored address.
+     */
+    const int ApplyMask(const IPAddress &mask);
+
+    /** Apply a mask to the stored address.
+     *  CIDR will be converted appropriate to map the stored content.
+     *  \param cidr   CIDR Mask being applied. As an integer in host format.
+     *  \param mtype  Type of CIDR mask being applied (IPv4,IPv6, or None for default)
+     */
+    bool ApplyMask(const unsigned int cidr, IPAddressType mtype = None);
+
+
+    /** Return the ASCII equivalent of the address
+     *  Semantically equivalent to the IPv4 inet_ntoa()
+     *  eg. 127.0.0.1 (IPv4) or ::1 (IPv6)
+     *  But for memory safety it requires a buffer as input
+     *  instead of producing one magically.
+     *  If buffer is not large enough the data is truncated silently.
+     * \param buf Allocated buffer to write address to
+     * \param len byte length of buffer available for writing.
+     * \return pointer to buffer received.
+     */
+    char* NtoA(char *buf, unsigned int len) const;
+
+    /** Return the ASCII equivalent of the address:port combination
+     *  Provides a URL formatted version of the content.
+     *  If buffer is not large enough the data is truncated silently.
+     *  eg. 127.0.0.1:80 (IPv4) or [::1]:80 (IPv6)
+     * \param buf Allocated buffer to write address:port to
+     * \param len byte length of buffer available for writing.
+     * \return pointer to buffer received.
+     */
+    char* ToURL(char *buf, unsigned int len) const;
+
+    /** \fn bool GetReverseString(char buf[], IPAddressType show_format)
+     *  Convert the content into a Reverse-DNS string.
+     *  The buffer sent MUST be allocated large enough to hold the resulting string.
+     *  Name truncation will occur if buf does not have enough space.
+     *  The constant MAX_IPSTRLEN is defined to provide for sizing arrays correctly.
+     *  \param show_format may be one of: IPv4,IPv6 for the format of rDNS string wanted.
+     *  \param buf buffer to receive the text string output.
+     */
+#ifdef USE_IPV6
+
+    bool GetReverseString(char buf[], IPAddressType show_format = IPv6) const;
+#else
+
+    bool GetReverseString(char buf[], IPAddressType show_format = IPv4) const;
+#endif
+
+#ifdef _GLIBCXX_IOSTREAM
+
+    std::ostream& operator<<(std::ostream& os) const;
+#endif
+
+
+public:
+    /* FIXME: When C => C++ conversion is done will be fully private.
+     * Legacy Transition Methods
+     * These are here solely to simplify the transition
+     * when moving from converted code to unconverted
+     * these functions can be used to convert this object
+     * and pull out the data needed by the unconverted code
+     * they are intentionaly hard to use, to encourage less use.
+     */
+
+    void GetSockAddr(struct sockaddr_in &) const;
+
+    bool GetInAddr(struct in_addr &) const; /* false if could not convert IPv6 down to IPv4 */
+#ifdef USE_IPV6
+
+    void GetSockAddr(struct sockaddr_in6 &) const;
+
+    void GetInAddr(struct in6_addr &) const;
+#endif
+
+private:
+    int matchIPAddr(const IPAddress &rhs) const;
+    /* Conversion for dual-type internals */
+
+    bool GetReverseString4(char buf[], struct in_addr &) const;
+#ifdef USE_IPV6
+
+    void check4Mapped();
+
+    bool GetReverseString6(char buf[], struct in6_addr &) const;
+
+    void Map4to6(const struct in_addr &src, struct in6_addr &dest) const;
+
+    void Map6to4(const struct in6_addr &src, struct in_addr &dest) const;
+#endif
+
+    /* variables */
+    IPAddressType m_Type;
+#ifdef USE_IPV6
+
+    struct sockaddr_in6 m_SocketAddr;
+#else
+
+    struct sockaddr_in m_SocketAddr;
+#endif
+};
+
+#endif /* _INC_IPADDRESS_H */
Index: squid3/include/util.h
diff -u squid3/include/util.h:1.15 squid3/include/util.h:1.10.8.12
--- squid3/include/util.h:1.15	Sat Oct 14 06:51:15 2006
+++ squid3/include/util.h	Sat Apr  7 04:16:40 2007
@@ -35,14 +35,18 @@
 #define SQUID_UTIL_H
 
 #include "config.h"
+#if HAVE_STDIO_H
 #include <stdio.h>
-#include <time.h>
+#endif
 #if HAVE_TIME_H
 #include <time.h>
 #endif
 #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
@@ -123,8 +127,7 @@
 extern void xmalloc_find_leaks(void);
 #endif
 
-typedef struct IN_ADDR SIA;
-SQUIDCEXTERN int safe_inet_addr(const char *, SIA *);
+SQUIDCEXTERN int safe_inet_addr(const char *, struct in_addr *);
 SQUIDCEXTERN time_t parse_iso3307_time(const char *buf);
 SQUIDCEXTERN char *base64_decode(const char *coded);
 SQUIDCEXTERN const char *base64_encode(const char *decoded);
Patch file generated Sun Apr  8 02:28:18 NZST 2007 from
CVS branch squid3-ipv6
CVS base branch HEAD
CVS repository: [EMAIL PROTECTED]:/cvsroot/squid
CVS module: squid3/lib

cvs -q rdiff -u -kk -r Z-squid3-ipv6_merge_HEAD -r squid3-ipv6 squid3/lib
Index: squid3/lib/IPAddress.cc
diff -u /dev/null squid3/lib/IPAddress.cc:1.1.2.25
--- /dev/null		Thu Jan  1 01:00:00 1970
+++ squid3/lib/IPAddress.cc	Sat Apr  7 07:25:38 2007
@@ -0,0 +1,863 @@
+
+/*
+ * $Id$
+ *
+ * DEBUG: section 14   IP Storage and Handling
+ * AUTHOR: Amos Jeffries
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * ----------------------------------------------------------
+ *
+ *  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.
+ *
+ */
+
+#include "config.h"
+
+#include "IPAddress.h"
+
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>  /* inet_ntoa() */
+#endif
+
+#include "util.h"
+
+#ifdef INET6
+#error "INET6 defined but has been deprecated! Try running bootstrap and configure again."
+#endif
+
+/* We want to use the debug routines when running as module of squid. */
+/* otherwise fallback to printf if those are not available. */
+#ifndef SQUID_DEBUG
+#    define debug(a,b)	printf
+#else
+#    include "../Debug.h"
+#endif
+
+/*
+    enum IPAddressType {
+            NONE=0,
+            SockAddr =1, // Full SocketAddr Details Stored.
+            IPv4     =2, // Pure IPv4 address stored (conversion up must be done explicitly)
+            IPv6     =4, // Pure IPv6 Address Stored (no conversion to IPv4 possible)
+            IPv64    =6  // Dual-Address Stored (can return either IPv6 OR IPv4)
+    } m_Type;
+    struct sockaddr m_SocketAddr;
+*/
+
+#ifndef USE_IPV6
+// AYJ: So there are some places where I will drop to using Macros too.
+//      At least I can restrict them to this file so they don't corrupt the app with C code.
+#  define sin6_addr	sin_addr
+#  define sin6_port	sin_port
+#endif
+
+static const unsigned int STRLEN_IP4A = 16;              // aaa.bbb.ccc.ddd\0
+static const unsigned int STRLEN_IP4R = 28;              // ddd.ccc.bbb.aaa.in-addr.arpa.\0
+static const unsigned int STRLEN_IP4S = 21;              // ddd.ccc.bbb.aaa:ppppp\0
+static const unsigned int MAX_IP4_STRLEN = STRLEN_IP4R;
+static const unsigned int STRLEN_IP6A = 42;           // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/0
+static const unsigned int STRLEN_IP6R = 75;           // f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f ipv6.arpa./0
+static const unsigned int STRLEN_IP6S = 48;           // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:00000/0
+static const unsigned int MAX_IP6_STRLEN = STRLEN_IP6R;
+
+
+IPAddress::IPAddress()
+{
+    memset(this,0,sizeof(IPAddress));
+#ifdef USE_IPV6
+
+    m_Type = IPv64;
+#else
+
+    m_Type = IPv4;
+#endif
+}
+
+IPAddress::~IPAddress()
+{
+    memset(this,0,sizeof(IPAddress));
+}
+
+int
+IPAddress::GetCIDR()
+{
+    u_char shift,byte;
+    char bit,caught;
+    int len = 0;
+    char *ptr= (char *)&m_SocketAddr.sin6_addr;
+
+    /* Let's scan all the bits from Most Significant to Least */
+    /* Until we find an "0" bit. Then, we return */
+
+    for (shift=0;shift<sizeof(m_SocketAddr.sin6_addr) ;shift++) {
+        byte= *(ptr+shift);
+
+        if (byte == 0xFF) {
+            len += 8;
+            continue ;  /* A short-cut */
+        }
+
+        for (caught = 0 , bit= 7 ; !caught && (bit >-1); bit--) {
+            caught = ((byte & 0x80) == 0x00);  /* Found a '0' at 'bit' ? */
+
+            if (!caught)
+                len++;
+
+            byte <<= 1;
+        }
+
+        if (caught)
+            break; /* We have found the most significant "0" bit.  */
+    }
+
+    return len;
+}
+
+const int IPAddress::ApplyMask(IPAddress const &mask_addr)
+{
+    uint32_t *p1 = (uint32_t*)(&m_SocketAddr.sin6_addr);
+    uint32_t const *p2 = (uint32_t const *)(&mask_addr.m_SocketAddr.sin6_addr);
+    unsigned int blen = sizeof(m_SocketAddr.sin6_addr)/sizeof(uint32_t);
+    unsigned int changes = 0;
+
+    for (unsigned int i = 0; i < blen; i++) {
+        if((p1[i] & p2[i]) != p1[i])
+            changes++;
+
+        p1[i] &= p2[i];
+    }
+
+    return changes;
+}
+
+bool IPAddress::ApplyMask(const unsigned int icidr, IPAddressType mtype)
+{
+    uint8_t clearbits = 0;
+    uint8_t* p = NULL;
+    unsigned int cidr = icidr;
+
+#ifdef USE_IPV6 /* IPv6 has IPv4 as Mapped-address */
+
+    if (cidr > 128)
+        return false;
+
+#else
+
+    if (cidr > 32)
+        return false;
+
+#endif
+
+    if(cidr < 0)
+        return true; // any err like this can be assumed /0
+
+    clearbits = (uint8_t)((m_Type&IPv6?128:32)-cidr);
+
+#ifdef USE_IPV6
+
+    p = (uint8_t*)(&m_SocketAddr.sin6_addr) + 15;
+
+#else
+
+    p = (uint8_t*)(&m_SocketAddr.sin6_addr) + 3;
+
+#endif
+
+    for (; clearbits>0 && p >= (uint8_t*)&m_SocketAddr.sin6_addr ; clearbits-=8, p-- ) {
+        *p &= ((0xFF << clearbits) & 0xFF);
+    }
+
+    return true;
+}
+
+bool IPAddress::IsAnyAddr() const
+{
+#ifdef USE_IPV6
+    return     m_SocketAddr.sin6_addr.s6_addr32[0] == 0
+               && m_SocketAddr.sin6_addr.s6_addr32[1] == 0
+               && m_SocketAddr.sin6_addr.s6_addr32[2] == 0
+               && m_SocketAddr.sin6_addr.s6_addr32[3] == 0
+               ;
+#else
+
+    return (INADDR_ANY == m_SocketAddr.sin_addr.s_addr);
+#endif
+}
+
+void IPAddress::SetAnyAddr()
+{
+    memset(&(m_SocketAddr.sin6_addr),0, sizeof(m_SocketAddr.sin6_addr));
+#ifdef USE_IPV6
+
+    m_Type = IPv64;
+#else
+
+    m_Type=IPv4;
+#endif
+}
+
+void IPAddress::SetEmpty()
+{
+    memset(&(m_SocketAddr.sin6_addr),0x0, sizeof(m_SocketAddr.sin6_addr));
+}
+
+bool IPAddress::IsNoAddr() const
+{
+    // IFF the address == 0xff..ff (all ones)
+#ifdef USE_IPV6
+    return     m_SocketAddr.sin6_addr.s6_addr32[0] == 0xFFFFFFFF
+               && m_SocketAddr.sin6_addr.s6_addr32[1] == 0xFFFFFFFF
+               && m_SocketAddr.sin6_addr.s6_addr32[2] == 0xFFFFFFFF
+               && m_SocketAddr.sin6_addr.s6_addr32[3] == 0xFFFFFFFF
+               ;
+#else
+
+    return 0xFFFFFFFF == m_SocketAddr.sin_addr.s_addr;
+#endif
+}
+
+void IPAddress::SetNoAddr()
+{
+    memset(&(m_SocketAddr.sin6_addr),0xFFFFFFFF,sizeof(m_SocketAddr.sin6_addr));
+#ifdef USE_IPV6
+
+    m_Type = IPv64;
+#else
+
+    m_Type=IPv4;
+#endif
+}
+
+#ifdef USE_IPV6
+
+bool IPAddress::GetReverseString6(char buf[MAX_IPSTRLEN], struct in6_addr &dat) const
+{
+    char *p = buf;
+    unsigned char *r = dat.s6_addr;
+
+    /* RFC1886 says: */
+    /*     4321:0:1:2:3:4:567:89ab */
+    /*     must be sent */
+    /*     b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.ip6.int. */
+
+    /* Work from the binary field. Anything else may have representation changes. */
+    /* The sin6_port and sin6_addr members shall be in network byte order. */
+
+    /* Compile Err: 'Too many arguments for format. */
+
+    for(int i = 15; i >= 0; i--, p+=4)
+    {
+        snprintf(p, 5, "%x.%x.", (((r[i])>>4)&0xf), ((r[i])&0xf) );
+    }
+
+    /* RFC3152 says: */
+    /*     ip6.int is now deprecated TLD, use ip6.arpa instead. */
+    snprintf(p,10,"ip6.arpa.");
+
+    return true;
+}
+
+#endif
+
+bool IPAddress::GetReverseString4(char buf[MAX_IPSTRLEN], struct in_addr &dat) const
+{
+    unsigned int i = (unsigned int) ntohl(dat.s_addr);
+    snprintf(buf, 32, "%u.%u.%u.%u.in-addr.arpa.",
+             i & 255,
+             (i >> 8) & 255,
+             (i >> 16) & 255,
+             (i >> 24) & 255);
+    return true;
+}
+
+bool IPAddress::GetReverseString(char buf[MAX_IPSTRLEN], IPAddressType show_type) const
+{
+    in_addr* ip4_ptr = NULL;
+#ifdef USE_IPV6
+
+    in6_addr* ip6_ptr = NULL;
+    in6_addr tmp_buf;
+#endif
+
+    if(m_Type == None)
+        return false;
+
+#ifdef USE_IPV6
+
+    if(show_type == None)
+        show_type = IPv6;
+
+#else
+
+    if(show_type == None)
+        show_type = IPv4;
+
+#endif
+
+    switch(m_Type & IPv64) // What we do depends on how we stored it.
+    {
+
+    case IPv4:
+#ifndef USE_IPV6
+
+        ip4_ptr = (in_addr*)&m_SocketAddr.sin_addr;
+#else /* USE_IPV6 */
+
+        ip4_ptr = (in_addr*)&m_SocketAddr.sin6_addr.s6_addr[12];
+        ip6_ptr = &tmp_buf;
+        Map4to6(*ip4_ptr, *ip6_ptr);
+#endif
+
+        break;
+
+    case IPv64:
+#ifndef USE_IPV6
+
+        ip4_ptr = (in_addr*)&m_SocketAddr.sin_addr;
+#else
+
+        ip4_ptr = (in_addr*)&m_SocketAddr.sin6_addr.s6_addr32[3];
+        // Fall through to setup IPv6 output ptr
+
+    case IPv6:
+        ip6_ptr = (in6_addr*)&m_SocketAddr.sin6_addr;
+#endif
+
+        break;
+    }
+
+    if(show_type == IPv4 && ip4_ptr != NULL) {
+        return GetReverseString4(buf, *(in_addr*)ip4_ptr);
+    }
+
+#ifdef USE_IPV6
+    if(show_type == IPv6 && ip6_ptr != NULL) {
+        return GetReverseString6(buf, *(in6_addr*)ip6_ptr);
+    }
+
+#endif
+
+    debug(14,1)("IPAddress::GetReverseString : Address stored cannot be converted to type requested.\n");
+
+    buf[0] = '\0';
+
+    return false;
+}
+
+IPAddress& IPAddress::operator =(const IPAddress &s)
+{
+    memcpy(this, &s, sizeof(IPAddress));
+    return *this;
+};
+
+IPAddress::IPAddress(const char*s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+}
+
+bool IPAddress::operator =(const char* s)
+{
+
+    struct hostent *hp = NULL;
+
+    if ((hp = gethostbyname(s)) == NULL) {
+        debug(14,1)("IPAddress::operator= : Given Bad IP '%s'\n", s);
+        return false;
+    }
+
+    if(hp->h_addrtype == AF_INET)
+
+        operator=( *((struct in_addr*)hp->h_addr_list[0]) );
+
+#ifdef USE_IPV6
+
+    else if(hp->h_addrtype == AF_INET6)
+
+        operator=( *((struct in6_addr*)hp->h_addr_list[0]) );
+
+#endif
+
+    else {
+        debug(14,1)("IPAddress::operator=(hostent*) : Discarding IP address '%s'.\n",s);
+        return false;
+    }
+
+    return true;
+}
+
+
+IPAddress::IPAddress(struct sockaddr_in const &s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+};
+
+IPAddress& IPAddress::operator =(struct sockaddr_in const &s)
+{
+#ifdef USE_IPV6
+    Map4to6((const in_addr)s.sin_addr, m_SocketAddr.sin6_addr);
+    m_SocketAddr.sin6_port = s.sin_port;
+    m_SocketAddr.sin6_family = AF_INET6;
+    m_Type=(IPAddressType)(IPv64 | SockAddr);
+#else
+
+    memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in));
+    m_Type=(IPAddressType)(IPv4 | SockAddr);
+#endif
+
+    return *this;
+};
+
+#ifdef USE_IPV6
+void IPAddress::check4Mapped()
+{
+    /* check for  ::ffff:x.x.x.x IPv4-mapped addresses */
+
+    if( 0 == memcmp(&m_SocketAddr.sin6_addr, &"\0x00000000\0x00000000\0x00000000\0xFFFF", sizeof(struct in6_addr)-sizeof(struct in_addr) ) ) {
+        m_Type = (IPAddressType)(m_Type | IPv4);
+    }
+
+    if( 0 == memcmp(&m_SocketAddr.sin6_addr, &"\0x00000000\0x00000000\0x00000000\0x00000000", sizeof(struct in6_addr) ) ) {
+        m_Type = (IPAddressType)(m_Type | IPv4);
+    }
+
+    if( 0 == memcmp(&m_SocketAddr.sin6_addr, &"\0xFFFFFFFF\0xFFFFFFFF\0xFFFFFFFF\0xFFFFFFFF", sizeof(struct in6_addr) ) ) {
+        m_Type = (IPAddressType)(m_Type | IPv4);
+    }
+
+    /* FIXME INET6 : maybe other tests can apply if the IPA was mapped in other ways */
+    /*        I know of 2002:0.0.0.0:: mappings and possibly fe80::???? mappings */
+
+}
+
+IPAddress::IPAddress(sockaddr_in6 const &s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+};
+
+IPAddress& IPAddress::operator =(sockaddr_in6 const &s)
+{
+
+    memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in6));
+    m_Type = (IPAddressType)(SockAddr | IPv6);
+
+    check4Mapped();
+    return *this;
+};
+
+#endif
+
+IPAddress::IPAddress(in_addr const &s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+};
+
+IPAddress& IPAddress::operator =(in_addr const &s)
+{
+#ifdef USE_IPV6
+    Map4to6((const in_addr)s, m_SocketAddr.sin6_addr);
+    m_SocketAddr.sin6_family = AF_INET6;
+
+    if(m_SocketAddr.sin6_port > 0)
+        m_Type=(IPAddressType)(SockAddr | IPv64);
+    else
+        m_Type=IPv64;
+
+#else
+
+    memcpy(&m_SocketAddr.sin_addr, &s, sizeof(struct in_addr));
+
+    m_SocketAddr.sin_family = AF_INET;
+
+    if(m_SocketAddr.sin_port > 0)
+        m_Type=(IPAddressType)(SockAddr | IPv4);
+    else
+        m_Type=IPv4;
+
+#endif
+
+    return *this;
+};
+
+#ifdef USE_IPV6
+
+IPAddress::IPAddress(struct in6_addr const &s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+};
+
+IPAddress& IPAddress::operator =(struct in6_addr const &s)
+{
+
+    memcpy(&m_SocketAddr.sin6_addr, &s, sizeof(struct in6_addr));
+    m_SocketAddr.sin6_family = AF_INET6;
+
+    if(m_SocketAddr.sin6_port > 0)
+        m_Type=(IPAddressType)(SockAddr | IPv6);
+    else
+        m_Type=IPv6;
+
+    check4Mapped();
+
+    return *this;
+};
+
+#endif
+
+IPAddress::IPAddress(const IPAddress &s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+}
+
+IPAddress::IPAddress(const struct hostent *s)
+{
+    memset(this,0,sizeof(IPAddress));
+    operator=(s);
+}
+
+bool IPAddress::operator =(const struct hostent *s)
+{
+
+    struct in_addr* ipv4 = NULL;
+
+    struct in6_addr* ipv6 = NULL;
+
+    //struct hostent {
+    //        char    *h_name;        /* official name of host */
+    //        char    **h_aliases;    /* alias list */
+    //        int     h_addrtype;     /* host address type */
+    //        int     h_length;       /* length of address */
+    //        char    **h_addr_list;  /* list of addresses */
+    //}
+
+    switch(s->h_addrtype)
+    {
+
+    case AF_INET:
+        ipv4 = (in_addr*)(s->h_addr_list[0]);
+        /* this */
+        operator=(*ipv4);
+        break;
+
+    case AF_INET6:
+        ipv6 = (in6_addr*)(s->h_addr_list[0]);
+#ifdef USE_IPV6
+        /* this */
+        operator=(*ipv6);
+#else
+
+        debug(14,1)("IPAddress::operator= : Discarded IPv6 Address. Protocol disabled.\n");
+
+        // TODO see if there is another address in the list that might be usable ??
+        return false;
+#endif
+
+        break;
+    }
+
+    return true;
+}
+
+#ifdef _GLIBCXX_IOSTREAM
+/// Operator to output ASCII version of Address:Port to a ostream
+std::ostream& IPAddress::operator<<(std::ostream& os) const
+{
+    char buf[MAX_IPSTRLEN];
+    // Dump the Current [Address]:Port to the debug stream.
+#ifdef USE_IPV6
+
+    if(IsIPv6())
+#else
+
+    if(false)
+#endif
+
+        os << "[" << NtoA(buf,MAX_IPSTRLEN) << "]:" << m_SocketAddr.sin6_port;
+    else
+        os << NtoA(buf,MAX_IPSTRLEN) << ":" << m_SocketAddr.sin6_port;
+
+    return os;
+}
+
+#endif
+
+int IPAddress::matchIPAddr(const IPAddress &rhs) const
+{
+    unsigned int slen = sizeof(m_SocketAddr.sin6_addr);
+    uint8_t *l = (uint8_t*)&m_SocketAddr.sin6_addr;
+    uint8_t *r = (uint8_t*)&rhs.m_SocketAddr.sin6_addr;
+    uint8_t *end = l+slen;
+
+    // loop a bit-wise compare
+
+    for( ; l <= end ; r++, l++) {
+        if(*l < *r)
+            return -1;
+
+        if(*l > *r)
+            return 1;
+    }
+
+    return true;
+}
+
+bool IPAddress::operator ==(const IPAddress &s) const
+{
+    if(m_Type != s.m_Type)
+        return false;
+
+    return (0 == matchIPAddr(s));
+}
+
+bool IPAddress::operator <=(const IPAddress &rhs) const
+{
+    if(IsAnyAddr() && !rhs.IsAnyAddr())
+        return true;
+
+    return (matchIPAddr(rhs) <= 0);
+}
+
+bool IPAddress::operator >=(const IPAddress &rhs) const
+{
+    if(IsNoAddr() && !rhs.IsNoAddr())
+        return true;
+
+    return ( matchIPAddr(rhs) >= 0);
+}
+
+u_short IPAddress::GetPort() const
+{
+    return ntohs( m_SocketAddr.sin6_port );
+}
+
+u_short IPAddress::SetPort(u_short prt)
+{
+    m_SocketAddr.sin6_port = htons(prt);
+
+    if(m_Type != None)
+        m_Type = (IPAddressType)(m_Type | SockAddr);
+
+    return prt;
+}
+
+/**
+ * NtoA Given a buffer writes a readable ascii version of the IPA and/or port stored
+ *
+ * Buffer must be of a size large enough to hold the converted address.
+ * This size if provided in the form of a defined variable MAX_IPSTRLEN
+ * Should a buffer shorter be provided the string result will be truncated
+ * at the length of the available buffer.
+ *
+ * A copy of the buffer is also returned for simple immediate display.
+ */
+char* IPAddress::NtoA(char* buf, unsigned int blen) const
+{
+    // Ensure we have a buffer.
+
+    if(buf == NULL) {
+        debug(14,1)("IPAddress::NtoA : Buffer received has no allocated space.\n");
+        return NULL;
+    }
+
+    memset(buf,0,blen);
+
+    if(m_Type & IPv6 )
+        inet_ntop(AF_INET6, &m_SocketAddr.sin6_addr, buf, blen);
+    else
+        inet_ntop(AF_INET, &m_SocketAddr.sin6_addr, buf, blen);
+
+    return buf;
+}
+
+char* IPAddress::ToURL(char* buf, unsigned int blen) const
+{
+    char *p = buf;
+
+    // Ensure we have a buffer.
+
+    if(buf == NULL) {
+        debug(14,1)("IPAddress::ToURL : Buffer received has no allocated space.\n");
+        return NULL;
+    }
+
+    memset(buf,0,blen);
+
+#ifdef USE_IPV6
+
+    if(blen > 0) {
+        *p = '[';
+        p++;
+    }
+
+#endif
+
+    /* 7 being space for [,], and port */
+    p = NtoA(p, blen-7);
+
+    // find the end of the new string
+    while(*p != '\0' && p < buf+blen)
+        p++;
+
+#ifdef USE_IPV6
+
+    if(p < buf+blen-1) {
+        *p = ']';
+        p++;
+    }
+
+#endif
+
+    if(m_SocketAddr.sin6_port > 0 && p < buf+blen-6) {
+        /* 6 is max length of expected ':port' (short int) */
+        snprintf(p,6,":%d", GetPort() );
+    }
+
+    // force a null-terminated string
+    buf[blen] = '\0';
+
+    return buf;
+}
+
+void IPAddress::GetSockAddr(struct sockaddr_in &buf) const
+{
+#ifdef USE_IPV6
+
+    if(m_Type & IPv4) // if can be converted down.
+    {
+        buf.sin_family = AF_INET;
+        buf.sin_port = m_SocketAddr.sin6_port;
+        Map6to4( m_SocketAddr.sin6_addr, buf.sin_addr);
+    } else // no conversion. set it to invalid content.
+    {
+
+        memset(&buf, 0, sizeof(struct sockaddr_in));
+    }
+
+#else
+
+    memcpy(&buf, &m_SocketAddr, sizeof(struct sockaddr_in));
+
+#endif
+}
+
+#ifdef USE_IPV6
+
+void IPAddress::GetSockAddr(struct sockaddr_in6 &buf) const
+{
+
+    memcpy(&buf, &m_SocketAddr, sizeof(struct sockaddr_in6));
+    buf.sin6_family = AF_INET6;
+}
+
+#endif
+
+#ifdef USE_IPV6
+
+void IPAddress::Map4to6(const struct in_addr &in, struct in6_addr &out) const
+{
+    /* check for special cases */
+
+    if( in.s_addr == 0x00000000)
+    {
+
+        memset(&out, 0, sizeof(struct in6_addr));
+    } else if( in.s_addr == 0xFFFFFFFF)
+    {
+        out.s6_addr32[0] = 0xFFFFFFFF;
+        out.s6_addr32[1] = 0xFFFFFFFF;
+        out.s6_addr32[2] = 0xFFFFFFFF;
+        out.s6_addr32[3] = 0xFFFFFFFF;
+    }
+
+    /* FIXME TODO : handle special case of localhost (IPv4 127.0.0.1, IPv6 ::1 ) */
+    else
+    {
+
+        memset(&out, 0, sizeof(struct in6_addr));
+        out.s6_addr32[3] = in.s_addr;
+        out.s6_addr16[5] = (unsigned short)0xFFFF;
+    }
+}
+
+void IPAddress::Map6to4(const struct in6_addr &in, struct in_addr &out) const
+{
+    /* FIXME TODO : handle special case of localhost (IPv4 127.0.0.1, IPv6 ::1 ) */
+
+    memset(&out, 0, sizeof(struct in_addr));
+    out.s_addr = in.s6_addr32[3];
+}
+
+#endif
+
+#ifdef USE_IPV6
+void IPAddress::GetInAddr(in6_addr &buf) const
+{
+    assert(m_Type & IPv6);
+
+    memcpy(&buf, &m_SocketAddr.sin6_addr, sizeof(struct in6_addr));
+}
+
+#endif
+
+bool IPAddress::GetInAddr(struct in_addr &buf) const
+{
+    switch(m_Type & IPv64)
+    {
+#ifdef USE_IPV6
+
+    case IPv64: // IPv4-Compatible IPv6 Address
+        Map6to4((const in6_addr)m_SocketAddr.sin6_addr, buf);
+        return true;
+#else
+
+    case IPv4: // Pure IPv4 Address.
+
+        memcpy(&buf, &m_SocketAddr.sin_addr,  sizeof(struct in_addr));
+        return true;
+#endif
+
+    case IPv6: // non-compatible IPv6 Pure Address
+
+    default:
+        debug(14,1)("IPAddress::GetInAddr : Cannot convert non-IP to IPv4.\n");
+
+        memset(&buf,0xFFFFFFFF,sizeof(struct in_addr));
+        return false;
+    }
+}
Index: squid3/lib/Makefile.am
diff -u squid3/lib/Makefile.am:1.17 squid3/lib/Makefile.am:1.12.4.2
--- squid3/lib/Makefile.am:1.17	Sat Sep  2 06:52:12 2006
+++ squid3/lib/Makefile.am	Sun Mar 18 02:07:02 2007
@@ -65,6 +65,7 @@
 	hash.c \
 	heap.c \
 	html_quote.c \
+	IPAddress.cc \
 	iso3307.c \
 	$(MD5SOURCE) \
 	radix.c \
Index: squid3/lib/rfc1035.c
diff -u squid3/lib/rfc1035.c:1.11 squid3/lib/rfc1035.c:1.5.2.14
--- squid3/lib/rfc1035.c:1.11	Wed May 11 19:13:16 2005
+++ squid3/lib/rfc1035.c	Wed Apr  4 01:15:16 2007
@@ -671,7 +671,7 @@
  * Returns the size of the query
  */
 ssize_t
-rfc1035BuildPTRQuery(const struct IN_ADDR addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query)
+rfc1035BuildPTRQuery(const struct in_addr addr, char *buf, size_t sz, unsigned short qid, rfc1035_query * query)
 {
     static rfc1035_message h;
     size_t offset = 0;
@@ -746,7 +746,7 @@
     S.sin_port = htons(atoi(argv[2]));
     S.sin_addr.s_addr = inet_addr(argv[1]);
     while (fgets(input, 512, stdin)) {
-	struct IN_ADDR junk;
+	struct in_addr junk;
 	strtok(input, "\r\n");
 	memset(buf, '\0', 512);
 	sz = 512;
@@ -788,7 +788,7 @@
 		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) {
Index: squid3/lib/safe_inet_addr.c
diff -u squid3/lib/safe_inet_addr.c:1.4 squid3/lib/safe_inet_addr.c:1.1.30.9
--- squid3/lib/safe_inet_addr.c:1.4	Mon Apr 18 19:14:45 2005
+++ squid3/lib/safe_inet_addr.c	Wed Apr  4 18:44:26 2007
@@ -31,11 +31,11 @@
 #include "snprintf.h"
 
 int
-safe_inet_addr(const char *buf, struct IN_ADDR *addr)
+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;
+    struct in_addr A;
     char x;
 #if defined(_SQUID_HPUX_)
     /*

Reply via email to