reSIProcate/stack  9694
Tuple.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include "resip/stack/Tuple.hxx"
00006 #include "rutil/compat.hxx"
00007 
00008 #include <iostream>
00009 #include <string.h>
00010 #include <sys/types.h>
00011 #include <cassert>
00012 
00013 #if !defined (WIN32)
00014 #include <arpa/inet.h>
00015 #include <netinet/in.h>
00016 #if defined(__APPLE__) && !defined(s6_addr16)
00017 #define s6_addr16 __u6_addr.__u6_addr16
00018 #endif
00019 #endif
00020 
00021 #include "rutil/Data.hxx"
00022 #include "rutil/DnsUtil.hxx"
00023 #include "rutil/GenericIPAddress.hxx"
00024 #include "rutil/HashMap.hxx"
00025 #include "rutil/MD5Stream.hxx"
00026 #include "rutil/Logger.hxx"
00027 #include "resip/stack/Transport.hxx"
00028 
00029 
00030 using namespace resip;
00031 
00032 #define RESIPROCATE_SUBSYSTEM Subsystem::DNS
00033 
00034 Tuple::Tuple() : 
00035    mFlowKey(0),
00036    transportKey(0),
00037    transport(0),
00038    onlyUseExistingConnection(false),
00039    mTransportType(UNKNOWN_TRANSPORT)
00040 {
00041    sockaddr_in* addr4 = (sockaddr_in*)&mSockaddr;
00042    memset(addr4, 0, sizeof(sockaddr_in));
00043    mSockaddr.sa_family = AF_INET;
00044 }
00045 
00046 Tuple::Tuple(const GenericIPAddress& genericAddress, TransportType type, 
00047              const Data& targetDomain) : 
00048    mFlowKey(0),
00049    transportKey(0),
00050    transport(0),
00051    onlyUseExistingConnection(false),
00052    mTransportType(type),
00053    mTargetDomain(targetDomain)
00054 {
00055   setSockaddr(genericAddress);
00056 }
00057 
00058 
00059 Tuple::Tuple(const Data& printableAddr, 
00060              int port,
00061              IpVersion ipVer,
00062              TransportType type,
00063              const Data& targetDomain) :
00064    mFlowKey(0),
00065    transportKey(0),
00066    transport(0),
00067    onlyUseExistingConnection(false),
00068    mTransportType(type),
00069    mTargetDomain(targetDomain)
00070 {
00071    if (ipVer == V4)
00072    {
00073       memset(&m_anonv4, 0, sizeof(m_anonv4));
00074       m_anonv4.sin_family = AF_INET;
00075       m_anonv4.sin_port = htons(port);
00076 
00077       if (printableAddr.empty())
00078       {
00079          m_anonv4.sin_addr.s_addr = htonl(INADDR_ANY); 
00080       }
00081       else
00082       {
00083          DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr);
00084       }
00085    }
00086    else
00087    {
00088 #ifdef USE_IPV6
00089       memset(&m_anonv6, 0, sizeof(m_anonv6));
00090       m_anonv6.sin6_family = AF_INET6;
00091       m_anonv6.sin6_port = htons(port);
00092       if (printableAddr.empty())
00093       {
00094          m_anonv6.sin6_addr = in6addr_any;
00095       }
00096       else
00097       {
00098          DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr);
00099       }
00100 #else
00101           assert(0);
00102 #endif
00103    }
00104 }
00105 
00106 Tuple::Tuple(const Data& printableAddr, 
00107              int port,
00108              TransportType ptype,
00109              const Data& targetDomain) : 
00110    mFlowKey(0),
00111    transportKey(0),
00112    transport(0),
00113    onlyUseExistingConnection(false),
00114    mTransportType(ptype),
00115    mTargetDomain(targetDomain)
00116 {
00117    if (DnsUtil::isIpV4Address(printableAddr))
00118    {
00119       memset(&m_anonv4, 0, sizeof(m_anonv4));
00120       
00121       DnsUtil::inet_pton( printableAddr, m_anonv4.sin_addr);
00122       m_anonv4.sin_family = AF_INET;
00123       m_anonv4.sin_port = htons(port);
00124    }
00125    else
00126    {
00127 #ifdef USE_IPV6
00128       memset(&m_anonv6, 0, sizeof(m_anonv6));
00129       DnsUtil::inet_pton( printableAddr, m_anonv6.sin6_addr);
00130       m_anonv6.sin6_family = AF_INET6;
00131       m_anonv6.sin6_port = htons(port);
00132 #else
00133           assert(0);
00134 #endif
00135    }
00136 }
00137 
00138 Tuple::Tuple(const in_addr& ipv4,
00139              int port,
00140              TransportType ptype,
00141              const Data& targetDomain)
00142      :mFlowKey(0),
00143      transportKey(0),
00144      transport(0),
00145      onlyUseExistingConnection(false),
00146      mTransportType(ptype),
00147      mTargetDomain(targetDomain)
00148 {
00149    memset(&m_anonv4, 0, sizeof(sockaddr_in));
00150    m_anonv4.sin_addr = ipv4;
00151    m_anonv4.sin_port = htons(port);
00152    m_anonv4.sin_family = AF_INET;
00153 }
00154 
00155 #ifdef USE_IPV6
00156 Tuple::Tuple(const in6_addr& ipv6,
00157              int port,
00158              TransportType ptype,
00159              const Data& targetDomaina)
00160      :mFlowKey(0),
00161      transportKey(0),
00162      transport(0),
00163      onlyUseExistingConnection(false),
00164      mTransportType(ptype),
00165      mTargetDomain(targetDomaina)
00166 {
00167    memset(&m_anonv6, 0, sizeof(sockaddr_in6));
00168    m_anonv6.sin6_addr = ipv6;
00169    m_anonv6.sin6_port = htons(port);
00170    m_anonv6.sin6_family = AF_INET6;
00171 }
00172 #endif
00173 
00174 Tuple::Tuple(const struct sockaddr& addr, 
00175              TransportType ptype,
00176              const Data& targetDomain) : 
00177    mFlowKey(0),
00178    transportKey(0),
00179    transport(0),
00180    onlyUseExistingConnection(false),
00181    mSockaddr(addr),
00182    mTransportType(ptype),
00183    mTargetDomain(targetDomain)
00184 {
00185    if (addr.sa_family == AF_INET)   
00186    {
00187       m_anonv4 = (sockaddr_in&)(addr);
00188    }
00189 #ifdef USE_IPV6
00190    else if (addr.sa_family == AF_INET6)
00191    {
00192       m_anonv6 = (sockaddr_in6&)(addr);
00193    }
00194 #endif
00195    else
00196    {
00197       assert(0);
00198    }
00199 }
00200 
00201 void
00202 Tuple::setSockaddr(const GenericIPAddress& addr)
00203 {
00204   if (addr.isVersion4())
00205   {
00206      m_anonv4 = addr.v4Address;
00207   }
00208   else
00209 #ifdef USE_IPV6
00210   {
00211      m_anonv6 = addr.v6Address;
00212   }
00213 #else
00214   {
00215      assert(0);
00216   }
00217 #endif
00218 }
00219 
00220 void
00221 Tuple::writeBinaryToken(const resip::Tuple& tuple, resip::Data& container, const Data& salt)
00222 {
00223    // .bwc. Maybe should just write the raw sockaddr into a buffer, and tack
00224    // on the flowid and onlyUseExistingConnection flag. Would require 10 extra
00225    // bytes for V6, and 14 extra bytes for V4. 
00226    // V6: sin6_len(1), sin6_flowinfo(4), flowId(4), onlyUseExistingConnection(1)
00227    // V4: sin_family(2 instead of 1), sin_zero(8), flowId(4), onlyUseExistingConnection(1)
00228    UInt32 rawToken[7];
00229    memset(&rawToken, 0, 28);
00230 
00231    rawToken[0] = tuple.mFlowKey;
00232 
00233    rawToken[1] = tuple.transportKey;
00234 
00235    // 0xXXXX0000
00236    rawToken[2] += (tuple.getPort() << 16);
00237 
00238    // 0x0000XX00
00239    rawToken[2] += (tuple.getType() << 8);
00240 
00241    // 0x000000X0
00242    if(tuple.onlyUseExistingConnection)
00243    {
00244       rawToken[2] += 0x00000010;
00245    }
00246 
00247 #ifdef USE_IPV6
00248    if(tuple.ipVersion()==V6)
00249    {
00250       // 0x0000000X
00251       rawToken[2] += 0x00000001;
00252       in6_addr address = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr()).sin6_addr;
00253       assert(sizeof(address)==16);
00254       memcpy(&rawToken[3],&address,16);
00255    }
00256    else
00257 #endif
00258    {
00259       in_addr address = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr()).sin_addr;
00260       assert(sizeof(address)==4);
00261       memcpy(&rawToken[3],&address,4);
00262    }
00263    
00264    container.clear();
00265    container.reserve(((tuple.ipVersion()==V6) ? 28 : 16) + (salt.empty() ? 0 : 32));
00266    container.append((char*)&rawToken[0],(tuple.ipVersion()==V6) ? 28 : 16);
00267 
00268    if(!salt.empty())
00269    {
00270       // TODO - potentially use SHA1 HMAC if USE_SSL is defined for stronger encryption
00271       MD5Stream ms;
00272       ms << container << salt;
00273       container += ms.getHex();
00274    }
00275 }
00276 
00277 
00278 Tuple
00279 Tuple::makeTupleFromBinaryToken(const resip::Data& binaryFlowToken, const Data& salt)
00280 {
00281    // To check if size is valid, we first need the IP version, so make sure the token is at least
00282    // the size of an IPv4 token
00283    if(binaryFlowToken.size()<16)
00284    {
00285       // !bwc! Should not assert here, since this sort of thing
00286       // can come off the wire easily.
00287       // TODO Throw an exception here?
00288       DebugLog(<<"binary flow token was too small: " << binaryFlowToken.size());
00289       return Tuple();
00290    }
00291 
00292    const UInt32* rawToken=reinterpret_cast<const UInt32*>(binaryFlowToken.data());
00293 
00294    FlowKey mFlowKey=rawToken[0];
00295    TransportKey transportKey=rawToken[1];
00296 
00297    IpVersion version = (rawToken[2] & 0x00000001 ? V6 : V4);
00298 
00299    bool isRealFlow = (rawToken[2] & 0x00000010 ? true : false);
00300 
00301    UInt8 temp = (TransportType)((rawToken[2] & 0x00000F00) >> 8);
00302    if(temp >= MAX_TRANSPORT)
00303    {
00304       DebugLog(<<"Garbage transport type in flow token: " << temp );
00305       return Tuple();
00306    }
00307    TransportType type = (TransportType)temp;
00308 
00309    UInt16 port= (rawToken[2] >> 16);
00310 
00311    // Now that we have the version we can do a more accurate check on the size
00312    if(!((version==V4 && salt.empty() && binaryFlowToken.size()==16) ||
00313         (version==V4 && !salt.empty() && binaryFlowToken.size()==48) ||
00314         (version==V6 && salt.empty() && binaryFlowToken.size()==28) ||
00315         (version==V6 && !salt.empty() && binaryFlowToken.size()==60)))
00316    {
00317       DebugLog(<<"Binary flow token is the wrong size for its IP version.");
00318       return Tuple();
00319    }
00320 
00321    // If salt is specified, validate HMAC
00322    if(!salt.empty())
00323    {
00324       unsigned int tokenSizeLessHMAC = version == V4 ? 16 : 28;
00325       Data flowTokenLessHMAC(Data::Share, binaryFlowToken.data(), tokenSizeLessHMAC);
00326       Data flowTokenHMAC(Data::Share, binaryFlowToken.data()+tokenSizeLessHMAC, 32);
00327       MD5Stream ms;
00328       ms << flowTokenLessHMAC << salt;
00329       if(ms.getHex() != flowTokenHMAC)
00330       {
00331          DebugLog(<<"Binary flow token has invalid HMAC, not our token");
00332          return Tuple();
00333       }
00334    }
00335 
00336    if(version==V6)
00337    {
00338 #ifdef USE_IPV6
00339       in6_addr address;
00340       assert(sizeof(address)==16);
00341       memcpy(&address,&rawToken[3],16);
00342       Tuple result(address,port,type);
00343 #else
00344       Tuple result(resip::Data::Empty, port, type);
00345 #endif
00346       result.mFlowKey=(FlowKey)mFlowKey;
00347       result.transportKey = (TransportKey)transportKey;
00348       result.onlyUseExistingConnection=isRealFlow;
00349       return result;
00350    }
00351 
00352    in_addr address;
00353    assert(sizeof(address)==4);
00354    memcpy(&address,&rawToken[3],4);
00355    Tuple result(address,port,type);
00356    result.mFlowKey=(FlowKey)mFlowKey;
00357    result.transportKey = (TransportKey)transportKey;
00358    result.onlyUseExistingConnection=isRealFlow;
00359    return result;
00360 }
00361 
00362 Data 
00363 Tuple::presentationFormat() const
00364 {
00365 #ifdef USE_IPV6
00366    if (isV4())
00367    {
00368       return Tuple::inet_ntop(*this);
00369    }
00370    else if (IN6_IS_ADDR_V4MAPPED(&m_anonv6.sin6_addr))
00371    {
00372       return DnsUtil::inet_ntop(*(reinterpret_cast<const in_addr*>(
00373                                    (reinterpret_cast<const unsigned char*>(&m_anonv6.sin6_addr) + 12))));
00374    }
00375    else
00376    {
00377       return Tuple::inet_ntop(*this);
00378    }
00379 #else
00380       return Tuple::inet_ntop(*this);
00381 #endif
00382 
00383 }
00384 
00385 void
00386 Tuple::setPort(int port)
00387 {
00388    if (mSockaddr.sa_family == AF_INET) // v4   
00389    {
00390       m_anonv4.sin_port = htons(port);
00391    }
00392    else
00393    {
00394 #ifdef USE_IPV6
00395       m_anonv6.sin6_port = htons(port);
00396 #else
00397           assert(0);
00398 #endif
00399    }
00400 }
00401 
00402 int 
00403 Tuple::getPort() const
00404 {
00405    if (mSockaddr.sa_family == AF_INET) // v4   
00406    {
00407       return ntohs(m_anonv4.sin_port);
00408    }
00409    else
00410    {
00411 #ifdef USE_IPV6
00412       return ntohs(m_anonv6.sin6_port);
00413 #else
00414           assert(0);
00415 #endif
00416    }
00417    
00418    return -1;
00419 }
00420 
00421 bool
00422 Tuple::isAnyInterface() const
00423 {
00424    if (isV4())
00425    {
00426       return m_anonv4.sin_addr.s_addr == htonl(INADDR_ANY); 
00427    }
00428 #if defined (USE_IPV6)
00429    else
00430    {
00431       return memcmp(&m_anonv6.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0;
00432    }
00433 #else
00434    return false;
00435 #endif
00436 }
00437 
00438 static Tuple loopbackv4("127.0.0.1",0,UNKNOWN_TRANSPORT);
00439 bool
00440 Tuple::isLoopback() const
00441 {
00442    if(ipVersion()==V4)
00443    {
00444       return isEqualWithMask(loopbackv4,8,true,true);
00445    }
00446    else if (ipVersion()==V6)
00447    {
00448 #ifdef USE_IPV6
00449 #if defined(__linux__) || defined(__APPLE__) || defined(WIN32)
00450       return IN6_IS_ADDR_LOOPBACK(&(m_anonv6.sin6_addr)) != 0;
00451 #else
00452       return ((*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[0])) == 0) && 
00453              (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[4])) == 0) && 
00454              (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[8])) == 0) && 
00455              (*(const __uint32_t *)(const void *)(&(m_anonv6.sin6_addr.s6_addr[12])) == ntohl(1)));
00456 #endif
00457 #endif
00458    }
00459    else
00460    {
00461       assert(0);
00462    }
00463    
00464    return false;
00465 }
00466 
00467 bool 
00468 Tuple::isV4() const
00469 {
00470    return mSockaddr.sa_family == AF_INET;
00471 }
00472 
00473 IpVersion 
00474 Tuple::ipVersion() const
00475 {
00476    return mSockaddr.sa_family == AF_INET ? V4 : V6;
00477 }
00478 
00479 static Tuple v4privateaddrbase1("10.0.0.0",0,UNKNOWN_TRANSPORT);
00480 static Tuple v4privateaddrbase2("172.16.0.0",0,UNKNOWN_TRANSPORT);
00481 static Tuple v4privateaddrbase3("192.168.0.0",0,UNKNOWN_TRANSPORT);
00482 
00483 #ifdef USE_IPV6
00484 static Tuple v6privateaddrbase("fc00::",0,UNKNOWN_TRANSPORT);
00485 #endif
00486 
00487 bool 
00488 Tuple::isPrivateAddress() const
00489 {
00490    if(ipVersion()==V4)
00491    {
00492       // RFC 1918
00493       return isEqualWithMask(v4privateaddrbase1,8,true,true) ||  // 10.0.0.0        -   10.255.255.255  (10/8 prefix)
00494              isEqualWithMask(v4privateaddrbase2,12,true,true) || // 172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
00495              isEqualWithMask(v4privateaddrbase3,16,true,true) || // 192.168.0.0     -   192.168.255.255 (192.168/16 prefix)
00496              isLoopback();
00497    }
00498 #ifdef USE_IPV6
00499    else if (ipVersion()==V6)
00500    {
00501       // RFC 4193
00502       // ?slg? should we look specifically for ipv4 mapped/compatible address and apply V4 rules to them?
00503       return isEqualWithMask(v6privateaddrbase,7,true,true) ||  // fc00::/7
00504              isLoopback();
00505    }
00506 #endif
00507    else
00508    {
00509       assert(0);
00510    }
00511    
00512    return false;
00513 }
00514 
00515 socklen_t
00516 Tuple::length() const
00517 {
00518    if (mSockaddr.sa_family == AF_INET) // v4
00519    {
00520       return sizeof(sockaddr_in);
00521    }
00522 #ifdef USE_IPV6
00523    else  if (mSockaddr.sa_family == AF_INET6) // v6
00524    {
00525       return sizeof(sockaddr_in6);
00526    }
00527 #endif
00528 
00529    assert(0);
00530    return 0;
00531 }
00532 
00533 
00534 bool Tuple::operator==(const Tuple& rhs) const
00535 {
00536    if (mSockaddr.sa_family == rhs.mSockaddr.sa_family)
00537    {
00538       if (mSockaddr.sa_family == AF_INET) // v4
00539       {
00540          return (m_anonv4.sin_port == rhs.m_anonv4.sin_port &&
00541                  mTransportType == rhs.mTransportType &&
00542                  memcmp(&m_anonv4.sin_addr, &rhs.m_anonv4.sin_addr, sizeof(in_addr)) == 0);
00543       }
00544       else // v6
00545       {
00546 #ifdef USE_IPV6
00547          return (m_anonv6.sin6_port == rhs.m_anonv6.sin6_port &&
00548                  mTransportType == rhs.mTransportType &&
00549                  memcmp(&m_anonv6.sin6_addr, &rhs.m_anonv6.sin6_addr, sizeof(in6_addr)) == 0);
00550 #else
00551          assert(0);
00552                 return false;
00553 #endif
00554       }
00555    }
00556    else
00557    {
00558       return false;
00559    }
00560 
00561    // !dlb! don't include connection 
00562 }
00563 
00564 bool
00565 Tuple::operator<(const Tuple& rhs) const
00566 {
00567    if (mTransportType < rhs.mTransportType)
00568    {
00569       return true;
00570    }
00571    else if (mTransportType > rhs.mTransportType)
00572    {
00573       return false;
00574    }
00575    else if (mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
00576    {
00577       int c=memcmp(&m_anonv4.sin_addr,
00578                    &rhs.m_anonv4.sin_addr,
00579                    sizeof(in_addr));
00580 
00581       if (c < 0)
00582       {
00583          return true;
00584       }
00585       else if (c > 0)
00586       {
00587          return false;
00588       }
00589       else if (m_anonv4.sin_port < rhs.m_anonv4.sin_port)
00590       {
00591          return true;
00592       }
00593       else
00594       {
00595          return false;
00596       }
00597    }
00598 #ifdef USE_IPV6
00599    else if (mSockaddr.sa_family == AF_INET6 &&
00600             rhs.mSockaddr.sa_family == AF_INET6)
00601    {
00602       int c = memcmp(&m_anonv6.sin6_addr,
00603                      &rhs.m_anonv6.sin6_addr,
00604                      sizeof(in6_addr));
00605       if (c < 0)
00606       {
00607          return true;
00608       }
00609       else if (c > 0)
00610       {
00611          return false;
00612       }
00613       else if (m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
00614       {
00615          return true;
00616       }
00617       else
00618       {
00619          return false;
00620       }
00621    }
00622    else if (mSockaddr.sa_family == AF_INET6 &&
00623             rhs.mSockaddr.sa_family == AF_INET)
00624    {
00625       return true;
00626    }
00627    else if (mSockaddr.sa_family == AF_INET &&
00628             rhs.mSockaddr.sa_family == AF_INET6)
00629    {
00630       return false;
00631    }
00632 #endif
00633    else
00634    {
00635       //assert(0);
00636       return false;
00637    }
00638 }
00639 
00640 EncodeStream&
00641 resip::operator<<(EncodeStream& ostrm, const Tuple& tuple)
00642 {
00643    ostrm << "[ " ;
00644    
00645 #ifdef USE_IPV6
00646    if (tuple.mSockaddr.sa_family == AF_INET6)
00647    {
00648       ostrm << "V6 " << DnsUtil::inet_ntop(tuple.m_anonv6.sin6_addr) << " port=" << tuple.getPort();
00649    }
00650    else
00651 #endif
00652    if (tuple.mSockaddr.sa_family == AF_INET)
00653    {
00654       ostrm << "V4 " << Tuple::inet_ntop(tuple) << ":" << tuple.getPort();
00655    }
00656    else
00657    {
00658       assert(0);
00659    }
00660 
00661    ostrm << " " << Tuple::toData(tuple.mTransportType);
00662    ostrm << " target domain=";
00663    if (tuple.mTargetDomain.empty()) ostrm << "unspecified";
00664    else ostrm << tuple.mTargetDomain;
00665    
00666    ostrm << " mFlowKey=" << tuple.mFlowKey
00667          << " ]";
00668    
00669    return ostrm;
00670 }
00671 
00672 size_t 
00673 Tuple::hash() const
00674 {
00675    // !dlb! do not include the connection
00676 #ifdef USE_IPV6
00677    if (mSockaddr.sa_family == AF_INET6)
00678    {
00679       const sockaddr_in6& in6 =
00680          reinterpret_cast<const sockaddr_in6&>(mSockaddr);
00681 
00682       return size_t(Data(Data::Share, (const char *)&in6.sin6_addr.s6_addr, sizeof(in6.sin6_addr.s6_addr)).hash() +
00683                     5*in6.sin6_port +
00684                     25*mTransportType);
00685    }
00686    else
00687 #endif
00688    {
00689       const sockaddr_in& in4 =
00690          reinterpret_cast<const sockaddr_in&>(mSockaddr);
00691          
00692       return size_t(in4.sin_addr.s_addr +
00693                     5*in4.sin_port +
00694                     25*mTransportType);
00695    }    
00696 }
00697 
00698 HashValueImp(resip::Tuple, data.hash());
00699 
00700 TransportType
00701 Tuple::toTransport(const Data& transportName)
00702 {
00703    return resip::toTransportType(transportName); // TransportTypes.hxx
00704 };
00705 
00706 const Data&
00707 Tuple::toData(TransportType type)
00708 {
00709    return resip::toData(type);  // TransportTypes.hxx
00710 }
00711 
00712 const Data&
00713 Tuple::toDataLower(TransportType type)
00714 {
00715    return resip::toDataLower(type);  // TransportTypes.hxx
00716 }
00717 
00718 Data
00719 Tuple::inet_ntop(const Tuple& tuple)
00720 {
00721 #ifdef USE_IPV6
00722    if (!tuple.isV4())
00723    {
00724       const sockaddr_in6& addr = reinterpret_cast<const sockaddr_in6&>(tuple.getSockaddr());
00725       return DnsUtil::inet_ntop(addr.sin6_addr);
00726    }
00727    else
00728 #endif
00729    {
00730       const sockaddr_in& addr = reinterpret_cast<const sockaddr_in&>(tuple.getSockaddr());
00731       return DnsUtil::inet_ntop(addr.sin_addr);
00732    }
00733 }
00734 
00735 
00736 bool
00737 Tuple::isEqualWithMask(const Tuple& compare, short mask, bool ignorePort, bool ignoreTransport) const
00738 {
00739    if(ignoreTransport || getType() == compare.getType())  // check if transport type matches
00740    {
00741       if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET) // v4
00742       {
00743          sockaddr_in* addr1 = (sockaddr_in*)&mSockaddr;
00744          sockaddr_in* addr2 = (sockaddr_in*)&compare.getSockaddr();
00745 
00746          return ((ignorePort || addr1->sin_port == addr2->sin_port)  &&
00747                  (addr1->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))) == 
00748                   (addr2->sin_addr.s_addr & htonl((0xFFFFFFFF << (32 - mask)))));
00749       }
00750 #ifdef USE_IPV6
00751       else if (mSockaddr.sa_family == compare.getSockaddr().sa_family && mSockaddr.sa_family == AF_INET6) // v6
00752       {
00753          sockaddr_in6* addr1 = (sockaddr_in6*)&mSockaddr;
00754          sockaddr_in6* addr2 = (sockaddr_in6*)&compare.getSockaddr();
00755 
00756          if(ignorePort || addr1->sin6_port == addr2->sin6_port)
00757          {
00758             unsigned long mask6part;
00759             unsigned long temp;
00760             bool match=true;
00761             for(int i = 3; i >= 0; i--)
00762             {
00763                if(mask <= 32*i)
00764                {
00765                   mask6part = 0;
00766                }
00767                else
00768                {
00769                   temp = mask - 32*i;
00770                   if(temp >= 32)
00771                   {
00772                      mask6part = 0xffffffff;
00773                   }
00774                   else
00775                   {
00776                      mask6part = 0xffffffff << (32 - temp);
00777                   }
00778                }
00779 #ifdef WIN32
00780                if((*((unsigned long*)&addr1->sin6_addr.u.Word[i*2]) & htonl(mask6part)) != 
00781                   (*((unsigned long*)&addr2->sin6_addr.u.Word[i*2]) & htonl(mask6part)))
00782 #elif defined(sun)
00783                // sun has no s6_addr16
00784                if((*((unsigned long*)&addr1->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)) !=
00785                   (*((unsigned long*)&addr2->sin6_addr._S6_un._S6_u32[i]) & htonl(mask6part)))
00786 #elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
00787                // bsd has no s6_addr16
00788                if((*((unsigned long*)&addr1->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)) != 
00789                   (*((unsigned long*)&addr2->sin6_addr.__u6_addr.__u6_addr32[i]) & htonl(mask6part)))                             
00790 #else
00791                if((*((unsigned long*)&addr1->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)) != 
00792                   (*((unsigned long*)&addr2->sin6_addr.s6_addr16[i*2]) & htonl(mask6part)))
00793 #endif
00794                {
00795                   match=false;
00796                   break;
00797                }
00798             }
00799             if(match)
00800             {
00801                return true;
00802             }
00803          }
00804       }
00805 #endif
00806    }
00807    return false;
00808 }
00809 
00810 
00811 // special comparitors
00812 bool
00813 Tuple::AnyInterfaceCompare::operator()(const Tuple& lhs,
00814                                        const Tuple& rhs) const
00815 {
00816    if (lhs.mTransportType < rhs.mTransportType)
00817    {
00818       return true;
00819    }
00820    else if (lhs.mTransportType > rhs.mTransportType)
00821    {
00822       return false;
00823    }
00824    else if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
00825    {
00826       if (lhs.m_anonv4.sin_port < rhs.m_anonv4.sin_port)
00827       {
00828          return true;
00829       }
00830       else
00831       {
00832          return false;
00833       }
00834    }
00835 #ifdef USE_IPV6
00836    else if (lhs.mSockaddr.sa_family == AF_INET6 &&
00837             rhs.mSockaddr.sa_family == AF_INET6)
00838    {
00839       if (lhs.m_anonv6.sin6_port < rhs.m_anonv6.sin6_port)
00840       {
00841          return true;
00842       }
00843       else
00844       {
00845          return false;
00846       }
00847    }
00848    else if (lhs.mSockaddr.sa_family == AF_INET6 &&
00849             rhs.mSockaddr.sa_family == AF_INET)
00850    {
00851       return true;
00852    }
00853    else if (lhs.mSockaddr.sa_family == AF_INET &&
00854             rhs.mSockaddr.sa_family == AF_INET6)
00855    {
00856       return false;
00857    }
00858 #endif
00859    else
00860    {
00861       return false;
00862    }
00863 };
00864 
00865 bool
00866 Tuple::AnyPortCompare::operator()(const Tuple& lhs,
00867                                   const Tuple& rhs) const
00868 {
00869    if (lhs.mTransportType < rhs.mTransportType)
00870    {
00871       return true;
00872    }
00873    else if (lhs.mTransportType > rhs.mTransportType)
00874    {
00875       return false;
00876    }
00877    else if (lhs.mSockaddr.sa_family == AF_INET && rhs.mSockaddr.sa_family == AF_INET)
00878    {
00879       int c = memcmp(&lhs.m_anonv4.sin_addr,
00880                      &rhs.m_anonv4.sin_addr,
00881                      sizeof(in_addr));
00882 
00883       if (c < 0)
00884       {
00885          return true;
00886       }
00887       else if (c > 0)
00888       {
00889          return false;
00890       }
00891    }
00892 #ifdef USE_IPV6
00893    else if (lhs.mSockaddr.sa_family == AF_INET6 &&
00894             rhs.mSockaddr.sa_family == AF_INET6)
00895    {
00896       int c = memcmp(&lhs.m_anonv6.sin6_addr,
00897                      &rhs.m_anonv6.sin6_addr,
00898                      sizeof(in6_addr));
00899       if (c < 0)
00900       {
00901          return true;
00902       }
00903       else if (c > 0)
00904       {
00905          return false;
00906       }
00907    }
00908    else if (lhs.mSockaddr.sa_family == AF_INET6 &&
00909             rhs.mSockaddr.sa_family == AF_INET)
00910    {
00911       return true;
00912    }
00913    else if (lhs.mSockaddr.sa_family == AF_INET &&
00914             rhs.mSockaddr.sa_family == AF_INET6)
00915    {
00916       return false;
00917    }
00918 #endif
00919 
00920    return false;
00921 }
00922 
00923 bool
00924 Tuple::FlowKeyCompare::operator()(const Tuple& lhs,
00925                                   const Tuple& rhs) const
00926 {
00927    if (lhs == rhs)
00928    {
00929       return lhs.mFlowKey < rhs.mFlowKey;
00930    }
00931    return lhs < rhs;
00932 };
00933 
00934 GenericIPAddress 
00935 Tuple::toGenericIPAddress() const
00936 {
00937    if (isV4())
00938    {
00939       return GenericIPAddress(m_anonv4);
00940    }
00941    else
00942 #ifdef USE_IPV6
00943   {
00944       return GenericIPAddress(m_anonv6);
00945   }
00946 #else
00947   {
00948      assert(0);
00949      return m_anonv4; //bogus
00950   }
00951 #endif
00952 }
00953 
00954 bool
00955 Tuple::AnyPortAnyInterfaceCompare::operator()(const Tuple& lhs,
00956                                               const Tuple& rhs) const
00957 {
00958    if (lhs.mTransportType < rhs.mTransportType)
00959    {
00960       return true;
00961    }
00962    else if (lhs.mTransportType > rhs.mTransportType)
00963    {
00964       return false;
00965    }
00966 #ifdef USE_IPV6
00967    else if (lhs.mSockaddr.sa_family == AF_INET6 &&
00968             rhs.mSockaddr.sa_family == AF_INET)
00969    {
00970       return true;
00971    }
00972    else if (lhs.mSockaddr.sa_family == AF_INET &&
00973             rhs.mSockaddr.sa_family == AF_INET6)
00974    {
00975       return false;
00976    }
00977 #endif
00978    else
00979    {
00980       return false;
00981    }
00982 };
00983 
00984 /* ====================================================================
00985  * The Vovida Software License, Version 1.0 
00986  * 
00987  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00988  * 
00989  * Redistribution and use in source and binary forms, with or without
00990  * modification, are permitted provided that the following conditions
00991  * are met:
00992  * 
00993  * 1. Redistributions of source code must retain the above copyright
00994  *    notice, this list of conditions and the following disclaimer.
00995  * 
00996  * 2. Redistributions in binary form must reproduce the above copyright
00997  *    notice, this list of conditions and the following disclaimer in
00998  *    the documentation and/or other materials provided with the
00999  *    distribution.
01000  * 
01001  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
01002  *    and "Vovida Open Communication Application Library (VOCAL)" must
01003  *    not be used to endorse or promote products derived from this
01004  *    software without prior written permission. For written
01005  *    permission, please contact vocal@vovida.org.
01006  *
01007  * 4. Products derived from this software may not be called "VOCAL", nor
01008  *    may "VOCAL" appear in their name, without prior written
01009  *    permission of Vovida Networks, Inc.
01010  * 
01011  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
01012  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
01013  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
01014  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
01015  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
01016  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
01017  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
01018  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
01019  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
01020  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
01021  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01022  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
01023  * DAMAGE.
01024  * 
01025  * ====================================================================
01026  * 
01027  * This software consists of voluntary contributions made by Vovida
01028  * Networks, Inc. and many individuals on behalf of Vovida Networks,
01029  * Inc.  For more information on Vovida Networks, Inc., please see
01030  * <http://www.vovida.org/>.
01031  *
01032  */