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);
	}
}
예제 #2
0
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();
	}
}