Bläddra i källkod

v4.10-9505-beta

dnobori 11 år sedan
förälder
incheckning
10d4b2c43d
100 ändrade filer med 2387 tillägg och 648 borttagningar
  1. 1 0
      src/BuildFiles/Manifests/x64_admin.manifest
  2. 1 0
      src/BuildFiles/Manifests/x64_user.manifest
  3. 1 0
      src/BuildFiles/Manifests/x86_admin.manifest
  4. 1 0
      src/BuildFiles/Manifests/x86_user.manifest
  5. 6 1
      src/Cedar/Account.c
  6. 18 14
      src/Cedar/Admin.c
  7. 165 6
      src/Cedar/BridgeUnix.c
  8. 1 0
      src/Cedar/BridgeUnix.h
  9. 137 0
      src/Cedar/Cedar.c
  10. 59 26
      src/Cedar/Cedar.h
  11. 22 9
      src/Cedar/Command.c
  12. 332 147
      src/Cedar/Connection.c
  13. 9 2
      src/Cedar/Connection.h
  14. 1 1
      src/Cedar/DDNS.c
  15. 4 4
      src/Cedar/DDNS.h
  16. 167 121
      src/Cedar/Hub.c
  17. 12 3
      src/Cedar/Hub.h
  18. 2 1
      src/Cedar/Interop_SSTP.c
  19. 111 8
      src/Cedar/Link.c
  20. 6 0
      src/Cedar/Link.h
  21. 104 9
      src/Cedar/Logging.c
  22. 5 2
      src/Cedar/Logging.h
  23. 1 1
      src/Cedar/NM.c
  24. 53 2
      src/Cedar/NullLan.c
  25. 2 0
      src/Cedar/NullLan.h
  26. 7 1
      src/Cedar/Protocol.c
  27. 14 7
      src/Cedar/SM.c
  28. 1 1
      src/Cedar/SW.c
  29. 32 13
      src/Cedar/SeLowUser.c
  30. 1 1
      src/Cedar/SeLowUser.h
  31. 199 14
      src/Cedar/Server.c
  32. 36 0
      src/Cedar/Server.h
  33. 164 35
      src/Cedar/Session.c
  34. 18 0
      src/Cedar/WinUi.c
  35. 2 0
      src/Cedar/WinUi.h
  36. 2 2
      src/CurrentBuild.txt
  37. 39 1
      src/Mayaqua/Cfg.c
  38. 2 0
      src/Mayaqua/Cfg.h
  39. 116 1
      src/Mayaqua/Encrypt.c
  40. 77 0
      src/Mayaqua/Internat.c
  41. 1 0
      src/Mayaqua/Internat.h
  42. 27 0
      src/Mayaqua/Kernel.c
  43. 1 0
      src/Mayaqua/Kernel.h
  44. 4 2
      src/Mayaqua/MayaType.h
  45. 7 0
      src/Mayaqua/Mayaqua.h
  46. 110 47
      src/Mayaqua/Memory.c
  47. 12 7
      src/Mayaqua/Memory.h
  48. 29 0
      src/Mayaqua/Microsoft.c
  49. 1 0
      src/Mayaqua/Microsoft.h
  50. 47 20
      src/Mayaqua/Network.c
  51. 3 2
      src/Mayaqua/Network.h
  52. 8 4
      src/Mayaqua/OS.c
  53. 1 1
      src/Mayaqua/TcpIp.c
  54. 63 12
      src/Mayaqua/Unix.c
  55. 5 1
      src/Mayaqua/Unix.h
  56. 17 4
      src/Mayaqua/Win32.c
  57. 1 1
      src/PenCore/PenCore.rc
  58. 78 49
      src/SeLow/SeLow.c
  59. 1 2
      src/SeLow/SeLow.h
  60. 3 2
      src/SeLow/SeLowCommon.h
  61. BIN
      src/bin/hamcore/SeLow_x64.sys
  62. BIN
      src/bin/hamcore/SeLow_x86.sys
  63. 0 24
      src/bin/hamcore/chain_certs.txt
  64. 2 2
      src/bin/hamcore/inf/selow_x64/SeLow_x64.inf
  65. BIN
      src/bin/hamcore/inf/selow_x64/inf.cat
  66. 2 2
      src/bin/hamcore/inf/selow_x86/SeLow_x86.inf
  67. BIN
      src/bin/hamcore/inf/selow_x86/inf.cat
  68. 1 1
      src/bin/hamcore/inf/x64/INF_VPN.inf
  69. 1 1
      src/bin/hamcore/inf/x64/INF_VPN10.inf
  70. 1 1
      src/bin/hamcore/inf/x64/INF_VPN100.inf
  71. 1 1
      src/bin/hamcore/inf/x64/INF_VPN101.inf
  72. 1 1
      src/bin/hamcore/inf/x64/INF_VPN102.inf
  73. 1 1
      src/bin/hamcore/inf/x64/INF_VPN103.inf
  74. 1 1
      src/bin/hamcore/inf/x64/INF_VPN104.inf
  75. 1 1
      src/bin/hamcore/inf/x64/INF_VPN105.inf
  76. 1 1
      src/bin/hamcore/inf/x64/INF_VPN106.inf
  77. 1 1
      src/bin/hamcore/inf/x64/INF_VPN107.inf
  78. 1 1
      src/bin/hamcore/inf/x64/INF_VPN108.inf
  79. 1 1
      src/bin/hamcore/inf/x64/INF_VPN109.inf
  80. 1 1
      src/bin/hamcore/inf/x64/INF_VPN11.inf
  81. 1 1
      src/bin/hamcore/inf/x64/INF_VPN110.inf
  82. 1 1
      src/bin/hamcore/inf/x64/INF_VPN111.inf
  83. 1 1
      src/bin/hamcore/inf/x64/INF_VPN112.inf
  84. 1 1
      src/bin/hamcore/inf/x64/INF_VPN113.inf
  85. 1 1
      src/bin/hamcore/inf/x64/INF_VPN114.inf
  86. 1 1
      src/bin/hamcore/inf/x64/INF_VPN115.inf
  87. 1 1
      src/bin/hamcore/inf/x64/INF_VPN116.inf
  88. 1 1
      src/bin/hamcore/inf/x64/INF_VPN117.inf
  89. 1 1
      src/bin/hamcore/inf/x64/INF_VPN118.inf
  90. 1 1
      src/bin/hamcore/inf/x64/INF_VPN119.inf
  91. 1 1
      src/bin/hamcore/inf/x64/INF_VPN12.inf
  92. 1 1
      src/bin/hamcore/inf/x64/INF_VPN120.inf
  93. 1 1
      src/bin/hamcore/inf/x64/INF_VPN121.inf
  94. 1 1
      src/bin/hamcore/inf/x64/INF_VPN122.inf
  95. 1 1
      src/bin/hamcore/inf/x64/INF_VPN123.inf
  96. 1 1
      src/bin/hamcore/inf/x64/INF_VPN124.inf
  97. 1 1
      src/bin/hamcore/inf/x64/INF_VPN125.inf
  98. 1 1
      src/bin/hamcore/inf/x64/INF_VPN126.inf
  99. 1 1
      src/bin/hamcore/inf/x64/INF_VPN127.inf
  100. 1 1
      src/bin/hamcore/inf/x64/INF_VPN13.inf

+ 1 - 0
src/BuildFiles/Manifests/x64_admin.manifest

@@ -18,6 +18,7 @@
   		<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
   		<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
   		<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+  		<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
   	</application>
   </compatibility>
   <asmv3:application>

+ 1 - 0
src/BuildFiles/Manifests/x64_user.manifest

@@ -18,6 +18,7 @@
   		<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
   		<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
   		<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+  		<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
   	</application>
   </compatibility>
   <asmv3:application>

+ 1 - 0
src/BuildFiles/Manifests/x86_admin.manifest

@@ -18,6 +18,7 @@
   		<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
   		<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
   		<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+  		<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
   	</application>
   </compatibility>
   <asmv3:application>

+ 1 - 0
src/BuildFiles/Manifests/x86_user.manifest

@@ -18,6 +18,7 @@
   		<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
   		<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
   		<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
+  		<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
   	</application>
   </compatibility>
   <asmv3:application>

+ 6 - 1
src/Cedar/Account.c

@@ -257,7 +257,7 @@ POLICY_ITEM *GetPolicyItem(UINT id)
 // Does cascade connection support the specified policy?
 bool PolicyIsSupportedForCascade(UINT i)
 {
-	if (i == 0 || i == 4 || i == 5 || i == 9 || i == 12 || i == 13 ||
+	if (i == 0 || i == 4 || i == 5 || i == 12 || i == 13 ||
 		i == 14 || i == 19 || i == 20 || i == 21 || i == 26 || i == 30 || i == 31 || i == 36)
 	{
 		// These items are not supported by cascade connection.
@@ -375,6 +375,11 @@ bool IsUserName(char *name)
 		return false;
 	}
 
+	if (StrCmpi(name, "link") == 0)
+	{
+		return false;
+	}
+
 	if (StrCmpi(name, LINK_USER_NAME) == 0)
 	{
 		return false;

+ 18 - 14
src/Cedar/Admin.c

@@ -3972,20 +3972,20 @@ UINT StDeleteMacTable(ADMIN *a, RPC_DELETE_TABLE *t)
 		return ERR_NOT_ENOUGH_RIGHT;
 	}
 
-	LockList(h->MacTable);
+	LockHashList(h->MacHashTable);
 	{
-		if (IsInListKey(h->MacTable, t->Key))
+		if (IsInHashListKey(h->MacHashTable, t->Key))
 		{
-			MAC_TABLE_ENTRY *e = ListKeyToPointer(h->MacTable, t->Key);
+			MAC_TABLE_ENTRY *e = HashListKeyToPointer(h->MacHashTable, t->Key);
+			DeleteHash(h->MacHashTable, e);
 			Free(e);
-			Delete(h->MacTable, e);
 		}
 		else
 		{
 			ret = ERR_OBJECT_NOT_FOUND;
 		}
 	}
-	UnlockList(h->MacTable);
+	UnlockHashList(h->MacHashTable);
 
 	if (ret == ERR_OBJECT_NOT_FOUND)
 	{
@@ -4040,15 +4040,15 @@ UINT SiEnumMacTable(SERVER *s, char *hubname, RPC_ENUM_MAC_TABLE *t)
 
 	StrCpy(t->HubName, sizeof(t->HubName), hubname);
 
-	LockList(h->MacTable);
+	LockHashList(h->MacHashTable);
 	{
-		t->NumMacTable = LIST_NUM(h->MacTable);
+		MAC_TABLE_ENTRY **pp = (MAC_TABLE_ENTRY **)HashListToArray(h->MacHashTable, &t->NumMacTable);
 		t->MacTables = ZeroMalloc(sizeof(RPC_ENUM_MAC_TABLE_ITEM) * t->NumMacTable);
 
 		for (i = 0;i < t->NumMacTable;i++)
 		{
 			RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];
-			MAC_TABLE_ENTRY *mac = LIST_DATA(h->MacTable, i);
+			MAC_TABLE_ENTRY *mac = pp[i];
 
 			e->Key = POINTER_TO_KEY(mac);
 			StrCpy(e->SessionName, sizeof(e->SessionName), mac->Session->Name);
@@ -4059,8 +4059,10 @@ UINT SiEnumMacTable(SERVER *s, char *hubname, RPC_ENUM_MAC_TABLE *t)
 
 			GetMachineName(e->RemoteHostname, sizeof(e->RemoteHostname));
 		}
+
+		Free(pp);
 	}
-	UnlockList(h->MacTable);
+	UnlockHashList(h->MacHashTable);
 
 	ReleaseHub(h);
 
@@ -5863,6 +5865,8 @@ UINT StDeleteLink(ADMIN *a, RPC_LINK *t)
 		return ERR_OBJECT_NOT_FOUND;
 	}
 
+	k->NoOnline = true;
+
 	ALog(a, h, "LA_DELETE_LINK", t->AccountName);
 
 	SetLinkOffline(k);
@@ -6880,7 +6884,7 @@ UINT StGetHubStatus(ADMIN *a, RPC_HUB_STATUS *t)
 			t->NumGroups = LIST_NUM(h->HubDb->GroupList);
 		}
 
-		t->NumMacTables = LIST_NUM(h->MacTable);
+		t->NumMacTables = HASH_LIST_NUM(h->MacHashTable);
 		t->NumIpTables = LIST_NUM(h->IpTable);
 
 		Lock(h->TrafficLock);
@@ -7863,11 +7867,11 @@ UINT StEnumHub(ADMIN *a, RPC_ENUM_HUB *t)
 
 				e->NumSessions = LIST_NUM(h->SessionList);
 
-				LockList(h->MacTable);
+				LockHashList(h->MacHashTable);
 				{
-					e->NumMacTables = LIST_NUM(h->MacTable);
+					e->NumMacTables = HASH_LIST_NUM(h->MacHashTable);
 				}
-				UnlockList(h->MacTable);
+				UnlockHashList(h->MacHashTable);
 
 				LockList(h->IpTable);
 				{
@@ -8876,7 +8880,7 @@ UINT StGetServerStatus(ADMIN *a, RPC_SERVER_STATUS *t)
 				}
 			}
 
-			t->NumMacTables += LIST_NUM(h->MacTable);
+			t->NumMacTables += HASH_LIST_NUM(h->MacHashTable);
 			t->NumIpTables += LIST_NUM(h->IpTable);
 
 			if (h->HubDb != NULL)

+ 165 - 6
src/Cedar/BridgeUnix.c

@@ -143,6 +143,22 @@
 #include <ifaddrs.h>
 #endif // BRIDGE_BPF
 
+#ifdef	UNIX_LINUX
+struct my_tpacket_auxdata
+{
+	UINT tp_status;
+	UINT tp_len;
+	UINT tp_snaplen;
+	USHORT tp_mac;
+	USHORT tp_net;
+	USHORT tp_vlan_tci;
+	USHORT tp_vlan_tpid;
+};
+#define MY_TP_STATUS_VLAN_VALID (1 << 4)
+#define MY_TP_STATUS_VLAN_TPID_VALID (1 << 6)
+#define	MY_PACKET_AUXDATA 8
+#endif	// UNIX_LINUX
+
 // Initialize
 void InitEth()
 {
@@ -543,6 +559,7 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
 	struct sockaddr_ll addr;
 	int s;
 	int index;
+	bool aux_ok = false;
 	CANCEL *c;
 	// Validate arguments
 	if (name == NULL)
@@ -624,12 +641,30 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
 		}
 	}
 
+	if (true)
+	{
+		int val = 1;
+		int ss_ret = setsockopt(s, SOL_PACKET, MY_PACKET_AUXDATA, &val, sizeof(val));
+
+		if (ss_ret < 0)
+		{
+			Debug("eth(%s): setsockopt: PACKET_AUXDATA failed.\n", name);
+		}
+		else
+		{
+			Debug("eth(%s): setsockopt: PACKET_AUXDATA ok.\n", name);
+			aux_ok = true;
+		}
+	}
+
 	e = ZeroMalloc(sizeof(ETH));
 	e->Name = CopyStr(name);
 	e->Title = CopyStr(name);
 	e->IfIndex = index;
 	e->Socket = s;
 
+	e->Linux_IsAuxDataSupported = aux_ok;
+
 	c = NewCancel();
 	UnixDeletePipe(c->pipe_read, c->pipe_write);
 	c->pipe_read = c->pipe_write = -1;
@@ -646,8 +681,11 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
 
 	if (tapmode == false)
 	{
-		// Disable hardware offloading
-		UnixDisableInterfaceOffload(name);
+		if (GetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD) == false)
+		{
+			// Disable hardware offloading
+			UnixDisableInterfaceOffload(name);
+		}
 	}
 
 	return e;
@@ -1566,10 +1604,19 @@ UINT EthGetPacket(ETH *e, void **data)
 }
 
 #ifdef	UNIX_LINUX
+
 UINT EthGetPacketLinux(ETH *e, void **data)
 {
 	int s, ret;
 	UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
+	struct iovec msg_iov;
+	struct msghdr msg_header;
+	struct cmsghdr *cmsg;
+	union
+	{
+		struct cmsghdr cmsg;
+		char buf[CMSG_SPACE(sizeof(struct my_tpacket_auxdata))];
+	} cmsg_buf;
 	// Validate arguments
 	if (e == NULL || data == NULL)
 	{
@@ -1603,7 +1650,28 @@ UINT EthGetPacketLinux(ETH *e, void **data)
 	}
 
 	// Read
-	ret = read(s, tmp, sizeof(tmp));
+	msg_iov.iov_base = tmp;
+	msg_iov.iov_len = sizeof(tmp);
+
+	msg_header.msg_name = NULL;
+	msg_header.msg_namelen = 0;
+	msg_header.msg_iov = &msg_iov;
+	msg_header.msg_iovlen = 1;
+	if (e->Linux_IsAuxDataSupported)
+	{
+		memset(&cmsg_buf, 0, sizeof(cmsg_buf));
+
+		msg_header.msg_control = &cmsg_buf;
+		msg_header.msg_controllen = sizeof(cmsg_buf);
+	}
+	else
+	{
+		msg_header.msg_control = NULL;
+		msg_header.msg_controllen = 0;
+	}
+	msg_header.msg_flags = 0;
+
+	ret = recvmsg(s, &msg_header, 0);
 	if (ret == 0 || (ret == -1 && errno == EAGAIN))
 	{
 		// No packet
@@ -1619,9 +1687,75 @@ UINT EthGetPacketLinux(ETH *e, void **data)
 	}
 	else
 	{
-		// Success to read a packet
-		*data = MallocFast(ret);
-		Copy(*data, tmp, ret);
+		bool flag = false;
+		USHORT api_vlan_id = 0;
+		USHORT api_vlan_tpid = 0;
+
+		if (e->Linux_IsAuxDataSupported)
+		{
+			for (cmsg = CMSG_FIRSTHDR(&msg_header); cmsg; cmsg = CMSG_NXTHDR(&msg_header, cmsg))
+			{
+				struct my_tpacket_auxdata *aux;
+				UINT len;
+				USHORT vlan_tpid = 0x8100;
+				USHORT vlan_id = 0;
+
+				if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct my_tpacket_auxdata)) ||
+					cmsg->cmsg_level != SOL_PACKET ||
+					cmsg->cmsg_type != MY_PACKET_AUXDATA)
+				{
+					continue;
+				}
+
+				aux = (struct my_tpacket_auxdata *)CMSG_DATA(cmsg);
+
+				if (aux != NULL)
+				{
+					if (aux->tp_vlan_tci != 0)
+					{
+						vlan_id = aux->tp_vlan_tci;
+					}
+				}
+
+				if (vlan_id != 0)
+				{
+					api_vlan_id = vlan_id;
+					api_vlan_tpid = vlan_tpid;
+					break;
+				}
+			}
+
+			if (api_vlan_id != 0 && api_vlan_tpid != 0)
+			{
+				// VLAN ID has been received with PACKET_AUXDATA.
+				// Insert the tag.
+				USHORT vlan_id_ne = Endian16(api_vlan_id);
+				USHORT vlan_tpid_ne = Endian16(api_vlan_tpid);
+
+				if (ret >= 14)
+				{
+					if (*((USHORT *)(tmp + 12)) != vlan_tpid_ne)
+					{
+						*data = MallocFast(ret + 4);
+						Copy(*data, tmp, 12);
+						Copy(((UCHAR *)*data) + 12, &vlan_tpid_ne, 2);
+						Copy(((UCHAR *)*data) + 14, &vlan_id_ne, 2);
+						Copy(((UCHAR *)*data) + 16, tmp + 12, ret - 12);
+
+						flag = true;
+
+						ret += 4;
+					}
+				}
+			}
+		}
+
+		// Success to read a packet (No VLAN)
+		if (flag == false)
+		{
+			*data = MallocFast(ret);
+			Copy(*data, tmp, ret);
+		}
 		return ret;
 	}
 
@@ -1824,11 +1958,36 @@ void EthPutPacket(ETH *e, void *data, UINT size)
 		Debug("EthPutPacket: ret:%d size:%d\n", ret, size);
 	}
 #else // BRIDGE_PCAP
+#ifndef	UNIX_LINUX
 	ret = write(s, data, size);
 	if (ret<0)
 	{
 		Debug("EthPutPacket: ret:%d errno:%d  size:%d\n", ret, errno, size);
 	}
+#else	// UNIX_LINUX
+	{
+		struct iovec msg_iov;
+		struct msghdr msg_header;
+
+		msg_iov.iov_base = data;
+		msg_iov.iov_len = size;
+
+		msg_header.msg_name = NULL;
+		msg_header.msg_namelen = 0;
+		msg_header.msg_iov = &msg_iov;
+		msg_header.msg_iovlen = 1;
+		msg_header.msg_control = NULL;
+		msg_header.msg_controllen = 0;
+		msg_header.msg_flags = 0;
+
+		ret = sendmsg(s, &msg_header, 0);
+
+		if (ret<0)
+		{
+			Debug("EthPutPacket: ret:%d errno:%d  size:%d\n", ret, errno, size);
+		}
+	}
+#endif	// UNIX_LINUX
 #endif //BRIDGE_PCAP
 	
 	Free(data);

+ 1 - 0
src/Cedar/BridgeUnix.h

@@ -161,6 +161,7 @@ struct ETH
 #endif // BRIDGE_BPF
 
 	VLAN *Tap;					// tap
+	bool Linux_IsAuxDataSupported;	// Is PACKET_AUXDATA supported
 };
 
 #if defined( BRIDGE_BPF ) || defined( BRIDGE_PCAP )

+ 137 - 0
src/Cedar/Cedar.c

@@ -235,6 +235,19 @@ bool IsSupportedWinVer(RPC_WINVER *v)
 		}
 	}
 
+#if	0
+	// Enable in future when supported
+	if (v->VerMajor == 6 && v->VerMinor == 4)
+	{
+		// Windows 10, Server 10
+		if (v->ServicePack <= 0)
+		{
+			// SP0 only
+			return true;
+		}
+	}
+#endif
+
 	return false;
 }
 
@@ -1149,6 +1162,118 @@ void StopAllListener(CEDAR *c)
 	Free(array);
 }
 
+// Budget management functions
+void CedarAddQueueBudget(CEDAR *c, int diff)
+{
+	// Validate arguments
+	if (c == NULL || diff == 0)
+	{
+		return;
+	}
+
+	Lock(c->QueueBudgetLock);
+	{
+		int v = (int)c->QueueBudget;
+		v += diff;
+		c->QueueBudget = (UINT)v;
+	}
+	Unlock(c->QueueBudgetLock);
+}
+void CedarAddFifoBudget(CEDAR *c, int diff)
+{
+	// Validate arguments
+	if (c == NULL || diff == 0)
+	{
+		return;
+	}
+
+	Lock(c->FifoBudgetLock);
+	{
+		int v = (int)c->FifoBudget;
+		v += diff;
+		c->FifoBudget = (UINT)v;
+	}
+	Unlock(c->FifoBudgetLock);
+}
+UINT CedarGetQueueBudgetConsuming(CEDAR *c)
+{
+	// Validate arguments
+	if (c == NULL)
+	{
+		return 0;
+	}
+
+	return c->QueueBudget;
+}
+UINT CedarGetFifoBudgetConsuming(CEDAR *c)
+{
+	// Validate arguments
+	if (c == NULL)
+	{
+		return 0;
+	}
+
+	return c->FifoBudget;
+}
+UINT CedarGetQueueBudgetBalance(CEDAR *c)
+{
+	UINT current = CedarGetQueueBudgetConsuming(c);
+	UINT budget = QUEUE_BUDGET;
+
+	if (current <= budget)
+	{
+		return budget - current;
+	}
+	else
+	{
+		return 0;
+	}
+}
+UINT CedarGetFifoBudgetBalance(CEDAR *c)
+{
+	UINT current = CedarGetFifoBudgetConsuming(c);
+	UINT budget = FIFO_BUDGET;
+
+	if (current <= budget)
+	{
+		return budget - current;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+// Add the current TCP queue size
+void CedarAddCurrentTcpQueueSize(CEDAR *c, int diff)
+{
+	// Validate arguments
+	if (c == NULL || diff == 0)
+	{
+		return;
+	}
+
+	Lock(c->CurrentTcpQueueSizeLock);
+	{
+		int v = (int)c->CurrentTcpQueueSize;
+		v += diff;
+		c->CurrentTcpQueueSize = (UINT)v;
+	}
+	Unlock(c->CurrentTcpQueueSizeLock);
+}
+
+// Get the current TCP queue size
+UINT CedarGetCurrentTcpQueueSize(CEDAR *c)
+{
+	// Validate arguments
+	if (c == NULL)
+	{
+		return 0;
+	}
+
+	return c->CurrentTcpQueueSize;
+}
+
 // Stop Cedar
 void StopCedar(CEDAR *c)
 {
@@ -1269,6 +1394,12 @@ void CleanupCedar(CEDAR *c)
 
 	DeleteLock(c->CurrentRegionLock);
 
+	DeleteLock(c->CurrentTcpQueueSizeLock);
+	DeleteLock(c->QueueBudgetLock);
+	DeleteLock(c->FifoBudgetLock);
+
+	DeleteCounter(c->CurrentActiveLinks);
+
 	Free(c);
 }
 
@@ -1524,6 +1655,8 @@ CEDAR *NewCedar(X *server_x, K *server_k)
 
 	c = ZeroMalloc(sizeof(CEDAR));
 
+	c->CurrentActiveLinks = NewCounter();
+
 	c->AcceptingSockets = NewCounter();
 
 	c->CedarSuperLock = NewLock();
@@ -1539,6 +1672,10 @@ CEDAR *NewCedar(X *server_x, K *server_k)
 	c->AssignedBridgeLicense = NewCounter();
 	c->AssignedClientLicense = NewCounter();
 
+	c->CurrentTcpQueueSizeLock = NewLock();
+	c->QueueBudgetLock = NewLock();
+	c->FifoBudgetLock = NewLock();
+
 	Rand(c->UniqueId, sizeof(c->UniqueId));
 
 	c->CreatedTick = Tick64();

+ 59 - 26
src/Cedar/Cedar.h

@@ -138,7 +138,7 @@
 #define	CEDAR_VER					410
 
 // Build Number
-#define	CEDAR_BUILD					9473
+#define	CEDAR_BUILD					9505
 
 // Beta number
 //#define	BETA_NUMBER					3
@@ -153,16 +153,16 @@
 
 // Specify the location to build
 #ifndef	BUILD_PLACE
-#define	BUILD_PLACE			"pc26"
+#define	BUILD_PLACE			"pc25"
 #endif	// BUILD_PLACE
 
 // Specifies the build date
 #define	BUILD_DATE_Y		2014
-#define	BUILD_DATE_M		7
-#define	BUILD_DATE_D		12
-#define	BUILD_DATE_HO		2
-#define	BUILD_DATE_MI		14
-#define	BUILD_DATE_SE		33
+#define	BUILD_DATE_M		10
+#define	BUILD_DATE_D		3
+#define	BUILD_DATE_HO		17
+#define	BUILD_DATE_MI		55
+#define	BUILD_DATE_SE		4
 
 // Tolerable time difference
 #define	ALLOW_TIMESTAMP_DIFF		(UINT64)(3 * 24 * 60 * 60 * 1000)
@@ -224,27 +224,45 @@
 #define	MAX_ACCESSLISTS				(4096 * 8)	// Maximum number of access list entries
 #define	MAX_USERS					10000	// The maximum number of users
 #define	MAX_GROUPS					10000	// Maximum number of groups
-#define	MAX_MAC_TABLES				65536	// Maximum number of MAC address table entries
-#define	MAX_IP_TABLES				65536	// Maximum number of IP address table entries
+#define	MAX_MAC_TABLES				VPN_GP(GP_MAX_MAC_TABLES, 65536)	// Maximum number of MAC address table entries
+#define	MAX_IP_TABLES				VPN_GP(GP_MAX_IP_TABLES, 65536)	// Maximum number of IP address table entries
 #define	MAX_HUB_CERTS				4096	// Maximum number of Root CA that can be registered
 #define	MAX_HUB_CRLS				4096	// Maximum number of CRL that can be registered
 #define	MAX_HUB_ACS					4096	// Maximum number of AC that can be registered
-#define	MAX_HUB_LINKS				128		// Maximum number of Cascade that can be registered
+#define	MAX_HUB_LINKS				VPN_GP(GP_MAX_HUB_LINKS, 1024)	// Maximum number of Cascade that can be registered
 #define	MAX_HUB_ADMIN_OPTIONS		4096	// Maximum number of Virtual HUB management options that can be registered
 
+#ifndef	USE_STRATEGY_LOW_MEMORY
+#define	MEM_FIFO_REALLOC_MEM_SIZE	VPN_GP(GP_MEM_FIFO_REALLOC_MEM_SIZE, (65536 * 10))
+#define	QUEUE_BUDGET				VPN_GP(GP_QUEUE_BUDGET, 2048)
+#define	FIFO_BUDGET					VPN_GP(GP_FIFO_BUDGET, 1600 * 1600 * 4)
+#else	// USE_STRATEGY_LOW_MEMORY
+#define	MEM_FIFO_REALLOC_MEM_SIZE	VPN_GP(GP_MEM_FIFO_REALLOC_MEM_SIZE, (65536))
+#define	QUEUE_BUDGET				VPN_GP(GP_QUEUE_BUDGET, 1024)
+#define	FIFO_BUDGET					VPN_GP(GP_FIFO_BUDGET, 1000000)
+#endif	// USE_STRATEGY_LOW_MEMORY
+
 #define	MAX_PACKET_SIZE				1560	// Maximum packet size
 #define	UDP_BUF_SIZE				(32 * 1024) // Aim of the UDP packet size
 
-#define	MAX_SEND_SOCKET_QUEUE_SIZE	(1600 * 1600 * 1)	// Maximum transmit queue size
-#define	MIN_SEND_SOCKET_QUEUE_SIZE	(1600 * 200 * 1)
-#define	MAX_SEND_SOCKET_QUEUE_NUM	128		// Maximum transmission queue items
+#ifndef	USE_STRATEGY_LOW_MEMORY
+#define	MAX_SEND_SOCKET_QUEUE_SIZE	VPN_GP(GP_MAX_SEND_SOCKET_QUEUE_SIZE, (1600 * 1600 * 1))	// Maximum transmit queue size
+#define	MIN_SEND_SOCKET_QUEUE_SIZE	VPN_GP(GP_MIN_SEND_SOCKET_QUEUE_SIZE, (1600 * 200 * 1))	// Minimum transmit queue size
+#define	MAX_STORED_QUEUE_NUM		VPN_GP(GP_MAX_STORED_QUEUE_NUM, 1024)		// The number of queues that can be stored in each session
+#define	MAX_BUFFERING_PACKET_SIZE	VPN_GP(GP_MAX_BUFFERING_PACKET_SIZE, (1600 * 1600))	// Maximum packet size can be buffered
+#else	// USE_STRATEGY_LOW_MEMORY
+#define	MAX_SEND_SOCKET_QUEUE_SIZE	VPN_GP(GP_MAX_SEND_SOCKET_QUEUE_SIZE, (1600 * 200 * 1))	// Maximum transmit queue size
+#define	MIN_SEND_SOCKET_QUEUE_SIZE	VPN_GP(GP_MIN_SEND_SOCKET_QUEUE_SIZE, (1600 * 50 * 1))	// Minimum transmit queue size
+#define	MAX_STORED_QUEUE_NUM		VPN_GP(GP_MAX_STORED_QUEUE_NUM, 384)		// The number of queues that can be stored in each session
+#define	MAX_BUFFERING_PACKET_SIZE	VPN_GP(GP_MAX_BUFFERING_PACKET_SIZE, (1600 * 300 * 1))	// Maximum packet size can be buffered
+#endif	// USE_STRATEGY_LOW_MEMORY
+
+#define	MAX_SEND_SOCKET_QUEUE_NUM	VPN_GP(GP_MAX_SEND_SOCKET_QUEUE_NUM, 128)		// Maximum number of transmission queue items per processing
 #define	MAX_TCP_CONNECTION			32		// The maximum number of TCP connections
 #define	NUM_TCP_CONNECTION_FOR_UDP_RECOVERY	2	// Maximum number of connections when using UDP recovery
-#define	SELECT_TIME					256
-#define	SELECT_TIME_FOR_NAT			30
+#define	SELECT_TIME					VPN_GP(GP_SELECT_TIME, 256)
+#define	SELECT_TIME_FOR_NAT			VPN_GP(GP_SELECT_TIME_FOR_NAT, 30)
 #define	SELECT_TIME_FOR_DELAYED_PKT	1		// If there is a delayed packet
-#define	MAX_STORED_QUEUE_NUM		1024		// The number of queues that can be stored in each session
-#define	MAX_BUFFERING_PACKET_SIZE	(1600 * 1600)	// Maximum packet size can be buffered
 
 #define	TIMEOUT_MIN					(5 * 1000)	// Minimum timeout in seconds
 #define	TIMEOUT_MAX					(60 * 1000)	// Maximum timeout in seconds
@@ -266,16 +284,16 @@
 
 #define	MAC_TABLE_EXCLUSIVE_TIME	(13 * 1000)			// Period that can occupy the MAC address
 #define	IP_TABLE_EXCLUSIVE_TIME		(13 * 1000)			// Period that can occupy the IP address
-#define	MAC_TABLE_EXPIRE_TIME		(600 * 1000)			// MAC address table expiration date
-#define	IP_TABLE_EXPIRE_TIME		(60 * 1000)			// IP address table expiration date
-#define	IP_TABLE_EXPIRE_TIME_DHCP	(5 * 60 * 1000)		// IP address table expiration date (In the case of DHCP)
-#define	HUB_ARP_SEND_INTERVAL		(5 * 1000)			// ARP packet transmission interval (alive check)
+#define	MAC_TABLE_EXPIRE_TIME		VPN_GP(GP_MAC_TABLE_EXPIRE_TIME, (600 * 1000))			// MAC address table expiration time
+#define	IP_TABLE_EXPIRE_TIME		VPN_GP(GP_IP_TABLE_EXPIRE_TIME, (60 * 1000))			// IP address table expiration time
+#define	IP_TABLE_EXPIRE_TIME_DHCP	VPN_GP(GP_IP_TABLE_EXPIRE_TIME_DHCP, (5 * 60 * 1000))		// IP address table expiration time (In the case of DHCP)
+#define	HUB_ARP_SEND_INTERVAL		VPN_GP(GP_HUB_ARP_SEND_INTERVAL, (5 * 1000))			// ARP packet transmission interval (alive check)
 
 #define	LIMITER_SAMPLING_SPAN		1000	// Sampling interval of the traffic limiting device
 
-#define	STORM_CHECK_SPAN			500		// Broadcast storm check interval
-#define	STORM_DISCARD_VALUE_START	3		// Broadcast packet discard value start value
-#define	STORM_DISCARD_VALUE_END		1024	// Broadcast packet discard value end value
+#define	STORM_CHECK_SPAN			VPN_GP(GP_STORM_CHECK_SPAN, 500)		// Broadcast storm check interval
+#define	STORM_DISCARD_VALUE_START	VPN_GP(GP_STORM_DISCARD_VALUE_START, 3)		// Broadcast packet discard value start value
+#define	STORM_DISCARD_VALUE_END		VPN_GP(GP_STORM_DISCARD_VALUE_END, 1024)	// Broadcast packet discard value end value
 
 #define	KEEP_INTERVAL_MIN			5		// Packet transmission interval minimum value
 #define	KEEP_INTERVAL_DEFAULT		50		// Packet transmission interval default value
@@ -526,7 +544,7 @@
 #define	PACKET_LOG_ALL				2		// Store also data
 
 // Timing of log switching
-#define	LOG_SWITCH_NO				0		// Without switching
+#define	LOG_SWITCH_NO				0		// No switching
 #define	LOG_SWITCH_SECOND			1		// Secondly basis
 #define	LOG_SWITCH_MINUTE			2		// Minutely basis
 #define	LOG_SWITCH_HOUR				3		// Hourly basis
@@ -539,7 +557,7 @@
 #define	DISK_FREE_SPACE_DEFAULT_WINDOWS	((UINT64)(8ULL * 1024ULL * 1024ULL * 1024ULL))	// 8GBytes
 
 // Interval to check the free space
-#define	DISK_FREE_CHECK_INTERVAL	(5 * 60 * 1000)
+#define	DISK_FREE_CHECK_INTERVAL_DEFAULT	(5 * 60 * 1000)
 
 // Simple log
 #define TINY_LOG_DIRNAME			"@tiny_log"
@@ -1026,6 +1044,13 @@ typedef struct CEDAR
 	LOCK *OpenVPNPublicPortsLock;	// Lock of OpenVPN public UDP port list
 	LOCK *CurrentRegionLock;		// Current region lock
 	char CurrentRegion[128];		// Current region
+	LOCK *CurrentTcpQueueSizeLock;	// Current TCP send queue size lock
+	UINT CurrentTcpQueueSize;		// Current TCP send queue size
+	COUNTER *CurrentActiveLinks;	// Current active cascade connections
+	LOCK *QueueBudgetLock;			// Queue budget lock
+	UINT QueueBudget;				// Queue budget
+	LOCK *FifoBudgetLock;			// Fifo budget lock
+	UINT FifoBudget;				// Fifo budget
 } CEDAR;
 
 // Type of CEDAR
@@ -1223,6 +1248,14 @@ SOCK *GetInProcListeningSock(CEDAR *c);
 SOCK *GetReverseListeningSock(CEDAR *c);
 void GetCedarVersion(char *tmp, UINT size);
 UINT64 GetCurrentBuildDate();
+void CedarAddCurrentTcpQueueSize(CEDAR *c, int diff);
+UINT CedarGetCurrentTcpQueueSize(CEDAR *c);
+void CedarAddQueueBudget(CEDAR *c, int diff);
+void CedarAddFifoBudget(CEDAR *c, int diff);
+UINT CedarGetQueueBudgetConsuming(CEDAR *c);
+UINT CedarGetFifoBudgetConsuming(CEDAR *c);
+UINT CedarGetQueueBudgetBalance(CEDAR *c);
+UINT CedarGetFifoBudgetBalance(CEDAR *c);
 
 
 

+ 22 - 9
src/Cedar/Command.c

@@ -9056,6 +9056,7 @@ UINT PsConfigGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
 			wchar_t tmp[MAX_SIZE];
 			UINT buf_size;
 			wchar_t *buf;
+			UNI_TOKEN_LIST *lines;
 
 			UniFormat(tmp, sizeof(tmp), _UU("CMD_ConfigGet_FILENAME"), t.FileName,
 				StrLen(t.FileData));
@@ -9067,7 +9068,19 @@ UINT PsConfigGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
 
 			Utf8ToUni(buf, buf_size, (BYTE *)t.FileData, StrLen(t.FileData));
 
-			c->Write(c, buf);
+			lines = UniGetLines(buf);
+			if (lines != NULL)
+			{
+				UINT i;
+
+				for (i = 0;i < lines->NumTokens;i++)
+				{
+					c->Write(c, lines->Token[i]);
+				}
+
+				UniFreeToken(lines);
+			}
+
 			c->Write(c, L"");
 
 			Free(buf);
@@ -22237,18 +22250,18 @@ void CtPrintCsv(CT *ct, CONSOLE *c)
 {
 	UINT i, j;
 	UINT num_columns = LIST_NUM(ct->Columns);
-	wchar_t buf[MAX_SIZE];
-	wchar_t fmtbuf[MAX_SIZE];
+	wchar_t buf[MAX_SIZE*4];
+	wchar_t fmtbuf[MAX_SIZE*4];
 
 	// Show the heading row
 	buf[0] = 0;
 	for(i=0; i<num_columns; i++)
 	{
 		CTC *ctc = LIST_DATA(ct->Columns, i);
-		CtEscapeCsv(fmtbuf, MAX_SIZE, ctc->String);
-		UniStrCat(buf, MAX_SIZE, fmtbuf);
+		CtEscapeCsv(fmtbuf, sizeof(fmtbuf), ctc->String);
+		UniStrCat(buf, sizeof(buf), fmtbuf);
 		if(i != num_columns-1)
-			UniStrCat(buf, MAX_SIZE, L",");
+			UniStrCat(buf, sizeof(buf), L",");
 	}
 	c->Write(c, buf);
 
@@ -22259,10 +22272,10 @@ void CtPrintCsv(CT *ct, CONSOLE *c)
 		buf[0] = 0;
 		for(i=0; i<num_columns; i++)
 		{
-			CtEscapeCsv(fmtbuf, MAX_SIZE, ctr->Strings[i]);
-			UniStrCat(buf, MAX_SIZE, fmtbuf);
+			CtEscapeCsv(fmtbuf, sizeof(fmtbuf), ctr->Strings[i]);
+			UniStrCat(buf, sizeof(buf), fmtbuf);
 			if(i != num_columns-1)
-				UniStrCat(buf, MAX_SIZE, L",");
+				UniStrCat(buf, sizeof(buf), L",");
 		}
 		c->Write(c, buf);
 	}

+ 332 - 147
src/Cedar/Connection.c

@@ -743,36 +743,32 @@ void SendDataWithUDP(SOCK *s, CONNECTION *c)
 		WriteBuf(b, dummy_buf, sizeof(dummy_buf));
 
 		// Pack the packets in transmission queue
-		LockQueue(c->SendBlocks);
+		while (true)
 		{
-			while (true)
-			{
-				BLOCK *block;
-
-				if (b->Size > UDP_BUF_SIZE)
-				{
-					break;
-				}
-				block = GetNext(c->SendBlocks);
-				if (block == NULL)
-				{
-					break;
-				}
+			BLOCK *block;
 
-				if (block->Size != 0)
-				{
-					WriteBufInt(b, block->Size);
-					WriteBuf(b, block->Buf, block->Size);
+			if (b->Size > UDP_BUF_SIZE)
+			{
+				break;
+			}
+			block = GetNext(c->SendBlocks);
+			if (block == NULL)
+			{
+				break;
+			}
 
-					c->Session->TotalSendSize += (UINT64)block->SizeofData;
-					c->Session->TotalSendSizeReal += (UINT64)block->Size;
-				}
+			if (block->Size != 0)
+			{
+				WriteBufInt(b, block->Size);
+				WriteBuf(b, block->Buf, block->Size);
 
-				FreeBlock(block);
-				break;
+				c->Session->TotalSendSize += (UINT64)block->SizeofData;
+				c->Session->TotalSendSizeReal += (UINT64)block->Size;
 			}
+
+			FreeBlock(block);
+			break;
 		}
-		UnlockQueue(c->SendBlocks);
 
 		// Write sequence number and session key
 		sign = (char *)(((UCHAR *)b->Buf));
@@ -896,7 +892,7 @@ void PutUDPPacketData(CONNECTION *c, void *data, UINT size)
 					block = NewBlock(tmp, size, 0);
 
 					// Insert Block
-					InsertReveicedBlockToQueue(c, block);
+					InsertReveicedBlockToQueue(c, block, false);
 				}
 			}
 
@@ -913,7 +909,7 @@ void PutUDPPacketData(CONNECTION *c, void *data, UINT size)
 }
 
 // Add a block to the receive queue
-void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block)
+void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block, bool no_lock)
 {
 	SESSION *s;
 	// Validate arguments
@@ -930,11 +926,24 @@ void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block)
 		s->TotalRecvSize += block->Size;
 	}
 
-	LockQueue(c->ReceivedBlocks);
+	if (no_lock == false)
+	{
+		LockQueue(c->ReceivedBlocks);
+	}
+
+	if (c->ReceivedBlocks->num_item < MAX_STORED_QUEUE_NUM)
 	{
 		InsertQueue(c->ReceivedBlocks, block);
 	}
-	UnlockQueue(c->ReceivedBlocks);
+	else
+	{
+		FreeBlock(block);
+	}
+
+	if (no_lock == false)
+	{
+		UnlockQueue(c->ReceivedBlocks);
+	}
 }
 
 // Generate the interval to the next Keep-Alive packet
@@ -1012,10 +1021,9 @@ void SendKeepAlive(CONNECTION *c, TCPSOCK *ts)
 }
 
 // Transmission of block
-void ConnectionSend(CONNECTION *c)
+void ConnectionSend(CONNECTION *c, UINT64 now)
 {
 	UINT i, num;
-	UINT64 now;
 	UINT min_count;
 	UINT64 max_recv_tick;
 	TCPSOCK **tcpsocks;
@@ -1037,8 +1045,6 @@ void ConnectionSend(CONNECTION *c)
 		hub = s->Hub;
 	}
 
-	now = Tick64();
-
 	// Protocol
 	if (c->Protocol == CONNECTION_TCP)
 	{
@@ -1048,6 +1054,8 @@ void ConnectionSend(CONNECTION *c)
 		TCPSOCK *ts_hp;
 		UINT num_available;
 		bool is_rudp = false;
+		UINT tcp_queue_size = 0;
+		int tcp_queue_size_diff = 0;
 		LockList(tcp->TcpSockList);
 		{
 			num = LIST_NUM(tcp->TcpSockList);
@@ -1143,8 +1151,16 @@ void ConnectionSend(CONNECTION *c)
 					}
 				}
 			}
+
+			tcp_queue_size += tcpsock->SendFifo->size;
 		}
 
+		tcp_queue_size_diff = ((int)tcp_queue_size) - ((int)c->LastTcpQueueSize);
+
+		CedarAddCurrentTcpQueueSize(c->Cedar, tcp_queue_size_diff);
+
+		c->LastTcpQueueSize = tcp_queue_size;
+
 		if (ts_hp == NULL)
 		{
 			ts_hp = ts;
@@ -1183,13 +1199,15 @@ void ConnectionSend(CONNECTION *c)
 					tss = ts;
 				}
 				// I reserve the data to send on the selected socket ts
-				LockQueue(c->SendBlocks);
 				if (q->num_item != 0)
 				{
 					UINT num_data;
 					BLOCK *b;
+					UINT size_quota_v1 = MAX_SEND_SOCKET_QUEUE_SIZE / s->MaxConnection;
+					UINT size_quota_v2 = MIN_SEND_SOCKET_QUEUE_SIZE;
+					UINT size_quota = MAX(size_quota_v1, size_quota_v2);
 
-					if (tss->SendFifo->size >= MAX((MAX_SEND_SOCKET_QUEUE_SIZE / s->MaxConnection), MIN_SEND_SOCKET_QUEUE_SIZE))
+					if (tss->SendFifo->size >= size_quota)
 					{
 						// The size of the socket send queue is exceeded
 						// Unable to send
@@ -1344,7 +1362,6 @@ void ConnectionSend(CONNECTION *c)
 						}
 					}
 				}
-				UnlockQueue(c->SendBlocks);
 			}
 		}
 
@@ -1428,7 +1445,7 @@ SEND_START:
 							PROBE_STR("TcpSockSend All Completed");
 						}
 						// Updated the last communication date and time
-						c->Session->LastCommTime = now;
+						UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
 
 						goto SEND_START;
 					}
@@ -1477,56 +1494,46 @@ SEND_START:
 		// SecureNAT session
 		SNAT *snat = s->SecureNAT;
 		VH *v = snat->Nat->Virtual;
+		BLOCK *block;
+		UINT num_packet = 0;
 
-		LockQueue(c->SendBlocks);
+		if (hub != NULL)
 		{
-			BLOCK *block;
-			UINT num_packet = 0;
-
-			if (hub != NULL)
-			{
-				NatSetHubOption(v, hub->Option);
-			}
+			NatSetHubOption(v, hub->Option);
+		}
 
-			while (block = GetNext(c->SendBlocks))
-			{
-				num_packet++;
-				c->CurrentSendQueueSize -= block->Size;
-				VirtualPutPacket(v, block->Buf, block->Size);
-				Free(block);
-			}
+		while (block = GetNext(c->SendBlocks))
+		{
+			num_packet++;
+			c->CurrentSendQueueSize -= block->Size;
+			VirtualPutPacket(v, block->Buf, block->Size);
+			Free(block);
+		}
 
-			if (num_packet != 0)
-			{
-				VirtualPutPacket(v, NULL, 0);
-			}
+		if (num_packet != 0)
+		{
+			VirtualPutPacket(v, NULL, 0);
 		}
-		UnlockQueue(c->SendBlocks);
 	}
 	else if (c->Protocol == CONNECTION_HUB_LAYER3)
 	{
 		// Layer-3 session
 		L3IF *f = s->L3If;
+		BLOCK *block;
+		UINT num_packet = 0;
 
-		LockQueue(c->SendBlocks);
+		while (block = GetNext(c->SendBlocks))
 		{
-			BLOCK *block;
-			UINT num_packet = 0;
-
-			while (block = GetNext(c->SendBlocks))
-			{
-				num_packet++;
-				c->CurrentSendQueueSize -= block->Size;
-				L3PutPacket(f, block->Buf, block->Size);
-				Free(block);
-			}
+			num_packet++;
+			c->CurrentSendQueueSize -= block->Size;
+			L3PutPacket(f, block->Buf, block->Size);
+			Free(block);
+		}
 
-			if (num_packet != 0)
-			{
-				L3PutPacket(f, NULL, 0);
-			}
+		if (num_packet != 0)
+		{
+			L3PutPacket(f, NULL, 0);
 		}
-		UnlockQueue(c->SendBlocks);
 	}
 	else if (c->Protocol == CONNECTION_HUB_LINK_SERVER)
 	{
@@ -1535,30 +1542,35 @@ SEND_START:
 
 		if (k != NULL)
 		{
-			LockQueue(c->SendBlocks);
+			UINT num_blocks = 0;
+			LockQueue(k->SendPacketQueue);
 			{
-				UINT num_blocks = 0;
-				LockQueue(k->SendPacketQueue);
+				BLOCK *block;
+
+				// Transfer the packet queue to the client thread
+				while (block = GetNext(c->SendBlocks))
 				{
-					BLOCK *block;
+					c->CurrentSendQueueSize -= block->Size;
 
-					// Transfer the packet queue to the client thread
-					while (block = GetNext(c->SendBlocks))
+					if (k->SendPacketQueue->num_item >= MAX_STORED_QUEUE_NUM)
+					{
+						FreeBlock(block);
+					}
+					else
 					{
 						num_blocks++;
-						c->CurrentSendQueueSize -= block->Size;
+						k->CurrentSendPacketQueueSize += block->Size;
 						InsertQueue(k->SendPacketQueue, block);
 					}
 				}
-				UnlockQueue(k->SendPacketQueue);
+			}
+			UnlockQueue(k->SendPacketQueue);
 
-				if (num_blocks != 0)
-				{
-					// Issue of cancellation
-					Cancel(k->ClientSession->Cancel1);
-				}
+			if (num_blocks != 0)
+			{
+				// Issue of cancellation
+				Cancel(k->ClientSession->Cancel1);
 			}
-			UnlockQueue(c->SendBlocks);
 		}
 	}
 	else if (c->Protocol == CONNECTION_HUB_BRIDGE)
@@ -1570,54 +1582,50 @@ SEND_START:
 		{
 			if (b->Active)
 			{
-				LockQueue(c->SendBlocks);
+				BLOCK *block;
+				UINT num_packet = c->SendBlocks->num_item; // Packet count
+
+				if (num_packet != 0)
 				{
-					BLOCK *block;
-					UINT num_packet = c->SendBlocks->num_item; // Packet count
+					// Packet data array
+					void **datas = MallocFast(sizeof(void *) * num_packet);
+					UINT *sizes = MallocFast(sizeof(UINT *) * num_packet);
+					UINT i;
 
-					if (num_packet != 0)
+					i = 0;
+					while (block = GetNext(c->SendBlocks))
 					{
-						// Packet data array
-						void **datas = MallocFast(sizeof(void *) * num_packet);
-						UINT *sizes = MallocFast(sizeof(UINT *) * num_packet);
-						UINT i;
+						if (hub != NULL && hub->Option != NULL && hub->Option->DisableUdpFilterForLocalBridgeNic == false &&
+							b->Eth != NULL && IsDhcpPacketForSpecificMac(block->Buf, block->Size, b->Eth->MacAddress))
+						{
+							// DHCP Packet is filtered
+							datas[i] = NULL;
+							sizes[i] = 0;
 
-						i = 0;
-						while (block = GetNext(c->SendBlocks))
+							Free(block->Buf);
+						}
+						else
 						{
-							if (hub != NULL && hub->Option != NULL && hub->Option->DisableUdpFilterForLocalBridgeNic == false &&
-								b->Eth != NULL && IsDhcpPacketForSpecificMac(block->Buf, block->Size, b->Eth->MacAddress))
-							{
-								// DHCP Packet is filtered
-								datas[i] = NULL;
-								sizes[i] = 0;
+							datas[i] = block->Buf;
+							sizes[i] = block->Size;
 
-								Free(block->Buf);
-							}
-							else
+							if (block->Size > 1514)
 							{
-								datas[i] = block->Buf;
-								sizes[i] = block->Size;
-
-								if (block->Size > 1514)
-								{
-									NormalizeEthMtu(b, c, block->Size);
-								}
+								NormalizeEthMtu(b, c, block->Size);
 							}
-
-							c->CurrentSendQueueSize -= block->Size;
-							Free(block);
-							i++;
 						}
 
-						// Write the packet
-						EthPutPackets(b->Eth, num_packet, datas, sizes);
-
-						Free(datas);
-						Free(sizes);
+						c->CurrentSendQueueSize -= block->Size;
+						Free(block);
+						i++;
 					}
+
+					// Write the packet
+					EthPutPackets(b->Eth, num_packet, datas, sizes);
+
+					Free(datas);
+					Free(sizes);
 				}
-				UnlockQueue(c->SendBlocks);
 			}
 		}
 	}
@@ -1632,10 +1640,10 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 	TCPSOCK **tcpsocks;
 	UCHAR *buf;
 	UINT size;
-	UINT64 now;
 	UINT time;
 	UINT num_delayed = 0;
 	bool no_spinlock_for_delay = false;
+	UINT64 now = Tick64();
 	HUB *hub = NULL;
 	// Validate arguments
 	if (c == NULL)
@@ -1657,8 +1665,6 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 		no_spinlock_for_delay = hub->Option->NoSpinLockForPacketDelay;
 	}
 
-	now = Tick64();
-
 	if (c->RecvBuf == NULL)
 	{
 		c->RecvBuf = Malloc(RECV_BUF_SIZE);
@@ -1671,6 +1677,8 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 		// TCP
 		TCP *tcp = c->Tcp;
 		UINT next_delay_packet_diff = 0;
+		UINT current_recv_fifo_size = 0;
+		int recv_fifo_size_middle_update = 0;
 
 		// Disconnect if disconnection interval is specified
 		if (s->ServerMode == false)
@@ -1784,6 +1792,8 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 			}
 		}
 
+		now = Tick64();
+
 		PROBE_STR("ConnectionReceive: Select 1");
 
 		if (s->UseUdpAcceleration && s->UdpAccel != NULL)
@@ -1799,6 +1809,7 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 
 			while (true)
 			{
+				UINT current_packet_index = 0;
 				BLOCK *b = GetNext(s->UdpAccel->RecvBlockQueue);
 
 				if (b == NULL)
@@ -1813,8 +1824,27 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 				}
 				else
 				{
-					// Add the data block to queue
-					InsertReveicedBlockToQueue(c, b);
+					if (CedarGetQueueBudgetBalance(c->Cedar) == 0)
+					{
+						FreeBlock(b);
+					}
+					else
+					{
+						// Add the data block to queue
+						InsertReveicedBlockToQueue(c, b, true);
+
+						if ((current_packet_index % 32) == 0)
+						{
+							UINT current_recv_block_num = c->ReceivedBlocks->num_item;
+							int diff = (int)current_recv_block_num - (int)c->LastRecvBlocksNum;
+
+							CedarAddQueueBudget(c->Cedar, diff);
+
+							c->LastRecvBlocksNum = current_recv_block_num;
+						}
+
+						current_packet_index++;
+					}
 				}
 			}
 		}
@@ -1845,6 +1875,7 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 					// R-UDP bulk transfer data reception
 					if (t != NULL && IsTubeConnected(t))
 					{
+						UINT current_packet_index = 0;
 						while (true)
 						{
 							TUBEDATA *d = TubeRecvAsync(t);
@@ -1876,15 +1907,34 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 							}
 							else
 							{
-								// Add the data block to queue
-								InsertReveicedBlockToQueue(c, block);
+								if (CedarGetQueueBudgetBalance(c->Cedar) == 0)
+								{
+									FreeBlock(block);
+								}
+								else
+								{
+									// Add the data block to queue
+									InsertReveicedBlockToQueue(c, block, true);
+
+									if ((current_packet_index % 32) == 0)
+									{
+										UINT current_recv_block_num = c->ReceivedBlocks->num_item;
+										int diff = (int)current_recv_block_num - (int)c->LastRecvBlocksNum;
+
+										CedarAddQueueBudget(c->Cedar, diff);
+
+										c->LastRecvBlocksNum = current_recv_block_num;
+									}
+
+									current_packet_index++;
+								}
 							}
 
 							FreeTubeData(d);
 
-							ts->LastCommTime = now;
-							ts->LastRecvTime = now;
-							c->Session->LastCommTime = now;
+							UPDATE_LAST_COMM_TIME(ts->LastCommTime, now);
+							UPDATE_LAST_COMM_TIME(ts->LastRecvTime, now);
+							UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
 						}
 					}
 				}
@@ -1893,6 +1943,8 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 			if (c->IsInProc)
 			{
 				TUBEDATA *d;
+				UINT current_packet_index = 0;
+
 				// Socket for in-process connection
 				if (IsTubeConnected(sock->RecvTube) == false)
 				{
@@ -1920,17 +1972,38 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 					}
 					else
 					{
-						// Add the data block to queue
-						InsertReveicedBlockToQueue(c, block);
+						if (CedarGetQueueBudgetBalance(c->Cedar) == 0)
+						{
+							FreeBlock(block);
+						}
+						else
+						{
+							// Add the data block to queue
+							InsertReveicedBlockToQueue(c, block, true);
+
+							if ((current_packet_index % 32) == 0)
+							{
+								UINT current_recv_block_num = c->ReceivedBlocks->num_item;
+								int diff = (int)current_recv_block_num - (int)c->LastRecvBlocksNum;
+
+								CedarAddQueueBudget(c->Cedar, diff);
+
+								c->LastRecvBlocksNum = current_recv_block_num;
+							}
+
+							current_packet_index++;
+						}
 					}
 
 					FreeTubeData(d);
 				}
 
-				c->Session->LastCommTime = now;
+				UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
 			}
 			else
 			{
+				UINT current_fifo_budget = 0;
+				UINT current_packet_index = 0;
 				// A normal socket (Not in-process)
 				if (ts->WantSize == 0)
 				{
@@ -1938,10 +2011,28 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
 					ts->WantSize = sizeof(UINT);
 				}
 
+				now = Tick64();
+
 RECV_START:
+				current_fifo_budget = CedarGetFifoBudgetBalance(c->Cedar);
 				// Receive
-				size = TcpSockRecv(s, ts, buf, RECV_BUF_SIZE);
-/*
+				if (ts->RecvFifo->size < current_fifo_budget)
+				{
+					UINT recv_buf_size = current_fifo_budget - ts->RecvFifo->size;
+
+					recv_buf_size = MIN(recv_buf_size, RECV_BUF_SIZE);
+
+					size = TcpSockRecv(s, ts, buf, recv_buf_size);
+				}
+				else
+				{
+					size = SOCK_LATER;
+
+					UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
+					UPDATE_LAST_COMM_TIME(ts->LastCommTime, now);
+				}
+
+				/*
 				// Experiment
 				if (c->ServerMode)
 				{
@@ -1988,22 +2079,34 @@ DISCONNECT_THIS_TCP:
 				}
 				else
 				{
+					UINT budget_balance = CedarGetFifoBudgetBalance(c->Cedar);
+					UINT fifo_size_limit = budget_balance;
+
+					if (fifo_size_limit > MAX_BUFFERING_PACKET_SIZE)
+					{
+						fifo_size_limit = MAX_BUFFERING_PACKET_SIZE;
+					}
+
 					// Update the last communication time
-					ts->LastCommTime = now;
-					c->Session->LastCommTime = now;
-					ts->LastRecvTime = now;
+					UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
+					UPDATE_LAST_COMM_TIME(ts->LastRecvTime, now);
+
+					CedarAddFifoBudget(c->Cedar, (int)size);
+					recv_fifo_size_middle_update += (int)size;
 
 					// Write the received data into the FIFO
 					PROBE_DATA2("WriteRecvFifo", buf, size);
 					WriteRecvFifo(s, ts, buf, size);
 
 					// Stop receiving  when the receive buffer is full
-					if (ts->RecvFifo->size < MAX_SEND_SOCKET_QUEUE_SIZE)
+					if (ts->RecvFifo->size < fifo_size_limit)
 					{
 						goto RECV_START;
 					}
 				}
 
+				current_recv_fifo_size += FifoSize(ts->RecvFifo);
+
 				// process the data written to FIFO
 				while (ts->RecvFifo->size >= ts->WantSize)
 				{
@@ -2088,6 +2191,9 @@ DISCONNECT_THIS_TCP:
 						ReadFifo(ts->RecvFifo, NULL, ts->NextBlockSize);
 						block = NewBlock(data, ts->NextBlockSize, s->UseCompress ? -1 : 0);
 
+						UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
+						UPDATE_LAST_COMM_TIME(ts->LastCommTime, now);
+
 						if (block->Size > MAX_PACKET_SIZE)
 						{
 							// Packet size exceeded
@@ -2095,8 +2201,27 @@ DISCONNECT_THIS_TCP:
 						}
 						else
 						{
-							// Add the data block to queue
-							InsertReveicedBlockToQueue(c, block);
+							if (CedarGetQueueBudgetBalance(c->Cedar) == 0)
+							{
+								FreeBlock(block);
+							}
+							else
+							{
+								// Add the data block to queue
+								InsertReveicedBlockToQueue(c, block, true);
+
+								if ((current_packet_index % 32) == 0)
+								{
+									UINT current_recv_block_num = c->ReceivedBlocks->num_item;
+									int diff = (int)current_recv_block_num - (int)c->LastRecvBlocksNum;
+
+									CedarAddQueueBudget(c->Cedar, diff);
+
+									c->LastRecvBlocksNum = current_recv_block_num;
+								}
+
+								current_packet_index++;
+							}
 						}
 
 						if (ts->CurrentPacketNum >= ts->NextBlockNum)
@@ -2127,6 +2252,9 @@ DISCONNECT_THIS_TCP:
 						ts->NextBlockSize = MIN(sz, MAX_KEEPALIVE_SIZE);
 						ReadFifo(ts->RecvFifo, NULL, sizeof(UINT));
 
+						UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
+						UPDATE_LAST_COMM_TIME(ts->LastCommTime, now);
+
 						s->TotalRecvSize += sizeof(UINT);
 						s->TotalRecvSizeReal += sizeof(UINT);
 
@@ -2169,6 +2297,9 @@ DISCONNECT_THIS_TCP:
 						PROBE_DATA2("ReadFifo 4", NULL, 0);
 						ReadFifo(ts->RecvFifo, NULL, sz);
 
+						UPDATE_LAST_COMM_TIME(c->Session->LastCommTime, now);
+						UPDATE_LAST_COMM_TIME(ts->LastCommTime, now);
+
 						s->TotalRecvSize += sz;
 						s->TotalRecvSizeReal += sz;
 
@@ -2176,9 +2307,33 @@ DISCONNECT_THIS_TCP:
 						break;
 					}
 				}
+
+				ShrinkFifoMemory(ts->RecvFifo);
+				//printf("Fifo: %u\n", ts->RecvFifo->memsize);
 			}
 		}
 
+		if (true)
+		{
+			int diff;
+
+			diff = (int)current_recv_fifo_size - (int)c->LastRecvFifoTotalSize;
+
+			CedarAddFifoBudget(c->Cedar, (diff - recv_fifo_size_middle_update));
+
+			c->LastRecvFifoTotalSize = current_recv_fifo_size;
+		}
+
+		if (true)
+		{
+			UINT current_recv_block_num = c->ReceivedBlocks->num_item;
+			int diff = (int)current_recv_block_num - (int)c->LastRecvBlocksNum;
+
+			CedarAddQueueBudget(c->Cedar, diff);
+
+			c->LastRecvBlocksNum = current_recv_block_num;
+		}
+
 		Free(tcpsocks);
 	}
 	else if (c->Protocol == CONNECTION_UDP)
@@ -2322,7 +2477,7 @@ DISCONNECT_THIS_TCP:
 			else
 			{
 				// Add the data block to queue
-				InsertReveicedBlockToQueue(c, block);
+				InsertReveicedBlockToQueue(c, block, true);
 			}
 			num++;
 			if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
@@ -2403,7 +2558,7 @@ DISCONNECT_THIS_TCP:
 			}
 			else
 			{
-				InsertReveicedBlockToQueue(c, block);
+				InsertReveicedBlockToQueue(c, block, true);
 			}
 
 			num++;
@@ -2443,7 +2598,9 @@ DISCONNECT_THIS_TCP:
 
 			if ((b->LastNumDeviceCheck + BRIDGE_NUM_DEVICE_CHECK_SPAN) <= Tick64())
 			{
+#ifdef	OS_WIN32
 				check_device_num = true;
+#endif	// OS_WIN32
 				b->LastNumDeviceCheck = Tick64();
 			}
 
@@ -2518,7 +2675,7 @@ DISCONNECT_THIS_TCP:
 						}
 						else
 						{
-							InsertReveicedBlockToQueue(c, block);
+							InsertReveicedBlockToQueue(c, block, true);
 						}
 						num++;
 						if (num >= MAX_SEND_SOCKET_QUEUE_NUM)
@@ -2641,6 +2798,8 @@ BLOCK *NewBlock(void *data, UINT size, int compress)
 
 	b = MallocFast(sizeof(BLOCK));
 
+	b->IsFlooding = false;
+
 	b->PriorityQoS = b->Ttl = b->Param1 = 0;
 
 	if (compress == 0)
@@ -2891,7 +3050,7 @@ void ConnectionAccept(CONNECTION *c)
 	SERVER *server;
 	UCHAR *peek_buf = NULL;
 	UINT peek_buf_size = 1500;
-	char sni[128] = {0};
+	char sni[256] = {0};
 	bool native1 = false;
 	bool native2 = false;
 	bool native3 = false;
@@ -3191,6 +3350,32 @@ void CleanupConnection(CONNECTION *c)
 		return;
 	}
 
+	if (c->LastRecvFifoTotalSize != 0)
+	{
+		CedarAddFifoBudget(c->Cedar, -((int)c->LastRecvFifoTotalSize));
+		c->LastRecvFifoTotalSize = 0;
+	}
+
+	if (c->LastRecvBlocksNum != 0)
+	{
+		CedarAddQueueBudget(c->Cedar, -((int)c->LastRecvBlocksNum));
+		c->LastRecvBlocksNum = 0;
+	}
+
+	if (c->LastTcpQueueSize != 0)
+	{
+		int diff = -((int)c->LastTcpQueueSize);
+		CedarAddCurrentTcpQueueSize(c->Cedar, diff);
+		c->LastTcpQueueSize = 0;
+	}
+
+	if (c->LastPacketQueueSize != 0)
+	{
+		int diff = -((int)c->LastPacketQueueSize);
+		CedarAddCurrentTcpQueueSize(c->Cedar, diff);
+		c->LastPacketQueueSize = 0;
+	}
+
 	DeleteLock(c->lock);
 	ReleaseCedar(c->Cedar);
 

+ 9 - 2
src/Cedar/Connection.h

@@ -119,6 +119,8 @@
 
 #define	KEEP_ALIVE_STRING				"Internet Connection Keep Alive Packet"
 
+#define	UPDATE_LAST_COMM_TIME(v, n)		{if ((v) <= (n)) { v = (n); } }
+
 // KEEP CONNECT structure
 struct KEEP
 {
@@ -258,6 +260,7 @@ struct BLOCK
 	bool PriorityQoS;				// Priority packet for VoIP / QoS function
 	UINT Ttl;						// TTL value (Used only in ICMP NAT of Virtual.c)
 	UINT Param1;					// Parameter 1
+	bool IsFlooding;				// Is flooding packet
 };
 
 // Connection structure
@@ -316,6 +319,10 @@ struct CONNECTION
 	bool WasSstp;					// Processed the SSTP
 	bool WasDatProxy;				// DAT proxy processed
 	UCHAR CToken_Hash[SHA1_SIZE];	// CTOKEN_HASH
+	UINT LastTcpQueueSize;			// The last queue size of TCP sockets
+	UINT LastPacketQueueSize;		// The last queue size of packets
+	UINT LastRecvFifoTotalSize;		// The last RecvFifo total size
+	UINT LastRecvBlocksNum;			// The last ReceivedBlocks num
 };
 
 
@@ -334,7 +341,7 @@ void StartTunnelingMode(CONNECTION *c);
 void EndTunnelingMode(CONNECTION *c);
 void DisconnectTcpSockets(CONNECTION *c);
 void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2);
-void ConnectionSend(CONNECTION *c);
+void ConnectionSend(CONNECTION *c, UINT64 now);
 TCPSOCK *NewTcpSock(SOCK *s);
 void FreeTcpSock(TCPSOCK *ts);
 BLOCK *NewBlock(void *data, UINT size, int compress);
@@ -345,7 +352,7 @@ void SendKeepAlive(CONNECTION *c, TCPSOCK *ts);
 void DisconnectUDPSockets(CONNECTION *c);
 void PutUDPPacketData(CONNECTION *c, void *data, UINT size);
 void SendDataWithUDP(SOCK *s, CONNECTION *c);
-void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block);
+void InsertReveicedBlockToQueue(CONNECTION *c, BLOCK *block, bool no_lock);
 void InitTcpSockRc4Key(TCPSOCK *ts, bool server_mode);
 UINT TcpSockRecv(SESSION *s, TCPSOCK *ts, void *data, UINT size);
 UINT TcpSockSend(SESSION *s, TCPSOCK *ts, void *data, UINT size);

+ 1 - 1
src/Cedar/DDNS.c

@@ -645,7 +645,7 @@ UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace
 	cert_hash = StrToBin(DDNS_CERT_HASH);
 
 	Format(url2, sizeof(url2), "%s?v=%I64u", url, Rand64());
-	Format(url3, sizeof(url3), url2, key_hash_str[0], key_hash_str[1], key_hash_str[2], key_hash_str[3]);
+	Format(url3, sizeof(url3), url2, key_hash_str[2], key_hash_str[3]);
 
 	if (use_https == false)
 	{

+ 4 - 4
src/Cedar/DDNS.h

@@ -118,8 +118,8 @@
 #define	DDNS_CERT_HASH		"EFAC5FA0CDD14E0F864EED58A73C35D7E33B62F3"
 
 // Destination URL
-#define	DDNS_URL_V4_GLOBAL	"https://x%c.x%c.x%c.x%c.servers.ddns.softether-network.net/ddns/ddns.aspx"
-#define	DDNS_URL_V6_GLOBAL	"https://x%c.x%c.x%c.x%c.servers-v6.ddns.softether-network.net/ddns/ddns.aspx"
+#define	DDNS_URL_V4_GLOBAL	"https://x%c.x%c.servers.ddns.softether-network.net/ddns/ddns.aspx"
+#define	DDNS_URL_V6_GLOBAL	"https://x%c.x%c.servers-v6.ddns.softether-network.net/ddns/ddns.aspx"
 #define	DDNS_URL2_V4_GLOBAL	"http://get-my-ip.ddns.softether-network.net/ddns/getmyip.ashx"
 #define	DDNS_URL2_V6_GLOBAL	"http://get-my-ip-v6.ddns.softether-network.net/ddns/getmyip.ashx"
 
@@ -132,8 +132,8 @@
 #define	DDNS_REPLACE_URL2_FOR_WEST_NGN		"http://senet.p-ns.flets-west.jp/ddns/getmyip.ashx"
 
 // For China: Free version
-#define	DDNS_URL_V4_ALT		"https://x%c.x%c.x%c.x%c.servers.ddns.uxcom.jp/ddns/ddns.aspx"
-#define	DDNS_URL_V6_ALT		"https://x%c.x%c.x%c.x%c.servers-v6.ddns.uxcom.jp/ddns/ddns.aspx"
+#define	DDNS_URL_V4_ALT		"https://x%c.x%c.servers.ddns.uxcom.jp/ddns/ddns.aspx"
+#define	DDNS_URL_V6_ALT		"https://x%c.x%c.servers-v6.ddns.uxcom.jp/ddns/ddns.aspx"
 #define	DDNS_URL2_V4_ALT	"http://get-my-ip.ddns.uxcom.jp/ddns/getmyip.ashx"
 #define	DDNS_URL2_V6_ALT	"http://get-my-ip-v6.ddns.uxcom.jp/ddns/getmyip.ashx"
 

+ 167 - 121
src/Cedar/Hub.c

@@ -596,6 +596,7 @@ void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
 	GetHubAdminOptionDataAndSet(ao, "DropBroadcastsInPrivacyFilterMode", &o->DropBroadcastsInPrivacyFilterMode);
 	GetHubAdminOptionDataAndSet(ao, "DropArpInPrivacyFilterMode", &o->DropArpInPrivacyFilterMode);
 	GetHubAdminOptionDataAndSet(ao, "SuppressClientUpdateNotification", &o->SuppressClientUpdateNotification);
+	GetHubAdminOptionDataAndSet(ao, "FloodingSendQueueBufferQuota", &o->FloodingSendQueueBufferQuota);
 }
 
 // Convert the contents of the HUB_OPTION to data
@@ -660,6 +661,7 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
 	Add(aol, NewAdminOption("DropBroadcastsInPrivacyFilterMode", o->DropBroadcastsInPrivacyFilterMode));
 	Add(aol, NewAdminOption("DropArpInPrivacyFilterMode", o->DropArpInPrivacyFilterMode));
 	Add(aol, NewAdminOption("SuppressClientUpdateNotification", o->SuppressClientUpdateNotification));
+	Add(aol, NewAdminOption("FloodingSendQueueBufferQuota", o->FloodingSendQueueBufferQuota));
 
 	Zero(ao, sizeof(RPC_ADMIN_OPTION));
 
@@ -2048,6 +2050,7 @@ bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT64 dest_usern
 	IPV6_HEADER *ip6 = NULL;
 	bool is_ipv4_packet = false;
 	bool is_ipv6_packet = false;
+	bool is_arp_packet = false;
 	// Validate arguments
 	if (s == NULL || p == NULL || a == NULL)
 	{
@@ -2180,6 +2183,11 @@ bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT64 dest_usern
 		is_ipv6_packet = true;
 	}
 
+	if (p->TypeL3 == L3_ARPV4)
+	{
+		is_arp_packet = true;
+	}
+
 	if (is_ipv4_packet)
 	{
 		ip = p->L3.IPv4Header;
@@ -2346,7 +2354,7 @@ bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT64 dest_usern
 	}
 
 	// Don't match the packet of non-IPv4 and non-IPv6
-	if (is_ipv4_packet == false && is_ipv6_packet==false)
+	if (is_arp_packet)
 	{
 		if (s->Hub != NULL && s->Hub->Option != NULL && s->Hub->Option->ApplyIPv4AccessListOnArpPacket)
 		{
@@ -2745,7 +2753,7 @@ void ForceRedirectToUrl(HUB *hub, SESSION *src_session, PKT *p, char *redirect_u
 
 	// Reply packet
 	StorePacketToHubPa((HUB_PA *)src_session->PacketAdapter->Param,
-		NULL, b->Buf, b->Size, NULL);
+		NULL, b->Buf, b->Size, NULL, false, false);
 
 	// Release the memory
 	Free(tcp_data);
@@ -3432,13 +3440,16 @@ void HubPaFree(SESSION *s)
 	}
 
 	// Erase MAC address table entries that is associated with this session
-	LockList(hub->MacTable);
+	LockHashList(hub->MacHashTable);
 	{
-		UINT i, num = LIST_NUM(hub->MacTable);
+		UINT i, num;
+		MAC_TABLE_ENTRY **pp;
 		LIST *o = NewListFast(NULL);
+
+		pp = (MAC_TABLE_ENTRY **)HashListToArray(hub->MacHashTable, &num);
 		for (i = 0;i < num;i++)
 		{
-			MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(hub->MacTable, i);
+			MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)pp[i];
 			if (e->Session == s)
 			{
 				Add(o, e);
@@ -3447,10 +3458,11 @@ void HubPaFree(SESSION *s)
 		for (i = 0;i < LIST_NUM(o);i++)
 		{
 			MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(o, i);
-			Delete(hub->MacTable, e);
+			DeleteHash(hub->MacHashTable, e);
 			Free(e);
 		}
 		ReleaseList(o);
+		Free(pp);
 	}
 	{
 		UINT i, num = LIST_NUM(hub->IpTable);
@@ -3471,7 +3483,7 @@ void HubPaFree(SESSION *s)
 		}
 		ReleaseList(o);
 	}
-	UnlockList(hub->MacTable);
+	UnlockHashList(hub->MacHashTable);
 
 	// Release the STORM list
 	LockList(pa->StormList);
@@ -3496,6 +3508,11 @@ void HubPaFree(SESSION *s)
 		while (b = GetNext(pa->PacketQueue))
 		{
 			// Release the block
+			if (b->IsFlooding)
+			{
+				CedarAddCurrentTcpQueueSize(s->Cedar, -((int)b->Size));
+			}
+
 			FreeBlock(b);
 		}
 	}
@@ -3538,6 +3555,11 @@ UINT HubPaGetNextPacket(SESSION *s, void **data)
 		}
 		else
 		{
+			if (block->IsFlooding)
+			{
+				CedarAddCurrentTcpQueueSize(s->Cedar, -((int)block->Size));
+			}
+
 			// Found
 			*data = block->Buf;
 			ret = block->Size;
@@ -3944,11 +3966,11 @@ void StorePacket(HUB *hub, SESSION *s, PKT *packet)
 	bool broadcast_mode;
 	HUB_PA *dest_pa;
 	SESSION *dest_session;
-	TRAFFIC traffic;
 	UINT64 now = Tick64();
 	bool no_heavy = false;
 	bool drop_broadcast_packet_privacy = false;
 	bool drop_arp_packet_privacy = false;
+	UINT tcp_queue_quota = 0;
 	// Validate arguments
 	if (hub == NULL || packet == NULL)
 	{
@@ -3971,10 +3993,11 @@ void StorePacket(HUB *hub, SESSION *s, PKT *packet)
 		no_heavy = hub->Option->DoNotSaveHeavySecurityLogs;
 		drop_broadcast_packet_privacy = hub->Option->DropBroadcastsInPrivacyFilterMode;
 		drop_arp_packet_privacy = hub->Option->DropArpInPrivacyFilterMode;
+		tcp_queue_quota = hub->Option->FloodingSendQueueBufferQuota;
 	}
 
 	// Lock the entire MAC address table
-	LockList(hub->MacTable);
+	LockHashList(hub->MacHashTable);
 	{
 		// Filtering
 		if (s != NULL && (packet->DelayedForwardTick == 0 && StorePacketFilter(s, packet) == false))
@@ -4035,7 +4058,7 @@ DISCARD_PACKET:
 
 			if (forward_now)
 			{
-				if (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) == 0)
+				if (memcmp(packet->MacAddressSrc, hub->HubMacAddr, 6) == 0)
 				{
 					if (s != NULL)
 					{
@@ -4043,7 +4066,7 @@ DISCARD_PACKET:
 						goto DISCARD_PACKET;
 					}
 				}
-				if (s != NULL && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0))
+				if (s != NULL && (memcmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0))
 				{
 					// Check whether the source MAC address is registered in the table
 					Copy(t.MacAddress, packet->MacAddressSrc, 6);
@@ -4055,29 +4078,40 @@ DISCARD_PACKET:
 					{
 						t.VlanId = 0;
 					}
-					entry = Search(hub->MacTable, &t);
+					entry = SearchHash(hub->MacHashTable, &t);
 
 					if (entry == NULL)
 					{
-						// Remove old entries
-						DeleteExpiredMacTableEntry(hub->MacTable);
+						if (hub->LastFlushTick == 0 || (hub->LastFlushTick + (UINT64)OLD_MAC_ADDRESS_ENTRY_FLUSH_INTERVAL) < now)
+						{
+							hub->LastFlushTick = now;
+
+							// Remove old entries
+							DeleteExpiredMacTableEntry(hub->MacHashTable);
+						}
 
 						// Register since it is not registered
 						if ((s->Policy->MaxMac != 0 || s->Policy->NoBridge) && (s->IsOpenVPNL3Session == false))
 						{
 							UINT i, num_mac_for_me = 0;
 							UINT limited_count;
+							MAC_TABLE_ENTRY **pp;
+							UINT num_pp;
+
+							pp = (MAC_TABLE_ENTRY **)HashListToArray(hub->MacHashTable, &num_pp);
 
 							// Examine a number of MAC addresses that are registered in this current session
-							for (i = 0;i < LIST_NUM(hub->MacTable);i++)
+							for (i = 0;i < num_pp;i++)
 							{
-								MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
+								MAC_TABLE_ENTRY *e = pp[i];
 								if (e->Session == s)
 								{
 									num_mac_for_me++;
 								}
 							}
 
+							Free(pp);
+
 							limited_count = 0xffffffff;
 							if (s->Policy->NoBridge)
 							{
@@ -4117,27 +4151,10 @@ DISCARD_PACKET:
 							}
 						}
 
-						if (LIST_NUM(hub->MacTable) >= MAX_MAC_TABLES)
+						if (HASH_LIST_NUM(hub->MacHashTable) >= MAX_MAC_TABLES)
 						{
-							// Delete the oldest entry because the MAC table database is
-							// exceeded the maximum number of entries
-							UINT i;
-							UINT64 old_time = 0xffffffffffffffffULL;
-							MAC_TABLE_ENTRY *old_entry = NULL;
-							for (i = 0;i < LIST_NUM(hub->MacTable);i++)
-							{
-								MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
-								if (e->UpdatedTime <= old_time)
-								{
-									old_time = e->UpdatedTime;
-									old_entry = e;
-								}
-							}
-							if (old_entry != NULL)
-							{
-								Delete(hub->MacTable, old_entry);
-								Free(old_entry);
-							}
+							// Number of MAC addresses exceeded, discard the packet
+							goto DISCARD_PACKET;
 						}
 
 						entry = ZeroMalloc(sizeof(MAC_TABLE_ENTRY));
@@ -4154,7 +4171,7 @@ DISCARD_PACKET:
 						entry->Session = s;
 						entry->UpdatedTime = entry->CreatedTime = now;
 
-						Insert(hub->MacTable, entry);
+						AddHash(hub->MacHashTable, entry);
 
 						if (hub->Option->NoMacAddressLog == false)
 						{
@@ -4163,19 +4180,16 @@ DISCARD_PACKET:
 
 							if (s != NULL)
 							{
-								MacToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc);
-//								Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
-
-								if (packet->VlanId == 0)
+								if (no_heavy == false)
 								{
-									if (no_heavy == false)
+									MacToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc);
+	//								Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
+
+									if (packet->VlanId == 0)
 									{
 										HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
 									}
-								}
-								else
-								{
-									if (no_heavy == false)
+									else
 									{
 										HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
 									}
@@ -4211,7 +4225,7 @@ DISCARD_PACKET:
 							}
 
 							// It's already registered and it's in another session
-							if (check_mac && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0) &&
+							if (check_mac && (memcmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0) &&
 								((entry->UpdatedTime + MAC_TABLE_EXCLUSIVE_TIME) >= now))
 							{
 								UCHAR *mac = packet->MacAddressSrc;
@@ -4228,7 +4242,7 @@ DISCARD_PACKET:
 
 									if ((s->LastDLinkSTPPacketSendTick != 0) &&
 										(tick_diff < 750ULL) &&
-										(Cmp(hash, s->LastDLinkSTPPacketDataHash, MD5_SIZE) == 0))
+										(memcmp(hash, s->LastDLinkSTPPacketDataHash, MD5_SIZE) == 0))
 									{
 										// Discard if the same packet sent before 750ms ago
 										Debug("D-Link Discard %u\n", (UINT)tick_diff);
@@ -4271,18 +4285,15 @@ UPDATE_FDB:
 
 									if (s != NULL)
 									{
-										MacToStr(mac_address, sizeof(mac_address), packet->MacHeader->SrcAddress);
-										Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
-										if (packet->VlanId == 0)
+										if (no_heavy == false)
 										{
-											if (no_heavy == false)
+											MacToStr(mac_address, sizeof(mac_address), packet->MacHeader->SrcAddress);
+											Debug("Register MAC Address %s to Session %X.\n", mac_address, s);
+											if (packet->VlanId == 0)
 											{
 												HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
 											}
-										}
-										else
-										{
-											if (no_heavy == false)
+											else
 											{
 												HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
 											}
@@ -4315,7 +4326,7 @@ UPDATE_FDB:
 					{
 						t.VlanId = 0;
 					}
-					entry = Search(hub->MacTable, &t);
+					entry = SearchHash(hub->MacHashTable, &t);
 
 					if (entry == NULL)
 					{
@@ -4736,30 +4747,6 @@ UPDATE_FDB:
 					}
 				}
 
-				// Adding traffic
-				Zero(&traffic, sizeof(traffic));
-				if (packet->BroadcastPacket)
-				{
-					// Broadcast
-					traffic.Send.BroadcastBytes = packet->PacketSize;
-					traffic.Send.BroadcastCount = 1;
-				}
-				else
-				{
-					// Unicast
-					traffic.Send.UnicastBytes = packet->PacketSize;
-					traffic.Send.UnicastCount = 1;
-				}
-
-				if (s != NULL)
-				{
-					AddTrafficForSession(s, &traffic);
-				}
-
-				// Invert the Recv and Send of traffic information
-				Copy(&traffic.Recv, &traffic.Send, sizeof(TRAFFIC_ENTRY));
-				Zero(&traffic.Send, sizeof(TRAFFIC_ENTRY));
-
 				// Broadcast this packet to the monitor port of the HUB
 				if (hub->MonitorList->num_item != 0)
 				{
@@ -4778,7 +4765,7 @@ UPDATE_FDB:
 								data = MallocFast(size);
 								Copy(data, packet->PacketData, size);
 								StorePacketToHubPa((HUB_PA *)monitor_session->PacketAdapter->Param,
-									s, data, size, packet);
+									s, data, size, packet, false, false);
 							}
 						}
 					}
@@ -4787,6 +4774,7 @@ UPDATE_FDB:
 
 				if (broadcast_mode == false)
 				{
+					// Unicast packet
 					if (dest_pa != NULL)
 					{
 						if (dest_session->Policy->NoIPv6DefaultRouterInRA ||
@@ -4894,8 +4882,8 @@ UPDATE_FDB:
 
 						if (s != NULL)
 						{
-							if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
-								Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
+							if (memcmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
+								memcmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
 							{
 								goto DISCARD_UNICAST_PACKET;
 							}
@@ -4912,10 +4900,7 @@ UPDATE_FDB:
 						}
 
 						// Store to the destination HUB_PA
-						StorePacketToHubPa(dest_pa, s, packet->PacketData, packet->PacketSize, packet);
-
-						// Adding traffic
-						AddTrafficForSession(dest_session, &traffic);
+						StorePacketToHubPa(dest_pa, s, packet->PacketData, packet->PacketSize, packet, false, false);
 					}
 					else
 					{
@@ -4925,6 +4910,9 @@ DISCARD_UNICAST_PACKET:
 				}
 				else
 				{
+					// Flooding as a broadcast packet
+					UINT current_tcp_queue_size = 0;
+
 					// Take a packet log
 					if (s != NULL)
 					{
@@ -4954,6 +4942,28 @@ DISCARD_UNICAST_PACKET:
 									discard = true;
 								}
 
+								if (tcp_queue_quota != 0)
+								{
+									current_tcp_queue_size = CedarGetCurrentTcpQueueSize(hub->Cedar);
+
+									if (current_tcp_queue_size >= tcp_queue_quota)
+									{
+										// Quota exceeded. Discard the packet for normal session.
+										if (dest_session->Connection != NULL &&
+											dest_session->Connection->Protocol == CONNECTION_TCP)
+										{
+											discard = true;
+										}
+
+										if (dest_session->LinkModeServer)
+										{
+											LINK *k = dest_session->Link;
+
+											discard = true;
+										}
+									}
+								}
+
 								if (dest_session->VLanId != 0 && packet->TypeL3 == L3_TAGVLAN &&
 									packet->VlanId != dest_session->VLanId)
 								{
@@ -5076,8 +5086,8 @@ DISCARD_UNICAST_PACKET:
 
 								if (s != NULL)
 								{
-									if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
-										Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
+									if (memcmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
+										memcmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
 									{
 										discard = true;
 									}
@@ -5085,24 +5095,25 @@ DISCARD_UNICAST_PACKET:
 
 								if (discard == false && dest_pa != NULL)
 								{
-									// Store in session other than its own
-									data = MallocFast(packet->PacketSize);
-									Copy(data, packet->PacketData, packet->PacketSize);
-									size = packet->PacketSize;
-
-									if (delete_default_router_in_ra)
+									if (s == NULL ||
+										ApplyAccessListToForwardPacket(s->Hub, s, dest_pa->Session, packet))
 									{
-										PKT *pkt2 = ParsePacket(data, size);
+										// Store in session other than its own
+										data = MallocFast(packet->PacketSize);
+										Copy(data, packet->PacketData, packet->PacketSize);
+										size = packet->PacketSize;
 
-										DeleteIPv6DefaultRouterInRA(pkt2);
+										if (delete_default_router_in_ra)
+										{
+											PKT *pkt2 = ParsePacket(data, size);
 
-										FreePacket(pkt2);
-									}
+											DeleteIPv6DefaultRouterInRA(pkt2);
 
-									StorePacketToHubPa(dest_pa, s, data, size, packet);
+											FreePacket(pkt2);
+										}
 
-									// Adding traffic
-									AddTrafficForSession(dest_session, &traffic);
+										StorePacketToHubPa(dest_pa, s, data, size, packet, true, true);
+									}
 								}
 							}
 						}
@@ -5116,7 +5127,7 @@ DISCARD_BROADCAST_PACKET:
 			}
 		}
 	}
-	UnlockList(hub->MacTable);
+	UnlockHashList(hub->MacHashTable);
 }
 
 // Examine the maximum number of logging target packets per minute
@@ -5278,7 +5289,7 @@ STORM *SearchStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip,
 }
 
 // Store the packet to destination HUB_PA
-void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet)
+void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet, bool is_flooding, bool no_check_acl)
 {
 	BLOCK *b;
 	// Validate arguments
@@ -5293,13 +5304,16 @@ void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *
 		return;
 	}
 
-	if (src != NULL)
+	if (no_check_acl == false)
 	{
-		// Apply the access list for forwarding
-		if (ApplyAccessListToForwardPacket(src->Hub, src, dest->Session, packet) == false)
+		if (src != NULL)
 		{
-			Free(data);
-			return;
+			// Apply the access list for forwarding
+			if (ApplyAccessListToForwardPacket(src->Hub, src, dest->Session, packet) == false)
+			{
+				Free(data);
+				return;
+			}
 		}
 	}
 
@@ -5400,11 +5414,19 @@ void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *
 	LockQueue(dest->PacketQueue);
 	{
 		// Measure the length of queue
-		if ((dest->PacketQueue->num_item < MAX_STORED_QUEUE_NUM) ||
-			(((UCHAR *)data)[12] == 'S' && ((UCHAR *)data)[13] == 'E'))
+		if (dest->PacketQueue->num_item < MAX_STORED_QUEUE_NUM)
 		{
 			// Store
 			InsertQueue(dest->PacketQueue, b);
+
+			if (is_flooding)
+			{
+				if (src != NULL)
+				{
+					b->IsFlooding = true;
+					CedarAddCurrentTcpQueueSize(src->Cedar, b->Size);
+				}
+			}
 		}
 		else
 		{
@@ -5731,7 +5753,7 @@ bool StorePacketFilterByPolicy(SESSION *s, PKT *p)
 						MAC_TABLE_ENTRY *mac_table, mt;
 						mt.VlanId = 0;
 						Copy(&mt.MacAddress, &h->ClientMacAddress, 6);
-						mac_table = Search(hub->MacTable, &mt);
+						mac_table = SearchHash(hub->MacHashTable, &mt);
 
 						if (mac_table != NULL)
 						{
@@ -5803,21 +5825,25 @@ UPDATE_DHCP_ALLOC_ENTRY:
 }
 
 // Delete the expired MAC table entries
-void DeleteExpiredMacTableEntry(LIST *o)
+void DeleteExpiredMacTableEntry(HASH_LIST *h)
 {
 	LIST *o2;
 	UINT i;
+	MAC_TABLE_ENTRY **pp;
+	UINT num;
 	// Validate arguments
-	if (o == NULL)
+	if (h == NULL)
 	{
 		return;
 	}
 
 	o2 = NewListFast(NULL);
 
-	for (i = 0;i < LIST_NUM(o);i++)
+	pp = (MAC_TABLE_ENTRY **)HashListToArray(h, &num);
+
+	for (i = 0;i < num;i++)
 	{
-		MAC_TABLE_ENTRY *e = LIST_DATA(o, i);
+		MAC_TABLE_ENTRY *e = pp[i];
 		if ((e->UpdatedTime + (UINT64)MAC_TABLE_EXPIRE_TIME) <= Tick64())
 		{
 			Add(o2, e);
@@ -5827,11 +5853,13 @@ void DeleteExpiredMacTableEntry(LIST *o)
 	for (i = 0;i < LIST_NUM(o2);i++)
 	{
 		MAC_TABLE_ENTRY *e = LIST_DATA(o2, i);
-		Delete(o, e);
+		DeleteHash(h, e);
 		Free(e);
 	}
 
 	ReleaseList(o2);
+
+	Free(pp);
 }
 
 // Delete the expired IP table entries
@@ -6633,7 +6661,7 @@ void CleanupHub(HUB *h)
 	DeleteLock(h->lock_online);
 	Free(h->Name);
 	ReleaseList(h->SessionList);
-	ReleaseList(h->MacTable);
+	ReleaseHashList(h->MacHashTable);
 	ReleaseList(h->IpTable);
 	ReleaseList(h->MonitorList);
 	ReleaseList(h->LinkList);
@@ -6694,6 +6722,24 @@ int CompareIpTable(void *p1, void *p2)
 	return CmpIpAddr(&e1->Ip, &e2->Ip);
 }
 
+// Get hash of MAC table entry
+UINT GetHashOfMacTable(void *p)
+{
+	UINT v;
+	MAC_TABLE_ENTRY *e = p;
+
+	if (e == NULL)
+	{
+		return 0;
+	}
+
+	v = e->MacAddress[0] + e->MacAddress[1] + e->MacAddress[2] + 
+		e->MacAddress[3] + e->MacAddress[4] + e->MacAddress[5] + 
+		e->VlanId;
+
+	return v;
+}
+
 // Comparison function of the MAC table entries
 int CompareMacTable(void *p1, void *p2)
 {
@@ -6709,7 +6755,7 @@ int CompareMacTable(void *p1, void *p2)
 	{
 		return 0;
 	}
-	r = Cmp(e1->MacAddress, e2->MacAddress, 6);
+	r = memcmp(e1->MacAddress, e2->MacAddress, 6);
 	if (r != 0)
 	{
 		return r;
@@ -6962,7 +7008,7 @@ HUB *NewHub(CEDAR *cedar, char *HubName, HUB_OPTION *option)
 	h->NumSessions = NewCounter();
 	h->NumSessionsClient = NewCounter();
 	h->NumSessionsBridge = NewCounter();
-	h->MacTable = NewList(CompareMacTable);
+	h->MacHashTable = NewHashList(GetHashOfMacTable, CompareMacTable, 8, false);
 	h->IpTable = NewList(CompareIpTable);
 	h->MonitorList = NewList(NULL);
 	h->LinkList = NewList(NULL);

+ 12 - 3
src/Cedar/Hub.h

@@ -128,6 +128,11 @@
 // <INFO> tags of the URL in the access list
 #define	ACCESS_LIST_URL_INFO_TAG					"<INFO>"
 
+// Old MAC address entry flush interval
+#define	OLD_MAC_ADDRESS_ENTRY_FLUSH_INTERVAL		1000
+
+// Default flooding queue length
+#define	DEFAULT_FLOODING_QUEUE_LENGTH				(32 * 1024 * 1024)
 
 // SoftEther link control packet
 struct SE_LINK
@@ -269,6 +274,7 @@ struct HUB_OPTION
 	bool DropBroadcastsInPrivacyFilterMode;	// Drop broadcasting packets if the both source and destination session is PrivacyFilter mode
 	bool DropArpInPrivacyFilterMode;	// Drop ARP packets if the both source and destination session is PrivacyFilter mode
 	bool SuppressClientUpdateNotification;	// Suppress the update notification function on the VPN Client
+	UINT FloodingSendQueueBufferQuota;	// The global quota of send queues of flooding packets
 };
 
 // MAC table entry
@@ -436,7 +442,7 @@ struct HUB
 	COUNTER *NumSessionsClient;			// The current number of sessions (client)
 	COUNTER *NumSessionsBridge;			// The current number of sessions (bridge)
 	HUB_OPTION *Option;					// HUB options
-	LIST *MacTable;						// MAC address table
+	HASH_LIST *MacHashTable;			// MAC address hash table
 	LIST *IpTable;						// IP address table
 	LIST *MonitorList;					// Monitor port session list
 	LIST *LinkList;						// Linked list
@@ -480,6 +486,8 @@ struct HUB
 	wchar_t *Msg;						// Message to be displayed when the client is connected
 	LIST *UserList;						// Cache of the user list file
 	bool IsVgsHub;						// Whether it's a VGS Virtual HUB
+	UINT64 LastFlushTick;				// Last tick to flush the MAC address table
+	bool StopAllLinkFlag;				// Stop all link flag
 };
 
 
@@ -520,9 +528,10 @@ UINT HubPaGetNextPacket(SESSION *s, void **data);
 bool HubPaPutPacket(SESSION *s, void *data, UINT size);
 PACKET_ADAPTER *GetHubPacketAdapter();
 int CompareMacTable(void *p1, void *p2);
+UINT GetHashOfMacTable(void *p);
 void StorePacket(HUB *hub, SESSION *s, PKT *packet);
 bool StorePacketFilter(SESSION *s, PKT *packet);
-void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet);
+void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet, bool is_flooding, bool no_check_acl);
 void SetHubOnline(HUB *h);
 void SetHubOffline(HUB *h);
 SESSION *GetSessionByPtr(HUB *hub, void *ptr);
@@ -565,7 +574,7 @@ void GetHubLogSetting(HUB *h, HUB_LOG *setting);
 void SetHubLogSetting(HUB *h, HUB_LOG *setting);
 void SetHubLogSettingEx(HUB *h, HUB_LOG *setting, bool no_change_switch_type);
 void DeleteExpiredIpTableEntry(LIST *o);
-void DeleteExpiredMacTableEntry(LIST *o);
+void DeleteExpiredMacTableEntry(HASH_LIST *h);
 void AddTrafficDiff(HUB *h, char *name, UINT type, TRAFFIC *traffic);
 void IncrementHubTraffic(HUB *h);
 void EnableSecureNAT(HUB *h, bool enable);

+ 2 - 1
src/Cedar/Interop_SSTP.c

@@ -1175,8 +1175,9 @@ bool ProcessSstpHttps(CEDAR *cedar, SOCK *s, SOCK_EVENT *se)
 		// Wait for the next state change
 		if (state_changed == false)
 		{
+			UINT select_time = SELECT_TIME;
 			UINT r = GetNextIntervalForInterrupt(sstp->Interrupt);
-			WaitSockEvent(se, MIN(r, SELECT_TIME));
+			WaitSockEvent(se, MIN(r, select_time));
 		}
 	}
 

+ 111 - 8
src/Cedar/Link.c

@@ -173,6 +173,11 @@ bool LinkPaInit(SESSION *s)
 		return false;
 	}
 
+	if (k->Halting || (*k->StopAllLinkFlag))
+	{
+		return false;
+	}
+
 	// Create a transmission packet queue
 	k->SendPacketQueue = NewQueue();
 
@@ -180,6 +185,9 @@ bool LinkPaInit(SESSION *s)
 	t = NewThread(LinkServerSessionThread, (void *)k);
 	WaitThreadInit(t);
 
+	k->LastServerConnectionReceivedBlocksNum = 0;
+	k->CurrentSendPacketQueueSize = 0;
+
 	ReleaseThread(t);
 
 	return true;
@@ -209,6 +217,10 @@ UINT LinkPaGetNextPacket(SESSION *s, void **data)
 		return INFINITE;
 	}
 
+	if (k->Halting || (*k->StopAllLinkFlag))
+	{
+		return INFINITE;
+	}
 	// Examine whether there are packets in the queue
 	LockQueue(k->SendPacketQueue);
 	{
@@ -219,6 +231,9 @@ UINT LinkPaGetNextPacket(SESSION *s, void **data)
 			// There was a packet
 			*data = block->Buf;
 			ret = block->Size;
+
+			k->CurrentSendPacketQueueSize -= block->Size;
+
 			// Discard the memory for the structure
 			Free(block);
 		}
@@ -232,32 +247,95 @@ UINT LinkPaGetNextPacket(SESSION *s, void **data)
 bool LinkPaPutPacket(SESSION *s, void *data, UINT size)
 {
 	LINK *k;
-	BLOCK *block;
+	BLOCK *block = NULL;
 	SESSION *server_session;
 	CONNECTION *server_connection;
+	bool ret = true;
+	bool halting = false;
 	// Validate arguments
 	if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
 	{
 		return false;
 	}
 
+	halting = (k->Halting || (*k->StopAllLinkFlag));
+
 	server_session = k->ServerSession;
 	server_connection = server_session->Connection;
 
+	k->Flag1++;
+	if ((k->Flag1 % 32) == 0)
+	{
+		// Ommit for performance
+		UINT current_num;
+		int diff;
+
+		current_num = GetQueueNum(server_connection->ReceivedBlocks);
+
+		diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum;
+
+		k->LastServerConnectionReceivedBlocksNum = current_num;
+
+		CedarAddQueueBudget(k->Cedar, diff);
+	}
+
 	// Since the packet arrives from the HUB of the link destination,
 	// deliver it to the ReceivedBlocks of the server session
 	if (data != NULL)
 	{
-		block = NewBlock(data, size, 0);
+		if (halting == false)
+		{
+			block = NewBlock(data, size, 0);
+		}
 
-		LockQueue(server_connection->ReceivedBlocks);
+		if (k->LockFlag == false)
 		{
-			InsertQueue(server_connection->ReceivedBlocks, block);
+			UINT current_num;
+			int diff;
+
+			k->LockFlag = true;
+			LockQueue(server_connection->ReceivedBlocks);
+
+			current_num = GetQueueNum(server_connection->ReceivedBlocks);
+
+			diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum;
+
+			k->LastServerConnectionReceivedBlocksNum = current_num;
+
+			CedarAddQueueBudget(k->Cedar, diff);
+		}
+
+		if (halting == false)
+		{
+			if (CedarGetFifoBudgetBalance(k->Cedar) == 0)
+			{
+				FreeBlock(block);
+			}
+			else
+			{
+				InsertReveicedBlockToQueue(server_connection, block, true);
+			}
 		}
-		UnlockQueue(server_connection->ReceivedBlocks);
 	}
 	else
 	{
+		UINT current_num;
+		int diff;
+
+		current_num = GetQueueNum(server_connection->ReceivedBlocks);
+
+		diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum;
+
+		k->LastServerConnectionReceivedBlocksNum = current_num;
+
+		CedarAddQueueBudget(k->Cedar, diff);
+
+		if (k->LockFlag)
+		{
+			k->LockFlag = false;
+			UnlockQueue(server_connection->ReceivedBlocks);
+		}
+
 		// Issue the Cancel, since finished store all packets when the data == NULL
 		Cancel(server_session->Cancel1);
 
@@ -267,7 +345,12 @@ bool LinkPaPutPacket(SESSION *s, void *data, UINT size)
 		}
 	}
 
-	return true;
+	if (halting)
+	{
+		ret = false;
+	}
+
+	return ret;
 }
 
 // Release the packet adapter
@@ -280,6 +363,9 @@ void LinkPaFree(SESSION *s)
 		return;
 	}
 
+	CedarAddQueueBudget(k->Cedar, -((int)k->LastServerConnectionReceivedBlocksNum));
+	k->LastServerConnectionReceivedBlocksNum = 0;
+
 	// Stop the server session
 	StopSession(k->ServerSession);
 	ReleaseSession(k->ServerSession);
@@ -296,6 +382,8 @@ void LinkPaFree(SESSION *s)
 	UnlockQueue(k->SendPacketQueue);
 
 	ReleaseQueue(k->SendPacketQueue);
+
+	k->CurrentSendPacketQueueSize = 0;
 }
 
 // Packet adapter
@@ -384,6 +472,11 @@ void SetLinkOnline(LINK *k)
 		return;
 	}
 
+	if (k->NoOnline)
+	{
+		return;
+	}
+
 	if (k->Offline == false)
 	{
 		return;
@@ -467,6 +560,8 @@ void StopAllLink(HUB *h)
 		return;
 	}
 
+	h->StopAllLinkFlag = true;
+
 	LockList(h->LinkList);
 	{
 		link_list = ToArray(h->LinkList);
@@ -485,6 +580,8 @@ void StopAllLink(HUB *h)
 	}
 
 	Free(link_list);
+
+	h->StopAllLinkFlag = false;
 }
 
 // Start the link
@@ -505,6 +602,8 @@ void StartLink(LINK *k)
 			return;
 		}
 		k->Started = true;
+
+		Inc(k->Cedar->CurrentActiveLinks);
 	}
 	UnlockLink(k);
 
@@ -536,6 +635,8 @@ void StopLink(LINK *k)
 		}
 		k->Started = false;
 		k->Halting = true;
+
+		Dec(k->Cedar->CurrentActiveLinks);
 	}
 	UnlockLink(k);
 
@@ -593,8 +694,7 @@ void NormalizeLinkPolicy(POLICY *p)
 	}
 
 	p->Access = true;
-	p->NoBridge = p->NoRouting = p->PrivacyFilter =
-		p->MonitorPort = false;
+	p->NoBridge = p->NoRouting = p->MonitorPort = false;
 	p->MaxConnection = 32;
 	p->TimeOut = 20;
 	p->FixPassword = false;
@@ -653,6 +753,9 @@ LINK *NewLink(CEDAR *cedar, HUB *hub, CLIENT_OPTION *option, CLIENT_AUTH *auth,
 
 	// Link object
 	k = ZeroMalloc(sizeof(LINK));
+
+	k->StopAllLinkFlag = &hub->StopAllLinkFlag;
+
 	k->lock = NewLock();
 	k->ref = NewRef();
 

+ 6 - 0
src/Cedar/Link.h

@@ -119,6 +119,7 @@ struct LINK
 	bool Started;					// Running flag
 	volatile bool Halting;			// Halting flag
 	bool Offline;					// Offline
+	bool NoOnline;					// Do not set to online flag
 	REF *ref;						// Reference counter
 	LOCK *lock;						// Lock
 	CEDAR *Cedar;					// Cedar
@@ -129,9 +130,14 @@ struct LINK
 	CLIENT_AUTH *Auth;				// Authentication data
 	POLICY *Policy;					// Policy
 	QUEUE *SendPacketQueue;			// Transmission packet queue
+	UINT CurrentSendPacketQueueSize;	// Current send packet queue size
 	UINT LastError;					// Last error
 	bool CheckServerCert;			// To check the server certificate
 	X *ServerCert;					// Server certificate
+	bool LockFlag;					// Lock flag
+	bool *StopAllLinkFlag;			// Stop all link flag
+	UINT LastServerConnectionReceivedBlocksNum;	// Last server connection recv queue num
+	UINT Flag1;
 };
 
 

+ 104 - 9
src/Cedar/Logging.c

@@ -127,8 +127,12 @@ static char *delete_targets[] =
 	"server_log",
 	"bridge_log",
 	"packet_log_archive",
+	"azure_log",
 };
 
+static UINT eraser_check_interval = DISK_FREE_CHECK_INTERVAL_DEFAULT;
+static UINT64 logger_max_log_size = MAX_LOG_SIZE_DEFAULT;
+
 // Send with syslog
 void SendSysLog(SLOG *g, wchar_t *str)
 {
@@ -479,8 +483,34 @@ void EraserThread(THREAD *t, void *p)
 		// Check the amount of free space on the disk periodically
 		EraserMain(e);
 
-		Wait(e->HaltEvent, DISK_FREE_CHECK_INTERVAL);
+		Wait(e->HaltEvent, GetEraserCheckInterval());
+	}
+}
+
+// Set the interval for disk free space check
+void SetEraserCheckInterval(UINT interval)
+{
+	if (interval == 0)
+	{
+		eraser_check_interval = DISK_FREE_CHECK_INTERVAL_DEFAULT;
+	}
+	else
+	{
+		eraser_check_interval = interval * 1000;
+	}
+}
+
+// Get the interval for disk free space check
+UINT GetEraserCheckInterval()
+{
+	UINT ret = eraser_check_interval / 1000;
+
+	if (ret == 0)
+	{
+		ret = 1;
 	}
+
+	return ret;
 }
 
 // Create a new eraser
@@ -1045,8 +1075,8 @@ bool PacketLog(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *packe
 		return true;
 	}
 
-	if (Cmp(hub->HubMacAddr, packet->MacAddressSrc, 6) == 0 ||
-		Cmp(hub->HubMacAddr, packet->MacAddressDest, 6) == 0)
+	if (memcmp(hub->HubMacAddr, packet->MacAddressSrc, 6) == 0 ||
+		memcmp(hub->HubMacAddr, packet->MacAddressDest, 6) == 0)
 	{
 		return true;
 	}
@@ -2400,7 +2430,49 @@ bool MakeLogFileName(LOG *g, char *name, UINT size, char *dir, char *prefix, UIN
 	}
 	else
 	{
-		snprintf(tmp2, sizeof(tmp2), "~%02u", num);
+		UINT64 max_log_size = GetMaxLogSize();
+		if (max_log_size == MAX_LOG_SIZE_DEFAULT)
+		{
+			snprintf(tmp2, sizeof(tmp2), "~%02u", num);
+		}
+		else
+		{
+			char tag[32];
+			char c = '2';
+			if (max_log_size >= 1000000000ULL)
+			{
+				c = '3';
+			}
+			else if (max_log_size >= 100000000ULL)
+			{
+				c = '4';
+			}
+			else if (max_log_size >= 10000000ULL)
+			{
+				c = '5';
+			}
+			else if (max_log_size >= 1000000ULL)
+			{
+				c = '6';
+			}
+			else if (max_log_size >= 100000ULL)
+			{
+				c = '7';
+			}
+			else if (max_log_size >= 10000ULL)
+			{
+				c = '8';
+			}
+			else if (max_log_size >= 1000ULL)
+			{
+				c = '9';
+			}
+
+			StrCpy(tag, sizeof(tag), "~%02u");
+			tag[3] = c;
+
+			snprintf(tmp2, sizeof(tmp2), tag, num);
+		}
 	}
 
 	if (strcmp(old_datestr, tmp) != 0)
@@ -2444,6 +2516,30 @@ void WaitLogFlush(LOG *g)
 	}
 }
 
+// Set the max log size
+void SetMaxLogSize(UINT64 size)
+{
+	if (size == 0)
+	{
+		size = MAX_LOG_SIZE_DEFAULT;
+	}
+
+	logger_max_log_size = size;
+}
+
+// Get the max log size
+UINT64 GetMaxLogSize()
+{
+	UINT64 ret = logger_max_log_size;
+
+	if (ret == 0)
+	{
+		ret = MAX_LOG_SIZE_DEFAULT;
+	}
+
+	return ret;
+}
+
 // Logging thread
 void LogThread(THREAD *thread, void *param)
 {
@@ -2520,7 +2616,7 @@ void LogThread(THREAD *thread, void *param)
 			}
 #endif	// OS_WIN32
 
-			if (b->Size > g->MaxLogFileSize)
+			if (b->Size > GetMaxLogSize())
 			{
 				// Erase if the size of the buffer is larger than the maximum log file size
 				ClearBuf(b);
@@ -2531,7 +2627,7 @@ void LogThread(THREAD *thread, void *param)
 				// Write the contents of the buffer to the file
 				if (io != NULL)
 				{
-					if ((g->CurrentFilePointer + (UINT64)b->Size) > g->MaxLogFileSize)
+					if ((g->CurrentFilePointer + (UINT64)b->Size) > GetMaxLogSize())
 					{
 						if (g->log_number_incremented == false)
 						{
@@ -2565,7 +2661,7 @@ void LogThread(THREAD *thread, void *param)
 					// Write the contents of the buffer to the file
 					if (io != NULL)
 					{
-						if ((g->CurrentFilePointer + (UINT64)b->Size) > g->MaxLogFileSize)
+						if ((g->CurrentFilePointer + (UINT64)b->Size) > GetMaxLogSize())
 						{
 							if (g->log_number_incremented == false)
 							{
@@ -2637,7 +2733,7 @@ void LogThread(THREAD *thread, void *param)
 					{
 						if (log_date_changed)
 						{
-							if ((g->CurrentFilePointer + (UINT64)b->Size) <= g->MaxLogFileSize)
+							if ((g->CurrentFilePointer + (UINT64)b->Size) <= GetMaxLogSize())
 							{
 								if (FileWrite(io, b->Buf, b->Size) == false)
 								{
@@ -2863,7 +2959,6 @@ LOG *NewLog(char *dir, char *prefix, UINT switch_type)
 	g->SwitchType = switch_type;
 	g->RecordQueue = NewQueue();
 	g->Event = NewEvent();
-	g->MaxLogFileSize = MAX_LOG_SIZE;
 	g->FlushEvent = NewEvent();
 
 	g->Thread = NewThread(LogThread, g);

+ 5 - 2
src/Cedar/Logging.h

@@ -119,7 +119,7 @@
 #define	LOG_HTTP_PORT						80
 
 
-#define	MAX_LOG_SIZE						1073741823ULL
+#define	MAX_LOG_SIZE_DEFAULT				1073741823ULL
 
 typedef char *(RECORD_PARSE_PROC)(RECORD *rec);
 
@@ -171,7 +171,6 @@ struct LOG
 	UINT LastSwitchType;
 	char LastStr[MAX_SIZE];
 	UINT64 CurrentFilePointer;				// The current file pointer
-	UINT64 MaxLogFileSize;					// Maximum log file size
 	UINT CurrentLogNumber;					// Log file number of the current
 	bool log_number_incremented;
 };
@@ -269,6 +268,10 @@ void WriteMultiLineLog(LOG *g, BUF *b);
 char *BuildHttpLogStr(HTTPLOG *h);
 void MakeSafeLogStr(char *str);
 void AddLogBufToStr(BUF *b, char *name, char *value);
+void SetEraserCheckInterval(UINT interval);
+UINT GetEraserCheckInterval();
+void SetMaxLogSize(UINT64 size);
+UINT64 GetMaxLogSize();
 
 #endif	// LOGGING_G
 

+ 1 - 1
src/Cedar/NM.c

@@ -185,7 +185,7 @@ UINT NmEditPushRouteProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void
 
 				if (ok)
 				{
-					if (IsEmptyStr(r->CurrentPushRouteStr) == false)
+					if (IsEmptyStr(str) == false)
 					{
 						if (GetCapsBool(r->p->CapsList, "b_suppport_push_route") == false)
 						{

+ 53 - 2
src/Cedar/NullLan.c

@@ -124,10 +124,41 @@ PACKET_ADAPTER *NullGetPacketAdapter()
 	return pa;
 }
 
+// Generate MAC address
+void NullGenerateMacAddress(UCHAR *mac, UINT id, UINT seq)
+{
+	UCHAR hash[SHA1_SIZE];
+	char name[MAX_SIZE];
+	BUF *b;
+	// Validate arguments
+	if (mac == NULL)
+	{
+		return;
+	}
+
+	b = NewBuf();
+	WriteBufInt(b, id);
+	WriteBufInt(b, seq);
+	GetMachineHostName(name, sizeof(name));
+#ifdef	OS_WIN32
+	WriteBufInt(b, MsGetCurrentProcessId());
+#endif	// OS_WIN32
+	WriteBufStr(b, name);
+
+	HashSha1(hash, b->Buf, b->Size);
+
+	FreeBuf(b);
+
+	Copy(mac, hash, 6);
+	mac[0] = 0x7E;
+}
+
 // 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)
 	{
@@ -136,7 +167,12 @@ void NullPacketGenerateThread(THREAD *t, void *param)
 
 	while (true)
 	{
-		Wait(n->Event, Rand32() % NULL_PACKET_GENERATE_INTERVAL);
+		/*if (Tick64() >= end_tick)
+		{
+			break;
+		}*/
+
+		Wait(n->Event, Rand32() % 1500);
 		if (n->Halt)
 		{
 			break;
@@ -147,14 +183,25 @@ void NullPacketGenerateThread(THREAD *t, void *param)
 			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++;
 	}
 }
 
@@ -162,20 +209,24 @@ void NullPacketGenerateThread(THREAD *t, void *param)
 bool NullPaInit(SESSION *s)
 {
 	NULL_LAN *n;
+	static UINT id_seed = 0;
 	// Validate arguments
 	if (s == NULL)
 	{
 		return false;
 	}
 
+	id_seed++;
+
 	n = ZeroMalloc(sizeof(NULL_LAN));
+	n->Id = id_seed;
 	s->PacketAdapter->Param = (void *)n;
 
 	n->Cancel = NewCancel();
 	n->PacketQueue = NewQueue();
 	n->Event = NewEvent();
 
-	GenMacAddress(n->MacAddr);
+	NullGenerateMacAddress(n->MacAddr, n->Id, 0);
 
 	n->PacketGeneratorThread = NewThread(NullPacketGenerateThread, n);
 

+ 2 - 0
src/Cedar/NullLan.h

@@ -127,6 +127,7 @@ struct NULL_LAN
 	EVENT *Event;
 	UCHAR MacAddr[6];
 	UCHAR Padding[2];
+	UINT Id;
 };
 
 PACKET_ADAPTER *NullGetPacketAdapter();
@@ -136,6 +137,7 @@ UINT NullPaGetNextPacket(SESSION *s, void **data);
 bool NullPaPutPacket(SESSION *s, void *data, UINT size);
 void NullPaFree(SESSION *s);
 void NullPacketGenerateThread(THREAD *t, void *param);
+void NullGenerateMacAddress(UCHAR *mac, UINT id, UINT seq);
 
 #endif	// NULLAN_H
 

+ 7 - 1
src/Cedar/Protocol.c

@@ -2707,6 +2707,12 @@ bool ServerAccept(CONNECTION *c)
 				}
 			}
 
+			if (use_encrypt == false && c->FirstSock->IsReverseAcceptedSocket)
+			{
+				// On VPN Azure, SSL encryption is mandated.
+				use_encrypt = true;
+			}
+
 			if (use_client_license || use_bridge_license)
 			{
 				// Examine whether not to conflict with the limit of simultaneous connections
@@ -6939,7 +6945,7 @@ SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag,
 	if (hWnd == NULL)
 	{
 #endif	// OS_WIN32
-		return ConnectEx3(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, ssl_no_tls, false);
+		return ConnectEx3(hostname, port, timeout, cancel_flag, (no_nat_t ? NULL : VPN_RUDP_SVC_NAME), nat_t_error_code, try_start_ssl, ssl_no_tls, true);
 #ifdef	OS_WIN32
 	}
 	else

+ 14 - 7
src/Cedar/SM.c

@@ -19097,13 +19097,6 @@ void SmConnectEx(HWND hWnd, SETTING *s, bool is_in_client)
 		return;
 	}
 
-	// Updater terminate
-	if (sm->Update != NULL)
-	{
-		FreeUpdateUi(sm->Update);
-		sm->Update = NULL;
-	}
-
 	// Disable the control
 	Disable(hWnd, L_SETTING);
 	Disable(hWnd, B_NEW_SETTING);
@@ -20272,6 +20265,8 @@ UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *para
 		switch (wParam)
 		{
 		case IDOK:
+			DisableUpdateUi(sm->Update);
+
 			// Connection
 			i = LvGetSelected(hWnd, L_SETTING);
 			if (i != INFINITE)
@@ -20301,6 +20296,8 @@ UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *para
 			break;
 
 		case B_NEW_SETTING:
+			DisableUpdateUi(sm->Update);
+
 			// Add
 			if (SmAddSettingDlg(hWnd, new_name, sizeof(new_name)))
 			{
@@ -20309,6 +20306,8 @@ UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *para
 			break;
 
 		case B_EDIT_SETTING:
+			DisableUpdateUi(sm->Update);
+
 			// Edit
 			if (SmEditSettingDlg(hWnd))
 			{
@@ -20319,6 +20318,8 @@ UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *para
 			break;
 
 		case B_DELETE:
+			DisableUpdateUi(sm->Update);
+
 			// Delete
 			i = LvGetSelected(hWnd, L_SETTING);
 			if (i != INFINITE)
@@ -20344,16 +20345,22 @@ UINT SmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *para
 			break;
 
 		case B_SECURE_MANAGER:
+			DisableUpdateUi(sm->Update);
+
 			// Smart Card Manager
 			SmSecureManager(hWnd);
 			break;
 
 		case B_SELECT_SECURE:
+			DisableUpdateUi(sm->Update);
+
 			// Smart card selection
 			SmSelectSecureId(hWnd);
 			break;
 
 		case B_CERT_TOOL:
+			DisableUpdateUi(sm->Update);
+
 			// Certificate Creation Tool
 			SmCreateCert(hWnd, NULL, NULL, false, NULL, false);
 			break;

+ 1 - 1
src/Cedar/SW.c

@@ -3166,7 +3166,7 @@ bool SwInstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c)
 	}
 
 	// Install the SeLow
-	if (SuIsSupportedOs())
+	if (SuIsSupportedOs(true))
 	{
 		// Only in the system mode
 		if (c->InstallService && sw->IsSystemMode)

+ 32 - 13
src/Cedar/SeLowUser.c

@@ -154,18 +154,12 @@ bool SuInstallDriverInner(bool force)
 	wchar_t tmp_dir[MAX_PATH];
 	char *cpu_type = MsIsX64() ? "x64" : "x86";
 
-	if (SuIsSupportedOs() == false)
+	if (SuIsSupportedOs(true) == false)
 	{
 		// Unsupported OS
 		return false;
 	}
 
-	if (MsIsServiceRunning("RemoteAccess"))
-	{
-		// Remote Access service is running
-		return false;
-	}
-
 	CombinePathW(tmp_dir, sizeof(tmp_dir), MsGetWindowsDirW(), L"Temp");
 	MakeDirExW(tmp_dir);
 
@@ -255,14 +249,36 @@ bool SuInstallDriverInner(bool force)
 }
 
 // Get whether the current OS is supported by SeLow
-bool SuIsSupportedOs()
+bool SuIsSupportedOs(bool on_install)
 {
+	if (MsRegReadIntEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, "EnableSeLow", false, true) != 0)
+	{
+		// Force enable
+		return true;
+	}
+
 	if (MsRegReadIntEx2(REG_LOCAL_MACHINE, SL_REG_KEY_NAME, "DisableSeLow", false, true) != 0)
 	{
 		// Force disable
 		return false;
 	}
 
+	if (MsIsWindows10())
+	{
+		// Windows 10 or later are always supported.
+		return true;
+	}
+
+	if (on_install)
+	{
+		// If Microsoft Routing and Remote Access service is running,
+		// then return false.
+		if (MsIsServiceRunning("RemoteAccess"))
+		{
+			return false;
+		}
+	}
+
 	// If the Su driver is currently running,
 	// then return true.
 	if (MsIsServiceRunning(SL_PROTOCOL_NAME))
@@ -276,11 +292,14 @@ bool SuIsSupportedOs()
 		return false;
 	}
 
-	// If Microsoft Routing and Remote Access service is running,
-	// then return false.
-	if (MsIsServiceRunning("RemoteAccess"))
+	if (on_install == false)
 	{
-		return false;
+		// If Microsoft Routing and Remote Access service is running,
+		// then return false.
+		if (MsIsServiceRunning("RemoteAccess"))
+		{
+			return false;
+		}
 	}
 
 	return true;
@@ -720,7 +739,7 @@ SU *SuInitEx(UINT wait_for_bind_complete_tick)
 	bool flag = false;
 	UINT64 giveup_tick = 0;
 
-	if (SuIsSupportedOs() == false)
+	if (SuIsSupportedOs(false) == false)
 	{
 		// Unsupported OS
 		return NULL;

+ 1 - 1
src/Cedar/SeLowUser.h

@@ -172,7 +172,7 @@ int SuCmpAdaterList(void *p1, void *p2);
 
 bool SuInstallDriver(bool force);
 bool SuInstallDriverInner(bool force);
-bool SuIsSupportedOs();
+bool SuIsSupportedOs(bool on_install);
 
 #endif	// SELOWUSER_H
 

+ 199 - 14
src/Cedar/Server.c

@@ -118,11 +118,15 @@ static LOCK *server_lock = NULL;
 char *SERVER_CONFIG_FILE_NAME = "@vpn_server.config";
 char *SERVER_CONFIG_FILE_NAME_IN_CLIENT = "@vpn_gate_svc.config";
 char *BRIDGE_CONFIG_FILE_NAME = "@vpn_bridge.config";
+char *SERVER_CONFIG_TEMPLATE_NAME = "@vpn_server_template.config";
+char *BRIDGE_CONFIG_TEMPLATE_NAME = "@vpn_server_template.config";
 
 static bool server_reset_setting = false;
 
 static volatile UINT global_server_flags[NUM_GLOBAL_SERVER_FLAGS] = {0};
 
+UINT vpn_global_parameters[NUM_GLOBAL_PARAMS] = {0};
+
 // Set the OpenVPN and SSTP setting
 void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
 {
@@ -255,6 +259,7 @@ UINT SiDebug(SERVER *s, RPC_TEST *ret, UINT i, char *str)
 		{9, "Set IPsecMessageDisplayed Flag", "", SiDebugProcSetIPsecMessageDisplayedValue},
 		{10, "Get VgsMessageDisplayed Flag", "", SiDebugProcGetVgsMessageDisplayedValue},
 		{11, "Set VgsMessageDisplayed Flag", "", SiDebugProcSetVgsMessageDisplayedValue},
+		{12, "Get the current TCP send queue length", "", SiDebugProcGetCurrentTcpSendQueueLength},
 	};
 	UINT num_proc_list = sizeof(proc_list) / sizeof(proc_list[0]);
 	UINT j;
@@ -452,6 +457,27 @@ UINT SiDebugProcGetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_s
 
 	return ERR_NO_ERROR;
 }
+UINT SiDebugProcGetCurrentTcpSendQueueLength(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
+{
+	char tmp1[64], tmp2[64], tmp3[64];
+	// Validate arguments
+	if (s == NULL || in_str == NULL || ret_str == NULL)
+	{
+		return ERR_INVALID_PARAMETER;
+	}
+
+	ToStr3(tmp1, 0, CedarGetCurrentTcpQueueSize(s->Cedar));
+	ToStr3(tmp2, 0, CedarGetQueueBudgetConsuming(s->Cedar));
+	ToStr3(tmp3, 0, CedarGetFifoBudgetConsuming(s->Cedar));
+
+	Format(ret_str, 0, 
+		"CurrentTcpQueueSize  = %s\n"
+		"QueueBudgetConsuming = %s\n"
+		"FifoBudgetConsuming  = %s\n",
+		tmp1, tmp2, tmp3);
+
+	return ERR_NO_ERROR;
+}
 UINT SiDebugProcSetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size)
 {
 	// Validate arguments
@@ -491,6 +517,7 @@ void SiCheckDeadLockMain(SERVER *s, UINT timeout)
 
 	//Debug("SiCheckDeadLockMain Start.\n");
 
+
 	cedar = s->Cedar;
 
 	if (s->ServerListenerList != NULL)
@@ -2440,6 +2467,7 @@ void SiSetDefaultHubOption(HUB_OPTION *o)
 	o->NoDhcpPacketLogOutsideHub = true;
 	o->AccessListIncludeFileCacheLifetime = ACCESS_LIST_INCLUDE_FILE_CACHE_LIFETIME;
 	o->RemoveDefGwOnDhcpForLocalhost = true;
+	o->FloodingSendQueueBufferQuota = DEFAULT_FLOODING_QUEUE_LENGTH;
 }
 
 // Create a default virtual HUB
@@ -2534,6 +2562,8 @@ void SiLoadInitialConfiguration(SERVER *s)
 
 	s->Weight = FARM_DEFAULT_WEIGHT;
 
+	SiLoadGlobalParamsCfg(NULL);
+
 	// KEEP related
 	Zero(&k, sizeof(k));
 
@@ -2676,8 +2706,9 @@ bool SiLoadConfigurationFile(SERVER *s)
 	}
 
 
-	s->CfgRw = NewCfgRw(&root,
-		s->Cedar->Bridge == false ? server_config_filename : BRIDGE_CONFIG_FILE_NAME);
+	s->CfgRw = NewCfgRwEx2A(&root,
+		s->Cedar->Bridge == false ? server_config_filename : BRIDGE_CONFIG_FILE_NAME, false,
+		s->Cedar->Bridge == false ? SERVER_CONFIG_TEMPLATE_NAME : BRIDGE_CONFIG_TEMPLATE_NAME);
 
 	if (server_reset_setting)
 	{
@@ -2731,6 +2762,8 @@ void SiInitConfiguration(SERVER *s)
 		SLog(s->Cedar, "LS_LOAD_CONFIG_3");
 		SiLoadInitialConfiguration(s);
 
+		SetFifoCurrentReallocMemSize(MEM_FIFO_REALLOC_MEM_SIZE);
+
 		server_reset_setting = false;
 	}
 	else
@@ -3155,6 +3188,10 @@ void SiWriteLocalBridges(FOLDER *f, SERVER *s)
 	CfgAddBool(f, "EnableSoftEtherKernelModeDriver", Win32GetEnableSeLow());
 #endif	// OS_WIN32
 
+#ifdef	UNIX_LINUX
+	CfgAddBool(f, "DoNotDisableOffloading", GetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD));
+#endif	// UNIX_LINUX
+
 	LockList(s->Cedar->LocalBridgeList);
 	{
 		UINT i;
@@ -3234,6 +3271,10 @@ void SiLoadLocalBridges(SERVER *s, FOLDER *f)
 	Win32EthSetShowAllIf(CfgGetBool(f, "ShowAllInterfaces"));
 #endif	// OS_WIN32
 
+#ifdef	UNIX_LINUX
+	SetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD, CfgGetBool(f, "DoNotDisableOffloading"));
+#endif	// UNIX_LINUX
+
 	t = CfgEnumFolderToTokenList(f);
 
 	for (i = 0;i < t->NumTokens;i++)
@@ -3972,6 +4013,14 @@ void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
 	o->FixForDLinkBPDU = CfgGetBool(f, "FixForDLinkBPDU");
 	o->BroadcastLimiterStrictMode = CfgGetBool(f, "BroadcastLimiterStrictMode");
 	o->MaxLoggedPacketsPerMinute = CfgGetInt(f, "MaxLoggedPacketsPerMinute");
+	if (CfgIsItem(f, "FloodingSendQueueBufferQuota"))
+	{
+		o->FloodingSendQueueBufferQuota = CfgGetInt(f, "FloodingSendQueueBufferQuota");
+	}
+	else
+	{
+		o->FloodingSendQueueBufferQuota = DEFAULT_FLOODING_QUEUE_LENGTH;
+	}
 	o->DoNotSaveHeavySecurityLogs = CfgGetBool(f, "DoNotSaveHeavySecurityLogs");
 
 	if (CfgIsItem(f, "DropBroadcastsInPrivacyFilterMode"))
@@ -4102,6 +4151,7 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
 	}
 	CfgAddBool(f, "BroadcastLimiterStrictMode", o->BroadcastLimiterStrictMode);
 	CfgAddInt(f, "MaxLoggedPacketsPerMinute", o->MaxLoggedPacketsPerMinute);
+	CfgAddInt(f, "FloodingSendQueueBufferQuota", o->FloodingSendQueueBufferQuota);
 	CfgAddBool(f, "DoNotSaveHeavySecurityLogs", o->DoNotSaveHeavySecurityLogs);
 	CfgAddBool(f, "DropBroadcastsInPrivacyFilterMode", o->DropBroadcastsInPrivacyFilterMode);
 	CfgAddBool(f, "DropArpInPrivacyFilterMode", o->DropArpInPrivacyFilterMode);
@@ -5697,6 +5747,7 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
 	K *k = NULL;
 	bool cluster_allowed = false;
 	UINT num_connections_per_ip = 0;
+	FOLDER *params_folder;
 	// Validate arguments
 	if (s == NULL || f == NULL)
 	{
@@ -5725,6 +5776,19 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
 		s->BackupConfigOnlyWhenModified = true;
 	}
 
+	// Server log switch type
+	if (CfgIsItem(f, "ServerLogSwitchType"))
+	{
+		UINT st = CfgGetInt(f, "ServerLogSwitchType");
+
+		SetLogSwitchType(s->Logger, st);
+	}
+
+	SetMaxLogSize(CfgGetInt64(f, "LoggerMaxLogSize"));
+
+	params_folder = CfgGetFolder(f, "GlobalParams");
+	SiLoadGlobalParamsCfg(params_folder);
+
 	c = s->Cedar;
 	Lock(c->lock);
 	{
@@ -5805,6 +5869,7 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
 		s->DisableDeadLockCheck = CfgGetBool(f, "DisableDeadLockCheck");
 
 		// Eraser
+		SetEraserCheckInterval(CfgGetInt(f, "AutoDeleteCheckIntervalSecs"));
 		s->Eraser = NewEraser(s->Logger, CfgGetInt64(f, "AutoDeleteCheckDiskFreeSpaceMin"));
 
 		// WebUI
@@ -6015,8 +6080,99 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
 
 		// Configuration of VPN Azure Client
 		s->EnableVpnAzure = CfgGetBool(f, "EnableVpnAzure");
+
+		// Disable GetHostName when accepting TCP
+		s->DisableGetHostNameWhenAcceptTcp = CfgGetBool(f, "DisableGetHostNameWhenAcceptTcp");
+
+		if (s->DisableGetHostNameWhenAcceptTcp)
+		{
+			DisableGetHostNameWhenAcceptInit();
+		}
+
+		// Disable core dump on UNIX
+		s->DisableCoreDumpOnUnix = CfgGetBool(f, "DisableCoreDumpOnUnix");
+
+		// Disable session reconnect
+		SetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT, CfgGetBool(f, "DisableSessionReconnect"));
 	}
 	Unlock(c->lock);
+
+#ifdef	OS_UNIX
+	if (s->DisableCoreDumpOnUnix)
+	{
+		UnixDisableCoreDump();
+	}
+#endif	// OS_UNIX
+}
+
+// Load global params
+void SiLoadGlobalParamsCfg(FOLDER *f)
+{
+	SiLoadGlobalParamItem(GP_MAX_SEND_SOCKET_QUEUE_SIZE, CfgGetInt(f, "MAX_SEND_SOCKET_QUEUE_SIZE"));
+	SiLoadGlobalParamItem(GP_MIN_SEND_SOCKET_QUEUE_SIZE, CfgGetInt(f, "MIN_SEND_SOCKET_QUEUE_SIZE"));
+	SiLoadGlobalParamItem(GP_MAX_SEND_SOCKET_QUEUE_NUM, CfgGetInt(f, "MAX_SEND_SOCKET_QUEUE_NUM"));
+	SiLoadGlobalParamItem(GP_SELECT_TIME, CfgGetInt(f, "SELECT_TIME"));
+	SiLoadGlobalParamItem(GP_SELECT_TIME_FOR_NAT, CfgGetInt(f, "SELECT_TIME_FOR_NAT"));
+	SiLoadGlobalParamItem(GP_MAX_STORED_QUEUE_NUM, CfgGetInt(f, "MAX_STORED_QUEUE_NUM"));
+	SiLoadGlobalParamItem(GP_MAX_BUFFERING_PACKET_SIZE, CfgGetInt(f, "MAX_BUFFERING_PACKET_SIZE"));
+	SiLoadGlobalParamItem(GP_HUB_ARP_SEND_INTERVAL, CfgGetInt(f, "HUB_ARP_SEND_INTERVAL"));
+	SiLoadGlobalParamItem(GP_MAC_TABLE_EXPIRE_TIME, CfgGetInt(f, "MAC_TABLE_EXPIRE_TIME"));
+	SiLoadGlobalParamItem(GP_IP_TABLE_EXPIRE_TIME, CfgGetInt(f, "IP_TABLE_EXPIRE_TIME"));
+	SiLoadGlobalParamItem(GP_IP_TABLE_EXPIRE_TIME_DHCP, CfgGetInt(f, "IP_TABLE_EXPIRE_TIME_DHCP"));
+	SiLoadGlobalParamItem(GP_STORM_CHECK_SPAN, CfgGetInt(f, "STORM_CHECK_SPAN"));
+	SiLoadGlobalParamItem(GP_STORM_DISCARD_VALUE_START, CfgGetInt(f, "STORM_DISCARD_VALUE_START"));
+	SiLoadGlobalParamItem(GP_STORM_DISCARD_VALUE_END, CfgGetInt(f, "STORM_DISCARD_VALUE_END"));
+	SiLoadGlobalParamItem(GP_MAX_MAC_TABLES, CfgGetInt(f, "MAX_MAC_TABLES"));
+	SiLoadGlobalParamItem(GP_MAX_IP_TABLES, CfgGetInt(f, "MAX_IP_TABLES"));
+	SiLoadGlobalParamItem(GP_MAX_HUB_LINKS, CfgGetInt(f, "MAX_HUB_LINKS"));
+	SiLoadGlobalParamItem(GP_MEM_FIFO_REALLOC_MEM_SIZE, CfgGetInt(f, "MEM_FIFO_REALLOC_MEM_SIZE"));
+	SiLoadGlobalParamItem(GP_QUEUE_BUDGET, CfgGetInt(f, "QUEUE_BUDGET"));
+	SiLoadGlobalParamItem(GP_FIFO_BUDGET, CfgGetInt(f, "FIFO_BUDGET"));
+
+	SetFifoCurrentReallocMemSize(MEM_FIFO_REALLOC_MEM_SIZE);
+}
+
+// Load global param itesm
+void SiLoadGlobalParamItem(UINT id, UINT value)
+{
+	// Validate arguments
+	if (id == 0)
+	{
+		return;
+	}
+
+	vpn_global_parameters[id] = value;
+}
+
+// Write global params
+void SiWriteGlobalParamsCfg(FOLDER *f)
+{
+	// Validate arguments
+	if (f == NULL)
+	{
+		return;
+	}
+
+	CfgAddInt(f, "MAX_SEND_SOCKET_QUEUE_SIZE", MAX_SEND_SOCKET_QUEUE_SIZE);
+	CfgAddInt(f, "MIN_SEND_SOCKET_QUEUE_SIZE", MIN_SEND_SOCKET_QUEUE_SIZE);
+	CfgAddInt(f, "MAX_SEND_SOCKET_QUEUE_NUM", MAX_SEND_SOCKET_QUEUE_NUM);
+	CfgAddInt(f, "SELECT_TIME", SELECT_TIME);
+	CfgAddInt(f, "SELECT_TIME_FOR_NAT", SELECT_TIME_FOR_NAT);
+	CfgAddInt(f, "MAX_STORED_QUEUE_NUM", MAX_STORED_QUEUE_NUM);
+	CfgAddInt(f, "MAX_BUFFERING_PACKET_SIZE", MAX_BUFFERING_PACKET_SIZE);
+	CfgAddInt(f, "HUB_ARP_SEND_INTERVAL", HUB_ARP_SEND_INTERVAL);
+	CfgAddInt(f, "MAC_TABLE_EXPIRE_TIME", MAC_TABLE_EXPIRE_TIME);
+	CfgAddInt(f, "IP_TABLE_EXPIRE_TIME", IP_TABLE_EXPIRE_TIME);
+	CfgAddInt(f, "IP_TABLE_EXPIRE_TIME_DHCP", IP_TABLE_EXPIRE_TIME_DHCP);
+	CfgAddInt(f, "STORM_CHECK_SPAN", STORM_CHECK_SPAN);
+	CfgAddInt(f, "STORM_DISCARD_VALUE_START", STORM_DISCARD_VALUE_START);
+	CfgAddInt(f, "STORM_DISCARD_VALUE_END", STORM_DISCARD_VALUE_END);
+	CfgAddInt(f, "MAX_MAC_TABLES", MAX_MAC_TABLES);
+	CfgAddInt(f, "MAX_IP_TABLES", MAX_IP_TABLES);
+	CfgAddInt(f, "MAX_HUB_LINKS", MAX_HUB_LINKS);
+	CfgAddInt(f, "MEM_FIFO_REALLOC_MEM_SIZE", MEM_FIFO_REALLOC_MEM_SIZE);
+	CfgAddInt(f, "QUEUE_BUDGET", QUEUE_BUDGET);
+	CfgAddInt(f, "FIFO_BUDGET", FIFO_BUDGET);
 }
 
 // Write the server-specific settings
@@ -6024,6 +6180,7 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
 {
 	BUF *b;
 	CEDAR *c;
+	FOLDER *params_folder;
 	// Validate arguments
 	if (f == NULL || s == NULL)
 	{
@@ -6037,6 +6194,20 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
 	CfgAddBool(f, "DontBackupConfig", s->DontBackupConfig);
 	CfgAddBool(f, "BackupConfigOnlyWhenModified", s->BackupConfigOnlyWhenModified);
 
+	if (s->Logger != NULL)
+	{
+		CfgAddInt(f, "ServerLogSwitchType", s->Logger->SwitchType);
+	}
+
+	CfgAddInt64(f, "LoggerMaxLogSize", GetMaxLogSize());
+
+	params_folder = CfgCreateFolder(f, "GlobalParams");
+
+	if (params_folder != NULL)
+	{
+		SiWriteGlobalParamsCfg(params_folder);
+	}
+
 	c = s->Cedar;
 
 	Lock(c->lock);
@@ -6084,6 +6255,7 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
 
 		// Eraser related
 		CfgAddInt64(f, "AutoDeleteCheckDiskFreeSpaceMin", s->Eraser->MinFreeSpace);
+		CfgAddInt(f, "AutoDeleteCheckIntervalSecs", GetEraserCheckInterval());
 
 		// WebUI
 		CfgAddBool(f, "UseWebUI", s->UseWebUI);
@@ -6222,6 +6394,12 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
 		{
 			CfgAddBool(f, "EnableVpnAzure", s->EnableVpnAzure);
 		}
+
+		CfgAddBool(f, "DisableGetHostNameWhenAcceptTcp", s->DisableGetHostNameWhenAcceptTcp);
+		CfgAddBool(f, "DisableCoreDumpOnUnix", s->DisableCoreDumpOnUnix);
+
+		// Disable session reconnect
+		CfgAddBool(f, "DisableSessionReconnect", GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT));
 	}
 	Unlock(c->lock);
 }
@@ -7115,7 +7293,7 @@ void SiCalledEnumHub(SERVER *s, PACK *p, PACK *req)
 				PackAddIntEx(p, "NumSessionsClient", Count(h->NumSessionsClient), i, num);
 				PackAddIntEx(p, "NumSessionsBridge", Count(h->NumSessionsBridge), i, num);
 
-				PackAddIntEx(p, "NumMacTables", LIST_NUM(h->MacTable), i, num);
+				PackAddIntEx(p, "NumMacTables", HASH_LIST_NUM(h->MacHashTable), i, num);
 
 				PackAddIntEx(p, "NumIpTables", LIST_NUM(h->IpTable), i, num);
 
@@ -7243,6 +7421,7 @@ void SiCalledUpdateHub(SERVER *s, PACK *p)
 	o.NoLookBPDUBridgeId = PackGetBool(p, "NoLookBPDUBridgeId");
 	o.NoManageVlanId = PackGetBool(p, "NoManageVlanId");
 	o.MaxLoggedPacketsPerMinute = PackGetInt(p, "MaxLoggedPacketsPerMinute");
+	o.FloodingSendQueueBufferQuota = PackGetInt(p, "FloodingSendQueueBufferQuota");
 	o.DoNotSaveHeavySecurityLogs = PackGetBool(p, "DoNotSaveHeavySecurityLogs");
 	o.DropBroadcastsInPrivacyFilterMode = PackGetBool(p, "DropBroadcastsInPrivacyFilterMode");
 	o.DropArpInPrivacyFilterMode = PackGetBool(p, "DropArpInPrivacyFilterMode");
@@ -7464,16 +7643,13 @@ void SiCalledDeleteMacTable(SERVER *s, PACK *p)
 		return;
 	}
 
-	LockList(h->MacTable);
+	LockHashList(h->MacHashTable);
 	{
-		if (IsInList(h->MacTable, (void *)key))
-		{
-			MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)key;
-			Delete(h->MacTable, e);
-			Free(e);
-		}
+		MAC_TABLE_ENTRY *e = HashListKeyToPointer(h->MacHashTable, key);
+		DeleteHash(h->MacHashTable, e);
+		Free(e);
 	}
-	UnlockList(h->MacTable);
+	UnlockHashList(h->MacHashTable);
 
 	ReleaseHub(h);
 }
@@ -8316,11 +8492,11 @@ void SiCallEnumHub(SERVER *s, FARM_MEMBER *f)
 							}
 							UnlockList(h->SessionList);
 
-							LockList(h->MacTable);
+							LockHashList(h->MacHashTable);
 							{
-								hh->NumMacTables = LIST_NUM(h->MacTable);
+								hh->NumMacTables = HASH_LIST_NUM(h->MacHashTable);
 							}
-							UnlockList(h->MacTable);
+							UnlockHashList(h->MacHashTable);
 
 							LockList(h->IpTable);
 							{
@@ -9084,6 +9260,7 @@ void SiPackAddCreateHub(PACK *p, HUB *h)
 	PackAddBool(p, "NoSpinLockForPacketDelay", h->Option->NoSpinLockForPacketDelay);
 	PackAddInt(p, "BroadcastStormDetectionThreshold", h->Option->BroadcastStormDetectionThreshold);
 	PackAddInt(p, "MaxLoggedPacketsPerMinute", h->Option->MaxLoggedPacketsPerMinute);
+	PackAddInt(p, "FloodingSendQueueBufferQuota", h->Option->FloodingSendQueueBufferQuota);
 	PackAddBool(p, "DoNotSaveHeavySecurityLogs", h->Option->DoNotSaveHeavySecurityLogs);
 	PackAddBool(p, "DropBroadcastsInPrivacyFilterMode", h->Option->DropBroadcastsInPrivacyFilterMode);
 	PackAddBool(p, "DropArpInPrivacyFilterMode", h->Option->DropArpInPrivacyFilterMode);
@@ -10631,6 +10808,8 @@ SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server)
 
 	s = ZeroMalloc(sizeof(SERVER));
 
+	SetEraserCheckInterval(0);
+
 	SiInitHubCreateHistory(s);
 
 	InitServerCapsCache(s);
@@ -10699,6 +10878,8 @@ SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server)
 	// Initialize the configuration
 	SiInitConfiguration(s);
 
+	SetFifoCurrentReallocMemSize(MEM_FIFO_REALLOC_MEM_SIZE);
+
 
 	if (s->DisableIntelAesAcceleration)
 	{
@@ -10712,6 +10893,10 @@ SERVER *SiNewServerEx(bool bridge, bool in_client_inner_server)
 		OSSetHighPriority();
 	}
 
+#ifdef	OS_UNIX
+	UnixSetHighOomScore();
+#endif	// OS_UNIX
+
 	if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
 	{
 		// Start a connection to the controller

+ 36 - 0
src/Cedar/Server.h

@@ -352,6 +352,9 @@ struct SERVER
 	AZURE_CLIENT *AzureClient;			// VPN Azure client
 	bool EnableVpnAzure;				// Flag whether VPN Azure client is enabled
 
+	bool DisableGetHostNameWhenAcceptTcp;	// Disable GetHostName when accepting TCP
+	bool DisableCoreDumpOnUnix;			// Disable core dump on UNIX
+
 	TINY_LOG *DebugLog;					// Debug log
 
 	DYNAMIC_LISTENER *DynListenerIcmp;	// VPN over ICMP listener
@@ -428,6 +431,35 @@ struct LOG_FILE
 #define	GSF_DISABLE_AC					5
 #define	GSF_DISABLE_SYSLOG				6
 #define	GSF_SHOW_OSS_MSG				7
+#define	GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD	8
+#define	GSF_DISABLE_SESSION_RECONNECT	9
+
+// Global parameters
+#define	NUM_GLOBAL_PARAMS					128
+#define	GP_MAX_SEND_SOCKET_QUEUE_SIZE		1
+#define	GP_MIN_SEND_SOCKET_QUEUE_SIZE		2
+#define	GP_MAX_SEND_SOCKET_QUEUE_NUM		3
+#define	GP_SELECT_TIME						4
+#define	GP_SELECT_TIME_FOR_NAT				5
+#define	GP_MAX_STORED_QUEUE_NUM				6
+#define	GP_MAX_BUFFERING_PACKET_SIZE		7
+#define	GP_HUB_ARP_SEND_INTERVAL			8
+#define	GP_MAC_TABLE_EXPIRE_TIME			9
+#define	GP_IP_TABLE_EXPIRE_TIME				10
+#define	GP_IP_TABLE_EXPIRE_TIME_DHCP		11
+#define	GP_STORM_CHECK_SPAN					12
+#define	GP_STORM_DISCARD_VALUE_START		13
+#define	GP_STORM_DISCARD_VALUE_END			14
+#define	GP_MAX_MAC_TABLES					15
+#define	GP_MAX_IP_TABLES					16
+#define	GP_MAX_HUB_LINKS					17
+#define	GP_MEM_FIFO_REALLOC_MEM_SIZE		18
+#define	GP_QUEUE_BUDGET						19
+#define	GP_FIFO_BUDGET						20
+
+extern UINT vpn_global_parameters[NUM_GLOBAL_PARAMS];
+
+#define	VPN_GP(id, default_value)	((UINT)(vpn_global_parameters[(id)] != 0 ? vpn_global_parameters[(id)] : (default_value)))
 
 
 
@@ -482,6 +514,9 @@ void SiWriteListenerCfg(FOLDER *f, SERVER_LISTENER *r);
 void SiLoadListenerCfg(SERVER *s, FOLDER *f);
 void SiWriteServerCfg(FOLDER *f, SERVER *s);
 void SiLoadServerCfg(SERVER *s, FOLDER *f);
+void SiWriteGlobalParamsCfg(FOLDER *f);
+void SiLoadGlobalParamsCfg(FOLDER *f);
+void SiLoadGlobalParamItem(UINT id, UINT value);
 void SiWriteTraffic(FOLDER *parent, char *name, TRAFFIC *t);
 void SiWriteTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e);
 void SiLoadTrafficInner(FOLDER *parent, char *name, TRAFFIC_ENTRY *e);
@@ -642,6 +677,7 @@ UINT SiDebugProcGetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret
 UINT SiDebugProcSetIPsecMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
 UINT SiDebugProcGetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
 UINT SiDebugProcSetVgsMessageDisplayedValue(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
+UINT SiDebugProcGetCurrentTcpSendQueueLength(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
 
 typedef UINT (SI_DEBUG_PROC)(SERVER *s, char *in_str, char *ret_str, UINT ret_str_size);
 

+ 164 - 35
src/Cedar/Session.c

@@ -137,6 +137,8 @@ void SessionMain(SESSION *s)
 	TRAFFIC t;
 	SOCK *msgdlg_sock = NULL;
 	SOCK *nicinfo_sock = NULL;
+	bool is_server_session = false;
+	bool lock_receive_blocks_queue = false;
 	// Validate arguments
 	if (s == NULL)
 	{
@@ -271,9 +273,14 @@ void SessionMain(SESSION *s)
 		}
 	}
 
+	is_server_session = s->ServerMode;
+
+	lock_receive_blocks_queue = s->LinkModeServer;
+
+	now = Tick64();
+
 	while (true)
 	{
-		now = Tick64();
 		Zero(&t, sizeof(t));
 
 
@@ -318,12 +325,22 @@ void SessionMain(SESSION *s)
 			}
 		}
 
+		
 		// Chance of additional connection
-		ClientAdditionalConnectChance(s);
+		if (is_server_session == false)
+		{
+			if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT) == false)
+			{
+				ClientAdditionalConnectChance(s);
+			}
+		}
 
 		// Receive a block
 		ConnectionReceive(c, s->Cancel1, s->Cancel2);
 
+		// Get the current time
+		now = Tick64();
+
 		if (s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->FatalError)
 		{
 			// A serious error occurs during sending any data on UDP socket
@@ -333,7 +350,10 @@ void SessionMain(SESSION *s)
 		}
 
 		// Pass the received block to the PacketAdapter
-		LockQueue(c->ReceivedBlocks);
+		if (lock_receive_blocks_queue)
+		{
+			LockQueue(c->ReceivedBlocks);
+		}
 		{
 			BLOCK *b;
 			packet_put = false;
@@ -349,17 +369,33 @@ void SessionMain(SESSION *s)
 
 				update_hub_last_comm = true;
 
-				if (s->ServerMode == false && b->Size >= 14)
+				if (b->Size >= 14)
 				{
-					if (b->Buf[0] & 0x40)
+					if (b->Buf[0] & 0x01)
 					{
-						t.Recv.BroadcastCount++;
-						t.Recv.BroadcastBytes += (UINT64)b->Size;
+						if (is_server_session == false)
+						{
+							t.Recv.BroadcastCount++;
+							t.Recv.BroadcastBytes += (UINT64)b->Size;
+						}
+						else
+						{
+							t.Send.BroadcastCount++;
+							t.Send.BroadcastBytes += (UINT64)b->Size;
+						}
 					}
 					else
 					{
-						t.Recv.UnicastCount++;
-						t.Recv.UnicastBytes += (UINT64)b->Size;
+						if (is_server_session == false)
+						{
+							t.Recv.UnicastCount++;
+							t.Recv.UnicastBytes += (UINT64)b->Size;
+						}
+						else
+						{
+							t.Send.UnicastCount++;
+							t.Send.UnicastBytes += (UINT64)b->Size;
+						}
 					}
 				}
 
@@ -375,7 +411,7 @@ void SessionMain(SESSION *s)
 				Free(b);
 			}
 
-			if (packet_put || s->ServerMode)
+			if (true /* packet_put || is_server_session 2014.7.23 for optimizing */)
 			{
 				PROBE_DATA2("pa->PutPacket", NULL, 0);
 				if (pa->PutPacket(s, NULL, 0) == false)
@@ -386,10 +422,12 @@ void SessionMain(SESSION *s)
 				}
 			}
 		}
-		UnlockQueue(c->ReceivedBlocks);
+		if (lock_receive_blocks_queue)
+		{
+			UnlockQueue(c->ReceivedBlocks);
+		}
 
 		// Add the packet to be transmitted to SendBlocks by acquiring from PacketAdapter
-		LockQueue(c->SendBlocks);
 		{
 			UINT i, max_num = MAX_SEND_SOCKET_QUEUE_NUM;
 			i = 0;
@@ -416,35 +454,75 @@ void SessionMain(SESSION *s)
 				else
 				{
 					bool priority;
+					QUEUE *q = NULL;
 					// Buffering
-					if (s->ServerMode == false && packet_size >= 14)
+					if (packet_size >= 14)
 					{
 						UCHAR *buf = (UCHAR *)packet;
 						if (buf[0] & 0x01)
 						{
-							t.Send.BroadcastCount++;
-							t.Send.BroadcastBytes += (UINT64)packet_size;
+							if (is_server_session == false)
+							{
+								t.Send.BroadcastCount++;
+								t.Send.BroadcastBytes += (UINT64)packet_size;
+							}
+							else
+							{
+								t.Recv.BroadcastCount++;
+								t.Recv.BroadcastBytes += (UINT64)packet_size;
+							}
 						}
 						else
 						{
-							t.Send.UnicastCount++;
-							t.Send.UnicastBytes += (UINT64)packet_size;
+							if (is_server_session == false)
+							{
+								t.Send.UnicastCount++;
+								t.Send.UnicastBytes += (UINT64)packet_size;
+							}
+							else
+							{
+								t.Recv.UnicastCount++;
+								t.Recv.UnicastBytes += (UINT64)packet_size;
+							}
 						}
 					}
 					priority = IsPriorityHighestPacketForQoS(packet, packet_size);
+
 					b = NewBlock(packet, packet_size, s->UseCompress ? 1 : 0);
 					b->PriorityQoS = priority;
-					c->CurrentSendQueueSize += b->Size;
 
 					if (b->PriorityQoS && c->Protocol == CONNECTION_TCP && s->QoS)
 					{
-						InsertQueue(c->SendBlocks2, b);
+						q = c->SendBlocks2;
+					}
+					else
+					{
+						q = c->SendBlocks;
+					}
+
+					if (q->num_item > MAX_STORED_QUEUE_NUM)
+					{
+						q = NULL;
+					}
+
+					if (q != NULL)
+					{
+						c->CurrentSendQueueSize += b->Size;
+						InsertQueue(q, b);
 					}
 					else
 					{
-						InsertQueue(c->SendBlocks, b);
+						FreeBlock(b);
 					}
 				}
+
+				if ((i % 16) == 0)
+				{
+					int diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
+					CedarAddCurrentTcpQueueSize(c->Cedar, diff);
+					c->LastPacketQueueSize = c->CurrentSendQueueSize;
+				}
+
 				i++;
 				if (i >= max_num)
 				{
@@ -452,15 +530,23 @@ void SessionMain(SESSION *s)
 				}
 			}
 		}
-		UnlockQueue(c->SendBlocks);
 
 		AddTrafficForSession(s, &t);
 
+		if (true)
+		{
+			int diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
+			CedarAddCurrentTcpQueueSize(c->Cedar, diff);
+			c->LastPacketQueueSize = c->CurrentSendQueueSize;
+		}
+
+		now = Tick64();
+
 		// Send a block
-		ConnectionSend(c);
+		ConnectionSend(c, now);
 
 		// Determine the automatic disconnection
-		if (auto_disconnect_tick != 0 && auto_disconnect_tick <= Tick64())
+		if (auto_disconnect_tick != 0 && auto_disconnect_tick <= now)
 		{
 			err = ERR_AUTO_DISCONNECTED;
 			s->CurrentRetryCount = INFINITE;
@@ -477,9 +563,6 @@ void SessionMain(SESSION *s)
 			break;
 		}
 
-		// Get the current time
-		now = Tick64();
-
 		// Increments the number of logins for user object and Virtual HUB object.
 		// (It's incremented only if the time 30 seconds passed after connection.
 		// If not do this, it will be incremented on DoS attacks or any error.)
@@ -498,7 +581,7 @@ void SessionMain(SESSION *s)
 			}
 		}
 
-		if (s->ServerMode)
+		if (is_server_session)
 		{
 			HUB *hub;
 
@@ -513,15 +596,11 @@ void SessionMain(SESSION *s)
 
 			if (hub != NULL)
 			{
-				Lock(hub->lock);
+				if ((hub->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
 				{
-					if ((hub->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
-					{
-						IncrementHubTraffic(s->Hub);
-						hub->LastIncrementTraffic = now;
-					}
+					hub->LastIncrementTraffic = now;
+					IncrementHubTraffic(s->Hub);
 				}
-				Unlock(hub->lock);
 			}
 		}
 
@@ -536,7 +615,22 @@ void SessionMain(SESSION *s)
 				WHERE;
 			}
 
-			if (s->ServerMode == false && s->ClientOption != NULL && s->ClientOption->ConnectionDisconnectSpan == 0)
+			if (c->Protocol == CONNECTION_TCP)
+			{
+				if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT))
+				{
+					UINT num_tcp_connections = Count(c->CurrentNumConnection);
+
+					if (num_tcp_connections == 0)
+					{
+						// All TCP connections are disconnected.
+						// Terminate the session immediately.
+						timeouted = true;
+					}
+				}
+			}
+
+			if (is_server_session == false && s->ClientOption != NULL && s->ClientOption->ConnectionDisconnectSpan == 0)
 			{
 				if (LIST_NUM(s->Connection->Tcp->TcpSockList) < s->MaxConnection)
 				{
@@ -588,7 +682,14 @@ CLEANUP:
 
 	if (s->Connection)
 	{
+		int diff =  -((int)s->Connection->LastTcpQueueSize);
+		s->Connection->LastTcpQueueSize = 0;
 		s->Connection->Halt = true;
+		CedarAddCurrentTcpQueueSize(s->Cedar, diff);
+
+		diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
+		CedarAddCurrentTcpQueueSize(c->Cedar, diff);
+		c->LastPacketQueueSize = c->CurrentSendQueueSize;
 	}
 
 	// Release the packet adapter
@@ -1343,6 +1444,12 @@ void ClientThread(THREAD *t, void *param)
 
 	while (true)
 	{
+		if (s->Link != NULL && ((*s->Link->StopAllLinkFlag) || s->Link->Halting))
+		{
+			s->Err = ERR_USER_CANCEL;
+			break;
+		}
+
 		CLog(s->Cedar->Client, "LC_CONNECT_1", s->ClientOption->AccountName, s->CurrentRetryCount + 1);
 		if (s->LinkModeClient && s->Link != NULL)
 		{
@@ -1424,6 +1531,21 @@ void ClientThread(THREAD *t, void *param)
 		{
 			UINT retry_interval = s->RetryInterval;
 
+			if (s->LinkModeClient)
+			{
+				UINT current_num_links = Count(s->Cedar->CurrentActiveLinks);
+				UINT max_retry_interval = MAX(1000 * current_num_links, retry_interval);
+
+				retry_interval += retry_interval * MIN(s->CurrentRetryCount, 1000);
+				retry_interval = MIN(retry_interval, max_retry_interval);
+
+				// On the cascade client, adjust the retry_interval. (+/- 20%)
+				if (retry_interval >= 1000 && retry_interval <= (60 * 60 * 1000))
+				{
+					retry_interval = (retry_interval * 8 / 10) + (Rand32() % (retry_interval * 4 / 10));
+				}
+			}
+
 			if (s->Err == ERR_HUB_IS_BUSY || s->Err == ERR_LICENSE_ERROR ||
 				s->Err == ERR_HUB_STOPPING || s->Err == ERR_TOO_MANY_USER_SESSION)
 			{
@@ -1812,6 +1934,13 @@ SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *au
 	s->ClientOption = Malloc(sizeof(CLIENT_OPTION));
 	Copy(s->ClientOption, option, sizeof(CLIENT_OPTION));
 
+	if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT))
+	{
+		s->ClientOption->DisableQoS = true;
+		s->ClientOption->MaxConnection = 1;
+		s->ClientOption->HalfConnection = false;
+	}
+
 	s->MaxConnection = option->MaxConnection;
 	s->UseEncrypt = option->UseEncrypt;
 	s->UseCompress = option->UseCompress;

+ 18 - 0
src/Cedar/WinUi.c

@@ -432,6 +432,12 @@ void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date,
 		}
 	}
 
+	if (u->CurrentlyDisabled)
+	{
+		// Hide
+		return;
+	}
+
 	// Show the update screen
 	Zero(&p, sizeof(p));
 
@@ -491,6 +497,18 @@ WINUI_UPDATE *InitUpdateUi(wchar_t *title, char *name, char *family_name, UINT64
 	return u;
 }
 
+// Disable the update notification UI
+void DisableUpdateUi(WINUI_UPDATE *u)
+{
+	// Validate arguments
+	if (u == NULL)
+	{
+		return;
+	}
+
+	u->CurrentlyDisabled = true;
+}
+
 // Release the update notification
 void FreeUpdateUi(WINUI_UPDATE *u)
 {

+ 2 - 0
src/Cedar/WinUi.h

@@ -554,6 +554,7 @@ struct WINUI_UPDATE
 	char RegKey[MAX_PATH];
 	UPDATE_CLIENT *UpdateClient;
 	bool UseSuppressFlag;
+	bool CurrentlyDisabled;
 };
 
 // Update notification parameters
@@ -579,6 +580,7 @@ void FreeWinUi();
 
 WINUI_UPDATE *InitUpdateUi(wchar_t *title, char *name, char *family_name, UINT64 current_date, UINT current_build, UINT current_ver, char *client_id, bool use_suppress_flag);
 void FreeUpdateUi(WINUI_UPDATE *u);
+void DisableUpdateUi(WINUI_UPDATE *u);
 void LoadUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s);
 void SaveUpdateUiSetting(WINUI_UPDATE *u, UPDATE_CLIENT_SETTING *s);
 void UpdateNotifyProcUi(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param);

+ 2 - 2
src/CurrentBuild.txt

@@ -1,4 +1,4 @@
-BUILD_NUMBER 9473
+BUILD_NUMBER 9505
 VERSION 410
 BUILD_NAME beta
-BUILD_DATE 20140712_021433
+BUILD_DATE 20141003_175504

+ 39 - 1
src/Mayaqua/Cfg.c

@@ -258,9 +258,27 @@ CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup)
 	return ret;
 }
 CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup)
+{
+	return NewCfgRwEx2W(root, cfg_name, dont_backup, NULL);
+}
+CFG_RW *NewCfgRwEx2A(FOLDER **root, char *cfg_name_a, bool dont_backup, char *template_name_a)
+{
+	CFG_RW *ret;
+	wchar_t *cfg_name_w = CopyStrToUni(cfg_name_a);
+	wchar_t *template_name_w = CopyStrToUni(template_name_a);
+
+	ret = NewCfgRwEx2W(root, cfg_name_w, dont_backup, template_name_w);
+
+	Free(cfg_name_w);
+	Free(template_name_w);
+
+	return ret;
+}
+CFG_RW *NewCfgRwEx2W(FOLDER **root, wchar_t *cfg_name, bool dont_backup, wchar_t *template_name)
 {
 	CFG_RW *rw;
 	FOLDER *f;
+	bool loaded_from_template = false;
 	// Validate arguments
 	if (cfg_name == NULL || root == NULL)
 	{
@@ -270,6 +288,18 @@ CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup)
 	f = CfgReadW(cfg_name);
 	if (f == NULL)
 	{
+		// Load from template
+		if (UniIsEmptyStr(template_name) == false)
+		{
+			f = CfgReadW(template_name);
+			if (f != NULL)
+			{
+				loaded_from_template = true;
+
+				goto LABEL_CONTIUNE;
+			}
+		}
+
 		rw = ZeroMalloc(sizeof(CFG_RW));
 		rw->lock = NewLock();
 		rw->FileNameW = CopyUniStr(cfg_name);
@@ -281,10 +311,18 @@ CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup)
 		return rw;
 	}
 
+LABEL_CONTIUNE:
 	rw = ZeroMalloc(sizeof(CFG_RW));
 	rw->FileNameW = CopyUniStr(cfg_name);
 	rw->FileName = CopyUniToStr(cfg_name);
-	rw->Io = FileOpenW(cfg_name, false);
+	if (loaded_from_template == false)
+	{
+		rw->Io = FileOpenW(cfg_name, false);
+	}
+	else
+	{
+		rw->Io = FileCreateW(cfg_name);
+	}
 	rw->lock = NewLock();
 
 	*root = f;

+ 2 - 0
src/Mayaqua/Cfg.h

@@ -252,6 +252,8 @@ CFG_RW *NewCfgRw(FOLDER **root, char *cfg_name);
 CFG_RW *NewCfgRwW(FOLDER **root, wchar_t *cfg_name);
 CFG_RW *NewCfgRwEx(FOLDER **root, char *cfg_name, bool dont_backup);
 CFG_RW *NewCfgRwExW(FOLDER **root, wchar_t *cfg_name, bool dont_backup);
+CFG_RW *NewCfgRwEx2W(FOLDER **root, wchar_t *cfg_name, bool dont_backup, wchar_t *template_name);
+CFG_RW *NewCfgRwEx2A(FOLDER **root, char *cfg_name_a, bool dont_backup, char *template_name_a);
 UINT SaveCfgRw(CFG_RW *rw, FOLDER *f);
 UINT SaveCfgRwEx(CFG_RW *rw, FOLDER *f, UINT revision_number);
 void FreeCfgRw(CFG_RW *rw);

+ 116 - 1
src/Mayaqua/Encrypt.c

@@ -1805,6 +1805,77 @@ X *NewRootX(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
 	return x2;
 }
 
+// Create new X509 basic & extended key usage
+void AddKeyUsageX509(EXTENDED_KEY_USAGE *ex, int nid)
+{
+	ASN1_OBJECT *obj;
+	// Validate arguments
+	if (ex == NULL)
+	{
+		return;
+	}
+
+	obj = OBJ_nid2obj(nid);
+	if (obj != NULL)
+	{
+		sk_ASN1_OBJECT_push(ex, obj);
+	}
+}
+X509_EXTENSION *NewExtendedKeyUsageForX509()
+{
+	EXTENDED_KEY_USAGE *ex = sk_ASN1_OBJECT_new_null();
+	X509_EXTENSION *ret;
+
+	AddKeyUsageX509(ex, NID_server_auth);
+	AddKeyUsageX509(ex, NID_client_auth);
+	AddKeyUsageX509(ex, NID_code_sign);
+	AddKeyUsageX509(ex, NID_email_protect);
+	AddKeyUsageX509(ex, NID_ipsecEndSystem);
+	AddKeyUsageX509(ex, NID_ipsecTunnel);
+	AddKeyUsageX509(ex, NID_ipsecUser);
+	AddKeyUsageX509(ex, NID_time_stamp);
+	AddKeyUsageX509(ex, NID_OCSP_sign);
+
+	ret = X509V3_EXT_i2d(NID_ext_key_usage, 0, ex);
+
+	sk_ASN1_OBJECT_pop_free(ex, ASN1_OBJECT_free);
+
+	return ret;
+}
+void BitStringSetBit(ASN1_BIT_STRING *str, int bit)
+{
+	// Validate arguments
+	if (str == NULL)
+	{
+		return;
+	}
+
+	ASN1_BIT_STRING_set_bit(str, bit, 1);
+}
+X509_EXTENSION *NewBasicKeyUsageForX509()
+{
+	X509_EXTENSION *ret = NULL;
+	ASN1_BIT_STRING *str;
+
+	str = ASN1_BIT_STRING_new();
+	if (str != NULL)
+	{
+		BitStringSetBit(str, 0);	// KU_DIGITAL_SIGNATURE
+		BitStringSetBit(str, 1);	// KU_NON_REPUDIATION
+		BitStringSetBit(str, 2);	// KU_KEY_ENCIPHERMENT
+		BitStringSetBit(str, 3);	// KU_DATA_ENCIPHERMENT
+		//BitStringSetBit(str, 4);	// KU_KEY_AGREEMENT
+		BitStringSetBit(str, 5);	// KU_KEY_CERT_SIGN
+		BitStringSetBit(str, 6);	// KU_CRL_SIGN
+
+		ret = X509V3_EXT_i2d(NID_key_usage, 0, str);
+
+		ASN1_BIT_STRING_free(str);
+	}
+
+	return ret;
+}
+
 // Issue an X509 certificate
 X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
 {
@@ -1812,6 +1883,9 @@ X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
 	UINT64 notBefore, notAfter;
 	ASN1_TIME *t1, *t2;
 	X509_NAME *subject_name, *issuer_name;
+	X509_EXTENSION *ex = NULL;
+	X509_EXTENSION *eku = NULL;
+	X509_EXTENSION *busage = NULL;
 	// Validate arguments
 	if (pub == NULL || name == NULL || ca == NULL)
 	{
@@ -1892,6 +1966,29 @@ X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial)
 		s->length = serial->size;
 	}
 
+	/*
+	// Extensions
+	ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,	"critical,CA:TRUE");
+	X509_add_ext(x509, ex, -1);
+	X509_EXTENSION_free(ex);
+*/
+
+	// Basic usage
+	busage = NewBasicKeyUsageForX509();
+	if (busage != NULL)
+	{
+		X509_add_ext(x509, busage, -1);
+		X509_EXTENSION_free(busage);
+	}
+
+	// EKU
+	eku = NewExtendedKeyUsageForX509();
+	if (eku != NULL)
+	{
+		X509_add_ext(x509, eku, -1);
+		X509_EXTENSION_free(eku);
+	}
+
 	Lock(openssl_lock);
 	{
 		// Set the public key
@@ -1914,6 +2011,8 @@ X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
 	ASN1_TIME *t1, *t2;
 	X509_NAME *subject_name, *issuer_name;
 	X509_EXTENSION *ex = NULL;
+	X509_EXTENSION *eku = NULL;
+	X509_EXTENSION *busage = NULL;
 	// Validate arguments
 	if (pub == NULL || name == NULL || priv == NULL)
 	{
@@ -2004,6 +2103,22 @@ X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial)
 	X509_add_ext(x509, ex, -1);
 	X509_EXTENSION_free(ex);
 
+	// Basic usage
+	busage = NewBasicKeyUsageForX509();
+	if (busage != NULL)
+	{
+		X509_add_ext(x509, busage, -1);
+		X509_EXTENSION_free(busage);
+	}
+
+	// EKU
+	eku = NewExtendedKeyUsageForX509();
+	if (eku != NULL)
+	{
+		X509_add_ext(x509, eku, -1);
+		X509_EXTENSION_free(eku);
+	}
+
 	Lock(openssl_lock);
 	{
 		// Set the public key
@@ -4105,7 +4220,7 @@ CRYPT *NewCrypt(void *key, UINT size)
 {
 	CRYPT *c = ZeroMalloc(sizeof(CRYPT));
 
-	c->Rc4Key = ZeroMalloc(sizeof(struct rc4_key_st));
+	c->Rc4Key = Malloc(sizeof(struct rc4_key_st));
 
 	RC4_set_key(c->Rc4Key, size, (UCHAR *)key);
 

+ 77 - 0
src/Mayaqua/Internat.c

@@ -3025,6 +3025,83 @@ wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt)
 	return ret;
 }
 
+// Get lines from a string
+UNI_TOKEN_LIST *UniGetLines(wchar_t *str)
+{
+	UINT i, len;
+	BUF *b = NULL;
+	LIST *o;
+	UNI_TOKEN_LIST *ret;
+	// Validate arguments
+	if (str == NULL)
+	{
+		return UniNullToken();
+	}
+
+	o = NewListFast(NULL);
+
+	len = UniStrLen(str);
+
+	b = NewBuf();
+
+	for (i = 0;i < len;i++)
+	{
+		wchar_t c = str[i];
+		bool f = false;
+
+		if (c == L'\r')
+		{
+			if (str[i + 1] == L'\n')
+			{
+				i++;
+			}
+			f = true;
+		}
+		else if (c == L'\n')
+		{
+			f = true;
+		}
+
+		if (f)
+		{
+			wchar_t zero = 0;
+			wchar_t *s;
+			WriteBuf(b, &zero, sizeof(wchar_t));
+
+			s = (wchar_t *)b->Buf;
+
+			Add(o, UniCopyStr(s));
+
+			ClearBuf(b);
+		}
+		else
+		{
+			WriteBuf(b, &c, sizeof(wchar_t));
+		}
+	}
+
+	if (true)
+	{
+		wchar_t zero = 0;
+		wchar_t *s;
+		WriteBuf(b, &zero, sizeof(wchar_t));
+
+		s = (wchar_t *)b->Buf;
+
+		Add(o, UniCopyStr(s));
+
+		ClearBuf(b);
+	}
+
+	FreeBuf(b);
+
+	ret = UniListToTokenList(o);
+
+	UniFreeStrList(o);
+
+	return ret;
+}
+
 // Display the string on the screen
 void UniPrintStr(wchar_t *string)
 {

+ 1 - 0
src/Mayaqua/Internat.h

@@ -232,6 +232,7 @@ bool UniInStr(wchar_t *str, wchar_t *keyword);
 bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive);
 void ClearUniStr(wchar_t *str, UINT str_size);
 bool UniInChar(wchar_t *string, wchar_t c);
+UNI_TOKEN_LIST *UniGetLines(wchar_t *str);
 
 #ifdef	OS_UNIX
 void GetCurrentCharSet(char *name, UINT size);

+ 27 - 0
src/Mayaqua/Kernel.c

@@ -319,6 +319,21 @@ void MainteThreadList(LIST *o)
 	UnlockList(o);
 }
 
+// Wait until all threads in the thread list will be stopped
+void WaitAllThreadsWillBeStopped(LIST *o)
+{
+	// Validate arguments
+	if (o == NULL)
+	{
+		return;
+	}
+
+	while (LIST_NUM(o) != 0)
+	{
+		SleepThread(100);
+	}
+}
+
 // Stop all the threads in the thread list
 void StopThreadList(LIST *o)
 {
@@ -1934,8 +1949,14 @@ INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
 		return 0;
 	}
 
+#ifndef	OS_UNIX
 	Copy(&t1, localtime(&tmp), sizeof(struct tm));
 	Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+#else	// OS_UNIX
+	localtime_r(&tmp, &t1);
+	gmtime_r(&tmp, &t2);
+#endif	// OS_UNIX
+
 	TmToSystem(&s1, &t1);
 	TmToSystem(&s2, &t2);
 
@@ -1970,8 +1991,14 @@ INT64 GetTimeDiff()
 		return 0;
 	}
 
+#ifndef	OS_UNIX
 	Copy(&t1, localtime(&tmp), sizeof(struct tm));
 	Copy(&t2, gmtime(&tmp), sizeof(struct tm));
+#else	// OS_UNIX
+	localtime_r(&tmp, &t1);
+	gmtime_r(&tmp, &t2);
+#endif	// OS_UNIX
+
 	TmToSystem(&s1, &t1);
 	TmToSystem(&s2, &t2);
 

+ 1 - 0
src/Mayaqua/Kernel.h

@@ -275,6 +275,7 @@ void DelThreadFromThreadList(LIST *o, THREAD *t);
 void MainteThreadList(LIST *o);
 void FreeThreadList(LIST *o);
 void StopThreadList(LIST *o);
+void WaitAllThreadsWillBeStopped(LIST *o);
 
 #endif	// KERNEL_H
 

+ 4 - 2
src/Mayaqua/MayaType.h

@@ -344,8 +344,10 @@ typedef UINT_PTR SOCKET;
 #define	OSTYPE_WINDOWS_SERVER_8					2710	// Windows Server 2012
 #define	OSTYPE_WINDOWS_81						2701	// Windows 8.1
 #define	OSTYPE_WINDOWS_SERVER_81				2711	// Windows Server 2012 R2
-#define	OSTYPE_WINDOWS_9						2800	// Windows 9
-#define	OSTYPE_WINDOWS_SERVER_9					2810	// Windows Server 9
+#define	OSTYPE_WINDOWS_10						2702	// Windows 10
+#define	OSTYPE_WINDOWS_SERVER_10				2712	// Windows Server 10
+#define	OSTYPE_WINDOWS_11						2800	// Windows 11 or later
+#define	OSTYPE_WINDOWS_SERVER_11				2810	// Windows Server 11 or later
 #define	OSTYPE_UNIX_UNKNOWN						3000	// Unknown UNIX
 #define	OSTYPE_LINUX							3100	// Linux
 #define	OSTYPE_SOLARIS							3200	// Solaris

+ 7 - 0
src/Mayaqua/Mayaqua.h

@@ -218,6 +218,13 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, char *CmdLine, int CmdShow)
 #define	USE_INTEL_AESNI_LIBRARY
 #endif
 
+// Determine the performance / memory strategy
+#if	(defined(CPU_X86) || defined(CPU_X64) || defined(CPU_X86_X64) || defined(CPU_SPARC) || defined(CPU_SPARC64) || defined(OS_WIN32) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__ia64__) || defined(__IA64__) || defined(_IA64))
+#define	USE_STRATEGY_PERFORMACE
+#else
+#define	USE_STRATEGY_LOW_MEMORY
+#endif
+
 // Macro that displays the current time
 #ifdef	WIN32
 #define	WHEN			if (IsDebug()){WHERE; MsPrintTick();}

+ 110 - 47
src/Mayaqua/Memory.c

@@ -129,11 +129,60 @@
 
 #define	FIFO_INIT_MEM_SIZE		4096
 #define	FIFO_REALLOC_MEM_SIZE	(65536 * 10)	// Exquisite value
-#define FIFO_REALLOC_MEM_SIZE_SMALL	65536
 
 #define	INIT_NUM_RESERVED		32
 
-static UINT fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+static UINT fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+
+// Check whether the specified key item is in the hash list
+bool IsInHashListKey(HASH_LIST *h, UINT key)
+{
+	// Validate arguments
+	if (h == NULL || key == 0)
+	{
+		return false;
+	}
+
+	if (HashListKeyToPointer(h, key) == NULL)
+	{
+		return false;
+	}
+
+	return true;
+}
+
+// Search the item in the hash list with the key
+void *HashListKeyToPointer(HASH_LIST *h, UINT key)
+{
+	UINT num, i;
+	void **pp;
+	void *ret = NULL;
+	// Validate arguments
+	if (h == NULL || key == 0)
+	{
+		return NULL;
+	}
+
+	pp = HashListToArray(h, &num);
+	if (pp == NULL)
+	{
+		return NULL;
+	}
+
+	for (i = 0;i < num;i++)
+	{
+		void *p = pp[i];
+
+		if (POINTER_TO_KEY(p) == key)
+		{
+			ret = p;
+		}
+	}
+
+	Free(pp);
+
+	return ret;
+}
 
 // Lock the hash list
 void LockHashList(HASH_LIST *h)
@@ -223,17 +272,11 @@ void *SearchHash(HASH_LIST *h, void *t)
 	if (h->Entries[r] != NULL)
 	{
 		LIST *o = h->Entries[r];
-		UINT i;
+		void *r = Search(o, t);
 
-		for (i = 0;i < LIST_NUM(o);i++)
+		if (r != NULL)
 		{
-			void *p = LIST_DATA(o, i);
-
-			if (h->CompareProc(&p, &t) == 0)
-			{
-				ret = p;
-				break;
-			}
+			ret = r;
 		}
 	}
 
@@ -293,10 +336,10 @@ void AddHash(HASH_LIST *h, void *p)
 
 	if (h->Entries[r] == NULL)
 	{
-		h->Entries[r] = NewListFast(NULL);
+		h->Entries[r] = NewListFast(h->CompareProc);
 	}
 
-	Add(h->Entries[r], p);
+	Insert(h->Entries[r], p);
 
 	if (h->AllList != NULL)
 	{
@@ -1031,6 +1074,18 @@ void *PeekQueue(QUEUE *q)
 	return p;
 }
 
+// Get the number of queued items
+UINT GetQueueNum(QUEUE *q)
+{
+	// Validate arguments
+	if (q == NULL)
+	{
+		return 0;
+	}
+
+	return q->num_item;
+}
+
 // Get one
 void *GetNext(QUEUE *q)
 {
@@ -1105,6 +1160,21 @@ void InsertQueue(QUEUE *q, void *p)
 
 	q->num_item++;
 
+	/*{
+		static UINT max_num_item;
+		static UINT64 next_tick = 0;
+		UINT64 now = Tick64();
+
+		max_num_item = MAX(q->num_item, max_num_item);
+
+		if (next_tick == 0 || next_tick <= now)
+		{
+			next_tick = now + (UINT64)1000;
+
+			printf("max_queue = %u\n", max_num_item);
+		}
+	}*/
+
 	// KS
 	KS_INC(KS_INSERT_QUEUE_COUNT);
 }
@@ -2327,9 +2397,26 @@ UINT ReadFifo(FIFO *f, void *p, UINT size)
 		f->pos = 0;
 	}
 
+	ShrinkFifoMemory(f);
+
+	// KS
+	KS_INC(KS_READ_FIFO_COUNT);
+
+	return read_size;
+}
+
+// Rearrange the memory
+void ShrinkFifoMemory(FIFO *f)
+{
+	// Validate arguments
+	if (f == NULL)
+	{
+		return;
+	}
+
 	// Rearrange the memory
-	if (f->pos >= FIFO_INIT_MEM_SIZE &&
-		f->memsize >= f->realloc_mem_size &&
+	if (f->pos >= FIFO_INIT_MEM_SIZE && 
+		f->memsize >= fifo_current_realloc_mem_size &&
 		(f->memsize / 2) > f->size)
 	{
 		void *new_p;
@@ -2345,11 +2432,6 @@ UINT ReadFifo(FIFO *f, void *p, UINT size)
 		f->p = new_p;
 		f->pos = 0;
 	}
-
-	// KS
-	KS_INC(KS_READ_FIFO_COUNT);
-
-	return read_size;
 }
 
 // Write to the FIFO
@@ -2497,19 +2579,19 @@ void CleanupFifo(FIFO *f)
 // Initialize the FIFO system
 void InitFifo()
 {
-	fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
+	fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
 }
 
 // Create a FIFO
 FIFO *NewFifo()
 {
-	return NewFifoEx(0, false);
+	return NewFifoEx(false);
 }
 FIFO *NewFifoFast()
 {
-	return NewFifoEx(0, true);
+	return NewFifoEx(true);
 }
-FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
+FIFO *NewFifoEx(bool fast)
 {
 	FIFO *f;
 
@@ -2531,13 +2613,6 @@ FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
 	f->memsize = FIFO_INIT_MEM_SIZE;
 	f->p = Malloc(FIFO_INIT_MEM_SIZE);
 
-	if (realloc_mem_size == 0)
-	{
-		realloc_mem_size = fifo_default_realloc_mem_size;
-	}
-
-	f->realloc_mem_size = realloc_mem_size;
-
 #ifndef	DONT_USE_KERNEL_STATUS
 //	TrackNewObj(POINTER_TO_UINT64(f), "FIFO", 0);
 #endif	// DONT_USE_KERNEL_STATUS
@@ -2549,20 +2624,20 @@ FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
 }
 
 // Get the default memory reclaiming size of the FIFO
-UINT GetFifoDefaultReallocMemSize()
+UINT GetFifoCurrentReallocMemSize()
 {
-	return fifo_default_realloc_mem_size;
+	return fifo_current_realloc_mem_size;
 }
 
 // Set the default memory reclaiming size of the FIFO
-void SetFifoDefaultReallocMemSize(UINT size)
+void SetFifoCurrentReallocMemSize(UINT size)
 {
 	if (size == 0)
 	{
 		size = FIFO_REALLOC_MEM_SIZE;
 	}
 
-	fifo_default_realloc_mem_size = size;
+	fifo_current_realloc_mem_size = size;
 }
 
 // Read a buffer from a file
@@ -3743,12 +3818,6 @@ char B64_CharToCode(char c)
 	return 0;
 }
 
-// High-speed Malloc (currently not implemented)
-void *MallocFast(UINT size)
-{
-	return Malloc(size);
-}
-
 // Malloc
 void *Malloc(UINT size)
 {
@@ -3899,12 +3968,6 @@ void *ZeroMallocEx(UINT size, bool zero_clear_when_free)
 	Zero(p, size);
 	return p;
 }
-void *ZeroMallocFast(UINT size)
-{
-	void *p = MallocFast(size);
-	Zero(p, size);
-	return p;
-}
 
 // Memory allocation
 void *InternalMalloc(UINT size)

+ 12 - 7
src/Mayaqua/Memory.h

@@ -114,6 +114,10 @@
 #ifndef	MEMORY_H
 #define	MEMORY_H
 
+// MallocFast (not implemented)
+#define	MallocFast		Malloc
+#define	ZeroMallocFast	ZeroMalloc
+
 // Memory size that can be passed to the kernel at a time
 #define	MAX_SEND_BUF_MEM_SIZE				(10 * 1024 * 1024)
 
@@ -154,7 +158,6 @@ struct FIFO
 	LOCK *lock;
 	void *p;
 	UINT pos, size, memsize;
-	UINT realloc_mem_size;
 	UINT64 total_read_size;
 	UINT64 total_write_size;
 };
@@ -214,7 +217,7 @@ struct SHARED_BUFFER
 // Macro
 #define	LIST_DATA(o, i)		(((o) != NULL) ? ((o)->p[(i)]) : NULL)
 #define	LIST_NUM(o)			(((o) != NULL) ? (o)->num_item : 0)
-
+#define	HASH_LIST_NUM(o)	(((o) != NULL) ? (o)->NumItems : 0)
 
 // Function pointer type to get a hash function
 typedef UINT (GET_HASH)(void *p);
@@ -244,6 +247,8 @@ UINT CalcHashForHashList(HASH_LIST *h, void *p);
 void **HashListToArray(HASH_LIST *h, UINT *num);
 void LockHashList(HASH_LIST *h);
 void UnlockHashList(HASH_LIST *h);
+bool IsInHashListKey(HASH_LIST *h, UINT key);
+void *HashListKeyToPointer(HASH_LIST *h, UINT key);
 
 LIST *NewCandidateList();
 void FreeCandidateList(LIST *o);
@@ -254,9 +259,7 @@ LIST *BufToCandidate(BUF *b);
 
 void *Malloc(UINT size);
 void *MallocEx(UINT size, bool zero_clear_when_free);
-void *MallocFast(UINT size);
 void *ZeroMalloc(UINT size);
-void *ZeroMallocFast(UINT size);
 void *ZeroMallocEx(UINT size, bool zero_clear_when_free);
 void *ReAlloc(void *addr, UINT size);
 void Free(void *addr);
@@ -333,6 +336,7 @@ bool CompareBuf(BUF *b1, BUF *b2);
 
 UINT PeekFifo(FIFO *f, void *p, UINT size);
 UINT ReadFifo(FIFO *f, void *p, UINT size);
+void ShrinkFifoMemory(FIFO *f);
 UCHAR *GetFifoPointer(FIFO *f);
 UCHAR *FifoPtr(FIFO *f);
 void WriteFifo(FIFO *f, void *p, UINT size);
@@ -344,10 +348,10 @@ void ReleaseFifo(FIFO *f);
 void CleanupFifo(FIFO *f);
 FIFO *NewFifo();
 FIFO *NewFifoFast();
-FIFO *NewFifoEx(UINT realloc_mem_size, bool fast);
+FIFO *NewFifoEx(bool fast);
 void InitFifo();
-UINT GetFifoDefaultReallocMemSize();
-void SetFifoDefaultReallocMemSize(UINT size);
+UINT GetFifoCurrentReallocMemSize();
+void SetFifoCurrentReallocMemSize(UINT size);
 
 void *Search(LIST *o, void *target);
 void Sort(LIST *o);
@@ -416,6 +420,7 @@ void ReleaseQueue(QUEUE *q);
 void CleanupQueue(QUEUE *q);
 QUEUE *NewQueue();
 QUEUE *NewQueueFast();
+UINT GetQueueNum(QUEUE *q);
 
 SK *NewSk();
 SK *NewSkEx(bool no_compact);

+ 29 - 0
src/Mayaqua/Microsoft.c

@@ -8729,6 +8729,35 @@ bool MsIsWindows7()
 	return false;
 }
 
+// Determine whether it's Windows 10 or later
+bool MsIsWindows10()
+{
+	OS_INFO *info = GetOsInfo();
+
+	if (info == NULL)
+	{
+		return false;
+	}
+
+	if (OS_IS_WINDOWS_NT(info->OsType))
+	{
+		if (GET_KETA(info->OsType, 100) == 7)
+		{
+			if (GET_KETA(info->OsType, 1) >= 2)
+			{
+				return true;
+			}
+		}
+
+		if (GET_KETA(info->OsType, 100) >= 8)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}
+
 // Determine whether it's Windows 8.1 or later
 bool MsIsWindows81()
 {

+ 1 - 0
src/Mayaqua/Microsoft.h

@@ -995,6 +995,7 @@ bool MsIsIA64();
 void *MsDisableWow64FileSystemRedirection();
 void MsRestoreWow64FileSystemRedirection(void *p);
 void MsSetWow64FileSystemRedirectionEnable(bool enable);
+bool MsIsWindows10();
 bool MsIsWindows81();
 bool MsIsWindows8();
 bool MsIsWindows7();

+ 47 - 20
src/Mayaqua/Network.c

@@ -4281,7 +4281,7 @@ void RUDPGetRegisterHostNameByIP(char *dst, UINT size, IP *ip)
 	StrLower(tmp);
 	Format(dst, size,
 		(IsUseAlternativeHostname() ? UDP_NAT_T_SERVER_TAG_ALT : UDP_NAT_T_SERVER_TAG),
-		tmp[0], tmp[1], tmp[2], tmp[3]);
+		tmp[2], tmp[3]);
 
 
 	if (false)
@@ -9302,6 +9302,12 @@ void UnixInitAsyncSocket(SOCK *sock)
 	{
 		UnixSetSocketNonBlockingMode(sock->socket, true);
 	}
+
+	if (sock->ssl != NULL && sock->ssl->s3 != NULL)
+	{
+		sock->Ssl_Init_Async_SendAlert[0] = sock->ssl->s3->send_alert[0];
+		sock->Ssl_Init_Async_SendAlert[1] = sock->ssl->s3->send_alert[1];
+	}
 }
 
 // Initializing the socket library
@@ -13139,6 +13145,15 @@ UINT SecureRecv(SOCK *sock, void *data, UINT size)
 			e = SSL_get_error(ssl, ret);
 			if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
 			{
+				if (e == SSL_ERROR_SSL &&
+					sock->ssl->s3->send_alert[0] == SSL3_AL_FATAL &&
+					sock->ssl->s3->send_alert[0] != sock->Ssl_Init_Async_SendAlert[0] &&
+					sock->ssl->s3->send_alert[1] != sock->Ssl_Init_Async_SendAlert[1])
+				{
+					Debug("%s %u SSL Fatal Error on ASYNC socket !!!\n", __FILE__, __LINE__);
+					Disconnect(sock);
+					return 0;
+				}
 				// Packet has not arrived yet, that is not to be read
 				return SOCK_LATER;
 			}
@@ -13202,6 +13217,7 @@ UINT SecureRecv(SOCK *sock, void *data, UINT size)
 		// Successful reception
 		sock->RecvSize += (UINT64)ret;
 		sock->RecvNum++;
+
 		return (UINT)ret;
 	}
 	if (ret == 0)
@@ -13215,6 +13231,16 @@ UINT SecureRecv(SOCK *sock, void *data, UINT size)
 	{
 		if (e == SSL_ERROR_WANT_READ || e == SSL_ERROR_WANT_WRITE || e == SSL_ERROR_SSL)
 		{
+			if (e == SSL_ERROR_SSL &&
+				sock->ssl->s3->send_alert[0] == SSL3_AL_FATAL &&
+				sock->ssl->s3->send_alert[0] != sock->Ssl_Init_Async_SendAlert[0] &&
+				sock->ssl->s3->send_alert[1] != sock->Ssl_Init_Async_SendAlert[1])
+			{
+				Debug("%s %u SSL Fatal Error on ASYNC socket !!!\n", __FILE__, __LINE__);
+				Disconnect(sock);
+				return 0;
+			}
+
 			// Packet has not yet arrived
 			return SOCK_LATER;
 		}
@@ -14220,24 +14246,6 @@ void Disconnect(SOCK *sock)
 						sock->ssl_ctx = NULL;
 					}
 					sock->Connected = false;
-					// Release the certificate
-					if (sock->RemoteX != NULL)
-					{
-						FreeX(sock->RemoteX);
-						sock->RemoteX = NULL;
-					}
-					if (sock->LocalX != NULL)
-					{
-						FreeX(sock->LocalX);
-						sock->LocalX = NULL;
-					}
-
-					// Cipher algorithm name
-					if (sock->CipherName != NULL)
-					{
-						Free(sock->CipherName);
-						sock->CipherName = NULL;
-					}
 					sock->SecureMode = false;
 				}
 			}
@@ -14957,7 +14965,7 @@ SOCK *ConnectEx(char *hostname, UINT port, UINT timeout)
 }
 SOCK *ConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag)
 {
-	return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, false, false);
+	return ConnectEx3(hostname, port, timeout, cancel_flag, NULL, NULL, false, false, true);
 }
 SOCK *ConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, char *nat_t_svc_name, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, bool no_get_hostname)
 {
@@ -15824,6 +15832,25 @@ void CleanupSock(SOCK *s)
 	}
 #endif	// OS_WIN32
 
+	// Release the certificate
+	if (s->RemoteX != NULL)
+	{
+		FreeX(s->RemoteX);
+		s->RemoteX = NULL;
+	}
+	if (s->LocalX != NULL)
+	{
+		FreeX(s->LocalX);
+		s->LocalX = NULL;
+	}
+
+	// Cipher algorithm name
+	if (s->CipherName != NULL)
+	{
+		Free(s->CipherName);
+		s->CipherName = NULL;
+	}
+
 	Free(s->WaitToUseCipher);
 	DeleteLock(s->lock);
 	DeleteLock(s->ssl_lock);

+ 3 - 2
src/Mayaqua/Network.h

@@ -304,6 +304,7 @@ struct SOCK
 	bool IsReverseAcceptedSocket;	// Whether it is a reverse socket
 	IP Reverse_MyServerGlobalIp;	// Self global IP address when using the reverse socket
 	UINT Reverse_MyServerPort;		// Self port number when using the reverse socket
+	UCHAR Ssl_Init_Async_SendAlert[2];	// Initial state of SSL send_alert
 
 #ifdef	ENABLE_SSL_LOGGING
 	// SSL Logging (for debug)
@@ -740,8 +741,8 @@ struct RUDP_SESSION
 };
 
 // NAT Traversal Server Information
-#define	UDP_NAT_T_SERVER_TAG				"x%c.x%c.x%c.x%c.servers.nat-traversal.softether-network.net."
-#define	UDP_NAT_T_SERVER_TAG_ALT			"x%c.x%c.x%c.x%c.servers.nat-traversal.uxcom.jp."
+#define	UDP_NAT_T_SERVER_TAG				"x%c.x%c.servers.nat-traversal.softether-network.net."
+#define	UDP_NAT_T_SERVER_TAG_ALT			"x%c.x%c.servers.nat-traversal.uxcom.jp."
 #define	UDP_NAT_T_PORT						5004
 
 // Related to processing to get the IP address of the NAT-T server

+ 8 - 4
src/Mayaqua/OS.c

@@ -197,10 +197,14 @@ char *OsTypeToStr(UINT type)
 		return "Windows 8.1\0\n";
 	case OSTYPE_WINDOWS_SERVER_81:
 		return "Windows Server 2012 R2\0\n";
-	case OSTYPE_WINDOWS_9:
-		return "Windows 8.2 or later\0\n";
-	case OSTYPE_WINDOWS_SERVER_9:
-		return "Windows Server 8.2 or later\0\n";
+	case OSTYPE_WINDOWS_10:
+		return "Windows 10\0\n";
+	case OSTYPE_WINDOWS_SERVER_10:
+		return "Windows Server 10\0\n";
+	case OSTYPE_WINDOWS_11:
+		return "Windows 11 or later\0\n";
+	case OSTYPE_WINDOWS_SERVER_11:
+		return "Windows Server 11 or later\0\n";
 	case OSTYPE_UNIX_UNKNOWN:
 		return "UNIX System\0\n";
 	case OSTYPE_LINUX:

+ 1 - 1
src/Mayaqua/TcpIp.c

@@ -2183,7 +2183,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
 			b2 = false;
 		}
 	}
-	if (b1 || b2 || (Cmp(p->MacHeader->SrcAddress, p->MacHeader->DestAddress, 6) == 0))
+	if (b1 || b2 || (memcmp(p->MacHeader->SrcAddress, p->MacHeader->DestAddress, 6) == 0))
 	{
 		p->InvalidSourcePacket = true;
 	}

+ 63 - 12
src/Mayaqua/Unix.c

@@ -966,6 +966,24 @@ void *UnixNewSingleInstance(char *instance_name)
 	}
 }
 
+// Set the high oom score
+void UnixSetHighOomScore()
+{
+	IO *o;
+	char tmp[256];
+
+	sprintf(tmp, "/proc/%u/oom_score_adj", getpid());
+
+	o = UnixFileCreate(tmp);
+	if (o != NULL)
+	{
+		char tmp[128];
+		sprintf(tmp, "%u\n", 800);
+		UnixFileWrite(o, tmp, strlen(tmp));
+		UnixFileClose(o, false);
+	}
+}
+
 // Raise the priority of the process
 void UnixSetHighPriority()
 {
@@ -2139,10 +2157,24 @@ void UnixSigChldHandler(int sig)
 	signal(SIGCHLD, UnixSigChldHandler);
 }
 
+// Disable core dump
+void UnixDisableCoreDump()
+{
+#ifdef	RLIMIT_CORE
+	UnixSetResourceLimit(RLIMIT_CORE, 0);
+#endif	// RLIMIT_CORE
+}
+
 // Initialize the library for UNIX
 void UnixInit()
 {
 	UNIXIO *o;
+	UINT64 max_memory = UNIX_MAX_MEMORY;
+
+	if (UnixIs64BitRlimSupported())
+	{
+		max_memory = UNIX_MAX_MEMORY_64;
+	}
 
 	UnixInitSolarisSleep();
 
@@ -2154,11 +2186,11 @@ void UnixInit()
 	current_process_id = getpid();
 
 #ifdef	RLIMIT_CORE
-	UnixSetResourceLimit(RLIMIT_CORE, UNIX_MAX_MEMORY);
+	UnixSetResourceLimit(RLIMIT_CORE, max_memory);
 #endif	// RLIMIT_CORE
 
 #ifdef	RLIMIT_DATA
-	UnixSetResourceLimit(RLIMIT_DATA, UNIX_MAX_MEMORY);
+	UnixSetResourceLimit(RLIMIT_DATA, max_memory);
 #endif	// RLIMIT_DATA
 
 #ifdef	RLIMIT_NOFILE
@@ -2170,11 +2202,11 @@ void UnixInit()
 #endif	// RLIMIT_NOFILE
 
 #ifdef	RLIMIT_STACK
-//	UnixSetResourceLimit(RLIMIT_STACK, UNIX_MAX_MEMORY);
+//	UnixSetResourceLimit(RLIMIT_STACK, max_memory);
 #endif	// RLIMIT_STACK
 
 #ifdef	RLIMIT_RSS
-	UnixSetResourceLimit(RLIMIT_RSS, UNIX_MAX_MEMORY);
+	UnixSetResourceLimit(RLIMIT_RSS, max_memory);
 #endif	// RLIMIT_RSS
 
 #ifdef	RLIMIT_LOCKS
@@ -2182,7 +2214,7 @@ void UnixInit()
 #endif	// RLIMIT_LOCKS
 
 #ifdef	RLIMIT_MEMLOCK
-	UnixSetResourceLimit(RLIMIT_MEMLOCK, UNIX_MAX_MEMORY);
+	UnixSetResourceLimit(RLIMIT_MEMLOCK, max_memory);
 #endif	// RLIMIT_MEMLOCK
 
 #ifdef	RLIMIT_NPROC
@@ -2226,27 +2258,46 @@ void UnixFree()
 }
 
 // Adjust the upper limit of resources that may be occupied
-void UnixSetResourceLimit(UINT id, UINT value)
+void UnixSetResourceLimit(UINT id, UINT64 value)
 {
 	struct rlimit t;
-	UINT hard_limit;
+	UINT64 hard_limit;
+
+	if (UnixIs64BitRlimSupported() == false)
+	{
+		if (value > (UINT64)4294967295ULL)
+		{
+			value = (UINT64)4294967295ULL;
+		}
+	}
 
 	Zero(&t, sizeof(t));
 	getrlimit(id, &t);
 
-	hard_limit = t.rlim_max;
+	hard_limit = (UINT64)t.rlim_max;
 
 	Zero(&t, sizeof(t));
-	t.rlim_cur = MIN(value, hard_limit);
-	t.rlim_max = hard_limit;
+	t.rlim_cur = (rlim_t)MIN(value, hard_limit);
+	t.rlim_max = (rlim_t)hard_limit;
 	setrlimit(id, &t);
 
 	Zero(&t, sizeof(t));
-	t.rlim_cur = value;
-	t.rlim_max = value;
+	t.rlim_cur = (rlim_t)value;
+	t.rlim_max = (rlim_t)value;
 	setrlimit(id, &t);
 }
 
+// Is the rlim_t type 64-bit?
+bool UnixIs64BitRlimSupported()
+{
+	if (sizeof(rlim_t) >= 8)
+	{
+		return true;
+	}
+
+	return false;
+}
+
 // Generate the PID file name
 void UnixGenPidFileName(char *name, UINT size)
 {

+ 5 - 1
src/Mayaqua/Unix.h

@@ -122,6 +122,7 @@
 #define	UNIX_LINUX_MAX_THREADS			200000000		// Maximum number of threads
 #define	UNIX_MAX_LOCKS					65536			// Maximum number of locks
 #define	UNIX_MAX_MEMORY					(2147483648UL)	// Maximum memory capacity
+#define	UNIX_MAX_MEMORY_64				((UINT64)((UINT64)65536ULL * (UINT64)2147483647ULL))	// Maximum memory capacity (64-bit)
 #define	UNIX_MAX_FD						(655360)		// Maximum number of FDs
 #define	UNIX_MAX_FD_MACOS				(10000)			// Maximum number of FDs (Mac OS X)
 #define	MAXIMUM_WAIT_OBJECTS			64				// Maximum number of select
@@ -201,6 +202,7 @@ void UnixAlert(char *msg, char *caption);
 void UnixAlertW(wchar_t *msg, wchar_t *caption);
 char *UnixGetProductId();
 void UnixSetHighPriority();
+void UnixSetHighOomScore();
 void UnixRestorePriority();
 void *UnixNewSingleInstance(char *instance_name);
 void UnixFreeSingleInstance(void *data);
@@ -211,12 +213,14 @@ void UnixExecSilent(char *cmd);
 void UnixDisableInterfaceOffload(char *name);
 void UnixSetEnableKernelEspProcessing(bool b);
 
+void UnixDisableCoreDump();
 void UnixSetThreadPriorityRealtime();
 void UnixSetThreadPriorityLow();
 void UnixSetThreadPriorityHigh();
 void UnixSetThreadPriorityIdle();
 void UnixRestoreThreadPriority();
-void UnixSetResourceLimit(UINT id, UINT value);
+void UnixSetResourceLimit(UINT id, UINT64 value);
+bool UnixIs64BitRlimSupported();
 UINT64 UnixGetTick64();
 void UnixSigChldHandler(int sig);
 void UnixCloseIO();

+ 17 - 4
src/Mayaqua/Win32.c

@@ -1407,17 +1407,30 @@ UINT Win32GetOsType()
 						return OSTYPE_WINDOWS_SERVER_81;
 					}
 				}
+				else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 4)
+				{
+					if (os.wProductType == VER_NT_WORKSTATION)
+					{
+						// Windows 10
+						return OSTYPE_WINDOWS_10;
+					}
+					else
+					{
+						// Windows Server 10
+						return OSTYPE_WINDOWS_SERVER_10;
+					}
+				}
 				else
 				{
 					if (os.wProductType == VER_NT_WORKSTATION)
 					{
-						// Windows 9?
-						return OSTYPE_WINDOWS_9;
+						// Windows 11 or later
+						return OSTYPE_WINDOWS_11;
 					}
 					else
 					{
-						// Windows Server 9?
-						return OSTYPE_WINDOWS_SERVER_9;
+						// Windows Server 11 or later
+						return OSTYPE_WINDOWS_SERVER_11;
 					}
 				}
 			}

+ 1 - 1
src/PenCore/PenCore.rc

@@ -4252,7 +4252,7 @@ FONT 9, "MS UI Gothic", 400, 0, 0x80
 BEGIN
     LTEXT           "@S_1",IDC_STATIC,7,2,309,12,WS_TABSTOP
     EDITTEXT        E_TEXT,7,19,309,111,ES_MULTILINE | ES_READONLY | WS_VSCROLL
-    CONTROL         "@B_AGREE",B_AGREE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,134,297,12
+    CONTROL         "@B_AGREE",B_AGREE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,138,297,12
 END
 
 D_SW_WARNING DIALOGEX 0, 0, 323, 181

+ 78 - 49
src/SeLow/SeLow.c

@@ -391,7 +391,7 @@ NTSTATUS SlDeviceOpenProc(DEVICE_OBJECT *device_object, IRP *irp)
 					p.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
 					p.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
 					p.fAllocateNetBuffer = true;
-					p.ContextSize = 32;
+					p.ContextSize = 32 + sizeof(UINT32) * 12;
 					p.DataSize = SL_MAX_PACKET_SIZE;
 
 					f->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p);
@@ -648,6 +648,7 @@ NTSTATUS SlDeviceReadProc(DEVICE_OBJECT *device_object, IRP *irp)
 						SlCopy(d->MacAddress, a->MacAddress, 6);
 						SlCopy(d->AdapterId, a->AdapterId, sizeof(a->AdapterId));
 						strcpy(d->FriendlyName, a->FriendlyName);
+						d->SupportsVLanHw = a->SupportVLan;
 					}
 				}
 				SlUnlockList(sl->AdapterList);
@@ -833,6 +834,9 @@ NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
 							UCHAR *packet_buf;
 							NET_BUFFER_LIST *nbl = NULL;
 							bool ok = false;
+							bool is_vlan = false;
+							UINT vlan_id = 0;
+							UINT vlan_user_priority = 0, vlan_can_format_id = 0;
 
 							if (packet_size > SL_MAX_PACKET_SIZE)
 							{
@@ -896,6 +900,32 @@ NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
 
 								NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
 
+								// Determine if the packet is IEEE802.1Q tagged packet
+								if (dev->Adapter->SupportVLan && packet_size >= 18)
+								{
+									if (packet_buf[12] == 0x81 && packet_buf[13] == 0x00)
+									{
+										USHORT tag_us = 0;
+
+										((UCHAR *)(&tag_us))[0] = packet_buf[15];
+										((UCHAR *)(&tag_us))[1] = packet_buf[14];
+
+										vlan_id = tag_us & 0x0FFF;
+										vlan_user_priority = (tag_us >> 13) & 0x07;
+										vlan_can_format_id = (tag_us >> 12) & 0x01;
+
+										if (vlan_id != 0)
+										{
+											is_vlan = true;
+										}
+									}
+								}
+
+								if (is_vlan)
+								{
+									packet_size -= 4;
+								}
+
 								if (nb != NULL && OK(NdisRetreatNetBufferDataStart(nb, packet_size, 0, NULL)))
 								{
 									// Buffer copy
@@ -903,7 +933,15 @@ NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
 
 									if (dst != NULL)
 									{
-										SlCopy(dst, packet_buf, packet_size);
+										if (is_vlan == false)
+										{
+											SlCopy(dst, packet_buf, packet_size);
+										}
+										else
+										{
+											SlCopy(dst, packet_buf, 12);
+											SlCopy(dst + 12, packet_buf + 16, packet_size + 4 - 16);
+										}
 
 										ok = true;
 									}
@@ -935,7 +973,25 @@ NTSTATUS SlDeviceWriteProc(DEVICE_OBJECT *device_object, IRP *irp)
 
 								nbl_tail = nbl;
 
-								*((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl)) = f;
+								((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl))[0] = f;
+
+								if (is_vlan == false)
+								{
+									NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo) = NULL;
+								}
+								else
+								{
+									NDIS_NET_BUFFER_LIST_8021Q_INFO qinfo;
+
+									qinfo.Value = &(((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl))[1]);
+									SlZero(qinfo.Value, sizeof(UINT32) * 12);
+
+									qinfo.TagHeader.VlanId = vlan_id;
+									qinfo.TagHeader.UserPriority = vlan_user_priority;
+									qinfo.TagHeader.CanonicalFormatId = vlan_can_format_id;
+
+									NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo) = qinfo.Value;
+								}
 
 								num_packets++;
 							}
@@ -1073,6 +1129,22 @@ NDIS_STATUS SlNdisBindAdapterExProc(NDIS_HANDLE protocol_driver_context, NDIS_HA
 		a->Lock = SlNewLock();
 		a->AdapterName = SlNewUnicodeFromUnicodeString(bind_parameters->AdapterName);
 
+/*
+		if (bind_parameters->MacOptions & NDIS_MAC_OPTION_8021Q_VLAN)
+		{
+			a->SupportVLan = true;
+		}
+
+		if (bind_parameters->TcpConnectionOffloadCapabilities != NULL)
+		{
+			if (bind_parameters->TcpConnectionOffloadCapabilities->Encapsulation & NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q ||
+				bind_parameters->TcpConnectionOffloadCapabilities->Encapsulation & NDIS_ENCAPSULATION_IEEE_802_3_P_AND_Q_IN_OOB)
+			{
+				a->SupportVLan = true;
+			}
+		}
+*/
+
 		SlCopy(a->AdapterId, a->AdapterName->String.Buffer, MIN(sizeof(a->AdapterId) - sizeof(wchar_t), a->AdapterName->String.Length));
 		SlCopy(a->AdapterId, adapter_id_tag, sizeof(adapter_id_tag) - sizeof(wchar_t));
 
@@ -1485,6 +1557,8 @@ void SlNdisReceiveNetBufferListsProc(NDIS_HANDLE protocol_binding_context, NET_B
 						USHORT tag_us;
 						is_vlan = true;
 
+						a->SupportVLan = true;
+
 						tag_us = (qinfo.TagHeader.UserPriority & 0x07 << 13) |
 							(qinfo.TagHeader.CanonicalFormatId & 0x01 << 12) |
 							(qinfo.TagHeader.VlanId & 0x0FFF);
@@ -1600,7 +1674,7 @@ void SlNdisSendNetBufferListsCompleteProc(NDIS_HANDLE protocol_binding_context,
 		}
 
 		// Get a file context
-		f = *((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl));
+		f = ((void **)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl))[0];
 
 		nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);
 		NET_BUFFER_LIST_NEXT_NBL(current_nbl) = NULL;
@@ -1921,51 +1995,6 @@ NDIS_STRING *SlGetUnicode(SL_UNICODE *u)
 	return &u->String;
 }
 
-// Create a packet buffer
-SL_PACKET_BUFFER *SlNewPacketBuffer()
-{
-	SL_PACKET_BUFFER *p;
-	NET_BUFFER_LIST_POOL_PARAMETERS p1;
-
-	// Memory allocation
-	p = SlZeroMalloc(sizeof(SL_PACKET_BUFFER));
-
-	// Create a NET_BUFFER_LIST pool
-	SlZero(&p1, sizeof(p1));
-	p1.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-	p1.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
-	p1.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
-	p1.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;
-	p1.fAllocateNetBuffer = TRUE;
-	p1.DataSize = SL_MAX_PACKET_SIZE;
-
-	p->NetBufferListPool = NdisAllocateNetBufferListPool(NULL, &p1);
-
-	// Create a NET_BUFFER_LIST
-	p->NetBufferList = NdisAllocateNetBufferList(p->NetBufferListPool, 0, 0);
-
-	return p;
-}
-
-// Release the packet buffer
-void SlFreePacketBuffer(SL_PACKET_BUFFER *p)
-{
-	// Validate arguments
-	if (p == NULL)
-	{
-		return;
-	}
-
-	// Release the NET_BUFFER_LIST
-	NdisFreeNetBufferList(p->NetBufferList);
-
-	// Release the NET_BUFFER_LIST pool
-	NdisFreeNetBufferListPool(p->NetBufferListPool);
-
-	// Release the memory
-	SlFree(p);
-}
-
 // Create a list
 SL_LIST *SlNewList()
 {

+ 1 - 2
src/SeLow/SeLow.h

@@ -301,6 +301,7 @@ typedef struct SL_ADAPTER
 	volatile UINT NumPendingSendPackets;	// Number of packets being transmitted
 	UCHAR TmpBuffer[SL_MAX_PACKET_SIZE];	// Temporally buffer size
 	char FriendlyName[256];				// Adapter name
+	bool SupportVLan;					// Supporting VLAN by hardware
 
 	SL_DEVICE *Device;					// Handle of the device
 } SL_ADAPTER;
@@ -367,8 +368,6 @@ SL_UNICODE *SlNewUnicode(char *str);
 SL_UNICODE *SlNewUnicodeFromUnicodeString(UNICODE_STRING *src);
 void SlFreeUnicode(SL_UNICODE *u);
 NDIS_STRING *SlGetUnicode(SL_UNICODE *u);
-SL_PACKET_BUFFER *SlNewPacketBuffer();
-void SlFreePacketBuffer(SL_PACKET_BUFFER *p);
 void SlCrash(UINT a, UINT b, UINT c, UINT d);
 SL_LIST *SlNewList();
 void SlAdd(SL_LIST *o, void *p);

+ 3 - 2
src/SeLow/SeLowCommon.h

@@ -115,7 +115,7 @@
 // Change this number every time functions are added or modified on the driver.
 // As long as this number does not change, installation of SeLow during the update
 // installation of the VPN Server / VPN Client / VPN Bridge is skipped.
-#define	SL_VER						42
+#define	SL_VER						43
 
 // Constants
 #define	SL_MAX_PACKET_SIZE			1560
@@ -165,7 +165,8 @@ typedef struct SL_ADAPTER_INFO
 	UCHAR Padding1[2];
 	UINT MtuSize;						// MTU size
 	char FriendlyName[256];				// Display name
-	UCHAR Reserved[256];				// Reserved area
+	UINT SupportsVLanHw;				// Supports VLAN by HW
+	UCHAR Reserved[256 - sizeof(UINT)];	// Reserved area
 } SL_ADAPTER_INFO;
 
 #define	SL_MAX_ADAPTER_INFO_LIST_ENTRY	256

BIN
src/bin/hamcore/SeLow_x64.sys


BIN
src/bin/hamcore/SeLow_x86.sys


+ 0 - 24
src/bin/hamcore/chain_certs.txt

@@ -1,24 +0,0 @@
-What is "chain_certs" directory?
---------------------------------
-
-If you are using a child SSL certificate file, which is issued by
-a CA (Certificate Authority), as the server certificate of VPN Server,
-you need to install X.509 format certificate files of the root
-certificate and all intermediate certificates on this "chain_certs"
-directory.
-
-If you don't know how to obtain root and intermediate certificate
-files of your certificate authority (CA), please refer to the CA's
-web site or contact support staffs of the CA.
-
-
-"chain_certs" ディレクトリについて
-----------------------------------
-VPN Server に登録する SSL 証明書が証明機関 (CA) によって発行されたもので
-ある場合は、この "chain_certs" ディレクトリに X.509 証明書のルート証明書
-および中間証明書ファイルをインストールしてください。
-
-ルート証明書および中間証明書ファイルの取得方法は、証明機関 (CA) が発行して
-いる Web サイトをお読みいただくか、証明機関 (CA) のサポートに問い合わせて
-ください。
-

+ 2 - 2
src/bin/hamcore/inf/selow_x64/SeLow_x64.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= NetTrans
 ClassGUID					= {4D36E975-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_selow.cat
 
@@ -66,5 +66,5 @@ SeLow_Description			= "A lightweight helper kernel-mode module for PacketiX VPN
 
 
 
-; Auto Generated 20140712_023530.474
+; Auto Generated 20141003_183142.008
 

BIN
src/bin/hamcore/inf/selow_x64/inf.cat


+ 2 - 2
src/bin/hamcore/inf/selow_x86/SeLow_x86.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= NetTrans
 ClassGUID					= {4D36E975-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_selow.cat
 
@@ -66,5 +66,5 @@ SeLow_Description			= "A lightweight helper kernel-mode module for PacketiX VPN
 
 
 
-; Auto Generated 20140712_023339.916
+; Auto Generated 20141003_182654.801
 

BIN
src/bin/hamcore/inf/selow_x86/inf.cat


+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN10.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN10.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN100.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN100.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN101.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN101.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN102.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN102.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN103.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN103.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN104.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN104.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN105.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN105.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN106.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN106.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN107.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN107.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN108.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN108.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN109.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN109.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN11.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN11.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN110.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN110.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN111.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN111.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN112.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN112.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN113.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN113.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN114.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN114.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN115.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN115.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN116.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN116.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN117.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN117.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN118.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN118.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN119.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN119.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN12.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN12.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN120.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN120.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN121.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN121.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN122.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN122.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN123.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN123.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN124.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN124.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN125.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN125.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN126.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN126.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN127.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN127.cat
 

+ 1 - 1
src/bin/hamcore/inf/x64/INF_VPN13.inf

@@ -8,7 +8,7 @@ Signature					= "$Windows NT$"
 Class						= Net
 ClassGUID					= {4D36E972-E325-11CE-BFC1-08002BE10318}
 Provider					= %CompanyName%
-DriverVer					= 07/12/2014, 4.10.0.9473
+DriverVer					= 10/03/2014, 4.10.0.9505
 
 CatalogFile.NT				= inf_VPN13.cat
 

Vissa filer visades inte eftersom för många filer har ändrats