CExternalIpCheck::CExternalIpCheck(CServerThread *pOwner) { ASSERT(pOwner); m_pOwner = pOwner; m_bActive = FALSE; m_nRetryCount = 0; m_nTimerID = SetTimer(0, 0, TIMERINTERVAL * 1000, 0); m_bTriggerUpdateCalled = FALSE; m_nFailedConnections = 0; m_nElapsedSeconds = 0; if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE)) return; if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 2) Start(); else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1) { CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP); SOCKADDR_IN sockAddr{}; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname)); if (sockAddr.sin_addr.s_addr == INADDR_NONE) { LPHOSTENT lphost; lphost = gethostbyname(ConvToLocal(hostname)); if (lphost != NULL) { sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr; } else { Close(); m_nRetryCount++; m_bActive = FALSE; return; } } const char *ip = inet_ntoa(sockAddr.sin_addr); if (!ip) return; m_IP = ConvFromLocal(ip); } }
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 CExternalIpCheck::OnTimer() { if (m_nElapsedSeconds <= 1000000) m_nElapsedSeconds += TIMERINTERVAL; if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE)) { m_nRetryCount = 0; Close(); m_bActive = FALSE; return; } else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1) { m_nRetryCount = 0; Close(); m_bActive = FALSE; CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP); SOCKADDR_IN sockAddr{}; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname)); if (sockAddr.sin_addr.s_addr == INADDR_NONE) { LPHOSTENT lphost; lphost = gethostbyname(ConvToLocal(hostname)); if (lphost != NULL) sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr; else { Close(); m_nRetryCount++; m_bActive = FALSE; return; } } const char *ip = inet_ntoa(sockAddr.sin_addr); if (!ip) return; m_IP = ConvFromLocal(ip); m_nFailedConnections = 0; return; } if (!m_bActive && m_nRetryCount) { if (m_nElapsedSeconds > 60 && m_nRetryCount < 5) { Start(); return; } else if (m_nElapsedSeconds > 300 && m_nRetryCount < 10) { Start(); return; } else if (m_nElapsedSeconds > 900 && m_nRetryCount < 20) { Start(); return; } else if (m_nElapsedSeconds > 3600) { Start(); return; } } else if (m_bActive) { if (m_nElapsedSeconds > 30) { m_bActive = FALSE; Close(); m_nRetryCount++; m_nElapsedSeconds = 0; } } else { if (m_nElapsedSeconds > 300 && m_bTriggerUpdateCalled) Start(); else if (m_nElapsedSeconds > 3600) Start(); } }