LCOV - code coverage report
Current view: top level - DCPS - NetworkAddress.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 87 113 77.0 %
Date: 2023-04-30 01:32:43 Functions: 24 31 77.4 %

          Line data    Source code
       1             : /*
       2             :  * Distributed under the OpenDDS License.
       3             :  * See: http://www.opendds.org/license.html
       4             :  */
       5             : 
       6             : #include "DCPS/DdsDcps_pch.h"
       7             : 
       8             : #include "NetworkAddress.h"
       9             : 
      10             : #include "Hash.h"
      11             : #include "LogAddr.h"
      12             : 
      13             : #include <cstring>
      14             : 
      15             : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
      16             : 
      17             : namespace OpenDDS {
      18             : namespace DCPS {
      19             : 
      20           7 : NetworkAddress::NetworkAddress()
      21             : {
      22             :   // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
      23           7 :   std::memset(&inet_addr_, 0, sizeof (inet_addr_));
      24             : 
      25             :   // The following is required to achieve equivalence between default-constructed NetworkAddress and ACE_INET_Addr
      26             : #if defined (ACE_HAS_IPV6)
      27             : #  if defined (ACE_USES_IPV4_IPV6_MIGRATION)
      28             :   if (ACE::ipv6_enabled()) {
      29             :     inet_addr_.in6_.sin6_family = AF_INET6;
      30             : #    ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
      31             :     inet_addr_.in6_.sin6_len = sizeof (inet_addr_);
      32             : #    endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
      33             :   } else {
      34             :     inet_addr_.in4_.sin_family = AF_INET;
      35             : #    ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
      36             :     inet_addr_.in4_.sin_len = sizeof (inet_addr_);
      37             : #    endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
      38             :   }
      39             : 
      40             : #  else /* ACE_USES_IPV4_IPV6_MIGRATION */
      41             :   inet_addr_.in6_.sin6_family = AF_INET6;
      42             : #    ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
      43             :   inet_addr_.in6_.sin6_len = sizeof (inet_addr_);
      44             : #    endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
      45             : #  endif /* ACE_USES_IPV4_IPV6_MIGRATION */
      46             : 
      47             : #else /* ACE_HAS_IPV6 */
      48           7 :   inet_addr_.in4_.sin_family = AF_INET;
      49             : #  ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
      50             :   inet_addr_.in4_.sin_len = sizeof (inet_addr_);
      51             : #  endif /* ACE_HAS_SOCKADDR_IN_SIN_LEN */
      52             : #endif /* ACE_HAS_IPV6 */
      53           7 : }
      54             : 
      55         290 : NetworkAddress::NetworkAddress(const NetworkAddress& val)
      56             : {
      57         290 :   *this = val;
      58         290 : }
      59             : 
      60          15 : NetworkAddress::NetworkAddress(const char* str)
      61             : {
      62          15 :   *this = ACE_INET_Addr(str);
      63          15 : }
      64             : 
      65          42 : NetworkAddress::NetworkAddress(ACE_UINT16 port, const char* str)
      66             : {
      67          42 :   *this = ACE_INET_Addr(port, str);
      68          42 : }
      69             : 
      70             : #if defined (ACE_HAS_WCHAR)
      71             : 
      72           0 : NetworkAddress::NetworkAddress(const wchar_t* str)
      73             : {
      74           0 :   *this = ACE_INET_Addr(str);
      75           0 : }
      76             : 
      77           0 : NetworkAddress::NetworkAddress(ACE_UINT16 port, const wchar_t* str)
      78             : {
      79           0 :   *this = ACE_INET_Addr(port, str);
      80           0 : }
      81             : 
      82             : #endif
      83             : 
      84         114 : NetworkAddress::NetworkAddress(const ACE_INET_Addr& addr)
      85             : {
      86             :   // We want to take care here to make sure that our NetworkAddress can be used with std::memcmp
      87         114 :   std::memset(&inet_addr_, 0, sizeof (inet_addr_));
      88             : 
      89         114 :   const ip46& in = *reinterpret_cast<ip46*>(addr.get_addr());
      90         114 :   if (in.in4_.sin_family == AF_INET) {
      91         114 :     inet_addr_.in4_.sin_family = in.in4_.sin_family;
      92         114 :     inet_addr_.in4_.sin_port = in.in4_.sin_port;
      93             : #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
      94             :     inet_addr_.in4_.sin_len = in.in4_.sin_len;
      95             : #endif
      96         114 :     inet_addr_.in4_.sin_addr = in.in4_.sin_addr;
      97             : #if defined (ACE_HAS_IPV6)
      98             :   } else if (in.in6_.sin6_family == AF_INET6) {
      99             :     inet_addr_.in6_.sin6_family = in.in6_.sin6_family;
     100             :     inet_addr_.in6_.sin6_port = in.in6_.sin6_port;
     101             :     inet_addr_.in6_.sin6_flowinfo = in.in6_.sin6_flowinfo;
     102             : #ifdef ACE_HAS_SOCKADDR_IN_SIN_LEN
     103             :     inet_addr_.in6_.sin6_len = in.in6_.sin6_len;
     104             : #endif
     105             :     inet_addr_.in6_.sin6_addr = in.in6_.sin6_addr;
     106             :     inet_addr_.in6_.sin6_scope_id = in.in6_.sin6_scope_id;
     107             : #endif
     108             :   }
     109         114 : }
     110             : 
     111         347 : NetworkAddress& NetworkAddress::operator=(const NetworkAddress& rhs)
     112             : {
     113         347 :   if (&rhs != this) {
     114         347 :     std::memcpy(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_));
     115             :   }
     116         347 :   return *this;
     117             : }
     118             : 
     119          57 : NetworkAddress& NetworkAddress::operator=(const ACE_INET_Addr& rhs)
     120             : {
     121          57 :   return *this = NetworkAddress(rhs);
     122             : }
     123             : 
     124           4 : NetworkAddress::operator bool() const
     125             : {
     126           4 :   static const NetworkAddress empty = NetworkAddress();
     127           4 :   return *this != empty;
     128             : }
     129             : 
     130          44 : bool NetworkAddress::operator!() const
     131             : {
     132          44 :   static const NetworkAddress empty = NetworkAddress();
     133          44 :   return *this == empty;
     134             : }
     135             : 
     136          70 : bool NetworkAddress::operator==(const NetworkAddress& rhs) const
     137             : {
     138          70 :   return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) == 0;
     139             : }
     140             : 
     141          16 : bool NetworkAddress::operator!=(const NetworkAddress& rhs) const
     142             : {
     143          16 :   return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) != 0;
     144             : }
     145             : 
     146          43 : bool NetworkAddress::operator<(const NetworkAddress& rhs) const
     147             : {
     148          43 :   return std::memcmp(&inet_addr_, &rhs.inet_addr_, sizeof (inet_addr_)) < 0;
     149             : }
     150             : 
     151             : #if defined ACE_HAS_CPP11
     152           9 : size_t NetworkAddress::hash(size_t start_hash) const {
     153           9 :   return static_cast<size_t>(OpenDDS::DCPS::one_at_a_time_hash(reinterpret_cast<const uint8_t*>(&inet_addr_), sizeof(inet_addr_), static_cast<uint32_t>(start_hash)));
     154             : }
     155             : #endif
     156             : 
     157           4 : bool NetworkAddress::addr_bytes_equal(const NetworkAddress& rhs) const
     158             : {
     159           4 :   if (inet_addr_.in4_.sin_family == AF_INET && rhs.inet_addr_.in4_.sin_family == AF_INET) {
     160           4 :     return std::memcmp(&inet_addr_.in4_.sin_addr, &rhs.inet_addr_.in4_.sin_addr, sizeof (inet_addr_.in4_.sin_addr)) == 0;
     161             : #if defined (ACE_HAS_IPV6)
     162             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6 && rhs.inet_addr_.in6_.sin6_family == AF_INET6) {
     163             :     return std::memcmp(&inet_addr_.in6_.sin6_addr, &rhs.inet_addr_.in6_.sin6_addr, sizeof (inet_addr_.in6_.sin6_addr)) == 0;
     164             : #endif
     165             :   }
     166             :   // Don't worry about ipv4 mapped / compatible ipv6 addresses for now
     167           0 :   return false;
     168             : }
     169             : 
     170           6 : ACE_INET_Addr NetworkAddress::to_addr() const
     171             : {
     172           6 :   ACE_INET_Addr result;
     173           6 :   result.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
     174           6 :   return result;
     175           0 : }
     176             : 
     177           0 : void NetworkAddress::to_addr(ACE_INET_Addr& addr) const
     178             : {
     179           0 :   addr.set_addr(const_cast<ip46*>(&inet_addr_), sizeof (inet_addr_));
     180           0 : }
     181             : 
     182           6 : ACE_INT16 NetworkAddress::get_type() const
     183             : {
     184           6 :   return static_cast<ACE_INT16>(inet_addr_.in4_.sin_family);
     185             : }
     186             : 
     187           0 : void NetworkAddress::set_type(ACE_INT16 type)
     188             : {
     189           0 :   inet_addr_.in4_.sin_family = type;
     190           0 : }
     191             : 
     192           7 : ACE_UINT16 NetworkAddress::get_port_number() const
     193             : {
     194           7 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     195           7 :     return ACE_NTOHS(inet_addr_.in4_.sin_port);
     196             : #if defined (ACE_HAS_IPV6)
     197             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
     198             :     return ACE_NTOHS(inet_addr_.in6_.sin6_port);
     199             : #endif
     200             :   }
     201           0 :   return 0;
     202             : }
     203             : 
     204           1 : void NetworkAddress::set_port_number(ACE_UINT16 port)
     205             : {
     206           1 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     207           1 :     inet_addr_.in4_.sin_port = ACE_HTONS(port);
     208             : #if defined (ACE_HAS_IPV6)
     209             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
     210             :     inet_addr_.in6_.sin6_port = ACE_HTONS(port);
     211             : #endif
     212             :   }
     213           1 : }
     214             : 
     215           3 : bool NetworkAddress::is_any() const
     216             : {
     217           3 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     218           3 :     return inet_addr_.in4_.sin_addr.s_addr == INADDR_ANY;
     219             : #if defined (ACE_HAS_IPV6)
     220             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
     221             :     if (IN6_IS_ADDR_UNSPECIFIED(&inet_addr_.in6_.sin6_addr)) {
     222             :       return true;
     223             :     }
     224             :     static const unsigned char buff[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
     225             :     return memcmp(buff, &inet_addr_.in6_.sin6_addr, sizeof (buff)) == 0;
     226             : #endif
     227             :   }
     228           0 :   return false;
     229             : }
     230             : 
     231          64 : bool NetworkAddress::is_loopback() const
     232             : {
     233          64 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     234             :     // RFC 3330 defines loopback as any address with 127.x.x.x
     235          64 :     return (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFF000000) == 0x7F000000;
     236             : #if defined (ACE_HAS_IPV6)
     237             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
     238             :     return IN6_IS_ADDR_LOOPBACK(&inet_addr_.in6_.sin6_addr);
     239             : #endif
     240             :   }
     241           0 :   return false;
     242             : }
     243             : 
     244           5 : bool NetworkAddress::is_multicast() const
     245             : {
     246           5 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     247           5 :     return (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xF0000000) == 0xE0000000;
     248             : #if defined (ACE_HAS_IPV6)
     249             :   } else if (inet_addr_.in6_.sin6_family == AF_INET6) {
     250             :     return this->inet_addr_.in6_.sin6_addr.s6_addr[0] == 0xFF;
     251             : #endif
     252             :   }
     253           0 :   return false;
     254             : }
     255             : 
     256          40 : bool NetworkAddress::is_private() const
     257             : {
     258          40 :   if (inet_addr_.in4_.sin_family == AF_INET) {
     259             :     // private address classes are 10.x.x.x/8, 172.16.x.x/16, 192.168.x.x/24
     260          72 :     return ((ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFF000000) == 0x0A000000 ||
     261          70 :             (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFF00000) == 0xAC100000 ||
     262          70 :             (ACE_HTONL(inet_addr_.in4_.sin_addr.s_addr) & 0xFFFF0000) == 0xC0A80000);
     263             :   }
     264           0 :   return false;
     265             : }
     266             : 
     267           0 : bool NetworkAddress::is_uniquelocal() const
     268             : {
     269             : #if defined (ACE_HAS_IPV6)
     270             :   if (inet_addr_.in6_.sin6_family == AF_INET6) {
     271             :     return (inet_addr_.in6_.sin6_addr.s6_addr[0] & 0xFE) == 0xFC;
     272             :   }
     273             : #endif
     274           0 :   return false;
     275             : }
     276             : 
     277           0 : bool NetworkAddress::is_linklocal() const
     278             : {
     279             : #if defined (ACE_HAS_IPV6)
     280             :   if (inet_addr_.in6_.sin6_family == AF_INET6) {
     281             :     return IN6_IS_ADDR_LINKLOCAL(&inet_addr_.in6_.sin6_addr);
     282             :   }
     283             : #endif
     284           0 :   return false;
     285             : }
     286             : 
     287           0 : bool NetworkAddress::is_sitelocal() const
     288             : {
     289             : #if defined (ACE_HAS_IPV6)
     290             :   if (inet_addr_.in6_.sin6_family == AF_INET6) {
     291             :     return IN6_IS_ADDR_SITELOCAL(&inet_addr_.in6_.sin6_addr);
     292             :   }
     293             : #endif
     294           0 :   return false;
     295             : }
     296             : 
     297          36 : bool is_more_local(const NetworkAddress& current, const NetworkAddress& incoming)
     298             : {
     299             :   // The question to answer here: "Is the incoming address 'more local' than the current address?"
     300             : 
     301          36 :   if (!current) {
     302           0 :     return true;
     303             :   }
     304             : 
     305             : #ifdef ACE_HAS_IPV6
     306             :   if (current.get_type() == AF_INET) {
     307             :     if (incoming.get_type() == AF_INET6) {
     308             :       return true;
     309             :     }
     310             : #endif /* ACE_HAS_IPV6 */
     311          36 :     if (current.is_loopback()) {
     312          12 :       return false;
     313          24 :     } else if (incoming.is_loopback()) {
     314           8 :       return true;
     315             :     }
     316             : 
     317          16 :     if (current.is_private()) {
     318           8 :       return false;
     319           8 :     } else if (incoming.is_private()) {
     320           4 :       return true;
     321             :     }
     322             : #ifdef ACE_HAS_IPV6
     323             :   } else if (current.get_type() == AF_INET6) {
     324             :     if (incoming.get_type() == AF_INET) {
     325             :       return false;
     326             :     }
     327             : 
     328             :     if (current.is_loopback()) {
     329             :       return false;
     330             :     } else if (incoming.is_loopback()) {
     331             :       return true;
     332             :     }
     333             : 
     334             :     if (current.is_linklocal()) {
     335             :       return false;
     336             :     } else if (incoming.is_linklocal()) {
     337             :       return true;
     338             :     }
     339             : 
     340             :     if (current.is_uniquelocal()) {
     341             :       return false;
     342             :     } else if (incoming.is_uniquelocal()) {
     343             :       return true;
     344             :     }
     345             : 
     346             :     if (current.is_sitelocal()) {
     347             :       return false;
     348             :     } else if (incoming.is_sitelocal()) {
     349             :       return true;
     350             :     }
     351             :   }
     352             : #endif /* ACE_HAS_IPV6 */
     353           4 :   return false;
     354             : }
     355             : 
     356             : #if defined ACE_HAS_CPP11
     357           9 : size_t calculate_hash(const AddrSet& addrs, size_t start_hash)
     358             : {
     359           9 :   size_t result = start_hash;
     360          18 :   for (AddrSet::const_iterator it = addrs.begin(), limit = addrs.end(); it != limit; ++it) {
     361           9 :     result = it->hash(result);
     362             :   }
     363           9 :   return result;
     364             : }
     365             : #endif
     366             : 
     367             : } // namespace DCPS
     368             : } // namespace OpenDDS
     369             : 
     370             : OPENDDS_END_VERSIONED_NAMESPACE_DECL

Generated by: LCOV version 1.16