//===========================================================================// // // Purpose: implementation of the CNetAdr class. // -------------------------------------------------------------------------- // // NOTE: This implementation is considered deprecated. I rebuilded this // not knowing that the engine supports IPv6 as well. I have fully rewritten // this class in 'tier1/NetAdr2.cpp' in modern C++. Please use this instead. // This class is for reference material only may some bits in the engine line // up with this original 'CNetAdr' implementation. // //===========================================================================// #include "core/stdafx.h" #include "tier1/netadr.h" #include "mathlib/swap.h" ////////////////////////////////////////////////////////////////////// // Constructors ////////////////////////////////////////////////////////////////////// netadr_s::netadr_s(void) { SetIP(0); SetPort(0); SetType(netadrtype_t::NA_IP); } netadr_s::netadr_s(std::uint32_t unIP, std::uint16_t usPort) { SetIP(unIP); SetPort(usPort); SetType(netadrtype_t::NA_IP); } netadr_s::netadr_s(const char* pch) { SetFromString(pch); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void netadr_t::SetFromSocket(int hSocket) { Clear(); type = netadrtype_t::NA_IP; struct sockaddr address{}; socklen_t namelen = sizeof(address); if (getsockname(hSocket, (struct sockaddr*)&address, &namelen) == 0) { SetFromSockadr(&address); } } ////////////////////////////////////////////////////////////////////// // Compares IP for equality ////////////////////////////////////////////////////////////////////// bool netadr_t::CompareAdr(const netadr_t& a, bool onlyBase) const { if (a.type != type) { return false; } if (type == netadrtype_t::NA_LOOPBACK) { return true; } if (type == netadrtype_t::NA_BROADCAST) { return true; } if (type == netadrtype_t::NA_IP) { if (!onlyBase && (port != a.port)) { return false; } if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3]) { return true; } } return false; } ////////////////////////////////////////////////////////////////////// // Compares Class-B IP for equality ////////////////////////////////////////////////////////////////////// bool netadr_t::CompareClassBAdr(const netadr_t& a) const { if (a.type != type) { return false; } if (type == netadrtype_t::NA_LOOPBACK) { return true; } if (type == netadrtype_t::NA_IP) { if (a.ip[0] == ip[0] && a.ip[1] == ip[1]) { return true; } } return false; } ////////////////////////////////////////////////////////////////////// // Compares Class-C IP for equality ////////////////////////////////////////////////////////////////////// bool netadr_t::CompareClassCAdr(const netadr_t& a) const { if (a.type != type) { return false; } if (type == netadrtype_t::NA_LOOPBACK) { return true; } if (type == netadrtype_t::NA_IP) { if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2]) { return true; } } return false; } ////////////////////////////////////////////////////////////////////// // Convert address to string ////////////////////////////////////////////////////////////////////// const char* netadr_t::ToString(bool onlyBase) const { // Select a static buffer. static char s[4][64]{}; static int slot = 0; int useSlot = (slot++) % 4; // Render into it. ToString(s[useSlot], sizeof(s[0]), onlyBase); // Pray the caller uses it before it gets clobbered. return s[useSlot]; } ////////////////////////////////////////////////////////////////////// // Convert address to string ////////////////////////////////////////////////////////////////////// void netadr_t::ToString(char* pchBuffer, std::uint32_t unBufferSize, bool bOnlyBase) const { if (type == netadrtype_t::NA_LOOPBACK) { memmove(pchBuffer, "loopback", unBufferSize); } else if (type == netadrtype_t::NA_BROADCAST) { memmove(pchBuffer, "broadcast", unBufferSize); } else if (type == netadrtype_t::NA_IP) { if (bOnlyBase) { snprintf(pchBuffer, unBufferSize, "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]); } else { snprintf(pchBuffer, unBufferSize, "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port)); } } else { memmove(pchBuffer, "unknown", unBufferSize); } } ////////////////////////////////////////////////////////////////////// // Clears IP ////////////////////////////////////////////////////////////////////// void netadr_t::Clear(void) { ip[0] = ip[1] = ip[2] = ip[3] = 0; port = 0; type = netadrtype_t::NA_NULL; } ////////////////////////////////////////////////////////////////////// // Sets IP ////////////////////////////////////////////////////////////////////// void netadr_t::SetIP(std::uint8_t b1, std::uint8_t b2, std::uint8_t b3, std::uint8_t b4) { ip[0] = b1; ip[1] = b2; ip[2] = b3; ip[3] = b4; } ////////////////////////////////////////////////////////////////////// // Sets IP ////////////////////////////////////////////////////////////////////// void netadr_t::SetIP(std::uint32_t unIP) { *((std::uint32_t*)ip) = DWordSwapC(unIP); } ////////////////////////////////////////////////////////////////////// // Sets type ////////////////////////////////////////////////////////////////////// void netadr_t::SetType(netadrtype_t newtype) { type = newtype; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// netadrtype_t netadr_t::GetType(void) const { return type; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// std::uint16_t netadr_t::GetPort(void) const { return WordSwapC(port); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// std::uint32_t netadr_t::GetIPNetworkByteOrder(void) const { return *(std::uint32_t*)&ip; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// std::uint32_t netadr_t::GetIPHostByteOrder(void) const { return DWordSwapC(GetIPNetworkByteOrder()); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void netadr_t::ToSockadr(struct sockaddr* s) const { memset(s, 0, sizeof(struct sockaddr)); if (type == netadrtype_t::NA_BROADCAST) { ((struct sockaddr_in*)s)->sin_family = AF_INET; ((struct sockaddr_in*)s)->sin_port = port; ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST; } else if (type == netadrtype_t::NA_IP) { ((struct sockaddr_in*)s)->sin_family = AF_INET; ((struct sockaddr_in*)s)->sin_addr.s_addr = *(int*)&ip; ((struct sockaddr_in*)s)->sin_port = port; } else if (type == netadrtype_t::NA_LOOPBACK) { ((struct sockaddr_in*)s)->sin_family = AF_INET; ((struct sockaddr_in*)s)->sin_port = port; ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK; } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool netadr_t::SetFromSockadr(const struct sockaddr* s) { if (s->sa_family == AF_INET) { type = netadrtype_t::NA_IP; *(int*)&ip = ((struct sockaddr_in*)s)->sin_addr.s_addr; port = ((struct sockaddr_in*)s)->sin_port; return true; } else { Clear(); return false; } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool netadr_t::IsValid(void) const { return ((port != 0) && (type != netadrtype_t::NA_NULL) && (ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0)); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool netadr_t::IsBaseAdrValid(void) const { return ((type != netadrtype_t::NA_NULL) && (ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0)); } ////////////////////////////////////////////////////////////////////// // Returns true if we are localhost ////////////////////////////////////////////////////////////////////// bool netadr_t::IsLocalhost(void) const { return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1); } ////////////////////////////////////////////////////////////////////// // Returns true if we use the loopback buffers ////////////////////////////////////////////////////////////////////// bool netadr_t::IsLoopback(void) const { return type == netadrtype_t::NA_LOOPBACK; } ////////////////////////////////////////////////////////////////////// // Check if address is reserved and not routable. ////////////////////////////////////////////////////////////////////// bool netadr_t::IsReservedAdr(void) const { if (type == netadrtype_t::NA_LOOPBACK) { return true; } if (type == netadrtype_t::NA_IP) { if ((ip[0] == 10) || // 10.x.x.x is reserved (ip[0] == 127) || // 127.x.x.x (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x (ip[0] == 192 && ip[1] >= 168)) // 192.168.x.x { return true; } } return false; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void netadr_t::SetPort(std::uint16_t newport) { port = WordSwapC(newport); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool netadr_t::SetFromString(const char* szIpAdr, bool bUseDNS) { Clear(); if (!szIpAdr) { Assert(szIpAdr, "Invalid call: 'szIpAdr' was nullptr."); return false; } type = netadrtype_t::NA_IP; char szAddress[128]{}; strcpy_s(szAddress, szIpAdr); if (!_strnicmp(szAddress, "loopback", 8)) { char szNewAddress[128]{}; type = netadrtype_t::NA_LOOPBACK; strcpy_s(szNewAddress, "127.0.0.1"); strcat_s(szNewAddress, szAddress + 8); // copy anything after "loopback" strcpy_s(szAddress, szNewAddress); } if (!_strnicmp(szAddress, "localhost", 9)) { memcpy(szAddress, "127.0.0.1", 9); // Note use of memcpy allows us to keep the colon and rest of string since localhost and 127.0.0.1 are both 9 characters. } // IPv4 starts with a number and has a dot. if (szAddress[0] >= '0' && szAddress[0] <= '9' && strchr(szAddress, '.')) { int i0 = -1, i1 = -1, i2 = -1, i3 = -1, n0 = 0; // Initialize port as zero int nRes = sscanf_s(szAddress, "%d.%d.%d.%d:%d", &i0, &i1, &i2, &i3, &n0); if ( nRes < 4 || i0 < 0 || i0 > 255 || i1 < 0 || i1 > 255 || i2 < 0 || i2 > 255 || i3 < 0 || i3 > 255 || n0 < 0 || n0 > 65535 ) { return false; } SetIP(i0, i1, i2, i3); SetPort((std::uint16_t)n0); return true; } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool netadr_t::operator<(const netadr_t& netadr) const { if (*((std::uint32_t*)netadr.ip) < *((std::uint32_t*)ip)) { return true; } else if (*((std::uint32_t*)netadr.ip) > *((std::uint32_t*)ip)) { return false; } return (netadr.port < port); }