Ejemplo n.º 1
0
//Transmission and reception of SOCKS protocol(UDP)
size_t __fastcall SOCKSUDPRequest(
	const char *OriginalSend, 
	const size_t SendSize, 
	char *OriginalRecv, 
	const size_t RecvSize)
{
//Initialization
	std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]());
	memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
	SOCKET_DATA TCPSocketData = {0}, LocalSocketData = {0}, UDPSocketData = {0};
	memset(OriginalRecv, 0, RecvSize);

//Socket initialization
	if (Parameter.SOCKS_Address_IPv6.Storage.ss_family > 0 && //IPv6
		(Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 || //IPv6
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 && Parameter.SOCKS_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4
	{
		if (!Parameter.SOCKS_UDP_NoHandshake)
		{
		//TCP process
			TCPSocketData.SockAddr.ss_family = AF_INET6;
			((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr;
			((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port;
			TCPSocketData.AddrLen = sizeof(sockaddr_in6);
			TCPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);

		//Local process
			LocalSocketData.SockAddr.ss_family = AF_INET6;
			LocalSocketData.AddrLen = sizeof(sockaddr_in6);
		}

	//UDP process
		UDPSocketData.SockAddr.ss_family = AF_INET6;
		((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr;
		if (Parameter.SOCKS_UDP_NoHandshake)
			((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port;
		UDPSocketData.AddrLen = sizeof(sockaddr_in6);
		UDPSocketData.Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
	}
	else if (Parameter.SOCKS_Address_IPv4.Storage.ss_family > 0 && //IPv4
		(Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 || //IPv4
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 && Parameter.SOCKS_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6
	{
		if (!Parameter.SOCKS_UDP_NoHandshake)
		{
		//TCP process
			TCPSocketData.SockAddr.ss_family = AF_INET;
			((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr;
			((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port;
			TCPSocketData.AddrLen = sizeof(sockaddr_in);
			TCPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

		//Local process
			LocalSocketData.SockAddr.ss_family = AF_INET;
			LocalSocketData.AddrLen = sizeof(sockaddr_in);
		}

	//UDP process
		UDPSocketData.SockAddr.ss_family = AF_INET;
		((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr;
		if (Parameter.SOCKS_UDP_NoHandshake)
			((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port;
		UDPSocketData.AddrLen = sizeof(sockaddr_in);
		UDPSocketData.Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	}
	else {
		return EXIT_FAILURE;
	}

//Socket check and Hop Limits setting
	if (!Parameter.SOCKS_UDP_NoHandshake && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr) || 
		TCPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, false, nullptr) || 
		TCPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, false, nullptr) || 
		!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr)) ||
		!SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr) || 
		UDPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, false, nullptr) || 
		UDPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, false, nullptr) || 
		!SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr)))
	{
		closesocket(UDPSocketData.Socket);
		if (!Parameter.SOCKS_UDP_NoHandshake)
			closesocket(TCPSocketData.Socket);
		PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"SOCKS socket initialization error", 0, nullptr, 0);

		return EXIT_FAILURE;
	}

//Non-blocking mode setting
	if (!Parameter.SOCKS_UDP_NoHandshake && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr) || 
		!SocketSetting(UDPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr))
	{
		closesocket(UDPSocketData.Socket);
		if (!Parameter.SOCKS_UDP_NoHandshake)
			closesocket(TCPSocketData.Socket);

		return EXIT_FAILURE;
	}

//Selecting structure setting
	fd_set ReadFDS = {0}, WriteFDS = {0};
	timeval Timeout = {0};

//UDP transmission of standard SOCKS protocol must connect with TCP to server at first.
	if (!Parameter.SOCKS_UDP_NoHandshake)
	{
	//Selection exchange process
		if (!SOCKSSelectionExchange(&TCPSocketData, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize))
		{
			shutdown(UDPSocketData.Socket, SD_BOTH);
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(UDPSocketData.Socket);
			closesocket(TCPSocketData.Socket);

			return EXIT_FAILURE;
		}
		else {
			memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
		}

	//UDP connecting and get UDP socket infomation.
		if (SocketConnecting(IPPROTO_UDP, UDPSocketData.Socket, (PSOCKADDR)&UDPSocketData.SockAddr, UDPSocketData.AddrLen, nullptr, 0) == EXIT_FAILURE || 
			getsockname(UDPSocketData.Socket, (PSOCKADDR)&LocalSocketData.SockAddr, &LocalSocketData.AddrLen) == SOCKET_ERROR)
		{
			shutdown(UDPSocketData.Socket, SD_BOTH);
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(UDPSocketData.Socket);
			closesocket(TCPSocketData.Socket);
			PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"SOCKS connecting error", 0, nullptr, 0);

			return EXIT_FAILURE;
		}

	//Client command request process
		if (!SOCKSClientCommandRequest(IPPROTO_UDP, TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize, &LocalSocketData))
		{
			shutdown(UDPSocketData.Socket, SD_BOTH);
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(UDPSocketData.Socket);
			closesocket(TCPSocketData.Socket);

			return EXIT_FAILURE;
		}
		else {
			memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);

		//Copy network infomation from server message.
			if (UDPSocketData.SockAddr.ss_family == AF_INET6)
				((PSOCKADDR_IN6)&UDPSocketData.SockAddr)->sin6_port = ((PSOCKADDR_IN6)&LocalSocketData.SockAddr)->sin6_port;
			else 
				((PSOCKADDR_IN)&UDPSocketData.SockAddr)->sin_port = ((PSOCKADDR_IN)&LocalSocketData.SockAddr)->sin_port;
		}
	}

//UDP connecting again
	if (SocketConnecting(IPPROTO_UDP, UDPSocketData.Socket, (PSOCKADDR)&UDPSocketData.SockAddr, UDPSocketData.AddrLen, nullptr, 0) == EXIT_FAILURE)
	{
		if (!Parameter.SOCKS_UDP_NoHandshake)
		{
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(TCPSocketData.Socket);
		}

		PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"SOCKS connecting error", 0, nullptr, 0);
		return EXIT_FAILURE;
	}

//SOCKS UDP relay header
	SSIZE_T RecvLen = sizeof(socks_udp_relay_request);
	void *SOCKS_Pointer = SendBuffer.get();
	if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET6) //IPv6
	{
		((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_IPV6;
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		RecvLen += (SSIZE_T)sizeof(in6_addr);
		*(in6_addr *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv6.sin6_addr;
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		RecvLen += (SSIZE_T)sizeof(uint16_t);
		*(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv6.sin6_port;
	}
	else if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET) //IPv4
	{
		((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_IPV4;
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		RecvLen += (SSIZE_T)sizeof(in_addr);
		*(in_addr *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv4.sin_addr;
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		RecvLen += (SSIZE_T)sizeof(uint16_t);
		*(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetServer.IPv4.sin_port;
	}
	else if (Parameter.SOCKS_TargetDomain != nullptr && !Parameter.SOCKS_TargetDomain->empty()) //Damain
	{
		((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type = SOCKS5_ADDRESS_DOMAIN;
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		RecvLen += (SSIZE_T)sizeof(uint8_t);
		*(uint8_t *)SOCKS_Pointer = (uint8_t)Parameter.SOCKS_TargetDomain->length();
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		memcpy_s(SOCKS_Pointer, (SSIZE_T)LARGE_PACKET_MAXSIZE - ((SSIZE_T)sizeof(socks_udp_relay_request) + RecvLen), Parameter.SOCKS_TargetDomain->c_str(), Parameter.SOCKS_TargetDomain->length());
		RecvLen += (SSIZE_T)Parameter.SOCKS_TargetDomain->length();
		SOCKS_Pointer = SendBuffer.get() + RecvLen;
		*(uint16_t *)SOCKS_Pointer = Parameter.SOCKS_TargetDomain_Port;
		RecvLen += (SSIZE_T)sizeof(uint16_t);
	}
	else {
		shutdown(UDPSocketData.Socket, SD_BOTH);
		closesocket(UDPSocketData.Socket);
		if (!Parameter.SOCKS_UDP_NoHandshake)
		{
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(TCPSocketData.Socket);
		}

		return EXIT_FAILURE;
	}

	memcpy_s(SendBuffer.get() + RecvLen, RecvSize, OriginalSend, SendSize);
	RecvLen += (SSIZE_T)SendSize;

//Socket timeout setting
#if defined(PLATFORM_WIN)
	Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Unreliable / SECOND_TO_MILLISECOND;
	Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Unreliable % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable.tv_sec;
	Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable.tv_usec;
#endif

//Data exchange
	RecvLen = ProxySocketSelecting(UDPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, sizeof(socks_udp_relay_request) + DNS_PACKET_MINSIZE, nullptr);
	shutdown(UDPSocketData.Socket, SD_BOTH);
	closesocket(UDPSocketData.Socket);
	if (!Parameter.SOCKS_UDP_NoHandshake)
	{
		shutdown(TCPSocketData.Socket, SD_BOTH);
		closesocket(TCPSocketData.Socket);
	}
	if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE)
	{
		SSIZE_T OriginalRecvLen = RecvLen;

	//Remove SOCKS UDP relay header
		SOCKS_Pointer = OriginalRecv;
		if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET6 && //IPv6
			((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV6 && 
			RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && 
			memcmp((in6_addr *)(OriginalRecv + sizeof(socks_udp_relay_request)), &Parameter.SOCKS_TargetServer.IPv6.sin6_addr, sizeof(in6_addr)) == 0 && 
			*(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr)) == Parameter.SOCKS_TargetServer.IPv6.sin6_port)
		{
			memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t)));
			RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t);
		}
		else if (Parameter.SOCKS_TargetServer.Storage.ss_family == AF_INET && //IPv4
			((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV4 && 
			RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && 
			(*(in_addr *)(OriginalRecv + sizeof(socks_udp_relay_request))).s_addr == Parameter.SOCKS_TargetServer.IPv4.sin_addr.s_addr && 
			*(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr)) == Parameter.SOCKS_TargetServer.IPv4.sin_port)
		{
			memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t)));
			RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t);
		}
		else if (Parameter.SOCKS_TargetDomain != nullptr && !Parameter.SOCKS_TargetDomain->empty()) //Domain
/* SOCKS server will reply IPv4/IPv6 address of domain.
			((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_DOMAIN && 
			RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t) + DNS_PACKET_MINSIZE) && 
			*(uint8_t *)(OriginalRecv + sizeof(socks_udp_relay_request)) == Parameter.SOCKS_TargetDomain->length() && 
			memcmp(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t), Parameter.SOCKS_TargetDomain->c_str(), Parameter.SOCKS_TargetDomain->length()) == 0 && 
			*(uint16_t *)(OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length()) == Parameter.SOCKS_TargetDomain_Port)
*/
		{
		//IPv6
			if (((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV6 && 
				RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE))
			{
				memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t)));
				RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in6_addr) + sizeof(uint16_t);
			}
		//IPv4
			else if (((psocks_udp_relay_request)SOCKS_Pointer)->Address_Type == SOCKS5_ADDRESS_IPV4 && 
				RecvLen >= (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t) + DNS_PACKET_MINSIZE))
			{
				memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t)));
				RecvLen -= sizeof(socks_udp_relay_request) + sizeof(in_addr) + sizeof(uint16_t);
			}

/* SOCKS server will reply IPv4/IPv6 address of domain.
			memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t), RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t)));
			return RecvLen - (SSIZE_T)(sizeof(socks_udp_relay_request) + sizeof(uint8_t) + Parameter.SOCKS_TargetDomain->length() + sizeof(uint16_t));
*/
		}

	//Server response check
		if (OriginalRecvLen != RecvLen)
		{
		//Responses check
			RecvLen = CheckResponseData(
				REQUEST_PROCESS_SOCKS, 
				OriginalRecv, 
				RecvLen, 
				RecvSize, 
				nullptr);
			if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE)
				return EXIT_FAILURE;

		//Mark DNS cache.
			if (Parameter.CacheType > 0)
				MarkDomainCache(OriginalRecv, RecvLen);

			return RecvLen;
		}
	}

	return EXIT_FAILURE;
}
Ejemplo n.º 2
0
//Transmission and reception of HTTP protocol
size_t __fastcall HTTPRequest(
	const char *OriginalSend, 
	const size_t SendSize, 
	char *OriginalRecv, 
	const size_t RecvSize)
{
//Initialization
	SOCKET_DATA HTTPSocketData = {0};
	memset(OriginalRecv, 0, RecvSize);

//Socket initialization
	if (Parameter.HTTP_Address_IPv6.Storage.ss_family > 0 && //IPv6
		(Parameter.HTTP_Protocol == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select
		Parameter.HTTP_Protocol == REQUEST_MODE_IPV6 || //IPv6
		Parameter.HTTP_Protocol == REQUEST_MODE_IPV4 && Parameter.HTTP_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4
	{
		HTTPSocketData.SockAddr.ss_family = AF_INET6;
		((PSOCKADDR_IN6)&HTTPSocketData.SockAddr)->sin6_addr = Parameter.HTTP_Address_IPv6.IPv6.sin6_addr;
		((PSOCKADDR_IN6)&HTTPSocketData.SockAddr)->sin6_port = Parameter.HTTP_Address_IPv6.IPv6.sin6_port;
		HTTPSocketData.AddrLen = sizeof(sockaddr_in6);
		HTTPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
	}
	else if (Parameter.HTTP_Address_IPv4.Storage.ss_family > 0 && //IPv4
		(Parameter.HTTP_Protocol == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select
		Parameter.HTTP_Protocol == REQUEST_MODE_IPV4 || //IPv4
		Parameter.HTTP_Protocol == REQUEST_MODE_IPV6 && Parameter.HTTP_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6
	{
		HTTPSocketData.SockAddr.ss_family = AF_INET;
		((PSOCKADDR_IN)&HTTPSocketData.SockAddr)->sin_addr = Parameter.HTTP_Address_IPv4.IPv4.sin_addr;
		((PSOCKADDR_IN)&HTTPSocketData.SockAddr)->sin_port = Parameter.HTTP_Address_IPv4.IPv4.sin_port;
		HTTPSocketData.AddrLen = sizeof(sockaddr_in);
		HTTPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	}
	else {
		return EXIT_FAILURE;
	}

//Socket check 
	if (!SocketSetting(HTTPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, nullptr))
	{
		PrintError(LOG_ERROR_NETWORK, L"HTTP socket initialization error", 0, nullptr, 0);
		return EXIT_FAILURE;
	}

//Non-blocking mode setting
	if (!SocketSetting(HTTPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, nullptr))
	{
		shutdown(HTTPSocketData.Socket, SD_BOTH);
		closesocket(HTTPSocketData.Socket);
		PrintError(LOG_ERROR_NETWORK, L"Socket non-blocking mode setting error", 0, nullptr, 0);

		return EXIT_FAILURE;
	}

//Selecting structure setting
	fd_set ReadFDS = {0}, WriteFDS = {0};
	timeval Timeout = {0};

//HTTP CONNECT request
	if (Parameter.HTTP_TargetDomain == nullptr || Parameter.HTTP_Version == nullptr || 
		!HTTP_CONNECTRequest(&HTTPSocketData, &ReadFDS, &WriteFDS, &Timeout, OriginalRecv, RecvSize))
	{
		shutdown(HTTPSocketData.Socket, SD_BOTH);
		closesocket(HTTPSocketData.Socket);

		return EXIT_FAILURE;
	}

//Add length of request packet(It must be written in header when transpot with TCP protocol).
	std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]());
	memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
	memcpy_s(SendBuffer.get(), RecvSize, OriginalSend, SendSize);
	SSIZE_T RecvLen = AddLengthDataToHeader(SendBuffer.get(), SendSize, RecvSize);
	if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE)
	{
		shutdown(HTTPSocketData.Socket, SD_BOTH);
		closesocket(HTTPSocketData.Socket);

		return EXIT_FAILURE;
	}

//Socket timeout setting
#if defined(PLATFORM_WIN)
	Timeout.tv_sec = Parameter.HTTP_SocketTimeout / SECOND_TO_MILLISECOND;
	Timeout.tv_usec = Parameter.HTTP_SocketTimeout % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Timeout.tv_sec = Parameter.HTTP_SocketTimeout.tv_sec;
	Timeout.tv_usec = Parameter.HTTP_SocketTimeout.tv_usec;
#endif

//Data exchange
	RecvLen = ProxySocketSelecting(HTTPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, DNS_PACKET_MINSIZE, nullptr);
	shutdown(HTTPSocketData.Socket, SD_BOTH);
	closesocket(HTTPSocketData.Socket);

//Server response check
	if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE && ntohs(((uint16_t *)OriginalRecv)[0]) >= DNS_PACKET_MINSIZE && 
		RecvLen >= ntohs(((uint16_t *)OriginalRecv)[0]))
	{
		RecvLen = ntohs(((uint16_t *)OriginalRecv)[0]);
		memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(uint16_t), RecvLen);

	//Responses check
		RecvLen = CheckResponseData(
			REQUEST_PROCESS_HTTP, 
			OriginalRecv, 
			RecvLen, 
			RecvSize, 
			nullptr);
		if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE)
			return EXIT_FAILURE;

	//Mark DNS cache.
		if (Parameter.CacheType > 0)
			MarkDomainCache(OriginalRecv, RecvLen);

		return RecvLen;
	}

	return EXIT_FAILURE;
}
Ejemplo n.º 3
0
//Transmission and reception of SOCKS protocol(TCP)
size_t __fastcall SOCKSTCPRequest(
	const char *OriginalSend, 
	const size_t SendSize, 
	char *OriginalRecv, 
	const size_t RecvSize)
{
//Initialization
	std::shared_ptr<char> SendBuffer(new char[LARGE_PACKET_MAXSIZE]());
	memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
	SOCKET_DATA TCPSocketData = {0};
	memset(OriginalRecv, 0, RecvSize);

//Socket initialization
	if (Parameter.SOCKS_Address_IPv6.Storage.ss_family > 0 && //IPv6
		(Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv6 || //Auto select
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 || //IPv6
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 && Parameter.SOCKS_Address_IPv4.Storage.ss_family == 0)) //Non-IPv4
	{
		TCPSocketData.SockAddr.ss_family = AF_INET6;
		((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_addr = Parameter.SOCKS_Address_IPv6.IPv6.sin6_addr;
		((PSOCKADDR_IN6)&TCPSocketData.SockAddr)->sin6_port = Parameter.SOCKS_Address_IPv6.IPv6.sin6_port;
		TCPSocketData.AddrLen = sizeof(sockaddr_in6);
		TCPSocketData.Socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
	}
	else if (Parameter.SOCKS_Address_IPv4.Storage.ss_family > 0 && //IPv4
		(Parameter.SOCKS_Protocol_Network == REQUEST_MODE_NETWORK_BOTH && GlobalRunningStatus.GatewayAvailable_IPv4 || //Auto select
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV4 || //IPv4
		Parameter.SOCKS_Protocol_Network == REQUEST_MODE_IPV6 && Parameter.SOCKS_Address_IPv6.Storage.ss_family == 0)) //Non-IPv6
	{
		TCPSocketData.SockAddr.ss_family = AF_INET;
		((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_addr = Parameter.SOCKS_Address_IPv4.IPv4.sin_addr;
		((PSOCKADDR_IN)&TCPSocketData.SockAddr)->sin_port = Parameter.SOCKS_Address_IPv4.IPv4.sin_port;
		TCPSocketData.AddrLen = sizeof(sockaddr_in);
		TCPSocketData.Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	}
	else {
		return EXIT_FAILURE;
	}

//Socket check 
	if (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_INVALID_CHECK, false, nullptr))
	{
		PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"SOCKS socket initialization error", 0, nullptr, 0);
		return EXIT_FAILURE;
	}

//Non-blocking mode setting and Hop Limits setting
	if (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_NON_BLOCKING_MODE, true, nullptr) || 
		TCPSocketData.SockAddr.ss_family == AF_INET6 && !SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV6, true, nullptr) || 
		TCPSocketData.SockAddr.ss_family == AF_INET && (!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_HOP_LIMITS_IPV4, true, nullptr) || 
		!SocketSetting(TCPSocketData.Socket, SOCKET_SETTING_DO_NOT_FRAGMENT, true, nullptr)))
	{
		shutdown(TCPSocketData.Socket, SD_BOTH);
		closesocket(TCPSocketData.Socket);

		return EXIT_FAILURE;
	}

//Selecting structure setting
	fd_set ReadFDS = {0}, WriteFDS = {0};
	timeval Timeout = {0};

//Selection exchange process
	if (Parameter.SOCKS_Version == SOCKS_VERSION_5)
	{
		if (!SOCKSSelectionExchange(&TCPSocketData, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize))
		{
			shutdown(TCPSocketData.Socket, SD_BOTH);
			closesocket(TCPSocketData.Socket);

			return EXIT_FAILURE;
		}
		else {
			memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
		}
	}

//Client command request process
	if (!SOCKSClientCommandRequest(IPPROTO_TCP, TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), OriginalRecv, RecvSize, &TCPSocketData))
	{
		shutdown(TCPSocketData.Socket, SD_BOTH);
		closesocket(TCPSocketData.Socket);

		return EXIT_FAILURE;
	}
	else {
		memset(SendBuffer.get(), 0, LARGE_PACKET_MAXSIZE);
	}

//Add length of request packet(It must be written in header when transpot with TCP protocol).
	memcpy_s(SendBuffer.get(), RecvSize, OriginalSend, SendSize);
	SSIZE_T RecvLen = AddLengthDataToHeader(SendBuffer.get(), SendSize, RecvSize);
	if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE)
	{
		shutdown(TCPSocketData.Socket, SD_BOTH);
		closesocket(TCPSocketData.Socket);

		return EXIT_FAILURE;
	}

//Socket timeout setting
#if defined(PLATFORM_WIN)
	Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable / SECOND_TO_MILLISECOND;
	Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Timeout.tv_sec = Parameter.SOCKS_SocketTimeout_Reliable.tv_sec;
	Timeout.tv_usec = Parameter.SOCKS_SocketTimeout_Reliable.tv_usec;
#endif

//Data exchange
	RecvLen = ProxySocketSelecting(TCPSocketData.Socket, &ReadFDS, &WriteFDS, &Timeout, SendBuffer.get(), RecvLen, OriginalRecv, RecvSize, DNS_PACKET_MINSIZE, nullptr);
	shutdown(TCPSocketData.Socket, SD_BOTH);
	closesocket(TCPSocketData.Socket);

//Server response check
	if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE && ntohs(((uint16_t *)OriginalRecv)[0]) >= DNS_PACKET_MINSIZE && 
		RecvLen >= ntohs(((uint16_t *)OriginalRecv)[0]))
	{
		RecvLen = ntohs(((uint16_t *)OriginalRecv)[0]);
		memmove_s(OriginalRecv, RecvSize, OriginalRecv + sizeof(uint16_t), RecvLen);

	//Responses check
		RecvLen = CheckResponseData(
			REQUEST_PROCESS_SOCKS, 
			OriginalRecv, 
			RecvLen, 
			RecvSize, 
			nullptr);
		if (RecvLen < (SSIZE_T)DNS_PACKET_MINSIZE)
			return EXIT_FAILURE;

	//Mark DNS cache.
		if (Parameter.CacheType > 0)
			MarkDomainCache(OriginalRecv, RecvLen);

		return RecvLen;
	}

	return EXIT_FAILURE;
}
Ejemplo n.º 4
0
//Network Layer(Internet Protocol/IP) process
bool __fastcall CaptureNetworkLayer(const char *Buffer, const size_t Length, const uint16_t Protocol)
{
//Initialization
	PDNS_SERVER_DATA PacketSource = nullptr;

//IPv6
	if (Protocol == PPP_IPV6 || Protocol == OSI_L2_IPV6)
	{
		auto IPv6_Header = (pipv6_hdr)Buffer;

	//Validate IPv6 header length.
		if (ntohs(IPv6_Header->PayloadLength) > Length - sizeof(ipv6_hdr))
			return false;

	//Mark source of packet.
		if (memcmp(&IPv6_Header->Source, &Parameter.DNSTarget.IPv6.AddressData.IPv6.sin6_addr, sizeof(in6_addr)) == EXIT_SUCCESS)
		{
			PacketSource = &Parameter.DNSTarget.IPv6;
		}
		else if (memcmp(&IPv6_Header->Source, &Parameter.DNSTarget.Alternate_IPv6.AddressData.IPv6.sin6_addr, sizeof(in6_addr)) == EXIT_SUCCESS)
		{
			PacketSource = &Parameter.DNSTarget.Alternate_IPv6;
		}
		else if (Parameter.DNSTarget.IPv6_Multi != nullptr)
		{
			for (auto &DNSServerDataIter:*Parameter.DNSTarget.IPv6_Multi)
			{
				if (memcmp(&IPv6_Header->Source, &DNSServerDataIter.AddressData.IPv6.sin6_addr, sizeof(in6_addr)) == EXIT_SUCCESS)
				{
					PacketSource = &DNSServerDataIter;
					break;
				}
			}

			if (PacketSource == nullptr)
				return false;
		}
		else {
			return false;
		}

	//Get Hop Limits from IPv6 DNS server.
	//ICMPv6 Protocol
		if (Parameter.ICMP_Speed > 0 && IPv6_Header->NextHeader == IPPROTO_ICMPV6 && ntohs(IPv6_Header->PayloadLength) >= sizeof(icmpv6_hdr))
		{
		//Validate ICMPv6 checksum.
			if (GetChecksum_ICMPv6((PUINT8)Buffer, ntohs(IPv6_Header->PayloadLength), IPv6_Header->Destination, IPv6_Header->Source) != CHECKSUM_SUCCESS)
				return false;

		//ICMPv6 check
			if (CaptureCheck_ICMP(Buffer + sizeof(ipv6_hdr), ntohs(IPv6_Header->PayloadLength), AF_INET6))
				PacketSource->HopLimitData.HopLimit = IPv6_Header->HopLimit;

			return true;
		}

	//TCP Protocol
		if (Parameter.HeaderCheck_TCP && IPv6_Header->NextHeader == IPPROTO_TCP && ntohs(IPv6_Header->PayloadLength) >= sizeof(tcp_hdr))
		{
		//Validate TCP checksum.
			if (GetChecksum_TCPUDP((PUINT8)Buffer, ntohs(IPv6_Header->PayloadLength), AF_INET6, IPPROTO_TCP) != CHECKSUM_SUCCESS)
				return false;

		//TCP check
			if (CaptureCheck_TCP(Buffer + sizeof(ipv6_hdr)))
				PacketSource->HopLimitData.HopLimit = IPv6_Header->HopLimit;

			return true;
		}

	//UDP Protocol
		if (IPv6_Header->NextHeader == IPPROTO_UDP && ntohs(IPv6_Header->PayloadLength) >= sizeof(udp_hdr) + DNS_PACKET_MINSIZE)
		{
		//Validate UDP checksum.
			if (GetChecksum_TCPUDP((PUINT8)Buffer, ntohs(IPv6_Header->PayloadLength), AF_INET6, IPPROTO_UDP) != CHECKSUM_SUCCESS)
				return false;

		//Port check
			auto UDP_Header = (pudp_hdr)(Buffer + sizeof(ipv6_hdr));
			if (UDP_Header->SrcPort == PacketSource->AddressData.IPv6.sin6_port)
			{
			//Domain Test and DNS Options check and get Hop Limit from Domain Test.
				auto IsMarkHopLimit = false;
				if (CheckResponseData(Buffer + sizeof(ipv6_hdr) + sizeof(udp_hdr), ntohs(IPv6_Header->PayloadLength) - sizeof(udp_hdr), false, &IsMarkHopLimit) < (SSIZE_T)DNS_PACKET_MINSIZE)
					return false;
				if (IsMarkHopLimit)
					PacketSource->HopLimitData.HopLimit = IPv6_Header->HopLimit;

			//DNSCurve encryption packet check
			#if defined(ENABLE_LIBSODIUM)
				if (Parameter.DNSCurve && 
				//Main(IPv6)
					(DNSCurveParameter.DNSCurveTarget.IPv6.AddressData.Storage.ss_family > 0 && DNSCurveParameter.DNSCurveTarget.IPv6.ReceiveMagicNumber != nullptr && 
					memcmp(Buffer + sizeof(ipv6_hdr) + sizeof(udp_hdr), DNSCurveParameter.DNSCurveTarget.IPv6.ReceiveMagicNumber, DNSCURVE_MAGIC_QUERY_LEN) == EXIT_SUCCESS || 
				//Alternate(IPv6)
					DNSCurveParameter.DNSCurveTarget.Alternate_IPv6.AddressData.Storage.ss_family > 0 && DNSCurveParameter.DNSCurveTarget.Alternate_IPv6.ReceiveMagicNumber != nullptr && 
					memcmp(Buffer + sizeof(ipv6_hdr) + sizeof(udp_hdr), DNSCurveParameter.DNSCurveTarget.Alternate_IPv6.ReceiveMagicNumber, DNSCURVE_MAGIC_QUERY_LEN) == EXIT_SUCCESS))
						return false;
			#endif

			//Hop Limit must not a ramdom value.
				if ((size_t)IPv6_Header->HopLimit + (size_t)Parameter.HopLimitFluctuation > (size_t)PacketSource->HopLimitData.HopLimit && 
					(size_t)IPv6_Header->HopLimit < (size_t)PacketSource->HopLimitData.HopLimit + (size_t)Parameter.HopLimitFluctuation)
				{
					MatchPortToSend(Buffer + sizeof(ipv6_hdr) + sizeof(udp_hdr), ntohs(IPv6_Header->PayloadLength) - sizeof(udp_hdr), AF_INET6, UDP_Header->DstPort);
					return true;
				}
			}
		}
	}
//IPv4
	else {
		auto IPv4_Header = (pipv4_hdr)Buffer;

	//Validate IPv4 header.
		if (ntohs(IPv4_Header->Length) <= IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES || ntohs(IPv4_Header->Length) > Length || 
			GetChecksum((PUINT16)Buffer, sizeof(ipv4_hdr)) != CHECKSUM_SUCCESS) //Validate IPv4 header checksum.
				return false;

	//Mark source of packet.
		if (IPv4_Header->Source.s_addr == Parameter.DNSTarget.IPv4.AddressData.IPv4.sin_addr.s_addr)
		{
			PacketSource = &Parameter.DNSTarget.IPv4;
		}
		else if (IPv4_Header->Source.s_addr == Parameter.DNSTarget.Alternate_IPv4.AddressData.IPv4.sin_addr.s_addr)
		{
			PacketSource = &Parameter.DNSTarget.Alternate_IPv4;
		}
		else if (Parameter.DNSTarget.IPv4_Multi != nullptr)
		{
			for (auto &DNSServerDataIter:*Parameter.DNSTarget.IPv4_Multi)
			{
				if (IPv4_Header->Source.s_addr == DNSServerDataIter.AddressData.IPv4.sin_addr.s_addr)
				{
					PacketSource = &DNSServerDataIter;
					break;
				}
			}

			if (PacketSource == nullptr)
				return false;
		}
		else {
			return false;
		}

	//IPv4 options check
		if (Parameter.HeaderCheck_IPv4)
		{
		//No standard header length and header ID check
			if (IPv4_Header->IHL > IPV4_STANDARD_IHL || IPv4_Header->ID == 0)
				PacketSource->HopLimitData.TTL = IPv4_Header->TTL;

		//TOS and Flags should not be set.
			if (IPv4_Header->TOS > 0 || IPv4_Header->Flags > 0)
				return false;
		}

	//Get TTL from IPv4 DNS server.
	//ICMP Protocol
		if (Parameter.ICMP_Speed > 0 && IPv4_Header->Protocol == IPPROTO_ICMP && ntohs(IPv4_Header->Length) >= IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(icmp_hdr))
		{
		//Validate ICMP checksum.
			if (GetChecksum((PUINT16)(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES), ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES) != CHECKSUM_SUCCESS)
				return false;

		//ICMP Check
			if (CaptureCheck_ICMP(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES, ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES, AF_INET))
				PacketSource->HopLimitData.TTL = IPv4_Header->TTL;

			return true;
		}

	//TCP Protocol
		if (Parameter.HeaderCheck_TCP && IPv4_Header->Protocol == IPPROTO_TCP && ntohs(IPv4_Header->Length) >= IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(tcp_hdr))
		{
		//Validate TCP checksum.
			if (GetChecksum_TCPUDP((PUINT8)Buffer, ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES, AF_INET, IPPROTO_TCP) != CHECKSUM_SUCCESS)
				return false;

		//TCP check
			if (CaptureCheck_TCP(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES))
				PacketSource->HopLimitData.TTL = IPv4_Header->TTL;

			return true;
		}

	//UDP Protocol
		if (IPv4_Header->Protocol == IPPROTO_UDP && ntohs(IPv4_Header->Length) >= IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(udp_hdr) + DNS_PACKET_MINSIZE)
		{
		//Validate UDP checksum.
			if (GetChecksum_TCPUDP((PUINT8)Buffer, ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES, AF_INET, IPPROTO_UDP) != CHECKSUM_SUCCESS)
				return false;

		//Port check
			auto UDP_Header = (pudp_hdr)(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES);
			if (UDP_Header->SrcPort == PacketSource->AddressData.IPv4.sin_port)
			{
			//Domain Test and DNS Options check and get TTL from Domain Test.
				auto IsMarkHopLimit = false;
				if (CheckResponseData(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(udp_hdr), ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES - sizeof(udp_hdr), false, &IsMarkHopLimit) < (SSIZE_T)DNS_PACKET_MINSIZE)
					return false;
				if (IsMarkHopLimit)
					PacketSource->HopLimitData.TTL = IPv4_Header->TTL;

			//DNSCurve encryption packet check
			#if defined(ENABLE_LIBSODIUM)
				if (Parameter.DNSCurve && 
				//Main(IPv4)
					(DNSCurveParameter.DNSCurveTarget.IPv4.AddressData.Storage.ss_family > 0 && DNSCurveParameter.DNSCurveTarget.IPv4.ReceiveMagicNumber != nullptr &&  
					memcmp(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(udp_hdr), DNSCurveParameter.DNSCurveTarget.IPv4.ReceiveMagicNumber, DNSCURVE_MAGIC_QUERY_LEN) == EXIT_SUCCESS || 
				//Alternate(IPv4)
					DNSCurveParameter.DNSCurveTarget.Alternate_IPv4.AddressData.Storage.ss_family > 0 && DNSCurveParameter.DNSCurveTarget.Alternate_IPv4.ReceiveMagicNumber != nullptr && 
					memcmp(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(udp_hdr), DNSCurveParameter.DNSCurveTarget.Alternate_IPv4.ReceiveMagicNumber, DNSCURVE_MAGIC_QUERY_LEN) == EXIT_SUCCESS))
						return false;
			#endif

			//TTL must not a ramdom value.
				if ((size_t)IPv4_Header->TTL + (size_t)Parameter.HopLimitFluctuation > (size_t)PacketSource->HopLimitData.TTL && 
					(size_t)IPv4_Header->TTL < (size_t)PacketSource->HopLimitData.TTL + (size_t)Parameter.HopLimitFluctuation)
				{
					MatchPortToSend(Buffer + IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES + sizeof(udp_hdr), ntohs(IPv4_Header->Length) - IPv4_Header->IHL * IPv4_IHL_BYTES_TIMES - sizeof(udp_hdr), AF_INET, UDP_Header->DstPort);
					return true;
				}
			}
		}
	}

	return true;
}