Inline some IPAddr methods.

This commit is contained in:
Jon Siwek 2012-02-09 12:53:37 -06:00
parent 3ff0eed3fc
commit 303f02d6f8
2 changed files with 204 additions and 279 deletions

View file

@ -1,167 +1,10 @@
#include "IPAddr.h" #include "IPAddr.h"
#include "Reporter.h" #include "Reporter.h"
#include "modp_numtoa.h"
#include <arpa/inet.h>
const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0, const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff }; 0, 0, 0xff, 0xff };
IPAddr::IPAddr()
{
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
IPAddr::IPAddr(const in4_addr& in4)
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], &in4.s_addr, sizeof(in4.s_addr));
}
IPAddr::IPAddr(const in6_addr& arg_in6)
: in6(arg_in6)
{
}
void IPAddr::Init(const std::string& s)
{
if ( s.find(':') == std::string::npos ) //IPv4
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
if ( inet_pton(AF_INET, s.c_str(), &in6.s6_addr[12]) <=0 )
{
reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
}
else
{
if ( inet_pton(AF_INET6, s.c_str(), in6.s6_addr) <=0 )
{
reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
}
}
IPAddr::IPAddr(const std::string& s)
{
Init(s);
}
IPAddr::IPAddr(const BroString& s)
{
Init(s.CheckString());
}
IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
{
if ( family == IPv4 )
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], bytes, sizeof(uint32_t));
if ( order == Host )
{
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
*p = htonl(*p);
}
}
else
{
memcpy(in6.s6_addr, bytes, sizeof(in6.s6_addr));
if ( order == Host )
{
for ( unsigned int i = 0; i < 4; ++ i)
{
uint32_t* p = (uint32_t*) &in6.s6_addr[i*4];
*p = htonl(*p);
}
}
}
}
IPAddr::IPAddr(const IPAddr& other)
{
in6 = other.in6;
}
IPAddr::~IPAddr()
{
}
IPAddr::Family IPAddr::family() const
{
if ( memcmp(in6.s6_addr, v4_mapped_prefix, 12) == 0 )
return IPv4;
else
return IPv6;
}
bool IPAddr::IsLoopback() const
{
if ( family() == IPv4 )
return in6.s6_addr[12] == 127;
else
return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0)
&& (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0)
&& (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0)
&& (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0)
&& (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0)
&& (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0)
&& (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0)
&& (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1));
}
bool IPAddr::IsMulticast() const
{
if ( family() == IPv4 )
return in6.s6_addr[12] == 224;
else
return in6.s6_addr[0] == 0xff;
}
bool IPAddr::IsBroadcast() const
{
if ( family() == IPv4 )
return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff)
&& (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff));
else
return false;
}
int IPAddr::GetBytes(uint32_t** bytes)
{
if ( family() == IPv4 )
{
*bytes = (uint32_t*) &in6.s6_addr[12];
return 1;
}
else
{
*bytes = (uint32_t*) in6.s6_addr;
return 4;
}
}
int IPAddr::GetBytes(const uint32_t** bytes) const
{
if ( family() == IPv4 )
{
*bytes = (uint32_t*) &in6.s6_addr[12];
return 1;
}
else
{
*bytes = (uint32_t*) in6.s6_addr;
return 4;
}
}
void IPAddr::CopyIPv6(uint32_t* bytes) const
{
memcpy(bytes, in6.s6_addr, sizeof(in6.s6_addr));
}
void IPAddr::Mask(int top_bits_to_keep) void IPAddr::Mask(int top_bits_to_keep)
{ {
if ( top_bits_to_keep <=0 || top_bits_to_keep > 128 ) if ( top_bits_to_keep <=0 || top_bits_to_keep > 128 )
@ -216,47 +59,25 @@ void IPAddr::ReverseMask(int top_bits_to_chop)
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr)); memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
} }
IPAddr& IPAddr::operator =(const IPAddr& other) void IPAddr::Init(const std::string& s)
{ {
// No self-assignment check here because it's correct without it and if ( s.find(':') == std::string::npos ) //IPv4
// makes the common case faster. {
in6 = other.in6; memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
return *this; if ( inet_pton(AF_INET, s.c_str(), &in6.s6_addr[12]) <=0 )
{
reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
} }
IPAddr::operator std::string() const
{
if ( family() == IPv4 )
{
char s[INET_ADDRSTRLEN];
if ( inet_ntop(AF_INET, &in6.s6_addr[12], s, INET_ADDRSTRLEN) == NULL )
return "<bad IPv4 address conversion";
else
return s;
} }
else else
{ {
char s[INET6_ADDRSTRLEN]; if ( inet_pton(AF_INET6, s.c_str(), in6.s6_addr) <=0 )
if ( inet_ntop(AF_INET6, in6.s6_addr, s, INET6_ADDRSTRLEN) == NULL )
return "<bad IPv64 address conversion";
else
return s;
}
}
bool operator ==(const IPAddr& addr1, const IPAddr& addr2)
{ {
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0; reporter->Error("Bad IP address: %s", s.c_str());
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
} }
bool operator !=(const IPAddr& addr1, const IPAddr& addr2)
{
return ! (addr1 == addr2);
} }
bool operator <(const IPAddr& addr1, const IPAddr& addr2)
{
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) < 0;
} }
IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length) IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length)
@ -304,61 +125,3 @@ IPPrefix::IPPrefix(const std::string& s, uint8_t length)
reporter->InternalError("Bad string IPPrefix length : %d", length); reporter->InternalError("Bad string IPPrefix length : %d", length);
prefix.Mask(this->length); prefix.Mask(this->length);
} }
IPPrefix::IPPrefix(const IPPrefix& other)
: prefix(other.prefix), length(other.length)
{
}
IPPrefix::~IPPrefix()
{
}
const IPAddr& IPPrefix::Prefix() const
{
return prefix;
}
uint8_t IPPrefix::Length() const
{
return prefix.family() == IPAddr::IPv4 ? length - 96 : length;
}
uint8_t IPPrefix::LengthIPv6() const
{
return length;
}
IPPrefix& IPPrefix::operator =(const IPPrefix& other)
{
// No self-assignment check here because it's correct without it and
// makes the common case faster.
prefix = other.Prefix();
length = other.Length();
return *this;
}
IPPrefix::operator std::string() const
{
char l[16];
if ( prefix.family() == IPAddr::IPv4 )
modp_uitoa10(length - 96, l);
else
modp_uitoa10(length, l);
return std::string(prefix).append("/").append(l);
}
bool operator ==(const IPPrefix& net1, const IPPrefix& net2)
{
return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length();
}
bool operator <(const IPPrefix& net1, const IPPrefix& net2)
{
if ( net1.Prefix() < net2.Prefix() )
return true;
else if ( net1.Prefix() == net2.Prefix() )
return net1.Length() < net2.Length();
else
return false;
}

View file

@ -3,6 +3,7 @@
#define IPADDR_H #define IPADDR_H
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h>
#include <string> #include <string>
#include "BroString.h" #include "BroString.h"
@ -21,29 +22,42 @@ public:
enum ByteOrder { Host, Network }; enum ByteOrder { Host, Network };
/// Constructs the unspecified IPv6 address (all 128 bits zeroed). /// Constructs the unspecified IPv6 address (all 128 bits zeroed).
IPAddr(); IPAddr()
{
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
/// Constructs an address instance from an IPv4 address. /// Constructs an address instance from an IPv4 address.
/// ///
/// @param in6 The IPv6 address. /// @param in6 The IPv6 address.
IPAddr(const in4_addr& in4); IPAddr(const in4_addr& in4)
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], &in4.s_addr, sizeof(in4.s_addr));
}
/// Constructs an address instance from an IPv6 address. /// Constructs an address instance from an IPv6 address.
/// ///
/// @param in6 The IPv6 address. /// @param in6 The IPv6 address.
IPAddr(const in6_addr& in6); IPAddr(const in6_addr& arg_in6) : in6(arg_in6) { }
/// Constructs an address instance from a string representation. /// Constructs an address instance from a string representation.
/// ///
/// @param s String containing an IP address as either a dotted IPv4 /// @param s String containing an IP address as either a dotted IPv4
/// address or a hex IPv6 address. /// address or a hex IPv6 address.
IPAddr(const std::string& s); IPAddr(const std::string& s)
{
Init(s);
}
/// Constructs an address instance from a string representation. /// Constructs an address instance from a string representation.
/// ///
/// @param s String containing an IP address as either a dotted IPv4 /// @param s String containing an IP address as either a dotted IPv4
/// address or a hex IPv6 address. /// address or a hex IPv6 address.
IPAddr(const BroString& s); IPAddr(const BroString& s)
{
Init(s.CheckString());
}
/// Constructs an address instance from a raw byte representation. /// Constructs an address instance from a raw byte representation.
/// ///
@ -55,25 +69,81 @@ public:
/// ///
/// @param order Indicates whether the raw representation pointed to /// @param order Indicates whether the raw representation pointed to
/// by \a bytes is stored in network or host order. /// by \a bytes is stored in network or host order.
IPAddr(Family family, const uint32_t* bytes, ByteOrder order); IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
{
if ( family == IPv4 )
{
memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix));
memcpy(&in6.s6_addr[12], bytes, sizeof(uint32_t));
if ( order == Host )
{
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
*p = htonl(*p);
}
}
else
{
memcpy(in6.s6_addr, bytes, sizeof(in6.s6_addr));
if ( order == Host )
{
for ( unsigned int i = 0; i < 4; ++ i)
{
uint32_t* p = (uint32_t*) &in6.s6_addr[i*4];
*p = htonl(*p);
}
}
}
}
/// Copy constructor. /// Copy constructor.
IPAddr(const IPAddr& other); IPAddr(const IPAddr& other) : in6(other.in6) { };
/// Destructor. /// Destructor.
~IPAddr(); ~IPAddr() { };
/// Returns the address' family. /// Returns the address' family.
Family family() const; Family family() const
{
if ( memcmp(in6.s6_addr, v4_mapped_prefix, 12) == 0 )
return IPv4;
else
return IPv6;
}
/// Returns true if the address represents a loopback device. /// Returns true if the address represents a loopback device.
bool IsLoopback() const; bool IsLoopback() const
{
if ( family() == IPv4 )
return in6.s6_addr[12] == 127;
else
return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0)
&& (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0)
&& (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0)
&& (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0)
&& (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0)
&& (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0)
&& (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0)
&& (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1));
}
/// Returns true if the address represents a multicast address. /// Returns true if the address represents a multicast address.
bool IsMulticast() const; bool IsMulticast() const
{
if ( family() == IPv4 )
return in6.s6_addr[12] == 224;
else
return in6.s6_addr[0] == 0xff;
}
/// Returns true if the address represents a broadcast address. /// Returns true if the address represents a broadcast address.
bool IsBroadcast() const; bool IsBroadcast() const
{
if ( family() == IPv4 )
return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff)
&& (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff));
else
return false;
}
/// Retrieves the raw byte representation of the address. /// Retrieves the raw byte representation of the address.
/// ///
@ -85,8 +155,33 @@ public:
/// ///
/// @return The number of 32-bit words the raw representation uses. This /// @return The number of 32-bit words the raw representation uses. This
/// will be 1 for an IPv4 address and 4 for an IPv6 address. /// will be 1 for an IPv4 address and 4 for an IPv6 address.
int GetBytes(uint32_t** bytes); int GetBytes(uint32_t** bytes)
int GetBytes(const uint32_t** bytes) const; {
if ( family() == IPv4 )
{
*bytes = (uint32_t*) &in6.s6_addr[12];
return 1;
}
else
{
*bytes = (uint32_t*) in6.s6_addr;
return 4;
}
}
int GetBytes(const uint32_t** bytes) const
{
if ( family() == IPv4 )
{
*bytes = (uint32_t*) &in6.s6_addr[12];
return 1;
}
else
{
*bytes = (uint32_t*) in6.s6_addr;
return 4;
}
}
/// Retrieves a copy of the IPv6 raw byte representation of the address. /// Retrieves a copy of the IPv6 raw byte representation of the address.
/// If the internal address is IPv4, then the copied bytes use the /// If the internal address is IPv4, then the copied bytes use the
@ -94,7 +189,10 @@ public:
/// ///
/// @param bytes The pointer to a memory location in which the /// @param bytes The pointer to a memory location in which the
/// raw bytes of the address are to be copied in network byte-order. /// raw bytes of the address are to be copied in network byte-order.
void CopyIPv6(uint32_t* bytes) const; void CopyIPv6(uint32_t* bytes) const
{
memcpy(bytes, in6.s6_addr, sizeof(in6.s6_addr));
}
/// Masks out lower bits of the address. /// Masks out lower bits of the address.
/// ///
@ -116,21 +214,55 @@ public:
void ReverseMask(int top_bits_to_chop); void ReverseMask(int top_bits_to_chop);
/// Assignment operator. /// Assignment operator.
IPAddr& operator=(const IPAddr& other); IPAddr& operator=(const IPAddr& other)
{
// No self-assignment check here because it's correct without it and
// makes the common case faster.
in6 = other.in6;
return *this;
}
/// Returns a string representation of the address. IPv4 addresses /// Returns a string representation of the address. IPv4 addresses
/// will be returned in dotted representation, IPv6 addresses in /// will be returned in dotted representation, IPv6 addresses in
/// compressed hex. /// compressed hex.
operator std::string() const; operator std::string() const
{
if ( family() == IPv4 )
{
char s[INET_ADDRSTRLEN];
if ( inet_ntop(AF_INET, &in6.s6_addr[12], s, INET_ADDRSTRLEN) == NULL )
return "<bad IPv4 address conversion";
else
return s;
}
else
{
char s[INET6_ADDRSTRLEN];
if ( inet_ntop(AF_INET6, in6.s6_addr, s, INET6_ADDRSTRLEN) == NULL )
return "<bad IPv64 address conversion";
else
return s;
}
}
/// Comparison operator for IP address. /// Comparison operator for IP address.
friend bool operator==(const IPAddr& addr1, const IPAddr& addr2); friend bool operator==(const IPAddr& addr1, const IPAddr& addr2)
friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2); {
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0;
}
friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2)
{
return ! (addr1 == addr2);
}
/// Comparison operator IP addresses. This defines a well-defined order for /// Comparison operator IP addresses. This defines a well-defined order for
/// IP addresses. However, the order does not necessarily correspond to /// IP addresses. However, the order does not necessarily correspond to
/// their numerical values. /// their numerical values.
friend bool operator<(const IPAddr& addr1, const IPAddr& addr2); friend bool operator<(const IPAddr& addr1, const IPAddr& addr2)
{
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) < 0;
}
unsigned int MemoryAllocation() const { return padded_sizeof(*this); } unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
@ -182,30 +314,49 @@ public:
IPPrefix(const std::string& s, uint8_t length); IPPrefix(const std::string& s, uint8_t length);
/// Copy constructor. /// Copy constructor.
IPPrefix(const IPPrefix& other); IPPrefix(const IPPrefix& other)
: prefix(other.prefix), length(other.length) { }
/// Destructor. /// Destructor.
~IPPrefix(); ~IPPrefix() { }
/// Returns the prefix in the form of an IP address. The address will /// Returns the prefix in the form of an IP address. The address will
/// have all bits not part of the prefixed set to zero. /// have all bits not part of the prefixed set to zero.
const IPAddr& Prefix() const; const IPAddr& Prefix() const { return prefix; }
/// Returns the bit length of the prefix, relative to the 32 bits /// Returns the bit length of the prefix, relative to the 32 bits
/// of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix. /// of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix.
uint8_t Length() const; uint8_t Length() const
{
return prefix.family() == IPAddr::IPv4 ? length - 96 : length;
}
/// Returns the bit length of the prefix always relative to a full /// Returns the bit length of the prefix always relative to a full
/// 128 bits of an IPv6 prefix (or IPv4 mapped to IPv6). /// 128 bits of an IPv6 prefix (or IPv4 mapped to IPv6).
uint8_t LengthIPv6() const; uint8_t LengthIPv6() const { return length; }
/// Assignment operator. /// Assignment operator.
IPPrefix& operator=(const IPPrefix& other); IPPrefix& operator=(const IPPrefix& other)
{
// No self-assignment check here because it's correct without it and
// makes the common case faster.
prefix = other.Prefix();
length = other.Length();
return *this;
}
/// Returns a string representation of the prefix. IPv4 addresses /// Returns a string representation of the prefix. IPv4 addresses
/// will be returned in dotted representation, IPv6 addresses in /// will be returned in dotted representation, IPv6 addresses in
/// compressed hex. /// compressed hex.
operator std::string() const; operator std::string() const
{
char l[16];
if ( prefix.family() == IPAddr::IPv4 )
modp_uitoa10(length - 96, l);
else
modp_uitoa10(length, l);
return std::string(prefix).append("/").append(l);
}
unsigned int MemoryAllocation() const { return padded_sizeof(*this); } unsigned int MemoryAllocation() const { return padded_sizeof(*this); }
@ -215,11 +366,22 @@ private:
}; };
/// Comparison operator for IP prefix. /// Comparison operator for IP prefix.
extern bool operator==(const IPPrefix& net1, const IPPrefix& net2); inline bool operator==(const IPPrefix& net1, const IPPrefix& net2)
{
return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length();
}
/// Comparison operator IP prefixes. This defines a well-defined order for /// Comparison operator IP prefixes. This defines a well-defined order for
/// IP prefix. However, the order does not necessarily corresponding to their /// IP prefix. However, the order does not necessarily corresponding to their
/// numerical values. /// numerical values.
extern bool operator<(const IPPrefix& net1, const IPPrefix& net2); inline bool operator<(const IPPrefix& net1, const IPPrefix& net2)
{
if ( net1.Prefix() < net2.Prefix() )
return true;
else if ( net1.Prefix() == net2.Prefix() )
return net1.Length() < net2.Length();
else
return false;
}
#endif #endif