bool IsIpAddress(const CStdString& address, bool allowNull) { if (GetIPV6LongForm(address) != _T("")) return true; int segment = 0; int dotcount = 0; for (int i = 0; i < address.GetLength(); ++i) { const TCHAR& c = address[i]; if (c == '.') { if (address[i + 1] == '.') // Disallow multiple dots in a row return false; if (segment > 255) return false; if (!dotcount && !segment && !allowNull) return false; dotcount++; segment = 0; } else if (c < '0' || c > '9') return false; segment = segment * 10 + c - '0'; } if (dotcount != 3) return false; if (segment > 255) return false; return true; }
bool IsIpAddress(const wxString& address) { if (!GetIPV6LongForm(address).empty()) return true; int segment = 0; int dotcount = 0; for (size_t i = 0; i < address.Len(); ++i) { wxChar const c = address[i]; if (c == '.') { if (i + 1 < address.Len() && address[i + 1] == '.') { // Disallow multiple dots in a row return false; } if (segment > 255) return false; if (!dotcount && !segment) return false; dotcount++; segment = 0; } else if (c < '0' || c > '9') { return false; } else { segment = segment * 10 + c - '0'; } } if (dotcount != 3) return false; if (segment > 255) return false; return true; }
bool IsIpAddress(const wxString& address) { if (GetIPV6LongForm(address) != _T("")) return true; int segment = 0; int dotcount = 0; for (size_t i = 0; i < address.Len(); i++) { const char& c = address[i]; if (c == '.') { if (address[i + 1] == '.') // Disallow multiple dots in a row return false; if (segment > 255) return false; if (!dotcount && !segment) return false; dotcount++; segment = 0; } else if (c < '0' || c > '9') return false; segment = segment * 10 + c - '0'; } if (dotcount != 3) return false; if (segment > 255) return false; return true; }
bool IsRoutableAddress(const wxString& address, CSocket::address_family family) { if (family == CSocket::ipv6) { wxString long_address = GetIPV6LongForm(address); if (long_address.size() != 39) return false; if (long_address[0] == '0') { // ::/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0000")) return false; // ::1/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0001")) return false; if (long_address.Left(30) == _T("0000:0000:0000:0000:0000:ffff:")) { // IPv4 mapped wxString ipv4 = wxString::Format(_T("%d.%d.%d.%d"), DigitHexToDecNum(long_address[30]) * 16 + DigitHexToDecNum(long_address[31]), DigitHexToDecNum(long_address[32]) * 16 + DigitHexToDecNum(long_address[33]), DigitHexToDecNum(long_address[35]) * 16 + DigitHexToDecNum(long_address[36]), DigitHexToDecNum(long_address[37]) * 16 + DigitHexToDecNum(long_address[38])); return IsRoutableAddress(ipv4, CSocket::ipv4); } return true; } if (long_address[0] == 'f') { if (long_address[1] == 'e') { // fe80::/10 (link local) const wxChar& c = long_address[2]; int v; if (c >= 'a') v = c - 'a' + 10; else v = c - '0'; if ((v & 0xc) == 0x8) return false; return true; } else if (long_address[1] == 'c' || long_address[1] == 'd') { // fc00::/7 (site local) return false; } } return true; } else { // Assumes address is already a valid IP address if (address.Left(3) == _T("127") || address.Left(3) == _T("10.") || address.Left(7) == _T("192.168") || address.Left(7) == _T("169.254")) return false; if (address.Left(3) == _T("172")) { wxString middle = address.Mid(4); int pos = address.Find(_T(".")); wxASSERT(pos != -1); long part; middle.Left(pos).ToLong(&part); if (part >= 16 && part <= 31) return false; } return true; } }
void CIPAddressTest::testIPV6LongForm() { // Valid addresses CPPUNIT_ASSERT(GetIPV6LongForm(_T("::1")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234::1")) == _T("1234:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("4::1")) == _T("0004:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:abcd::1234:ef01")) == _T("1234:abcd:0000:0000:0000:0000:1234:ef01")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:ABCD::1234:ef01")) == _T("1234:abcd:0000:0000:0000:0000:1234:ef01")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0:0:0:0:0:0:0:1")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0:0:0::0:0:0:0:1")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("::0:0:0:0:0:0:0:1")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0000:0000:0000:0000:0000:0000:0000:0001")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[::1]")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[1234::1]")) == _T("1234:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[4::1]")) == _T("0004:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[1234:abcd::1234:ef01]")) == _T("1234:abcd:0000:0000:0000:0000:1234:ef01")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[1234:ABCD::1234:ef01]")) == _T("1234:abcd:0000:0000:0000:0000:1234:ef01")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[0:0:0:0:0:0:0:1]")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[0:0:0::0:0:0:0:1]")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[::0:0:0:0:0:0:0:1]")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[0000:0000:0000:0000:0000:0000:0000:0001]")) == _T("0000:0000:0000:0000:0000:0000:0000:0001")); // Invalid ones CPPUNIT_ASSERT(GetIPV6LongForm(_T("::")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T(":::")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:abcd::1234::ef01")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[1234:abcd::1234::ef01")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:abcd::1234::ef01]")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("[[1234:abcd::1234::ef01]]")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:abcde:1234::ef01")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("1234:abcg:1234::ef01")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T(":::1")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0:0:0:0:0:0:0:1:2")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0:0:0:0:0:0:0:1:2:0:0:0:0:0:0:1:2")) == _T("")); CPPUNIT_ASSERT(GetIPV6LongForm(_T("0::0:0:0:0:0:0:1:2:0:0:0:0:0:0:1")) == _T("")); }
CStdString GetIPV6ShortForm(const CStdString& ip) { // This could be optimized a lot. // First get the long form in a well-known format CStdString l = GetIPV6LongForm(ip); if (l.IsEmpty()) return CStdString(); LPCTSTR p = l; TCHAR outbuf[42]; *outbuf = ':'; TCHAR* out = outbuf + 1; bool segmentStart = true; bool readLeadingZero = false; while (*p) { switch (*p) { case ':': if (readLeadingZero) *(out++) = '0'; *out++ = ':'; readLeadingZero = false; segmentStart = true; break; case '0': if (segmentStart) readLeadingZero = true; else { *out++ = '0'; readLeadingZero = false; } break; default: readLeadingZero = false; segmentStart = false; *out++ = *p; break; } ++p; } *(out++) = ':'; *out = 0; // Replace longest run of consecutive zeroes CStdString shortIp(outbuf); CStdString s = _T(":0:0:0:0:0:0:0:0:"); while (s.GetLength() > 2) { int pos = shortIp.Find(s); if (pos != -1) { shortIp = shortIp.Left( pos + 1 ) + shortIp.Mid(pos + s.GetLength() -1); break; } s = s.Mid(2); } shortIp.Replace(_T(":::"), _T("::")); if (shortIp[0] == ':' && shortIp[1] != ':') shortIp = shortIp.Mid(1); if (shortIp.GetLength() >= 2 && shortIp[shortIp.GetLength()-1] == ':' && shortIp[shortIp.GetLength()-2] != ':') shortIp = shortIp.Left(shortIp.GetLength()-1); return shortIp; }
bool IsRoutableAddress(const CStdString& address) { if (address.Find(_T(":")) != -1) { CStdString long_address = GetIPV6LongForm(address); if (long_address.IsEmpty()) return false; if (long_address[0] == '0') { // ::/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0000")) return false; // ::1/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0001")) return false; if (long_address.Left(30) == _T("0000:0000:0000:0000:0000:ffff:")) { // IPv4 mapped CStdString ipv4; ipv4.Format(_T("%d.%d.%d.%d"), DigitHexToDecNum(long_address[30]) * 16 + DigitHexToDecNum(long_address[31]), DigitHexToDecNum(long_address[32]) * 16 + DigitHexToDecNum(long_address[33]), DigitHexToDecNum(long_address[35]) * 16 + DigitHexToDecNum(long_address[36]), DigitHexToDecNum(long_address[37]) * 16 + DigitHexToDecNum(long_address[38])); return IsRoutableAddress(ipv4); } return true; } if (long_address[0] == 'f') { if (long_address[1] == 'e') { // fe80::/10 (link local) const TCHAR& c = long_address[2]; int v; if (c >= 'a') v = c - 'a' + 10; else v = c - '0'; if ((v & 0xc) == 0x8) return false; return true; } else if (long_address[1] == 'c' || long_address[1] == 'd') { // fc00::/7 (site local) return false; } } return true; } else { // Assumes address is already a valid IP address if (address.Left(3) == _T("127") || address.Left(3) == _T("10.") || address.Left(7) == _T("192.168") || address.Left(7) == _T("169.254")) return false; if (address.Left(3) == _T("172")) { CStdString middle = address.Mid(4); int pos = address.Find(_T(".")); if (pos == -1) return false; int part = _ttoi(middle.Left(pos)); if (part >= 16 && part <= 31) return false; } return true; } }
bool MatchesFilter(CStdString filter, CStdString ip) { // A single asterix matches all IPs. if (filter == _T("*")) return true; // Check for IP range syntax. int pos = filter.Find('/'); if (pos != -1) { // CIDR filter int prefixLength = _ttoi(filter.Mid(pos+1)); if (ip.Find(':') != -1) { // IPv6 address CStdString left = GetIPV6LongForm(filter.Left(pos)); if (left.Find(':') == -1) return false; ip = GetIPV6LongForm(ip); LPCTSTR i = ip; LPCTSTR f = left; while (prefixLength >= 4) { if (*i != *f) return false; if (!*i) return true; if (*i == ':') { ++i; ++f; } ++i; ++f; prefixLength -= 4; } if (!prefixLength) return true; int mask; if (prefixLength == 1) mask = 0x8; else if (prefixLength == 2) mask = 0xc; else mask = 0xe; return (DigitHexToDecNum(*i) & mask) == (DigitHexToDecNum(*f) & mask); } else { if (prefixLength < 0) prefixLength = 0; else if (prefixLength > 32) prefixLength = 32; // IPv4 address CStdString left = filter.Left(pos); if (left.Find(':') != -1) return false; unsigned long i = ntohl(inet_addr(ConvToLocal(ip))); unsigned long f = ntohl(inet_addr(ConvToLocal(left))); i &= prefixMasksV4[prefixLength]; f &= prefixMasksV4[prefixLength]; return i == f; } } else { // Literal filter if (filter.Find(':') != -1) return filter == GetIPV6ShortForm(ip); else return filter == ip; } }
void CExternalIPResolver::OnData(char* buffer, unsigned int len) { if (buffer) { unsigned int i; for (i = 0; i < len; i++) { if (buffer[i] == '\r' || buffer[i] == '\n') break; if (buffer[i] & 0x80) { Close(false); return; } } if (i) m_data += wxString(buffer, wxConvLocal, i); if (i == len) return; } if (m_protocol == CSocket::ipv6) { if (m_data[0] == '[') { if (m_data.Last() != ']') { Close(false); return; } m_data.RemoveLast(); m_data = m_data.Mid(1); } if (GetIPV6LongForm(m_data).IsEmpty()) { Close(false); return; } m_ip = m_data; } else { // Validate ip address wxString digit = _T("0*[0-9]{1,3}"); const wxChar* dot = _T("\\."); wxString exp = _T("(^|[^\\.[:digit:]])(") + digit + dot + digit + dot + digit + dot + digit + _T(")([^\\.[:digit:]]|$)"); wxRegEx regex; regex.Compile(exp); if (!regex.Matches(m_data)) { Close(false); return; } m_ip = regex.GetMatch(m_data, 2); } Close(true); }