summaryrefslogtreecommitdiff
path: root/node/InetAddress.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/InetAddress.hpp')
-rw-r--r--node/InetAddress.hpp76
1 files changed, 75 insertions, 1 deletions
diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp
index e03deb71..c37fa621 100644
--- a/node/InetAddress.hpp
+++ b/node/InetAddress.hpp
@@ -301,6 +301,19 @@ struct InetAddress : public sockaddr_storage
inline unsigned int netmaskBits() const throw() { return port(); }
/**
+ * @return True if netmask bits is valid for the address type
+ */
+ inline bool netmaskBitsValid() const
+ {
+ const unsigned int n = port();
+ switch(ss_family) {
+ case AF_INET: return (n <= 32);
+ case AF_INET6: return (n <= 128);
+ }
+ return false;
+ }
+
+ /**
* Alias for port()
*
* This just aliases port() because for gateways we use this field to
@@ -356,7 +369,6 @@ struct InetAddress : public sockaddr_storage
* @return pointer to raw address bytes or NULL if not available
*/
inline const void *rawIpData() const
- throw()
{
switch(ss_family) {
case AF_INET: return (const void *)&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
@@ -366,6 +378,25 @@ struct InetAddress : public sockaddr_storage
}
/**
+ * @return InetAddress containing only the IP portion of this address and a zero port, or NULL if not IPv4 or IPv6
+ */
+ inline InetAddress ipOnly() const
+ {
+ InetAddress r;
+ switch(ss_family) {
+ case AF_INET:
+ r.ss_family = AF_INET;
+ reinterpret_cast<struct sockaddr_in *>(&r)->sin_addr.s_addr = reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ r.ss_family = AF_INET6;
+ memcpy(reinterpret_cast<struct sockaddr_in6 *>(&r)->sin6_addr.s6_addr,reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr,16);
+ break;
+ }
+ return r;
+ }
+
+ /**
* Performs an IP-only comparison or, if that is impossible, a memcmp()
*
* @param a InetAddress to compare again
@@ -383,6 +414,25 @@ struct InetAddress : public sockaddr_storage
return false;
}
+ inline unsigned long hashCode() const
+ {
+ if (ss_family == AF_INET) {
+ return ((unsigned long)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr + (unsigned long)reinterpret_cast<const struct sockaddr_in *>(this)->sin_port);
+ } else if (ss_family == AF_INET6) {
+ unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
+ const uint8_t *a = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+ for(long i=0;i<16;++i)
+ reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
+ return tmp;
+ } else {
+ unsigned long tmp = reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_port;
+ const uint8_t *a = reinterpret_cast<const uint8_t *>(this);
+ for(long i=0;i<(long)sizeof(InetAddress);++i)
+ reinterpret_cast<uint8_t *>(&tmp)[i % sizeof(tmp)] ^= a[i];
+ return tmp;
+ }
+ }
+
/**
* Set to null/zero
*/
@@ -400,6 +450,30 @@ struct InetAddress : public sockaddr_storage
throw();
/**
+ * @return 14-bit (0-16383) hash of this IP's first 24 or 48 bits (for V4 or V6) for rate limiting code, or 0 if non-IP
+ */
+ inline unsigned long rateGateHash() const
+ {
+ unsigned long h = 0;
+ switch(ss_family) {
+ case AF_INET:
+ h = (Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr) & 0xffffff00) >> 8;
+ h ^= (h >> 14);
+ break;
+ case AF_INET6: {
+ const uint8_t *ip = reinterpret_cast<const uint8_t *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
+ h = ((unsigned long)ip[0]); h <<= 1;
+ h += ((unsigned long)ip[1]); h <<= 1;
+ h += ((unsigned long)ip[2]); h <<= 1;
+ h += ((unsigned long)ip[3]); h <<= 1;
+ h += ((unsigned long)ip[4]); h <<= 1;
+ h += ((unsigned long)ip[5]);
+ } break;
+ }
+ return (h & 0x3fff);
+ }
+
+ /**
* @return True if address family is non-zero
*/
inline operator bool() const throw() { return (ss_family != 0); }