// Create a SSTP server
SSTP_SERVER *NewSstpServer(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip,
						   UINT server_port, SOCK_EVENT *se,
						   char *client_host_name, char *crypt_name)
{
	SSTP_SERVER *s = ZeroMalloc(sizeof(SSTP_SERVER));

	s->LastRecvTick = Tick64();

	StrCpy(s->ClientHostName, sizeof(s->ClientHostName), client_host_name);
	StrCpy(s->ClientCipherName, sizeof(s->ClientCipherName), crypt_name);

	s->Cedar = cedar;
	AddRef(s->Cedar->ref);

	NewTubePair(&s->TubeSend, &s->TubeRecv, 0);
	SetTubeSockEvent(s->TubeSend, se);

	s->Now = Tick64();

	Copy(&s->ClientIp, client_ip, sizeof(IP));
	s->ClientPort = client_port;
	Copy(&s->ServerIp, server_ip, sizeof(IP));
	s->ServerPort = server_port;

	s->SockEvent = se;

	AddRef(s->SockEvent->ref);

	s->RecvQueue = NewQueueFast();
	s->SendQueue = NewQueueFast();

	s->Interrupt = NewInterruptManager();

	return s;
}
Exemple #2
0
// Check whether the specified IP address is in Non-SSL connection list
bool IsInNoSsl(CEDAR *c, IP *ip)
{
	bool ret = false;
	// Validate arguments
	if (c == NULL || ip == NULL)
	{
		return false;
	}

	LockList(c->NonSslList);
	{
		NON_SSL *n = SearchNoSslList(c, ip);

		if (n != NULL)
		{
			if (n->EntryExpires > Tick64() && n->Count > NON_SSL_MIN_COUNT)
			{
				n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;
				ret = true;
			}
		}
	}
	UnlockList(c->NonSslList);

	return ret;
}
// Wait for a event until the cancel flag becomes true
bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel)
{
	bool dummy_bool = false;
	UINT64 start, giveup;
	// Validate arguments
	if (cancel == NULL)
	{
		cancel = &dummy_bool;
	}

	start = Tick64();

	if (timeout == INFINITE || timeout == 0x7FFFFFFF)
	{
		giveup = 0;
	}
	else
	{
		giveup = start + (UINT64)timeout;
	}

	while (true)
	{
		UINT64 now = Tick64();
		UINT interval_to_giveup = (UINT)(giveup - now);
		if (giveup == 0)
		{
			interval_to_giveup = INFINITE;
		}
		else
		{
			if (now >= giveup)
			{
				// Time-out occurs
				return false;
			}
		}

		interval_to_giveup = MIN(interval_to_giveup, 25);

		if (*cancel)
		{
			// Cancel flag is set to true. Time-out occurs
			return false;
		}

		if (e != NULL)
		{
			if (Wait(e, interval_to_giveup))
			{
				// Event is set
				return true;
			}
		}
		else
		{
			SleepThread(interval_to_giveup);
		}
	}
}
Exemple #4
0
// Initialize the client-side
bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *server_key, IP *server_ip, UINT server_port, UINT server_cookie, UINT client_cookie, IP *server_ip_2)
{
	char tmp[MAX_SIZE];
	// Validate arguments
	if (a == NULL || server_key == NULL || server_ip == NULL || server_port == 0)
	{
		return false;
	}

	IPToStr(tmp, sizeof(tmp), server_ip);
	Debug("UdpAccelInitClient: server_ip=%s, server_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, server_port, server_cookie, client_cookie);

	if (IsIP6(server_ip) != a->IsIPv6)
	{
		return false;
	}

	Copy(a->YourKey, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE);

	Copy(&a->YourIp, server_ip, sizeof(IP));
	Copy(&a->YourIp2, server_ip_2, sizeof(IP));
	a->YourPort = server_port;

	a->Now = Tick64();

	a->MyCookie = client_cookie;
	a->YourCookie = server_cookie;

	a->Inited = true;

	return true;
}
Exemple #5
0
// Delete old entries in Non-SSL connection list
void DeleteOldNoSsl(CEDAR *c)
{
	UINT i;
	LIST *o;
	// Validate arguments
	if (c == NULL)
	{
		return;
	}

	o = NewListFast(NULL);

	for (i = 0;i < LIST_NUM(c->NonSslList);i++)
	{
		NON_SSL *n = LIST_DATA(c->NonSslList, i);

		if (n->EntryExpires <= Tick64())
		{
			Add(o, n);
		}
	}

	for (i = 0;i < LIST_NUM(o);i++)
	{
		NON_SSL *n = LIST_DATA(o, i);

		Delete(c->NonSslList, n);
		Free(n);
	}

	ReleaseList(o);
}
Exemple #6
0
// Send an IP packet
void L3SendIp(L3IF *f, L3PACKET *p)
{
	L3ARPENTRY *a = NULL;
	bool broadcast = false;
	IPV4_HEADER *ip;
	bool for_me = false;
	// Validate arguments
	if (f == NULL || p == NULL)
	{
		return;
	}
	if (p->Packet->TypeL3 != L3_IPV4)
	{
		return;
	}

	ip = p->Packet->L3.IPv4Header;

	// Determining whether it's a broadcast
	if (p->NextHopIp == 0xffffffff ||
		((p->NextHopIp & f->SubnetMask) == (f->IpAddress & f->SubnetMask)) &&
		((p->NextHopIp & (~f->SubnetMask)) == (~f->SubnetMask)))
	{
		broadcast = true;
	}

	if (broadcast == false && ip->DstIP == f->IpAddress)
	{
		// me?
	}
	else if (broadcast == false)
	{
		// Examine whether the ARP entry contains this in the case of unicast
		a = L3SearchArpTable(f, p->NextHopIp);

		if (a == NULL)
		{
			// Since It is not in the ARP table,
			// insert it into the IP waiting list without sending immediately
			p->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;

			Insert(f->IpWaitList, p);

			// Issue an ARP query
			L3SendArp(f, p->NextHopIp);
			return;
		}
	}

	if (for_me == false)
	{
		// Send the IP packet
		L3SendIpNow(f, a, p);
	}

	// Release the packet
	Free(p->Packet->PacketData);
	FreePacket(p->Packet);
	Free(p);
}
Exemple #7
0
// Register in the ARP table
void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac)
{
	L3ARPENTRY *a, t;
	// Validate arguments
	if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
	{
		return;
	}

	Zero(&t, sizeof(t));
	t.IpAddress = ip;

	a = Search(f->ArpTable, &t);

	if (a == NULL)
	{
		// Since this is not registered, register this
		a = ZeroMalloc(sizeof(L3ARPENTRY));
		a->IpAddress = ip;
		Copy(a->MacAddress, mac, 6);
		Insert(f->ArpTable, a);
	}

	// Extend the expiration date
	a->Expire = Tick64() + ARP_ENTRY_EXPIRES;

	// Send waiting IP packets
	L3SendWaitingIp(f, mac, ip, a);
}
Exemple #8
0
// Issue an ARP query
void L3SendArp(L3IF *f, UINT ip)
{
	L3ARPWAIT t, *w;
	// Validate arguments
	if (f == NULL || ip == 0 || ip == 0xffffffff)
	{
		return;
	}

	// Examine whether it has not already registered
	Zero(&t, sizeof(t));
	t.IpAddress = ip;
	w = Search(f->ArpWaitTable, &t);

	if (w != NULL)
	{
		// Do not do anything because it is already registered in the waiting list
		return;
	}
	else
	{
		// Register in the waiting list newly
		w = ZeroMalloc(sizeof(L3ARPWAIT));
		w->Expire = Tick64() + ARP_REQUEST_GIVEUP;
		w->IpAddress = ip;
		Insert(f->ArpWaitTable, w);
	}
}
Exemple #9
0
// Polling for the ARP resolution waiting list
void L3PollingArpWaitTable(L3IF *f)
{
	UINT i;
	LIST *o = NULL;
	// Validate arguments
	if (f == NULL)
	{
		return;
	}

	for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
	{
		L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);

		if (w->Expire <= Tick64())
		{
			// The ARP request entry is expired
			if (o == NULL)
			{
				o = NewListFast(NULL);
			}

			Insert(o, w);
		}
		else if ((w->LastSentTime + ARP_REQUEST_TIMEOUT) <= Tick64())
		{
			// Send a next ARP request packet
			w->LastSentTime = Tick64();

			L3SendArpRequestNow(f, w->IpAddress);
		}
	}

	if (o != NULL)
	{
		for (i = 0;i < LIST_NUM(o);i++)
		{
			L3ARPWAIT *w = LIST_DATA(o, i);

			Delete(f->ArpWaitTable, w);
			Free(w);
		}

		ReleaseList(o);
	}
}
Exemple #10
0
// Clear old ARP table entries
void L3DeleteOldArpTable(L3IF *f)
{
	UINT i;
	LIST *o = NULL;
	// Validate arguments
	if (f == NULL)
	{
		return;
	}

	if ((f->LastDeleteOldArpTable + ARP_ENTRY_POLLING_TIME) > Tick64())
	{
		return;
	}
	f->LastDeleteOldArpTable = Tick64();

	for (i = 0;i < LIST_NUM(f->ArpTable);i++)
	{
		L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);

		if (a->Expire <= Tick64())
		{
			// Expired
			if (o == NULL)
			{
				o = NewListFast(NULL);
			}

			Insert(o, a);
		}
	}

	if (o != NULL)
	{
		for (i = 0;i < LIST_NUM(o);i++)
		{
			L3ARPENTRY *a = LIST_DATA(o, i);

			Delete(f->ArpTable, a);
			Free(a);
		}

		ReleaseList(o);
	}
}
Exemple #11
0
// Get the high-resolution time
UINT64 TickHighres64()
{

#ifdef	OS_WIN32

	return (UINT64)(MsGetHiResTimeSpan(MsGetHiResCounter()) * 1000.0f);

#else	// OS_WIN32

	return Tick64();

#endif	// OS_WIN32

}
// Packet generation thread
void NullPacketGenerateThread(THREAD *t, void *param)
{
	NULL_LAN *n = (NULL_LAN *)param;
	UINT64 end_tick = Tick64() + (UINT64)(60 * 1000);
	UINT seq = 0;
	// Validate arguments
	if (t == NULL || param == NULL)
	{
		return;
	}

	while (true)
	{
		/*if (Tick64() >= end_tick)
		{
			break;
		}*/

		Wait(n->Event, Rand32() % 1500);
		if (n->Halt)
		{
			break;
		}

		LockQueue(n->PacketQueue);
		{
			UCHAR *data;
			BLOCK *b;
			UINT size = Rand32() % 1500 + 14;
			UCHAR dst_mac[6];

			NullGenerateMacAddress(n->MacAddr, n->Id, seq);

			//NullGenerateMacAddress(dst_mac, n->Id + 1, 0);
			//StrToMac(dst_mac, "00-1B-21-A9-47-E6");
			StrToMac(dst_mac, "00-AC-7A-EF-83-FD");

			data = Malloc(size);
			Copy(data, null_lan_broadcast_address, 6);
			//Copy(data, dst_mac, 6);
			Copy(data + 6, n->MacAddr, 6);
			b = NewBlock(data, size, 0);
			InsertQueue(n->PacketQueue, b);
		}
		UnlockQueue(n->PacketQueue);
		Cancel(n->Cancel);

		//seq++;
	}
}
Exemple #13
0
// Release the packet adapter
void VLanPaFree(SESSION *s)
{
	VLAN *v;
	ROUTE_TRACKING *t;
	// Validate arguments
	if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
	{
		return;
	}

	// Release the IP address if you are using DHCP
	if (IsNt())
	{
		char tmp[MAX_SIZE];
		MS_ADAPTER *a;
		UINT64 now = Tick64();
		UINT64 suspend_tick = MsGetSuspendModeBeginTick();

		if (suspend_tick == 0 || (suspend_tick + (UINT64)(30 * 1000)) < now)
		{
			Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
			a = MsGetAdapter(tmp);

			if (a != NULL)
			{
				if (a->UseDhcp)
				{
					bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 50);
					Debug("*** Win32ReleaseAddressByGuid = %u\n", ret);
				}

				MsFreeAdapter(a);
			}
		}
	}

	t = v->RouteState;
	// End the virtual LAN card
	FreeVLan(v);

	// End the routing table tracking 
	if (s->ClientModeAndUseVLan)
	{
		RouteTrackingStop(s, t);
	}
	s->PacketAdapter->Param = NULL;
}
// Create a new EtherIP server
ETHERIP_SERVER *NewEtherIPServer(CEDAR *cedar, IPSEC_SERVER *ipsec, IKE_SERVER *ike,
								 IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *crypt_name,
								 bool is_tunnel_mode, UINT crypt_block_size,
								 char *client_id, UINT id)
{
	ETHERIP_SERVER *s;
	// Validate arguments
	if (cedar == NULL || ipsec == NULL || ike == NULL || client_ip == NULL || server_ip == NULL || client_id == NULL)
	{
		return NULL;
	}

	s = ZeroMalloc(sizeof(ETHERIP_SERVER));

	s->Ref = NewRef();

	s->Id = id;

	s->Cedar = cedar;
	AddRef(s->Cedar->ref);
	s->IPsec = ipsec;
	s->Ike = ike;
	s->IsTunnelMode = is_tunnel_mode;

	StrCpy(s->ClientId, sizeof(s->ClientId), client_id);

	s->SendPacketList = NewList(NULL);

	s->Now = Tick64();

	s->Lock = NewLock();

	Copy(&s->ClientIP, client_ip, sizeof(IP));
	s->ClientPort = client_port;

	Copy(&s->ServerIP, server_ip, sizeof(IP));
	s->ServerPort = server_port;

	StrCpy(s->CryptName, sizeof(s->CryptName), crypt_name);
	s->CryptBlockSize = crypt_block_size;

	EtherIPLog(s, "LE_START_MODULE");

	return s;
}
Exemple #15
0
// Clear the IP waiting list
void L3DeleteOldIpWaitList(L3IF *f)
{
	UINT i;
	LIST *o = NULL;
	// Validate arguments
	if (f == NULL)
	{
		return;
	}

	for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
	{
		L3PACKET *p = LIST_DATA(f->IpWaitList, i);

		if (p->Expire <= Tick64())
		{
			if (o == NULL)
			{
				o = NewListFast(NULL);
			}

			Insert(o, p);
		}
	}

	if (o != NULL)
	{
		for (i = 0;i < LIST_NUM(o);i++)
		{
			L3PACKET *p = LIST_DATA(o, i);

			Delete(f->IpWaitList, p);

			Free(p->Packet->PacketData);
			FreePacket(p->Packet);
			Free(p);
		}

		ReleaseList(o);
	}
}
Exemple #16
0
// Create a new key
void DCGenNewKey(UCHAR *key)
{
	BUF *b;
	UINT64 tick;
	UCHAR hash[SHA1_SIZE];
	UCHAR rand[SHA1_SIZE];
	UINT i;
	// Validate arguments
	if (key == NULL)
	{
		return;
	}

	b = NewBuf();

	Rand(rand, sizeof(rand));
	WriteBuf(b, rand, sizeof(rand));

	tick = TickHighres64();
	WriteBufInt64(b, tick);

	tick = Tick64();
	WriteBufInt64(b, tick);

	tick = SystemTime64();
	WriteBufInt64(b, tick);

	GetCurrentMachineIpProcessHash(hash);
	WriteBuf(b, hash, sizeof(hash));

	HashSha1(key, b->Buf, b->Size);
	Rand(rand, sizeof(rand));

	for (i = 0;i < SHA1_SIZE;i++)
	{
		key[i] = key[i] ^ rand[i];
	}

	FreeBuf(b);
}
Exemple #17
0
// Add new entry to Non-SSL connection list
bool AddNoSsl(CEDAR *c, IP *ip)
{
	NON_SSL *n;
	bool ret = true;
	// Validate arguments
	if (c == NULL || ip == NULL)
	{
		return true;
	}

	LockList(c->NonSslList);
	{
		DeleteOldNoSsl(c);

		n = SearchNoSslList(c, ip);

		if (n == NULL)
		{
			n = ZeroMalloc(sizeof(NON_SSL));
			Copy(&n->IpAddress, ip, sizeof(IP));
			n->Count = 0;

			Add(c->NonSslList, n);
		}

		n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;

		n->Count++;

		if (n->Count > NON_SSL_MIN_COUNT)
		{
			ret = false;
		}
	}
	UnlockList(c->NonSslList);

	return ret;
}
// IPC connection processing thread
void EtherIPIpcConnectThread(THREAD *t, void *p)
{
	ETHERIP_SERVER *s;
	IPC *ipc = NULL;
	UINT error_code = 0;
	char tmp[MAX_SIZE];
	ETHERIP_ID id;
	// Validate arguments
	if (t == NULL || p == NULL)
	{
		return;
	}

	s = (ETHERIP_SERVER *)p;

	GetHostName(tmp, sizeof(tmp), &s->ClientIP);

	// Get the setting of the virtual HUB to be connected based on the client ID presented
	if (SearchEtherIPId(s->Ike->IPsec, &id, s->ClientId) == false &&
		SearchEtherIPId(s->Ike->IPsec, &id, "*") == false)
	{
		// Failed to get the settings for the virtual HUB
		Debug("Not Found: EtherIP Settings for Client ID \"%s\".\n", s->ClientId);

		EtherIPLog(s, "LE_NO_SETTING", s->ClientId);
	}
	else
	{
		UINT mss = CalcEtherIPTcpMss(s);
		char client_name[MAX_SIZE];

		if (s->L2TPv3 == false)
		{
			StrCpy(client_name, sizeof(client_name), ETHERIP_CLIENT_NAME);
		}
		else
		{
			if (IsEmptyStr(s->VendorName))
			{
				StrCpy(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME);
			}
			else
			{
				Format(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME_EX, s->VendorName);
			}
		}

		// Execution of IPC connection process
		EtherIPLog(s, "LE_START_IPC", id.HubName, id.UserName, mss);
		ipc = NewIPC(s->Cedar, client_name,
			(s->L2TPv3 ? ETHERIP_L2TPV3_POSTFIX : ETHERIP_POSTFIX),
			id.HubName, id.UserName, id.Password,
			&error_code,
			&s->ClientIP, s->ClientPort,
			&s->ServerIP, s->ServerPort,
			tmp,
			s->CryptName, true, mss);

		if (ipc != NULL)
		{
			Copy(&s->CurrentEtherIPIdSetting, &id, sizeof(ETHERIP_ID));
			EtherIPLog(s, "LE_IPC_CONNECT_OK", id.HubName);
		}
		else
		{
			EtherIPLog(s, "LE_IPC_CONNECT_ERROR", id.HubName, error_code, _E(error_code));
		}
	}

	Lock(s->Lock);
	{
		// Set the results
		ReleaseThread(s->IpcConnectThread);
		s->IpcConnectThread = NULL;

		s->Ipc = ipc;

		s->LastConnectFailedTick = Tick64();
	}
	Unlock(s->Lock);

	// Hit the event to cause interrupt
	SetSockEvent(s->SockEvent);

	// Release the EtherIP object that is hold by this thread
	ReleaseEtherIPServer(s);
}
Exemple #19
0
// Attempts Radius authentication (with specifying retry interval and multiple server)
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20)
{
	UCHAR random[MD5_SIZE];
	UCHAR id;
	BUF *encrypted_password = NULL;
	BUF *user_name = NULL;
	//IP ip;
	bool ret = false;
	TOKEN_LIST *token;
	UINT i;
	LIST *ip_list;
	IPC_MSCHAP_V2_AUTHINFO mschap;
	bool is_mschap;
	char client_ip_str[MAX_SIZE];
	static UINT packet_id = 0;
	// Validate arguments
	if (server == NULL || port == 0 || (secret_size != 0 && secret == NULL) || username == NULL || password == NULL)
	{
		return false;
	}

	Zero(client_ip_str, sizeof(client_ip_str));
	if (c != NULL && c->FirstSock != NULL)
	{
		IPToStr(client_ip_str, sizeof(client_ip_str), &c->FirstSock->RemoteIP);
	}

	// Parse the MS-CHAP v2 authentication data
	Zero(&mschap, sizeof(mschap));
	is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, password);

	// Split the server into tokens
	token = ParseToken(server, " ,;\t");

	// Get the IP address of the server
	ip_list = NewListFast(NULL);
	for(i = 0; i < token->NumTokens; i++)
	{
		IP *tmp_ip = Malloc(sizeof(IP));
		if (GetIP(tmp_ip, token->Token[i]))
		{
			Add(ip_list, tmp_ip);
		}
		else if (GetIPEx(tmp_ip, token->Token[i], true))
		{
			Add(ip_list, tmp_ip);
		}
		else
		{
			Free(tmp_ip);
		}
	}

	FreeToken(token);

	if(LIST_NUM(ip_list) == 0)
	{
		ReleaseList(ip_list);
		return false;
	}

	// Random number generation
	Rand(random, sizeof(random));

	// ID generation
	id = (UCHAR)(packet_id % 254 + 1);
	packet_id++;

	if (is_mschap == false)
	{
		// Encrypt the password
		encrypted_password = RadiusEncryptPassword(password, random, secret, secret_size);
		if (encrypted_password == NULL)
		{
			// Encryption failure
			ReleaseList(ip_list);
			return false;
		}
	}

	// Generate the user name packet
	user_name = RadiusCreateUserName(username);

	if (user_name != NULL)
	{
		// Generate a password packet
		BUF *user_password = (is_mschap ? NULL : RadiusCreateUserPassword(encrypted_password->Buf, encrypted_password->Size));
		BUF *nas_id = RadiusCreateNasId(CEDAR_SERVER_STR);

		if (is_mschap || user_password != NULL)
		{
			UINT64 start;
			UINT64 next_send_time;
			UCHAR tmp[MAX_SIZE];
			UINT recv_buf_size = 32768;
			UCHAR *recv_buf = MallocEx(recv_buf_size, true);
			// Generate an UDP packet
			BUF *p = NewBuf();
			UCHAR type = 1;
			SOCK *sock;
			USHORT sz = 0;
			UINT pos = 0;
			BOOL *finish = ZeroMallocEx(sizeof(BOOL) * LIST_NUM(ip_list), true);

			Zero(tmp, sizeof(tmp));

			WriteBuf(p, &type, 1);
			WriteBuf(p, &id, 1);
			WriteBuf(p, &sz, 2);
			WriteBuf(p, random, 16);
			WriteBuf(p, user_name->Buf, user_name->Size);

			if (is_mschap == false)
			{
				UINT ui;
				// PAP
				WriteBuf(p, user_password->Buf, user_password->Size);
				WriteBuf(p, nas_id->Buf, nas_id->Size);

				// Service-Type
				ui = Endian32(2);
				RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));

				// NAS-Port-Type
				ui = Endian32(5);
				RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));

				// Tunnel-Type
				ui = Endian32(1);
				RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));

				// Tunnel-Medium-Type
				ui = Endian32(1);
				RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));

				// Calling-Station-Id
				RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));

				// Tunnel-Client-Endpoint
				RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));
			}
			else
			{
				// MS-CHAP v2
				static UINT session_id = 0;
				USHORT us;
				UINT ui;
				char *ms_ras_version = "MSRASV5.20";
				UCHAR ms_chapv2_response[50];

				// Acct-Session-Id
				us = Endian16(session_id % 254 + 1);
				session_id++;
				RadiusAddValue(p, 44, 0, 0, &us, sizeof(us));

				// NAS-IP-Address
				if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false)
				{
					ui = IPToUINT(&c->FirstSock->LocalIP);
					RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui));
				}

				// Service-Type
				ui = Endian32(2);
				RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));

				// MS-RAS-Vendor
				ui = Endian32(311);
				RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui));

				// MS-RAS-Version
				RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version));

				// NAS-Port-Type
				ui = Endian32(5);
				RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));

				// Tunnel-Type
				ui = Endian32(1);
				RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));

				// Tunnel-Medium-Type
				ui = Endian32(1);
				RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));

				// Calling-Station-Id
				RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));

				// Tunnel-Client-Endpoint
				RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));

				// MS-RAS-Client-Version
				RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version));

				// MS-RAS-Client-Name
				RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str));

				// MS-CHAP-Challenge
				RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge));

				// MS-CHAP2-Response
				Zero(ms_chapv2_response, sizeof(ms_chapv2_response));
				Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16);
				Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24);
				RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response));

				// NAS-ID
				WriteBuf(p, nas_id->Buf, nas_id->Size);
			}

			SeekBuf(p, 0, 0);

			WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);

			// Create a socket
			sock = NewUDPEx(0, IsIP6(LIST_DATA(ip_list, pos)));

			// Transmission process start
			start = Tick64();
			if(interval < RADIUS_RETRY_INTERVAL)
			{
				interval = RADIUS_RETRY_INTERVAL;
			}
			else if(interval > RADIUS_RETRY_TIMEOUT)
			{
				interval = RADIUS_RETRY_TIMEOUT;
			}
			next_send_time = start + (UINT64)interval;

			while (true)
			{
				UINT server_port;
				UINT recv_size;
				//IP server_ip;
				SOCKSET set;
				UINT64 now;

SEND_RETRY:
				//SendTo(sock, &ip, port, p->Buf, p->Size);
				SendTo(sock, LIST_DATA(ip_list, pos), port, p->Buf, p->Size);

				Debug("send to host:%u\n", pos);

				next_send_time = Tick64() + (UINT64)interval;

RECV_RETRY:
				now = Tick64();
				if (next_send_time <= now)
				{
					// Switch the host to refer
					pos++;
					pos = pos % LIST_NUM(ip_list);

					goto SEND_RETRY;
				}

				if ((start + RADIUS_RETRY_TIMEOUT) < now)
				{
					// Time-out
					break;
				}

				InitSockSet(&set);
				AddSockSet(&set, sock);
				Select(&set, (UINT)(next_send_time - now), NULL, NULL);

				recv_size = RecvFrom(sock, LIST_DATA(ip_list, pos), &server_port, recv_buf, recv_buf_size);

				if (recv_size == 0)
				{
					Debug("Radius recv_size 0\n");
					finish[pos] = TRUE;
					for(i = 0; i < LIST_NUM(ip_list); i++)
					{
						if(finish[i] == FALSE)
						{
							// Switch the host to refer
							pos++;
							pos = pos % LIST_NUM(ip_list);
							goto SEND_RETRY;
						}
					}
					// Failure
					break;
				}
				else if (recv_size == SOCK_LATER)
				{
					// Waiting
					goto RECV_RETRY;
				}
				else
				{
					// Check such as the IP address
					if (/*Cmp(&server_ip, &ip, sizeof(IP)) != 0 || */server_port != port)
					{
						goto RECV_RETRY;
					}
					// Success
					if (recv_buf[0] == 2)
					{
						ret = true;

						if (is_mschap && mschap_v2_server_response_20 != NULL)
						{
							// Cutting corners Zurukko
							UCHAR signature[] = {0x1A, 0x33, 0x00, 0x00, 0x01, 0x37, 0x1A, 0x2D, 0x00, 0x53, 0x3D, };
							UINT i = SearchBin(recv_buf, 0, recv_buf_size, signature, sizeof(signature));

							if (i == INFINITE || ((i + sizeof(signature) + 40) > recv_buf_size))
							{
								ret = false;
							}
							else
							{
								char tmp[MAX_SIZE];
								BUF *b;

								Zero(tmp, sizeof(tmp));
								Copy(tmp, recv_buf + i + sizeof(signature), 40);

								b = StrToBin(tmp);

								if (b != NULL && b->Size == 20)
								{
									WHERE;
									Copy(mschap_v2_server_response_20, b->Buf, 20);
								}
								else
								{
									WHERE;
									ret = false;
								}

								FreeBuf(b);
							}
						}
					}
					break;
				}
			}

			Free(finish);

			// Release the socket
			ReleaseSock(sock);

			FreeBuf(p);
			FreeBuf(user_password);

			Free(recv_buf);
		}

		FreeBuf(nas_id);
		FreeBuf(user_name);
	}

	// Release the ip_list
	for(i = 0; i < LIST_NUM(ip_list); i++)
	{
		IP *tmp_ip = LIST_DATA(ip_list, i);
		Free(tmp_ip);
	}
	ReleaseList(ip_list);

	// Release the memory
	FreeBuf(encrypted_password);

	return ret;
}
Exemple #20
0
// DDNS client thread
void DCThread(THREAD *thread, void *param)
{
	DDNS_CLIENT *c;
	INTERRUPT_MANAGER *interrput;
	UINT last_ip_hash = 0;
	void *route_change_poller = NULL;
	bool last_time_ip_changed = false;
	UINT last_azure_ddns_trigger_int = 0;
	UINT last_vgs_ddns_trigger_int = 0;
	UINT n;
	INTERNET_SETTING last_t;
	// Validate arguments
	if (thread == NULL || param == NULL)
	{
		return;
	}

	c = (DDNS_CLIENT *)param;

	interrput = NewInterruptManager();

	route_change_poller = NewRouteChange();
	IsRouteChanged(route_change_poller);

	Zero(&last_t, sizeof(last_t));

	n = 0;

	while (c->Halt == false)
	{
		UINT ip_hash = GetHostIPAddressHash32();
		UINT interval;
		UINT64 now = Tick64();
		bool ip_changed = false;
		bool azure_client_triggered = false;
		bool internet_setting_changed = false;
		bool vgs_server_triggered = false;


		if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
		{
			if (c->Cedar->Server->AzureClient->DDnsTriggerInt != last_azure_ddns_trigger_int)
			{
				azure_client_triggered = true;
				last_azure_ddns_trigger_int = c->Cedar->Server->AzureClient->DDnsTriggerInt;
				last_time_ip_changed = false;
				Debug("DDNS Thread Triggered by AzureClient.\n");
			}
		}

		if (Cmp(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
		{
			Copy(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING));
			internet_setting_changed = true;
			last_time_ip_changed = false;
		}

		if (ip_hash != last_ip_hash)
		{
			last_time_ip_changed = false;
			Debug("DDNS Thread Triggered by IP Hash Changed.\n");
		}

		if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)) || azure_client_triggered || internet_setting_changed || vgs_server_triggered)
		{
			if (last_time_ip_changed == false)
			{
				// Call all getting functions from the beginning if the routing
				//  table or the IP address of this host has changed
				c->NextRegisterTick_IPv4 = 0;
				c->NextRegisterTick_IPv6 = 0;
				c->NextGetMyIpTick_IPv4 = 0;
				c->NextGetMyIpTick_IPv6 = 0;

				last_ip_hash = ip_hash;

				last_time_ip_changed = true;

				ip_changed = true;

				Debug("DDNS Internet Condition Changed.\n");
			}
		}
		else
		{
			last_time_ip_changed = false;
		}

		if ((n++) >= 1)
		{
			// Self IPv4 address acquisition
			if (c->NextGetMyIpTick_IPv4 == 0 || now >= c->NextGetMyIpTick_IPv4)
			{
				UINT next_interval;
				char ip[MAX_SIZE];

				Zero(ip, sizeof(ip));
				c->Err_IPv4_GetMyIp = DCGetMyIp(c, false, ip, sizeof(ip), NULL);

				if (c->Err_IPv4_GetMyIp == ERR_NO_ERROR)
				{
					if (StrCmpi(c->LastMyIPv4, ip) != 0)
					{
						ip_changed = true;
						StrCpy(c->LastMyIPv4, sizeof(c->LastMyIPv4), ip);
					}

					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
				}
				else
				{
					if (IsEmptyStr(c->LastMyIPv4) == false)
					{
						ip_changed = true;
					}

					Zero(c->LastMyIPv4, sizeof(c->LastMyIPv4));
					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
				}

				c->NextGetMyIpTick_IPv4 = Tick64() + (UINT64)next_interval;

				AddInterrupt(interrput, c->NextGetMyIpTick_IPv4);
			}

			// Self IPv6 address acquisition
			if (c->NextGetMyIpTick_IPv6 == 0 || now >= c->NextGetMyIpTick_IPv6)
			{
				UINT next_interval;
				char ip[MAX_SIZE];

				Zero(ip, sizeof(ip));
				c->Err_IPv6_GetMyIp = DCGetMyIp(c, true, ip, sizeof(ip), NULL);

				if (c->Err_IPv6_GetMyIp == ERR_NO_ERROR)
				{
					if (StrCmpi(c->LastMyIPv6, ip) != 0)
					{
						ip_changed = true;
						StrCpy(c->LastMyIPv6, sizeof(c->LastMyIPv6), ip);
					}

					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
				}
				else
				{
					if (IsEmptyStr(c->LastMyIPv6) == false)
					{
						ip_changed = true;
					}

					Zero(c->LastMyIPv6, sizeof(c->LastMyIPv6));
					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
				}

				c->NextGetMyIpTick_IPv6 = Tick64() + (UINT64)next_interval;

				AddInterrupt(interrput, c->NextGetMyIpTick_IPv6);
			}
		}

		if (ip_changed)
		{
			c->NextRegisterTick_IPv4 = 0;
			c->NextRegisterTick_IPv6 = 0;
		}

		// IPv4 host registration
		if (c->NextRegisterTick_IPv4 == 0 || now >= c->NextRegisterTick_IPv4)
		{
			UINT next_interval;

			c->Err_IPv4 = DCRegister(c, false, NULL, NULL);

			if (c->Err_IPv4 == ERR_NO_ERROR)
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
			}
			else
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
			}
			//next_interval = 0;

			c->NextRegisterTick_IPv4 = Tick64() + (UINT64)next_interval;

			if (true)
			{
				DDNS_CLIENT_STATUS st;

				DCGetStatus(c, &st);

				SiApplyAzureConfig(c->Cedar->Server, &st);
			}

			AddInterrupt(interrput, c->NextRegisterTick_IPv4);
		}

		if (c->Halt)
		{
			break;
		}

		// IPv6 host registration
		if (c->NextRegisterTick_IPv6 == 0 || now >= c->NextRegisterTick_IPv6)
		{
			UINT next_interval;

			c->Err_IPv6 = DCRegister(c, true, NULL, NULL);

			if (c->Err_IPv6 == ERR_NO_ERROR)
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
			}
			else
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
			}

			c->NextRegisterTick_IPv6 = Tick64() + (UINT64)next_interval;

			if (true)
			{
				DDNS_CLIENT_STATUS st;

				DCGetStatus(c, &st);

				SiApplyAzureConfig(c->Cedar->Server, &st);
			}

			AddInterrupt(interrput, c->NextRegisterTick_IPv6);
		}

		interval = GetNextIntervalForInterrupt(interrput);
		interval = MIN(interval, 1234);

		if (n == 1)
		{
			interval = MIN(interval, 0);
		}

		if (c->Halt)
		{
			break;
		}

		if (c->KeyChanged)
		{
			c->KeyChanged = false;
			c->NextRegisterTick_IPv4 = c->NextRegisterTick_IPv6 = 0;

			interval = 0;
		}

		if (last_time_ip_changed)
		{
			if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
			{
				c->Cedar->Server->AzureClient->IpStatusRevision++;
			}
		}

		Wait(c->Event, interval);
	}

	FreeRouteChange(route_change_poller);
	FreeInterruptManager(interrput);
}
Exemple #21
0
// Create Cedar object
CEDAR *NewCedar(X *server_x, K *server_k)
{
	CEDAR *c;
	char tmp[MAX_SIZE];
	char tmp2[MAX_SIZE];
	char *beta_str;

	CedarForceLink();

	c = ZeroMalloc(sizeof(CEDAR));

	c->CurrentActiveLinks = NewCounter();

	c->AcceptingSockets = NewCounter();

	c->CedarSuperLock = NewLock();

	c->CurrentRegionLock = NewLock();

	StrCpy(c->OpenVPNDefaultClientOption, sizeof(c->OpenVPNDefaultClientOption), OVPN_DEF_CLIENT_OPTION_STRING);

#ifdef	BETA_NUMBER
	c->Beta = BETA_NUMBER;
#endif	// BETA_NUMBER

	InitNoSslList(c);

	c->AssignedBridgeLicense = NewCounter();
	c->AssignedClientLicense = NewCounter();

	c->CurrentTcpQueueSizeLock = NewLock();
	c->QueueBudgetLock = NewLock();
	c->FifoBudgetLock = NewLock();

	Rand(c->UniqueId, sizeof(c->UniqueId));

	c->CreatedTick = Tick64();

	c->lock = NewLock();
	c->ref = NewRef();

	c->OpenVPNPublicPortsLock = NewLock();
	c->CurrentTcpConnections = GetNumTcpConnectionsCounter();

	c->ListenerList = NewList(CompareListener);
	c->UDPEntryList = NewList(CompareUDPEntry);
	c->HubList = NewList(CompareHub);
	c->ConnectionList = NewList(CompareConnection);

	c->ConnectionIncrement = NewCounter();
	c->CurrentSessions = NewCounter();

	if (server_k && server_x)
	{
		c->ServerK = CloneK(server_k);
		c->ServerX = CloneX(server_x);
	}

	c->Version = CEDAR_VER;
	c->Build = CEDAR_BUILD;
	c->ServerStr = CopyStr(CEDAR_SERVER_STR);

	GetMachineName(tmp, sizeof(tmp));
	c->MachineName = CopyStr(tmp);

	c->HttpUserAgent = CopyStr(DEFAULT_USER_AGENT);
	c->HttpAccept = CopyStr(DEFAULT_ACCEPT);
	c->HttpAcceptLanguage = CopyStr("ja");
	c->HttpAcceptEncoding = CopyStr(DEFAULT_ENCODING);

	c->Traffic = NewTraffic();
	c->TrafficLock = NewLock();
	c->CaList = NewList(CompareCert);

	c->TrafficDiffList = NewList(NULL);

	SetCedarCipherList(c, "RC4-MD5");

	c->ClientId = _II("CLIENT_ID");

	c->UdpPortList = NewIntList(false);

	InitNetSvcList(c);

	InitLocalBridgeList(c);

	InitCedarLayer3(c);

	c->WebUI = WuNewWebUI(c);

#ifdef	ALPHA_VERSION
	beta_str = "Alpha";
#else	// ALPHA_VERSION
#ifndef	RELEASE_CANDIDATE
	beta_str = "Beta";
#else	// RELEASE_CANDIDATE
	beta_str = "Release Candidate";
#endif	// RELEASE_CANDIDATE
#endif	// ALPHA_VERSION

	ToStr(tmp2, c->Beta);

	Format(tmp, sizeof(tmp), "Version %u.%02u Build %u %s %s (%s)",
		CEDAR_VER / 100, CEDAR_VER - (CEDAR_VER / 100) * 100,
		CEDAR_BUILD,
		c->Beta == 0 ? "" : beta_str,
		c->Beta == 0 ? "" : tmp2,
		_SS("LANGSTR"));
	Trim(tmp);

	if (true)
	{
		SYSTEMTIME st;
		Zero(&st, sizeof(st));

		st.wYear = BUILD_DATE_Y;
		st.wMonth = BUILD_DATE_M;
		st.wDay = BUILD_DATE_D;

		c->BuiltDate = SystemToUINT64(&st);
	}

	c->VerString = CopyStr(tmp);

	Format(tmp, sizeof(tmp), "Compiled %04u/%02u/%02u %02u:%02u:%02u by %s at %s",
		BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D, BUILD_DATE_HO, BUILD_DATE_MI, BUILD_DATE_SE, BUILDER_NAME, BUILD_PLACE);

	c->BuildInfo = CopyStr(tmp);

	return c;
}
Exemple #22
0
// Process IP packets
void L3RecvIp(L3IF *f, PKT *p, bool self)
{
	IPV4_HEADER *ip;
	UINT header_size;
	UINT next_hop = 0;
	L3IF *dst;
	L3PACKET *packet;
	UINT new_ttl = 0;
	// Validate arguments
	if (f == NULL || p == NULL)
	{
		return;
	}

	ip = p->L3.IPv4Header;
	header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;

	// Calculate the checksum
	if (IpCheckChecksum(ip) == false)
	{
		// The checksum does not match
		goto FREE_PACKET;
	}

	// Register in the ARP table
	L3KnownArp(f, ip->SrcIP, p->MacAddressSrc);

	if (p->BroadcastPacket)
	{
		// Not to route in the case of broadcast packet
		goto FREE_PACKET;
	}

	// Calculate the TTL
	if (ip->TimeToLive >= 1)
	{
		new_ttl = ip->TimeToLive - 1;
	}
	else
	{
		new_ttl = 0;
	}

	if (new_ttl == 0)
	{
		if (ip->DstIP != f->IpAddress)
		{
			UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
			UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
			UCHAR *buf;
			IPV4_HEADER *ipv4;
			ICMP_HEADER *icmpv4;
			UCHAR *data;
			PKT *pkt;
			UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);

			// Generate an ICMP message that means that the TTL has expired
			buf = ZeroMalloc(icmp_packet_total_size);
			ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
			icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
			data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;

			IPV4_SET_VERSION(ipv4, 4);
			IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
			ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
			ipv4->TimeToLive = 0xff;
			ipv4->Protocol = IP_PROTO_ICMPV4;
			ipv4->SrcIP = f->IpAddress;
			ipv4->DstIP = ip->SrcIP;
			ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));

			icmpv4->Type = 11;
			Copy(data, ip, data_size);
			icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);

			buf[12] = 0x08;
			buf[13] = 0x00;

			pkt = ParsePacket(buf, icmp_packet_total_size);
			if (pkt == NULL)
			{
				Free(buf);
			}
			else
			{
				L3RecvIp(f, pkt, true);
			}

			// Discard the packet body whose the TTL has expired
			goto FREE_PACKET;
		}
	}

	// Rewrite the TTL
	p->L3.IPv4Header->TimeToLive = (UCHAR)new_ttl;

	// Get the interface corresponding to the destination IP address
	dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);

	if (dst == NULL && self == false)
	{
		UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
		UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
		UCHAR *buf;
		IPV4_HEADER *ipv4;
		ICMP_HEADER *icmpv4;
		UCHAR *data;
		PKT *pkt;
			UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);

		// Respond with ICMP that indicates that no route can be found
		buf = ZeroMalloc(icmp_packet_total_size);
		ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
		icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
		data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;

		IPV4_SET_VERSION(ipv4, 4);
		IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
		ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
		ipv4->TimeToLive = 0xff;
		ipv4->Protocol = IP_PROTO_ICMPV4;
		ipv4->SrcIP = f->IpAddress;
		ipv4->DstIP = ip->SrcIP;
		ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));

		icmpv4->Type = 3;
		Copy(data, ip, data_size);
		icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);

		buf[12] = 0x08;
		buf[13] = 0x00;

		pkt = ParsePacket(buf, icmp_packet_total_size);
		if (pkt == NULL)
		{
			Free(buf);
		}
		else
		{
			L3RecvIp(f, pkt, true);
		}

		// Discard the packet body whose route can not be found
		goto FREE_PACKET;
	}

	if (dst != NULL && ip->DstIP == dst->IpAddress)
	{
		bool free_packet = true;
		// IP packet addressed to myself has arrived
		if (p->TypeL4 == L4_ICMPV4)
		{
			ICMP_HEADER *icmp = p->L4.ICMPHeader;
			if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
			{
				// Reply by rewriting the source and destination of the IP packet
				UINT src_ip, dst_ip;
				src_ip = p->L3.IPv4Header->DstIP;
				dst_ip = p->L3.IPv4Header->SrcIP;

				p->L3.IPv4Header->DstIP = dst_ip;
				p->L3.IPv4Header->SrcIP = src_ip;

				ip->TimeToLive = 0xff;

				// Recalculates the checksum
				ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
				icmp->Checksum = 0;
				icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
				icmp->Checksum = IpChecksum(icmp, p->PacketSize - sizeof(MAC_HEADER) - header_size);

				dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);

				free_packet = false;
			}
		}

		if (free_packet)
		{
			goto FREE_PACKET;
		}
	}

	if (dst == NULL)
	{
		// The destination does not exist
		goto FREE_PACKET;
	}

	// Recalculate the IP checksum
	ip->Checksum = 0;
	ip->Checksum = IpChecksum(ip, header_size);

	// Treat as a Layer-3 packet
	packet = ZeroMalloc(sizeof(L3PACKET));
	packet->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
	packet->NextHopIp = next_hop;
	packet->Packet = p;

	// Store to the destination session
	L3StoreIpPacketToIf(f, dst, packet);

	return;

FREE_PACKET:
	// Release the packet
	Free(p->PacketData);
	FreePacket(p);
	return;
}
Exemple #23
0
// Beacon transmission
void L3PollingBeacon(L3IF *f)
{
	// Validate arguments
	if (f == NULL)
	{
		return;
	}

	if (f->LastBeaconSent == 0 ||
		(f->LastBeaconSent + BEACON_SEND_INTERVAL) <= Tick64())
	{
		UINT dest_ip;
		UCHAR *udp_buf;
		UINT udp_buf_size;
		ARPV4_HEADER arp;
		IPV4_HEADER *ip;
		UDP_HEADER *udp;
		static char beacon_str[] =
			"PacketiX VPN Virtual Layer-3 Switch Beacon";

		// Send an UDP
		dest_ip = (f->IpAddress & f->SubnetMask) | (~f->SubnetMask);
		udp_buf_size = sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + sizeof(beacon_str);
		udp_buf = ZeroMalloc(udp_buf_size);

		ip = (IPV4_HEADER *)udp_buf;
		udp = (UDP_HEADER *)(udp_buf + sizeof(IPV4_HEADER));
		udp->DstPort = Endian16(7);
		udp->SrcPort = Endian16(7);
		udp->PacketLength = Endian16(sizeof(UDP_HEADER) + sizeof(beacon_str));

		Copy(udp_buf + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), beacon_str, sizeof(beacon_str));

		udp->Checksum = CalcChecksumForIPv4(f->IpAddress, dest_ip, 0x11, udp, sizeof(UDP_HEADER) + sizeof(beacon_str), 0);

		ip->DstIP = dest_ip;
		IPV4_SET_VERSION(ip, 4);
		IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
		ip->TypeOfService = DEFAULT_IP_TOS;
		ip->TotalLength = Endian16((USHORT)(udp_buf_size));
		ip->TimeToLive = DEFAULT_IP_TTL;
		ip->Protocol = IP_PROTO_UDP;
		ip->SrcIP = f->IpAddress;
		ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);

		L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_IPV4, udp_buf, udp_buf_size);

		Free(udp_buf);

		// Build the ARP header
		arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
		arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
		arp.HardwareSize = 6;
		arp.ProtocolSize = 4;
		arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
		Copy(arp.SrcAddress, f->MacAddress, 6);
		arp.SrcIP = f->IpAddress;
		arp.TargetAddress[0] =
			arp.TargetAddress[1] =
			arp.TargetAddress[2] =
			arp.TargetAddress[3] =
			arp.TargetAddress[4] =
			arp.TargetAddress[5] = 0xff;
		arp.TargetIP = dest_ip;

		// Transmission
		L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));

		f->LastBeaconSent = Tick64();
	}
}
Exemple #24
0
// Routing table tracking main
void RouteTrackingMain(SESSION *s)
{
	ROUTE_TRACKING *t;
	UINT64 now;
	ROUTE_TABLE *table;
	ROUTE_ENTRY *rs;
	bool changed = false;
	bool check = false;
	bool any_modified = false;
	// Validate arguments
	if (s == NULL)
	{
		return;
	}
	if (s->ClientModeAndUseVLan == false)
	{
		return;
	}

	// Get the state
	t = ((VLAN *)s->PacketAdapter->Param)->RouteState;
	if (t == NULL)
	{
		return;
	}

	// Current time
	PROBE_STR("RouteTrackingMain 1");
	now = Tick64();

	if (t->RouteChange != NULL)
	{
		if (t->NextRouteChangeCheckTime == 0 ||
			t->NextRouteChangeCheckTime <= now)
		{
			t->NextRouteChangeCheckTime = now + 1000ULL;

			check = IsRouteChanged(t->RouteChange);

			if (check)
			{
				Debug("*** Routing Table Changed ***\n");
				t->NextTrackingTime = 0;
			}
		}
	}
	if (t->NextTrackingTime != 0 && t->NextTrackingTime > now)
	{
		if (s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->NatT_IP_Changed)
		{
			// Check always if the IP address of the NAT-T server has changed
		}
		else
		{
			PROBE_STR("RouteTrackingMain 2");
			return;
		}
	}
	PROBE_STR("RouteTrackingMain 3");

	if (s->UseUdpAcceleration && s->UdpAccel != NULL)
	{
		IP nat_t_ip;

		s->UdpAccel->NatT_IP_Changed = false;

		Zero(&nat_t_ip, sizeof(nat_t_ip));

		Lock(s->UdpAccel->NatT_Lock);
		{
			Copy(&nat_t_ip, &s->UdpAccel->NatT_IP, sizeof(IP));
		}
		Unlock(s->UdpAccel->NatT_Lock);

		// Add a route to the NAT-T server
		if (IsZeroIp(&nat_t_ip) == false)
		{
			if (t->RouteToNatTServer == NULL)
			{
				if (t->RouteToEight != NULL)
				{
					ROUTE_ENTRY *e = Clone(t->RouteToEight, sizeof(ROUTE_ENTRY));
					char ip_str[64];
					char ip_str2[64];

					Copy(&e->DestIP, &nat_t_ip, sizeof(IP));
					e->Metric = e->OldIfMetric;

					IPToStr(ip_str, sizeof(ip_str), &e->DestIP);
					IPToStr(ip_str2, sizeof(ip_str2), &e->GatewayIP);

					t->RouteToNatTServer = e;

					if (AddRouteEntry(t->RouteToNatTServer))
					{
						Debug("Adding Static Route to %s via %s metric %u: ok.\n", ip_str, ip_str2, e->Metric);
					}
					else
					{
						FreeRouteEntry(t->RouteToNatTServer);
						t->RouteToNatTServer = NULL;
					}
				}
			}
		}
	}

	// Get the current routing table
	table = GetRouteTable();
	rs = t->RouteToServer;
	if (table != NULL)
	{
		UINT i;
		bool route_to_server_erased = true;
		bool is_vlan_want_to_be_default_gateway = false;
		UINT vlan_default_gatewat_metric = 0;
		UINT other_if_default_gateway_metric_min = INFINITE;

		// Get whether the routing table have been changed
		if (t->LastRoutingTableHash != table->HashedValue)
		{
			t->LastRoutingTableHash = table->HashedValue;
			changed = true;
		}

		//DebugPrintRouteTable(table);

		// Scan the routing table
		for (i = 0;i < table->NumEntry;i++)
		{
			ROUTE_ENTRY *e = table->Entry[i];

			if (rs != NULL)
			{
				if (CmpIpAddr(&e->DestIP, &rs->DestIP) == 0 &&
					CmpIpAddr(&e->DestMask, &rs->DestMask) == 0
//					&& CmpIpAddr(&e->GatewayIP, &rs->GatewayIP) == 0
//					&& e->InterfaceID == rs->InterfaceID &&
//					e->LocalRouting == rs->LocalRouting &&
//					e->Metric == rs->Metric
					)
				{
					// Routing entry to the server that added at the time of connection is found
					route_to_server_erased = false;
				}
			}

			// Search for the default gateway
			if (IPToUINT(&e->DestIP) == 0 &&
				IPToUINT(&e->DestMask) == 0)
			{
				Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
					e->InterfaceID, t->VLanInterfaceId);

				if (e->InterfaceID == t->VLanInterfaceId)
				{
					// The virtual LAN card think that he want to be a default gateway
					is_vlan_want_to_be_default_gateway = true;
					vlan_default_gatewat_metric = e->Metric;

					if (vlan_default_gatewat_metric >= 2 &&
						t->OldDefaultGatewayMetric == (vlan_default_gatewat_metric - 1))
					{
						// Restore because the PPP server rewrites
						// the routing table selfishly
						DeleteRouteEntry(e);
						e->Metric--;
						AddRouteEntry(e);
						Debug("** Restore metric destroyed by PPP.\n");

						any_modified = true;
					}

					// Keep this entry
					if (t->DefaultGatewayByVLan != NULL)
					{
						// Delete if there is one added last time
						FreeRouteEntry(t->DefaultGatewayByVLan);
					}

					t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY));
					Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY));

					t->OldDefaultGatewayMetric = vlan_default_gatewat_metric;
				}
				else
				{
					// There are default gateway other than the virtual LAN card
					// Save the metric value of the default gateway
					if (other_if_default_gateway_metric_min > e->Metric)
					{
						// Ignore the metric value of all PPP connection in the case of Windows Vista
						if (MsIsVista() == false || e->PPPConnection == false)
						{
							other_if_default_gateway_metric_min = e->Metric;
						}
						else
						{
							// a PPP is used to Connect to the network
							// in using Windows Vista
							t->VistaAndUsingPPP = true;
						}
					}
				}
			}
		}

		if (t->VistaAndUsingPPP)
		{
			if (t->DefaultGatewayByVLan != NULL)
			{
				if (is_vlan_want_to_be_default_gateway)
				{
					if (t->VistaOldDefaultGatewayByVLan == NULL || Cmp(t->VistaOldDefaultGatewayByVLan, t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY)) != 0)
					{
						ROUTE_ENTRY *e;
						// Add the route of 0.0.0.0/1 and 128.0.0.0/1
						// to the system if the virtual LAN card should be
						// the default gateway in the case of the connection
						// using PPP in Windows Vista

						if (t->VistaOldDefaultGatewayByVLan != NULL)
						{
							FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
						}

						if (t->VistaDefaultGateway1 != NULL)
						{
							DeleteRouteEntry(t->VistaDefaultGateway1);
							FreeRouteEntry(t->VistaDefaultGateway1);

							DeleteRouteEntry(t->VistaDefaultGateway2);
							FreeRouteEntry(t->VistaDefaultGateway2);
						}

						t->VistaOldDefaultGatewayByVLan = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));

						e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
						SetIP(&e->DestIP, 0, 0, 0, 0);
						SetIP(&e->DestMask, 128, 0, 0, 0);
						t->VistaDefaultGateway1 = e;

						e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
						SetIP(&e->DestIP, 128, 0, 0, 0);
						SetIP(&e->DestMask, 128, 0, 0, 0);
						t->VistaDefaultGateway2 = e;

						AddRouteEntry(t->VistaDefaultGateway1);
						AddRouteEntry(t->VistaDefaultGateway2);

						Debug("Vista PPP Fix Route Table Added.\n");

						any_modified = true;
					}
				}
				else
				{
					if (t->VistaOldDefaultGatewayByVLan != NULL)
					{
						FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
						t->VistaOldDefaultGatewayByVLan = NULL;
					}

					if (t->VistaDefaultGateway1 != NULL)
					{
						Debug("Vista PPP Fix Route Table Deleted.\n");
						DeleteRouteEntry(t->VistaDefaultGateway1);
						FreeRouteEntry(t->VistaDefaultGateway1);

						DeleteRouteEntry(t->VistaDefaultGateway2);
						FreeRouteEntry(t->VistaDefaultGateway2);

						any_modified = true;

						t->VistaDefaultGateway1 = t->VistaDefaultGateway2 = NULL;
					}
				}
			}
		}

		// If the virtual LAN card want to be the default gateway and
		// there is no LAN card with smaller metric of 0.0.0.0/0 than
		// the virtual LAN card, delete other default gateway entries
		// to elect the virtual LAN card as the default gateway
//		Debug("is_vlan_want_to_be_default_gateway = %u, rs = %u, route_to_server_erased = %u, other_if_default_gateway_metric_min = %u, vlan_default_gatewat_metric = %u\n",
//			is_vlan_want_to_be_default_gateway, rs, route_to_server_erased, other_if_default_gateway_metric_min, vlan_default_gatewat_metric);
		if (is_vlan_want_to_be_default_gateway && (rs != NULL && route_to_server_erased == false) &&
			other_if_default_gateway_metric_min >= vlan_default_gatewat_metric)
		{
			// Scan the routing table again
			for (i = 0;i < table->NumEntry;i++)
			{
				ROUTE_ENTRY *e = table->Entry[i];

				if (e->InterfaceID != t->VLanInterfaceId)
				{
					if (IPToUINT(&e->DestIP) == 0 &&
					IPToUINT(&e->DestMask) == 0)
					{
						char str[64];
						// Default gateway is found
						ROUTE_ENTRY *r = ZeroMalloc(sizeof(ROUTE_ENTRY));

						Copy(r, e, sizeof(ROUTE_ENTRY));

						// Put in the queue
						InsertQueue(t->DeletedDefaultGateway, r);

						// Delete this gateway entry once
						DeleteRouteEntry(e);

						IPToStr(str, sizeof(str), &e->GatewayIP);
						Debug("Default Gateway %s Deleted.\n", str);

						any_modified = true;
					}
				}
			}
		}

		if (rs != NULL && route_to_server_erased)
		{
			// Physical entry to the server has disappeared
			Debug("Route to Server entry ERASED !!!\n");

			// Forced disconnection (reconnection enabled)
			s->RetryFlag = true;
			s->Halt = true;
		}

		// Release the routing table
		FreeRouteTable(table);
	}

	// Set the time to perform the next track
	if (t->NextTrackingTimeAdd == 0 || changed)
	{
		t->NextTrackingTimeAdd = TRACKING_INTERVAL_INITIAL;
	}
	else
	{
		UINT64 max_value = TRACKING_INTERVAL_MAX;
		if (t->RouteChange != NULL)
		{
			max_value = TRACKING_INTERVAL_MAX_RC;
		}

		t->NextTrackingTimeAdd += TRACKING_INTERVAL_ADD;

		if (t->NextTrackingTimeAdd >= max_value)
		{
			t->NextTrackingTimeAdd = max_value;
		}
	}
	//Debug("t->NextTrackingTimeAdd = %I64u\n", t->NextTrackingTimeAdd);
	t->NextTrackingTime = now + t->NextTrackingTimeAdd;

	if (any_modified)
	{
		// Clear the DNS cache
		Win32FlushDnsCache();
	}
}
Exemple #25
0
// Create a new UDP acceleration function
UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t)
{
	UDP_ACCEL *a;
	SOCK *s;
	UINT max_udp_size;
	bool is_in_cedar_port_list = false;

	if (IsZeroIP(ip))
	{
		ip = NULL;
	}

	if (client_mode || random_port)
	{
		// Use a appropriate vacant port number in the case of using random port or client mode
		s = NewUDPEx3(0, ip);
	}
	else
	{
		// Specify in the range in the case of server mode
		UINT i;
		s = NULL;

		LockList(cedar->UdpPortList);
		{
			for (i = UDP_SERVER_PORT_LOWER;i <= UDP_SERVER_PORT_HIGHER;i++)
			{
				if (IsIntInList(cedar->UdpPortList, i) == false)
				{
					s = NewUDPEx3(i, ip);

					if (s != NULL)
					{
						is_in_cedar_port_list = true;
						break;
					}
				}
			}

			if (s == NULL)
			{
				// Leave the port selection to the OS because the available port is not found within the range
				s = NewUDPEx3(0, ip);
			}

			if (s != NULL && is_in_cedar_port_list)
			{
				AddIntDistinct(cedar->UdpPortList, i);
			}
		}
		UnlockList(cedar->UdpPortList);
	}

	if (s == NULL)
	{
		return NULL;
	}

	a = ZeroMalloc(sizeof(UDP_ACCEL));

	a->Cedar = cedar;
	AddRef(a->Cedar->ref);

	a->NoNatT = no_nat_t;


	a->NatT_TranId = Rand64();

	a->CreatedTick = Tick64();

	a->IsInCedarPortList = is_in_cedar_port_list;

	a->ClientMode = client_mode;

	a->Now = Tick64();
	a->UdpSock = s;
	Rand(a->MyKey, sizeof(a->MyKey));
	Rand(a->YourKey, sizeof(a->YourKey));

	Copy(&a->MyIp, ip, sizeof(IP));
	a->MyPort = s->LocalPort;

	a->IsIPv6 = IsIP6(ip);

	if (a->IsIPv6)
	{
		a->NoNatT = true;
	}

	a->RecvBlockQueue = NewQueue();

	Rand(a->NextIv, sizeof(a->NextIv));

	do
	{
		a->MyCookie = Rand32();
	}
	while (a->MyCookie == 0);

	do
	{
		a->YourCookie = Rand32();
	}
	while (a->MyCookie == 0 || a->MyCookie == a->YourCookie);

	// Calculate the maximum transmittable UDP packet size
	max_udp_size = MTU_FOR_PPPOE;

	if (a->IsIPv6 == false)
	{
		// IPv4
		max_udp_size -= 20;
	}
	else
	{
		// IPv6
		max_udp_size -= 40;
	}

	// UDP
	max_udp_size -= 8;

	a->MaxUdpPacketSize = max_udp_size;

	Debug("Udp Accel My Port = %u\n", a->MyPort);

	// Initialize the NAT-T server IP address acquisition thread
	a->NatT_Lock = NewLock();
	a->NatT_HaltEvent = NewEvent();

	if (a->NoNatT == false)
	{
		a->NatT_GetIpThread = NewThread(NatT_GetIpThread, a);
	}

	return a;
}
// VPN Azure client main thread
void AcMainThread(THREAD *thread, void *param)
{
	AZURE_CLIENT *ac = (AZURE_CLIENT *)param;
	UINT last_ip_revision = INFINITE;
	UINT64 last_reconnect_tick = 0;
	UINT64 next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
	UINT num_reconnect_retry = 0;
	UINT64 next_ddns_retry_tick = 0;
	bool last_connect_ok = false;
	// Validate arguments
	if (ac == NULL || thread == NULL)
	{
		return;
	}

	while (ac->Halt == false)
	{
		UINT64 now = Tick64();
		bool connect_was_ok = false;
		// Wait for enabling VPN Azure function
		if (ac->IsEnabled)
		{
			// VPN Azure is enabled
			DDNS_CLIENT_STATUS st;
			bool connect_now = false;
			bool azure_ip_changed = false;

			Lock(ac->Lock);
			{
				Copy(&st, &ac->DDnsStatus, sizeof(DDNS_CLIENT_STATUS));

				if (StrCmpi(st.CurrentAzureIp, ac->DDnsStatusCopy.CurrentAzureIp) != 0)
				{
					if (IsEmptyStr(st.CurrentAzureIp) == false)
					{
						// Destination IP address is changed
						connect_now = true;
						num_reconnect_retry = 0;
					}
				}

				if (StrCmpi(st.CurrentHostName, ac->DDnsStatusCopy.CurrentHostName) != 0)
				{
					// DDNS host name is changed
					connect_now = true;
					num_reconnect_retry = 0;
				}

				Copy(&ac->DDnsStatusCopy, &st, sizeof(DDNS_CLIENT_STATUS));
			}
			Unlock(ac->Lock);

			if (last_ip_revision != ac->IpStatusRevision)
			{
				last_ip_revision = ac->IpStatusRevision;

				connect_now = true;

				num_reconnect_retry = 0;
			}

			if (last_reconnect_tick == 0 || (now >= (last_reconnect_tick + next_reconnect_interval)))
			{
				UINT r;

				last_reconnect_tick = now;
				num_reconnect_retry++;
				next_reconnect_interval = (UINT64)num_reconnect_retry * AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
				next_reconnect_interval = MIN(next_reconnect_interval, AZURE_CONNECT_MAX_RETRY_INTERVAL);

				r = (UINT)next_reconnect_interval;

				r = GenRandInterval(r / 2, r);

				next_reconnect_interval = r;

				connect_now = true;
			}

			if (IsEmptyStr(st.CurrentAzureIp) == false && IsEmptyStr(st.CurrentHostName) == false)
			{
				if (connect_now)
				{
					SOCK *s;
					char *host = NULL;
					UINT port = AZURE_SERVER_PORT;

					Debug("VPN Azure: Connecting to %s...\n", st.CurrentAzureIp);

					if (ParseHostPort(st.CurrentAzureIp, &host, &port, AZURE_SERVER_PORT))
					{
						if (st.InternetSetting.ProxyType == PROXY_DIRECT)
						{
							s = ConnectEx2(host, port, 0, (bool *)&ac->Halt);
						}
						else
						{
							s = WpcSockConnect2(host, port, &st.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT);
						}

						if (s != NULL)
						{
							PACK *p;
							UINT64 established_tick = 0;

							Debug("VPN Azure: Connected.\n");

							SetTimeout(s, AZURE_PROTOCOL_CONTROL_TIMEOUT_DEFAULT);

							Lock(ac->Lock);
							{
								ac->CurrentSock = s;
								ac->IsConnected = true;
								StrCpy(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp), st.CurrentAzureIp);
							}
							Unlock(ac->Lock);

							SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), false);

							// Receive parameter
							p = RecvPackWithHash(s);
							if (p != NULL)
							{
								UCHAR c;
								AZURE_PARAM param;
								bool hostname_changed = false;

								Zero(&param, sizeof(param));

								param.ControlKeepAlive = PackGetInt(p, "ControlKeepAlive");
								param.ControlTimeout = PackGetInt(p, "ControlTimeout");
								param.DataTimeout = PackGetInt(p, "DataTimeout");
								param.SslTimeout = PackGetInt(p, "SslTimeout");

								FreePack(p);

								param.ControlKeepAlive = MAKESURE(param.ControlKeepAlive, 1000, AZURE_SERVER_MAX_KEEPALIVE);
								param.ControlTimeout = MAKESURE(param.ControlTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);
								param.DataTimeout = MAKESURE(param.DataTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);
								param.SslTimeout = MAKESURE(param.SslTimeout, 1000, AZURE_SERVER_MAX_TIMEOUT);

								Lock(ac->Lock);
								{
									Copy(&ac->AzureParam, &param, sizeof(AZURE_PARAM));
								}
								Unlock(ac->Lock);

								SetTimeout(s, param.ControlTimeout);

								// Send parameter
								p = NewPack();
								PackAddStr(p, "CurrentHostName", st.CurrentHostName);
								PackAddStr(p, "CurrentAzureIp", st.CurrentAzureIp);
								PackAddInt64(p, "CurrentAzureTimestamp", st.CurrentAzureTimestamp);
								PackAddStr(p, "CurrentAzureSignature", st.CurrentAzureSignature);

								Lock(ac->Lock);
								{
									if (StrCmpi(st.CurrentHostName, ac->DDnsStatus.CurrentHostName) != 0)
									{
										hostname_changed = true;
									}
								}
								Unlock(ac->Lock);

								if (hostname_changed == false)
								{
									if (SendPackWithHash(s, p))
									{
										// Receive result
										if (RecvAll(s, &c, 1, false))
										{
											if (c && ac->Halt == false)
											{
												connect_was_ok = true;

												established_tick = Tick64();

												AcWaitForRequest(ac, s, &param);
											}
										}
									}
								}

								FreePack(p);
							}
							else
							{
								WHERE;
							}

							Debug("VPN Azure: Disconnected.\n");

							Lock(ac->Lock);
							{
								ac->IsConnected = false;
								ac->CurrentSock = NULL;
								ClearStr(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp));
							}
							Unlock(ac->Lock);

							if (established_tick != 0)
							{
								if ((established_tick + (UINT64)AZURE_CONNECT_MAX_RETRY_INTERVAL) <= Tick64())
								{
									// If the connected time exceeds the AZURE_CONNECT_MAX_RETRY_INTERVAL, reset the retry counter.
									last_reconnect_tick = 0;
									num_reconnect_retry = 0;
									next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
								}
							}

							Disconnect(s);
							ReleaseSock(s);
						}
						else
						{
							Debug("VPN Azure: Error: Connect Failed.\n");
						}

						Free(host);
					}
				}
			}
		}
		else
		{
			last_reconnect_tick = 0;
			num_reconnect_retry = 0;
			next_reconnect_interval = AZURE_CONNECT_INITIAL_RETRY_INTERVAL;
		}

		if (ac->Halt)
		{
			break;
		}

		if (connect_was_ok)
		{
			// If connection goes out after connected, increment connection success count to urge DDNS client query
			next_ddns_retry_tick = Tick64() + MIN((UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF * (UINT64)(num_reconnect_retry + 1), (UINT64)DDNS_VPN_AZURE_CONNECT_ERROR_DDNS_RETRY_TIME_DIFF_MAX);
		}

		if ((next_ddns_retry_tick != 0) && (Tick64() >= next_ddns_retry_tick))
		{
			next_ddns_retry_tick = 0;

			ac->DDnsTriggerInt++;
		}

		Wait(ac->Event, rand() % 1000);
	}
}
// Send multiple packets
void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
{
	UINT i, total_size;
	UCHAR *buf;
	UINT write_pointer;
	UINT err = 0;
	// Validate arguments
	if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
	{
		return;
	}
	if (e->HasFatalError)
	{
		return;
	}

	if (e->SuAdapter != NULL)
	{
		bool ok = true;

		// Send packets with SeLow
		for (i = 0;i < num;i++)
		{
			UCHAR *data = datas[i];
			UINT size = sizes[i];

			if (ok)
			{
				// Actually, only enqueuing
				ok = SuPutPacket(e->SuAdapter, data, size);
			}

			if (ok == false)
			{
				// Free memory on write error
				Free(data);
			}
		}

		if (ok)
		{
			// Send all data in queue at once
			ok = SuPutPacket(e->SuAdapter, NULL, 0);
		}

		if (ok == false)
		{
			// Error occurred
			e->HasFatalError = true;
		}

		return;
	}

	if (IsWin32BridgeWithSee() == false)
	{
		if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())
		{
			e->LastSetSingleCpu = Tick64();
			MsSetThreadSingleCpu();
		}
	}

	// Calculate buffer size
	total_size = 0;
	for (i = 0;i < num;i++)
	{
		void *data = datas[i];
		UINT size = sizes[i];
		if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
		{
			total_size += size + sizeof(struct dump_bpf_hdr);
		}
	}

	buf = MallocFast(total_size * 100 / 75 + 1600);

	write_pointer = 0;
	// Enqueue
	for (i = 0;i < num;i++)
	{
		void *data = datas[i];
		UINT size = sizes[i];
		if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
		{
			struct dump_bpf_hdr *h;

			h = (struct dump_bpf_hdr *)(buf + write_pointer);
			Zero(h, sizeof(struct dump_bpf_hdr));
			h->caplen = h->len = size;
			write_pointer += sizeof(struct dump_bpf_hdr);
			Copy(buf + write_pointer, data, size);
			write_pointer += size;

			PROBE_DATA2("EthPutPackets", data, size);
		}
		// Free original buffer
		Free(data);
	}

	// Send
	if (total_size != 0)
	{
		err = wp->PacketSendPackets(e->Adapter, buf, total_size, true);
	}

	Free(buf);

	if (err == 0x7FFFFFFF)
	{
		// Critical error (infinite loop) occurred on sending
		e->HasFatalError = true;
	}
}
Exemple #28
0
// Process the timer interrupt
void SstpProcessInterrupt(SSTP_SERVER *s)
{
	// Validate arguments
	if (s == NULL)
	{
		return;
	}

	s->Now = Tick64();

	s->FlushRecvTube = false;

	// Process the received packet
	while (true)
	{
		BLOCK *b = GetNext(s->RecvQueue);
		SSTP_PACKET *p;

		if (b == NULL)
		{
			break;
		}

		p = SstpParsePacket(b->Buf, b->Size);
		if (p == NULL)
		{
			// Disconnect the SSTP since a bad packet received
			SstpAbort(s);
		}
		else
		{
			// Process the received packet
			SstpProcessPacket(s, p);

			SstpFreePacket(p);
		}

		FreeBlock(b);
	}

	if (s->FlushRecvTube)
	{
		TubeFlush(s->TubeRecv);
	}

	// Transmit a packet that the PPP module is trying to send via the SSTP
	while (true)
	{
		TUBEDATA *d = TubeRecvAsync(s->TubeSend);
		SSTP_PACKET *p;
		if (d == NULL)
		{
			break;
		}

		p = SstpNewDataPacket(d->Data, d->DataSize);

		SstpSendPacket(s, p);

		SstpFreePacket(p);

		FreeTubeData(d);
	}

	if (s->Status == SSTP_SERVER_STATUS_ESTABLISHED)
	{
		if (s->Disconnecting == false && s->Aborting == false)
		{
			// Periodic transmission of Echo Request
			if (s->NextSendEchoRequestTick == 0 || s->NextSendEchoRequestTick <= s->Now)
			{
				UINT64 next_interval = (UINT64)(SSTP_ECHO_SEND_INTERVAL_MIN + Rand32() % (SSTP_ECHO_SEND_INTERVAL_MAX - SSTP_ECHO_SEND_INTERVAL_MIN));
				SSTP_PACKET *p;

				s->NextSendEchoRequestTick = s->Now + next_interval;
				AddInterrupt(s->Interrupt, s->NextSendEchoRequestTick);

				p = SstpNewControlPacket(SSTP_MSG_ECHO_REQUEST);

				SstpSendPacket(s, p);

				SstpFreePacket(p);
			}
		}
	}

	if ((s->LastRecvTick + (UINT64)SSTP_TIMEOUT) <= s->Now)
	{
		// Disconnect the SSTP because a timeout occurred
		SstpAbort(s);
		s->Disconnected = true;
	}

	if (IsTubeConnected(s->TubeRecv) == false || IsTubeConnected(s->TubeSend) == false)
	{
		// Disconnect the SSTP since the PPP module is disconnected
		SstpDisconnect(s);
	}

	if (s->Disconnecting)
	{
		// Normal disconnection process
		if (s->DisconnectSent == false)
		{
			// Send a Disconnect
			SSTP_PACKET *ret = SstpNewControlPacket(s->DisconnectRecved ? SSTP_MSG_CALL_DISCONNECT_ACK : SSTP_MSG_CALL_DISCONNECT);

			SstpSendPacket(s, ret);

			SstpFreePacket(ret);

			s->DisconnectSent = true;
		}
	}

	if (s->Aborting)
	{
		// Abnormal disconnection processing
		if (s->AbortSent == false)
		{
			// Send the Abort
			SSTP_PACKET *ret = SstpNewControlPacket(SSTP_MSG_CALL_ABORT);

			SstpSendPacket(s, ret);

			SstpFreePacket(ret);

			s->AbortSent = true;
		}
	}

	if (s->DisconnectSent && s->DisconnectRecved)
	{
		// Disconnect after exchanging the Disconnect each other
		s->Disconnected = true;
	}

	if (s->AbortSent && s->AbortReceived)
	{
		// Disconnect after exchanging the Abort each other
		s->Disconnected = true;
	}
}
Exemple #29
0
SU *SuInitEx(UINT wait_for_bind_complete_tick)
{
    void *h;
    SU *u;
    UINT read_size;
    bool flag = false;
    UINT64 giveup_tick = 0;
    static bool flag2 = false; // flag2 must be global

    if (SuIsSupportedOs(false) == false)
    {
        // Unsupported OS
        return NULL;
    }

LABEL_RETRY:

    // Open the device driver
    h = CreateFileA(SL_BASIC_DEVICE_FILENAME_WIN32, GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

    if (h == INVALID_HANDLE_VALUE)
    {
        Debug("CreateFileA(%s) Failed.\n", SL_BASIC_DEVICE_FILENAME_WIN32);

        // Start the service if it fails to start the device driver
        if (flag == false)
        {
            if (MsStartService(SL_PROTOCOL_NAME) == false)
            {
                Debug("MsStartService(%s) Failed.\n", SL_PROTOCOL_NAME);

                if (MsIsWindows10())
                {
                    if (flag2 == false)
                    {
                        flag2 = true;

                        if (SuInstallDriver(true))
                        {
                            goto LABEL_RETRY;
                        }
                    }
                }
            }
            else
            {
                Debug("MsStartService(%s) Ok.\n", SL_PROTOCOL_NAME);
                flag = true;

                goto LABEL_RETRY;
            }
        }
        return NULL;
    }

    //Debug("CreateFileA(%s) Ok.\n", SL_BASIC_DEVICE_FILENAME_WIN32);

    u = ZeroMalloc(sizeof(SU));

    giveup_tick = Tick64() + (UINT64)wait_for_bind_complete_tick;

    if (wait_for_bind_complete_tick == 0)
    {
        if (ReadFile(h, &u->AdapterInfoList, sizeof(u->AdapterInfoList), &read_size, NULL) == false ||
                u->AdapterInfoList.Signature != SL_SIGNATURE)
        {
            // Signature reception failure
            Debug("Bad Signature.\n");

            Free(u);
            CloseHandle(h);

            return NULL;
        }
    }
    else
    {
        while (giveup_tick >= Tick64())
        {
            // Wait until the enumeration is completed
            if (ReadFile(h, &u->AdapterInfoList, sizeof(u->AdapterInfoList), &read_size, NULL) == false ||
                    u->AdapterInfoList.Signature != SL_SIGNATURE)
            {
                // Signature reception failure
                Debug("Bad Signature.\n");

                Free(u);
                CloseHandle(h);

                return NULL;
            }

            if (u->AdapterInfoList.EnumCompleted)
            {
                // Complete enumeration
                Debug("Bind Completed! %u\n", u->AdapterInfoList.EnumCompleted);
                break;
            }

            // Incomplete enumeration
            Debug("Waiting for Bind Complete.\n");

            SleepThread(25);
        }
    }

    u->hFile = h;

    return u;
}
Exemple #30
0
// Read the string table
bool LoadTableMain(wchar_t *filename)
{
	BUF *b;
	UINT64 t1, t2;
	UCHAR hash[MD5_SIZE];
	// Validate arguments
	if (filename == NULL)
	{
		return false;
	}

	if (MayaquaIsMinimalMode())
	{
		return true;
	}

	if (UniStrCmpi(old_table_name, filename) == 0)
	{
		// Already loaded
		return true;
	}

	t1 = Tick64();

	// Open the file
	b = ReadDumpW(filename);
	if (b == NULL)
	{
		char tmp[MAX_SIZE];
		StrCpy(tmp, sizeof(tmp), "Error: Can't read string tables (file not found).\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)");
		Alert(tmp, NULL);
		exit(-1);
		return false;
	}

	Hash(hash, b->Buf, b->Size, false);

	if (LoadUnicodeCache(filename, b->Size, hash) == false)
	{
		if (LoadTableFromBuf(b) == false)
		{
			FreeBuf(b);
			return false;
		}

		SaveUnicodeCache(filename, b->Size, hash);

		//Debug("Unicode Source: strtable.stb\n");
	}
	else
	{
		//Debug("Unicode Source: unicode_cache\n");
	}

	FreeBuf(b);

	SetLocale(_UU("DEFAULE_LOCALE"));

	UniStrCpy(old_table_name, sizeof(old_table_name), filename);

	t2 = Tick64();

	if (StrCmpi(_SS("STRTABLE_ID"), STRTABLE_ID) != 0)
	{
		char tmp[MAX_SIZE];
		Format(tmp, sizeof(tmp), "Error: Can't read string tables (invalid version: '%s'!='%s').\r\nPlease check hamcore.se2.\r\n\r\n(First, reboot the computer. If this problem occurs again, please reinstall VPN software files.)",
			_SS("STRTABLE_ID"), STRTABLE_ID);
		Alert(tmp, NULL);
		exit(-1);
		return false;
	}

	//Debug("Unicode File Read Cost: %u (%u Lines)\n", (UINT)(t2 - t1), LIST_NUM(TableList));

	return true;
}