--------------------- PatchSet 4091 Date: 2007/03/09 05:48:32 Author: amosjeffries Branch: squid3-ipv6 Tag: (none) Log: Rolled into ACLIP Some code comment updates Members: src/ACLIP.cc:1.8.2.10->1.8.2.11 src/ACLIP.h:1.6.2.2->1.6.2.3 src/IPAddress.cc:1.1.2.6->1.1.2.7 src/IPAddress.h:1.1.2.6->1.1.2.7 src/Makefile.am:1.58.2.3->1.58.2.4 src/ipc.cc:1.9.4.5->1.9.4.6 Index: squid3/src/ACLIP.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ACLIP.cc,v retrieving revision 1.8.2.10 retrieving revision 1.8.2.11 diff -u -r1.8.2.10 -r1.8.2.11 --- squid3/src/ACLIP.cc 25 Jan 2007 09:26:59 -0000 1.8.2.10 +++ squid3/src/ACLIP.cc 9 Mar 2007 05:48:32 -0000 1.8.2.11 @@ -1,5 +1,5 @@ /* - * $Id: ACLIP.cc,v 1.8.2.10 2007/01/25 09:26:59 amosjeffries Exp $ + * $Id: ACLIP.cc,v 1.8.2.11 2007/03/09 05:48:32 amosjeffries Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -58,13 +58,13 @@ MemBuf mb; wordlist **W = static_cast(state); mb.init(); - mb.Printf("%s", INET_NTOA(ip->addr1)); + mb.Printf("%s", ip->addr1.NtoA()); - if (!ADDR_IS_ANYADDR(ip->addr2)) - mb.Printf("-%s", INET_NTOA(ip->addr2)); + if (!ip->addr2.IsAnyAddr()) + mb.Printf("-%s", ip->addr2.NtoA()); - if (!ADDR_IS_NOADDR(ip->mask)) - mb.Printf("/%s", INET_NTOA(ip->mask)); + if (!ip->mask.IsNoAddr()) + mb.Printf("/%s", ip->mask.NtoA()); wordlistAdd(W, mb.buf); @@ -81,15 +81,15 @@ char b1[MAXIPSTRLEN+1]; char b2[MAXIPSTRLEN+1]; char b3[MAXIPSTRLEN+1]; - snprintf(b1, MAXIPSTRLEN+1, "%s", INET_NTOA(addr1)); + snprintf(b1, MAXIPSTRLEN+1, "%s", addr1.NtoA()); - if (!ADDR_IS_ANYADDR(addr2)) - snprintf(b2, MAXIPSTRLEN+1, "-%s", INET_NTOA(addr2)); + if (!addr2.IsAnyAddr()) + snprintf(b2, MAXIPSTRLEN+1, "-%s", addr2.NtoA()); else b2[0] = '\0'; - if (!ADDR_IS_NOADDR(mask)) - snprintf(b3, MAXIPSTRLEN+1, "/%s", INET_NTOA(mask)); + if (!mask.IsNoAddr()) + snprintf(b3, MAXIPSTRLEN+1, "/%s", mask.NtoA()); else b3[0] = '\0'; @@ -113,34 +113,23 @@ int aclIpAddrNetworkCompare(acl_ip_data * const &p, acl_ip_data * const &q) { - - struct IN_ADDR A = p->addr1; - - struct IN_ADDR B = q->addr1; - - struct IN_ADDR C = q->addr2; + IPAddress A = p->addr1; unsigned int i; char *p1,*p2; - /* apply netmask ** FIXME... review this ** */ - p1 = (char *)&A; - p2 = (char *)&q->mask; - for (i = 0; i < sizeof(struct IN_ADDR); i++) { - *(p1++) &= *(p2++); - } + /* apply netmask */ + A.ApplyMask(q->mask); - if (ADDR_IS_ANYADDR(C)) { /* single address check */ - return memcmp(&A, &B, sizeof(struct IN_ADDR)); + if (q->addr2.IsAnyAddr()) { /* single address check */ + return (A == q->addr1); } else { /* range address check */ - if ((memcmp(&A, &B, sizeof(struct IN_ADDR)) >= 0) && - (memcmp(&A, &C, sizeof(struct IN_ADDR)) <= 0)) + if ( (A >= q->addr1) && (A <= q->addr2) ) return 0; /* valid */ else return -1; /* outside of range, 'less than' */ } - } @@ -154,24 +143,28 @@ 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[3*(MAXIPSTRLEN+1)]; char buf_n2[3*(MAXIPSTRLEN+1)]; - char buf_a[3*(MAXIPSTRLEN+1)]; - b->toStr(buf_n1, 3*(MAXIPSTRLEN+1)); - a->toStr(buf_n2, 3*(MAXIPSTRLEN+1)); - a->toStr(buf_a, 3*(MAXIPSTRLEN+1)); - /* TODO: this warning may display the wrong way around */ + if(bina) { + b->toStr(buf_n1, 3*(MAXIPSTRLEN+1)); + a->toStr(buf_n2, 3*(MAXIPSTRLEN+1)); + } else { + a->toStr(buf_n1, 3*(MAXIPSTRLEN+1)); + b->toStr(buf_n2, 3*(MAXIPSTRLEN+1)); + } debug(28, 0) ("WARNING: '%s' is a subnetwork of " "'%s'\n", buf_n1, buf_n2); debug(28, 0) ("WARNING: because of this '%s' is ignored " - "to keep splay tree searching predictable\n", buf_a); + "to keep splay tree searching predictable\n", buf_n1); debug(28, 0) ("WARNING: You should probably remove '%s' " "from the ACL named '%s'\n", buf_n1, AclMatchedName); } @@ -184,60 +177,48 @@ * adress and netmask information in addr and mask. * This function should NOT be called if 'asc' is a hostname! */ +/* FIXME: AYJ: the above docs mention setting addr, which is never done within!! */ bool - -acl_ip_data::DecodeMask(const char *asc, struct IN_ADDR *mask) +acl_ip_data::DecodeMask(const char *asc, IPAddress &mask, IPAddressType ctype) { char junk; int a1 = 0; - - memset(mask, 0xff, sizeof(*mask)); + mask.SetNoAddr(); if (!asc || !*asc) { - return 1; + return true; } - /* An int mask 128, 32 */ - if ((sscanf(asc, "%d%c", &a1,&junk)==1) && (a1 <= (AF_FAMILY==AF_INET6)? 128:32) && (a1 >= 0)) { -#ifdef INET6 - unsigned int bp; - for (bp = a1/8; bp < sizeof(struct IN_ADDR); bp++) { - int clearbits = (bp+1)*8 - a1; - if (clearbits > 0) { - if (clearbits >= 8) - mask->s6_addr[bp] = 0x00; - else - mask->s6_addr[bp] = 0xff << clearbits; - } - } -#else - mask->s_addr = a1 ? htonl(0xfffffffful << (32 - a1)) : 0; -#endif - return 1; + if ((sscanf(asc, "%d%c", &a1,&junk)==1) && + (a1 <= (AF_FAMILY==AF_INET6)? 128:32) && (a1 >= 0) + ) + { + mask.ApplyMask(a1, mask_type); + return true; } /* dotted notation 2003:800::3 */ /* 255.255.255.0 */ - if (SAFE_INET_ADDR(asc, mask)) - return 1; - - - return 0; - -} - -#ifdef INET6 -#define SCAN_ACL1 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]/%[0123456789]" -#define SCAN_ACL2 "%[0123456789ABCDEFabcdef:]-%[0123456789ABCDEFabcdef:]%c" -#define SCAN_ACL3 "%[0123456789ABCDEFabcdef:]/%[0123456789]" -#else -#define SCAN_ACL1 "%[0123456789.]-%[0123456789.]/%[0123456789]" -#define SCAN_ACL2 "%[0123456789.]-%[0123456789.]%c" -#define SCAN_ACL3 "%[0123456789.]/%[0123456789]" -#endif + if (mask = asc) + return true; + // else false. + + return false; +} + +/* 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:]/%s" +/* 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.]/%s" acl_ip_data * acl_ip_data::FactoryParse(const char *t) @@ -251,22 +232,44 @@ char c; debug(28, 5) ("aclParseIpData: %s\n", t); acl_ip_data *q = new acl_ip_data; + IPAddressType iptype = None; if (!strcasecmp(t, "all")) { - memset(&q->addr1, '\0', sizeof(q->addr1)); - memset(&q->addr2, '\0', sizeof(q->addr2)); - memset(&q->mask, '\0', sizeof(q->mask)); + q->addr1.SetAnyAddr(); + q->addr2.SetAnyAddr(); + q->mask.SetAnyAddr(); return q; } - if (sscanf(t, SCAN_ACL1, addr1, addr2, mask) == 3) { +// IPv4 + if (sscanf(t, SCAN_ACL1_4, addr1, addr2, mask) == 3) { + (void) 0; + iptype=IPv4; + } else if (sscanf(t, SCAN_ACL2_4, addr1, addr2, &c) >= 2) { + mask[0] = '\0'; + iptype=IPv4; + } else if (sscanf(t, SCAN_ACL3_4, addr1, mask) == 2) { + addr2[0] = '\0'; + iptype=IPv4; + } else if (sscanf(t, SCAN_ACL4_4, addr1, mask) == 2) { + addr2[0] = '\0'; + iptype=IPv4; + +// IPv6 + } else if (sscanf(t, SCAN_ACL1_6, addr1, addr2, mask) == 3) { (void) 0; - } else if (sscanf(t, SCAN_ACL2, addr1, addr2, &c) == 2) { + iptype=IPv6; + } else if (sscanf(t, SCAN_ACL2_6, addr1, addr2, &c) >= 2) { mask[0] = '\0'; - } else if (sscanf(t, SCAN_ACL3, addr1, mask) == 2) { + iptype=IPv6; + } else if (sscanf(t, SCAN_ACL3_6, addr1, mask) == 2) { addr2[0] = '\0'; - } else if (sscanf(t, "%[^/]/%s", addr1, mask) == 2) { + iptype=IPv6; + } else if (sscanf(t, SCAN_ACL4_6, addr1, mask) == 2) { addr2[0] = '\0'; + iptype=IPv6; + +// Neither } else if (sscanf(t, "%s", addr1) == 1) { addr2[0] = '\0'; mask[0] = '\0'; @@ -279,6 +282,7 @@ */ struct hostent *hp; +/* Fixme grab the dual-capable format for looking up IPA of a host name */ if ((hp = GETHOSTBYNAME(addr1)) == NULL) { debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t); @@ -291,11 +295,10 @@ if ((r = *Q) == NULL) r = *Q = new acl_ip_data; - xmemcpy(&r->addr1, *x, sizeof(r->addr1)); - - memset(&r->addr2, '\0', sizeof(r->addr2)); + r->addr1 = *x; + r->addr2.SetAnyAddr(); - if (!DecodeMask(mask, &r->mask)) { + if (!DecodeMask(mask, r->mask, iptype)) { debug(28, 0) ("aclParseIpData: unknown netmask '%s' in '%s'\n", mask, t); delete r; *Q = NULL; @@ -303,10 +306,9 @@ continue; } - Q = &r->next; - debug(28, 3) ("%s --> %s\n", addr1, INET_NTOA(r->addr1)); + debug(28, 3) ("%s --> %s\n", addr1, r->addr1.NtoA()); } if (*Q != NULL) { @@ -318,7 +320,7 @@ } /* Decode addr1 */ - if (!SAFE_INET_ADDR(addr1, &q->addr1)) { + if (!( &q->addr1 = addr1) ) { debug(28, 0) ("aclParseIpData: unknown first address in '%s'\n", t); delete q; self_destruct(); @@ -326,21 +328,26 @@ } /* Decode addr2 */ - if (!SAFE_INET_ADDR(addr2, &q->addr2)) { + if (!( &q->addr2 = addr2) ) { debug(28, 0) ("aclParseIpData: unknown second address in '%s'\n", t); delete q; self_destruct(); return NULL; } + /* Decode mask */ - if (!DecodeMask(mask, &q->mask)) { + if (!DecodeMask(mask, q->mask, iptype)) { debug(28, 0) ("aclParseIpData: unknown netmask '%s' in '%s'\n", mask, t); delete q; self_destruct(); return NULL; } +/* FIXME: convert all the code below to work with IPAddress */ +// Hmm, to do that we need to know what the mask is in CIDR bits! +// maybe now would be a good time to make mask into a cidr value instead of bitmask-address +// since we are making IPAddress handle both ? { unsigned int i; char *p1,*p2,*p3; @@ -402,25 +409,25 @@ } int - -ACLIP::match(struct IN_ADDR &clientip) +ACLIP::match(IPAddress &clientip) { static acl_ip_data ClientAddress (any_addr, any_addr, no_addr, NULL); /* * 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 128 IPv6/ 32 IPv4 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; + ClientAddress.addr2.SetEmpty(); + ClientAddress.mask.SetEmpty(); acl_ip_data *ClientAddressPointer = &ClientAddress; data = data->splay(ClientAddressPointer, aclIpAddrNetworkCompare); debug(28, 3) ("aclMatchIp: '%s' %s\n", - INET_NTOA(clientip), splayLastResult ? "NOT found" : "found"); + clientip.NtoA(), 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){} Index: squid3/src/ACLIP.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ACLIP.h,v retrieving revision 1.6.2.2 retrieving revision 1.6.2.3 diff -u -r1.6.2.2 -r1.6.2.3 --- squid3/src/ACLIP.h 5 Jan 2007 16:57:55 -0000 1.6.2.2 +++ squid3/src/ACLIP.h 9 Mar 2007 05:48:32 -0000 1.6.2.3 @@ -1,6 +1,6 @@ /* - * $Id: ACLIP.h,v 1.6.2.2 2007/01/05 16:57:55 hno Exp $ + * $Id: ACLIP.h,v 1.6.2.3 2007/03/09 05:48:32 amosjeffries Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,6 +37,7 @@ #define SQUID_ACLIP_H #include "ACL.h" #include "splay.h" +#include "IPAddress.h" class acl_ip_data { @@ -48,19 +49,18 @@ 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; /* if addr2 non-zero then its a range */ + IPAddress addr2; + IPAddress mask; /* This should perhapse be stored as a CIDR range now instead of a full IP mask. */ - struct IN_ADDR addr2; - - 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); }; MEMPROXY_CLASS_INLINE(acl_ip_data) @@ -87,7 +87,7 @@ protected: - int match(struct IN_ADDR &); + int match(IPAddress &); IPSplay *data; private: Index: squid3/src/IPAddress.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/IPAddress.cc,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid3/src/IPAddress.cc 5 Mar 2007 11:27:01 -0000 1.1.2.6 +++ squid3/src/IPAddress.cc 9 Mar 2007 05:48:32 -0000 1.1.2.7 @@ -1,5 +1,5 @@ /* - * $Id: IPAddress.cc,v 1.1.2.6 2007/03/05 11:27:01 amosjeffries Exp $ + * $Id: IPAddress.cc,v 1.1.2.7 2007/03/09 05:48:32 amosjeffries Exp $ */ #include "IPAddress.h" @@ -9,7 +9,7 @@ #include /* inet Macros */ #include /* inet_ntoa() */ -// #include "util.h" +#include "util.h" /* enum IPAddressType { @@ -22,6 +22,27 @@ struct sockaddr m_SocketAddr; */ +#ifndef INET6 +// 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; +#ifdef INET6 +static const unsigned int MAX_IPSTRLEN = MAX_IP6_STRLEN; +#else +static const unsigned int MAX_IPSTRLEN = MAX_IP4_STRLEN; +#endif + IPAddress::IPAddress() { memset(this,0,sizeof(IPAddress)); @@ -32,6 +53,52 @@ if(m_cacheStringValue) delete m_cacheStringValue; memset(this,0,sizeof(IPAddress)); } + +bool IPAddress::ApplyMask(const IPAddress &mask_addr) +{ + uint32_t *p1 = (uint32_t*)(&m_SocketAddr.sin6_addr); + const uint32_t *p2 = (const uint32_t*)(&mask_addr.m_SocketAddr.sin6_addr); + unsigned int blen = sizeof(m_SocketAddr.sin6_addr)/sizeof(uint32_t); + + for (unsigned int i = 0; i < blen; i++) { + p1[i] &= p2[i]; + } + RebuildStringCache(); + return true; +} +bool IPAddress::ApplyMask(const unsigned int cidr, IPAddressType mtype) +{ + uint8_t clearbits; + uint8_t* p; + +#ifdef INET6 /* IPv6 has IPv4 as Mapped-address */ + if(mtype & IPv4) + { + cidr += 96; // keep the 96 bits added during the IPv4 mapping process. + } + + if (cidr > 128) return false; +#else + /* FIXME: is it worth trying to convert IPv6 CIDR to IPv4 + * it would mean accepting CIDR from /96 to /128 + * as in /0 to /32 range and mapping the rest to /0 + */ + + if (cidr > 32) return false; +#endif + if(cidr < 0) return true; // any err like this can be assumed /0 + + clearbits = (m_Type&IPv6?128:32) - cidr; + p = (uint8_t*)(&m_SocketAddr.sin6_addr + sizeof(m_SocketAddr.sin6_addr)); + + for (; clearbits >0; clearbits-=8, p++ ) { + *p &= ((0xFF << clearbits) & 0xFF); + } + + RebuildStringCache(); + return true; +} + bool IPAddress::IsAnyAddr() { #ifdef INET6 @@ -42,30 +109,18 @@ } void IPAddress::SetAnyAddr() { -#ifdef INET6 - memcpy(&(m_SocketAddr.sin6_addr), &in6addr_any, sizeof(in6addr_any)); -#else - m_SocketAddr.sin_addr.s_addr = INADDR_ANY; -#endif + memset(&(m_SocketAddr.sin6_addr),0, sizeof(m_SocketAddr.sin6_addr)); m_Type = IPv64; } bool IPAddress::IsNoAddr() { -// IFF the address = 0xffffffffff...fffff (all ones) -#ifdef INET6 - return (0 == memcmp(&(m_SocketAddr.sin6_addr),&"\0xffffffff\0xffffffff\0xffffffff\0xffffffff", sizeof(in6addr_any))); -#else - return (0xFFFFFFFF == m_SocketAddr.sin_addr.s_addr); -#endif + // IFF the address == 0xff..ff (all ones) + return (0 == memcmp(&m_SocketAddr.sin6_addr, &"\0xFFFFFFFF\0xFFFFFFFF\0xFFFFFFFF\0xFFFFFFFF", sizeof(m_SocketAddr.sin6_addr) ) ); } void IPAddress::SetNoAddr() { -#ifdef INET6 - memset(&(m_SocketAddr.sin6_addr),255,sizeof(in6_addr)); -#else - m_SocketAddr.sin_addr.s_addr = 0xFFFFFFFF; -#endif + memset(&(m_SocketAddr.sin6_addr),255,sizeof(m_SocketAddr.sin6_addr)); m_Type = IPv64; } @@ -163,6 +218,8 @@ // return an empty string for the buffer, and log an error buf[0] = '\0'; +// TODO debug output a warning. + return false; } @@ -193,27 +250,32 @@ }; #ifdef INET6 +void IPAddress::check4Mapped() +{ + /* check for ::ffff:0.0.0.0 IPv4-mapped addresses */ + if( 0 == memcmp(&m_SocketAddress.sin6_addr, &"\0x00000000\0x00000000\0x00000000\0xFFFF", (96 + 16) ) ) + { + m_Type |= IPv4; + } + /* FIXME: maybe other tests thay 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)); memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in6)); m_Type = (IPAddressType)(SockAddr | IPv6); - RebuildStringCache(); - // FIXME: check to see what type of in*_addr is in this sockaddr. Update type to show it. - // AYJ: Not sure about the following. - // Only absolute test is if first 96 bits are 0 then 16 of 0xFFFF - // m_Type |= IPv4; + check4Mapped(); + RebuildStringCache(); }; IPAddress& IPAddress::operator =(sockaddr_in6 const &s) { memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in6)); m_Type = (IPAddressType)(SockAddr | IPv6); - RebuildStringCache(); - - // FIXME: check to see what type of in*_addr is in this sockaddr. Update type to show it. - // AYJ: Not sure about the following. - // Only absolute test is if first 96 bits are 0 then 16 of 0xFFFF - // m_Type |= IPv4; + check4Mapped(); + RebuildStringCache(); return *this; }; #endif @@ -256,6 +318,7 @@ m_SocketAddr.sin6_port = 0; m_SocketAddr.sin6_family = AF_INET6; m_Type=IPv6; + check4Mapped(); }; IPAddress& IPAddress::operator =(struct in6_addr const &s) { // FIXME: convert properly from in6_addr to the storage method. @@ -263,6 +326,7 @@ m_SocketAddr.sin6_port = 0; m_SocketAddr.sin6_family = AF_INET6; m_Type=IPv6; + check4Mapped(); RebuildStringCache(); return *this; }; @@ -271,7 +335,7 @@ IPAddress::IPAddress(const IPAddress &s) { memcpy(this,&s,sizeof(IPAddress)); // Special Drop of the duplicated m_cacheStringValue ptr - // and rebuild of a new strign in new memory for this copy of the object. + // and rebuild of a new string in new memory for this copy of the object. m_cacheStringValue = NULL; RebuildStringCache(); } @@ -298,20 +362,12 @@ u_short IPAddress::GetPort() { -#ifdef INET6 return ntohs( m_SocketAddr.sin6_port ); -#else - return ntohs( m_SocketAddr.sin_port ); -#endif } u_short IPAddress::SetPort(u_short prt) { -#ifdef INET6 m_SocketAddr.sin6_port = htons(prt); -#else - m_SocketAddr.sin_port = htons(prt); -#endif if(m_Type != None) m_Type = (IPAddressType)(m_Type | SockAddr); RebuildStringCache(); return prt; @@ -319,58 +375,57 @@ void IPAddress::RebuildStringCache() { - if(m_cacheStringValue == NULL) - { - m_cacheStringValue = new char[MAX_IPSTRLEN]; - memset(m_cacheStringValue,0,MAX_IPSTRLEN); - } -#ifdef INET6 + if(m_cacheStringValue == NULL) return; // Quick-abort if no strings used yet. + if(m_SocketAddr.sin6_port > 0) { char t[MAX_IPSTRLEN]; - if(inet_ntop(AF_INET6, &m_SocketAddr.sin6_addr, t, MAX_IPSTRLEN )) - { + if(inet_ntop((m_Type&IPv6?AF_INET6:AF_INET), &m_SocketAddr.sin6_addr, t, MAX_IPSTRLEN )) +#ifdef INET6 sprintf(m_cacheStringValue,"[%s]:%d",t, ntohs(m_SocketAddr.sin6_port) ); - } - } - else - { - inet_ntop(AF_INET6, &m_SocketAddr.sin6_addr, m_cacheStringValue, STRLEN_IP6A); - } #else - if(m_SocketAddr.sin_port > 0) - { - char t[MAX_IPSTRLEN]; - if(inet_ntop(AF_INET6, &m_SocketAddr.sin6_addr, t, MAX_IPSTRLEN)) - { sprintf(m_cacheStringValue,"%s:%d",t, ntohs(m_SocketAddr.sin_port) ); - } - } - else - { - xstrncpy(m_cacheStringValue, inet_ntoa(m_SocketAddr.sin_addr), STRLEN_IP4A); - } #endif + } else { + inet_ntop((m_Type&IPv6?AF_INET6:AF_INET), &m_SocketAddr.sin6_addr, m_cacheStringValue, (m_Type&IPv6?STRLEN_IP6A:STRLEN_IP4A)); + } } + const char* IPAddress::NtoA() { + // Ensure we have a buffer to return. + if(m_cacheStringValue == NULL) + { + m_cacheStringValue = new char[MAX_IPSTRLEN]; + memset(m_cacheStringValue,0,MAX_IPSTRLEN); + } RebuildStringCache(); return m_cacheStringValue; } + bool IPAddress::GetString(char *buf, unsigned int blen) { unsigned int slen; - RebuildStringCache(); + if(m_cacheStringValue) { slen = strlen(m_cacheStringValue); xstrncpy(buf, m_cacheStringValue, (blen < slen? blen:slen) ); - return true; } - return false; + else // fool RebuildStringCache into filling the buffer for us + { + if(blen < MAX_IPSTRLEN) + { + // FIXME : log a debug saying the buffer received was too small at needs defining at least MAX_IPSTRLEN + return false; + } + m_cacheStringValue=buf; + RebuildStringCache(); + m_cacheStringValue = NULL; // we don't want to cache the external buffer ourselves. + } + return true; } - void IPAddress::GetSockAddr(struct sockaddr_in &buf) { #ifdef INET6 @@ -434,7 +489,7 @@ case IPv6: // non-compatible IPv6 Pure Address default: // flow through to error case. - // FIXME: Log the call to this function ?? + // FIXME: debug Log the call to this function ?? // FIXME: Or return the IPv4 version of 'no address' and let the ACL deal with it?? return false; } Index: squid3/src/IPAddress.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Attic/IPAddress.h,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -r1.1.2.6 -r1.1.2.7 --- squid3/src/IPAddress.h 5 Mar 2007 11:27:01 -0000 1.1.2.6 +++ squid3/src/IPAddress.h 9 Mar 2007 05:48:32 -0000 1.1.2.7 @@ -1,12 +1,5 @@ /* - * Class to hold and manipulate IPv4, IPv6 and Sock Addresses - * This is primarily to reduce old c-style code and improve - * the success of Protocol Changes now and in the future. - * Will also centralise and improve code-reusage where IPA are involved. - * - * Intended for use by the DNS, ACLs, and Client-Server connection parts of Squid3. - * - * $Id: IPAddress.h,v 1.1.2.6 2007/03/05 11:27:01 amosjeffries Exp $ + * $Id: IPAddress.h,v 1.1.2.7 2007/03/09 05:48:32 amosjeffries Exp $ */ #ifndef _INC_IPADDRESS_H #define _INC_IPADDRESS_H @@ -15,29 +8,31 @@ #include #include +/// Specify the type of Address being or to be handled. 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) + None =0, /// Nothing Secial. Equates to default if used as a parameter. + 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) }; -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; -#ifdef INET6 -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 - /* not certain yet how much space extn. ports will use */ -static const unsigned int MAX_IP6_STRLEN = STRLEN_IP6R; -static const unsigned int MAX_IPSTRLEN = STRLEN_IP6R; -#else -static const unsigned int MAX_IPSTRLEN = MAX_IP4_STRLEN; +// AYJ: Lets see how many of these we can hide internally to the object. +//SQUIDEXTERN const unsigned int STRLEN_IP4A; // aaa.bbb.ccc.ddd\0 +//SQUIDEXTERN const unsigned int STRLEN_IP4R; // ddd.ccc.bbb.aaa.in-addr.arpa.\0 +//SQUIDEXTERN const unsigned int STRLEN_IP4S; // ddd.ccc.bbb.aaa:ppppp\0 +//SQUIDEXTERN const unsigned int MAX_IP4_STRLEN; +#ifdef INET6 +//SQUIDEXTERN const unsigned int STRLEN_IP6A; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/0 +//SQUIDEXTERN const unsigned int STRLEN_IP6R; // 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 +//SQUIDEXTERN const unsigned int STRLEN_IP6S; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:00000/0 +//SQUIDEXTERN const unsigned int MAX_IP6_STRLEN; +SQUIDEXTERN const unsigned int MAX_IPSTRLEN; #endif +/** + * Holds and manipulates IPv4, IPv6, and Socket Addresses. + */ class IPAddress { public: @@ -66,27 +61,33 @@ public: /* methods */ - inline bool IsIPv4() { return (m_Type & IPv4); }; - inline bool IsIPv6() { return (m_Type & IPv6); }; + inline bool IsIPv4() { return (m_Type & IPv4); }; /// test whether content can be used as an IPv4. + inline bool IsIPv6() { return (m_Type & IPv6); }; /// test whether content can be used as an IPv6. + inline bool IsSockAddr() { return (m_Type & SockAddr); }; /// test whether content can be used as a sockaddr (Address and Port combo). + bool IsNoAddr(); /// Content-neutral test for whether specific IP case ANY_ADDR is stored. + bool IsAnyAddr(); /// Content-neutral test for whether specific IP case NO_ADDR is stored. #ifdef INET6 - bool GetReverseString(char buf[MAX_IPSTRLEN], IPAddressType show_type = IPv6); + bool GetReverseString(char buf[], IPAddressType show_format = IPv6); #else - bool GetReverseString(char buf[MAX_IPSTRLEN], IPAddressType show_type = IPv4); + /// Return + bool GetReverseString(char buf[], IPAddressType show_format = IPv4); #endif u_short GetPort(); u_short SetPort(u_short port); - bool IsAnyAddr(); - void SetAnyAddr(); - bool IsNoAddr(); - void SetNoAddr(); - bool GetString(char *buf, unsigned int len); + void SetAnyAddr(); /// Set object to contain the specific IP case ANY_ADDR (format-neutral). + void SetNoAddr(); /// Set object to contain the specific IP case NO_ADDR (format-neutral). + void SetEmpty(); /// Fast reset of the stored content to what would be after default constructor. + bool GetString(char *buf, unsigned int len); std::ostream& operator<<(std::ostream& os); // After reading Debug.h and debug.cc I thought '<<' was all that was needed now. // Apparently not, so here is 'char* NtoA()' const char* NtoA(); + bool ApplyMask(const IPAddress &); + bool ApplyMask(const unsigned int cidr, IPAddressType mtype = None); + /* variables */ @@ -112,6 +113,7 @@ bool GetReverseString4(char buf[], struct in_addr &); void RebuildStringCache(); #ifdef INET6 + void check4Mapped(); bool GetReverseString6(char buf[], struct in6_addr &); void Map4to6(const struct in_addr &src, struct in6_addr &dest); void Map6to4(const struct in6_addr &src, struct in_addr &dest); Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.58.2.3 retrieving revision 1.58.2.4 diff -u -r1.58.2.3 -r1.58.2.4 --- squid3/src/Makefile.am 1 Mar 2007 09:25:46 -0000 1.58.2.3 +++ squid3/src/Makefile.am 9 Mar 2007 05:48:32 -0000 1.58.2.4 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.58.2.3 2007/03/01 09:25:46 amosjeffries Exp $ +# $Id: Makefile.am,v 1.58.2.4 2007/03/09 05:48:32 amosjeffries Exp $ # # Uncomment and customize the following to suit your needs: # @@ -512,6 +512,8 @@ $(IDENT_SOURCE) \ int.cc \ internal.cc \ + IPAddress.cc \ + IPAddress.h \ $(IPC_SOURCE) \ ipcache.cc \ $(LEAKFINDERSOURCE) \ Index: squid3/src/ipc.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ipc.cc,v retrieving revision 1.9.4.5 retrieving revision 1.9.4.6 diff -u -r1.9.4.5 -r1.9.4.6 --- squid3/src/ipc.cc 3 Mar 2007 14:44:05 -0000 1.9.4.5 +++ squid3/src/ipc.cc 9 Mar 2007 05:48:32 -0000 1.9.4.6 @@ -1,6 +1,6 @@ /* - * $Id: ipc.cc,v 1.9.4.5 2007/03/03 14:44:05 amosjeffries Exp $ + * $Id: ipc.cc,v 1.9.4.6 2007/03/09 05:48:32 amosjeffries Exp $ * * DEBUG: section 54 Interprocess Communication * AUTHOR: Duane Wessels @@ -247,7 +247,7 @@ cwfd = crfd = -1; if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { - /* FIXME Remove: */ IPAddress ChS_b = ChS; + /* FIXME Remove: */ IPAddress ChS_b(ChS); if (comm_connect_addr(pwfd, ChS_b) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); }