1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // Protocol.h
103 // Header of Protocol.c
104 
105 #ifndef	PROTOCOL_H
106 #define	PROTOCOL_H
107 
108 // MIME types
109 struct HTTP_MIME_TYPE
110 {
111 	char *Extension;
112 	char *MimeType;
113 };
114 
115 // The parameters that will be passed to the certificate confirmation thread
116 struct CHECK_CERT_THREAD_PROC
117 {
118 	CONNECTION *Connection;
119 	X *ServerX;
120 	CHECK_CERT_PROC *CheckCertProc;
121 	bool UserSelected;
122 	bool Exipred;
123 	bool Ok;
124 };
125 
126 // The parameters that will be passed to the secure device signature thread
127 struct SECURE_SIGN_THREAD_PROC
128 {
129 	SECURE_SIGN_PROC *SecureSignProc;
130 	CONNECTION *Connection;
131 	SECURE_SIGN *SecureSign;
132 	bool UserFinished;
133 	bool Ok;
134 };
135 
136 // Signature sending thread parameters
137 struct SEND_SIGNATURE_PARAM
138 {
139 	char Hostname[MAX_PATH];		// Host name
140 	UINT Port;						// Port number
141 	BUF *Buffer;					// Packet contents
142 };
143 
144 // Software update client callback
145 typedef void (UPDATE_NOTIFY_PROC)(UPDATE_CLIENT *c, UINT latest_build, UINT64 latest_date, char *latest_ver, char *url, volatile bool *halt_flag, void *param);
146 typedef bool (UPDATE_ISFOREGROUND_PROC)(UPDATE_CLIENT *c, void *param);
147 
148 // Configure the software update client
149 struct UPDATE_CLIENT_SETTING
150 {
151 	bool DisableCheck;				// Disable the update check
152 	UINT LatestIgnoreBuild;			// Ignore for earlier or identical to this build number
153 };
154 
155 // Software update client
156 struct UPDATE_CLIENT
157 {
158 	char FamilyName[MAX_SIZE];		// Product family name
159 	char SoftwareName[MAX_SIZE];	// Software Name
160 	wchar_t SoftwareTitle[MAX_SIZE];	// Software display name
161 	char ClientId[128];				// Client ID
162 	UINT MyBuild;					// Build number of myself
163 	UINT64 MyDate;					// Build date of myself
164 	char MyLanguage[MAX_SIZE];		// My language
165 	UPDATE_CLIENT_SETTING Setting;	// Setting
166 	UINT LatestBuild;				// Latest build number that was successfully acquired
167 	volatile bool HaltFlag;			// Halting flag
168 	EVENT *HaltEvent;				// Halting event
169 	void *Param;					// Any parameters
170 	THREAD *Thread;					// Thread
171 	UPDATE_NOTIFY_PROC *Callback;	// Callback function
172 	UPDATE_ISFOREGROUND_PROC *IsForegroundCb;	// Callback function for retrieving whether foreground
173 };
174 
175 //// Constant related to updating of the software
176 
177 // Family
178 #define	UPDATE_FAMILY_NAME			_SS("PRODUCT_FAMILY_NAME")
179 
180 // Software update server certificate hash
181 #define	UPDATE_SERVER_CERT_HASH		DDNS_CERT_HASH
182 
183 // URL
184 #define	UPDATE_SERVER_URL_GLOBAL	"https://update-check.softether-network.net/update/update.aspx?family=%s&software=%s&mybuild=%u&lang=%s"
185 #define	UPDATE_SERVER_URL_CHINA		"https://update-check.uxcom.jp/update/update.aspx?family=%s&software=%s&mybuild=%u&lang=%s"
186 
187 // Update check interval
188 #define	UPDATE_CHECK_INTERVAL_MIN		(12 * 3600 * 1000)
189 #define	UPDATE_CHECK_INTERVAL_MAX		(24 * 7200 * 1000)
190 
191 // Connection parameters
192 #define	UPDATE_CONNECT_TIMEOUT			5000
193 #define	UPDATE_COMM_TIMEOUT				5000
194 
195 // Dynamic root cert fetch function
196 #define	CERT_HTTP_DOWNLOAD_MAXSIZE	65536
197 #define	CERT_HTTP_DOWNLOAD_TIMEOUT	(10 * 1000)
198 #define	ROOT_CERTS_FILENAME			"|root_certs.dat"
199 #define	AUTO_DOWNLOAD_CERTS_PREFIX	L".autodownload_"
200 #define	FIND_CERT_CHAIN_MAX_DEPTH	16
201 
202 #define	PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGKEY	"Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Client Update Notification"
203 #define	PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGVALUE	"Suppress"
204 
205 // WebSocket
206 struct WS
207 {
208 	SOCK *Sock;
209 	WSP *Wsp;
210 	REF *Ref;
211 	bool Disconnected;
212 	UINT MaxBufferSize;
213 	UCHAR TmpBuf[65536];
214 };
215 
216 // WebSocket Protocol
217 struct WSP
218 {
219 	UINT MaxBufferSize;
220 	FIFO *PhysicalSendFifo;		// WSP -> Network
221 	FIFO *PhysicalRecvFifo;		// WSP <- Network
222 	FIFO *AppSendFifo;			// APP -> WSP
223 	FIFO *AppRecvFifo;			// APP <- WSP
224 	bool HasError;
225 };
226 
227 // WebSocket constants
228 #define WS_MAX_PAYLOAD_LEN_PER_FRAME	(8 * 1024 * 1024)
229 #define WS_SEND_SINGLE_FRAGMENT_SIZE	(32 * 1024)
230 
231 #define WS_OPCODE_CONTINUE		0x00
232 #define WS_OPCODE_TEXT			0x01
233 #define WS_OPCODE_BIN			0x02
234 #define WS_OPCODE_CLOSE			0x08
235 #define WS_OPCODE_PING			0x09
236 #define WS_OPCODE_PONG			0x0A
237 
238 // MVPN constants
239 #define MVPN_VERSION_MIN			100
240 #define MVPN_VERSION_CURRENT		100
241 #define MVPN_MAX_AUTH_RETRY			10
242 #define	MVPN_CLIENT_NAME			"Modern VPN Client"
243 #define	NVPN_POSTFIX				"MVPN"
244 
245 // MVPN protocol constants
246 #define MVPN_AUTHTYPE_ANONYMOUS				"anonymous"
247 #define MVPN_AUTHTYPE_PASSWORD_PLAIN		"password_plain"
248 #define MVPN_AUTHTYPE_PASSWORD_MSCHAPV2		"password_mschapv2"
249 #define MVPN_AUTHTYPE_CERT					"x509cert"
250 
251 #define MVPN_HEARTBEAT_INTERVAL_DEFAULT		1234
252 #define	MVPN_HEARTBEAT_INTERVAL_MIN			100
253 #define	MVPN_HEARTBEAT_INTERVAL_MAX			15000
254 
255 #define MVPN_DISCONNECT_TIMEOUT_DEFAULT		15000
256 #define MVPN_DISCONNECT_TIMEOUT_MIN			5000
257 #define MVPN_DISCONNECT_TIMEOUT_MAX			60000
258 
259 #define MVPN_PACKET_MAGIC_NUMBER		0xCAFEBEEF
260 #define MVPN_PACKET_TYPE_ETHERNET		0
261 #define MVPN_PACKET_TYPE_IPV4			1
262 #define MVPN_PACKET_TYPE_HEARTBEAT		254
263 
264 #define MVPN_ADDRESS_TYPE_STATIC		"static"
265 #define MVPN_ADDRESS_TYPE_DYNAMIC		"dynamic"
266 
267 
268 
269 #define MVPN_AUTHTYPE_ALL_SUPPORTED			MVPN_AUTHTYPE_ANONYMOUS "," MVPN_AUTHTYPE_PASSWORD_PLAIN "," MVPN_AUTHTYPE_PASSWORD_MSCHAPV2 "," MVPN_AUTHTYPE_CERT
270 
271 
272 
273 
274 
275 // Function prototype
276 UPDATE_CLIENT *NewUpdateClient(UPDATE_NOTIFY_PROC *cb, UPDATE_ISFOREGROUND_PROC *isforeground_cb, void *param, char *family_name, char *software_name, wchar_t *software_title, UINT my_build, UINT64 my_date, char *my_lang, UPDATE_CLIENT_SETTING *current_setting, char *client_id);
277 void FreeUpdateClient(UPDATE_CLIENT *c);
278 void UpdateClientThreadProc(THREAD *thread, void *param);
279 void UpdateClientThreadMain(UPDATE_CLIENT *c);
280 void UpdateClientThreadProcessResults(UPDATE_CLIENT *c, BUF *b);
281 void SetUpdateClientSetting(UPDATE_CLIENT *c, UPDATE_CLIENT_SETTING *s);
282 UINT64 ShortStrToDate64(char *str);
283 
284 
285 bool ServerAccept(CONNECTION *c);
286 bool ClientConnect(CONNECTION *c);
287 SOCK *ClientConnectToServer(CONNECTION *c);
288 SOCK *TcpIpConnect(char *hostname, UINT port, bool try_start_ssl, bool ssl_no_tls);
289 SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd, UINT *nat_t_error_code, bool no_nat_t, bool try_start_ssl, bool ssl_no_tls, IP *ret_ip);
290 bool ClientUploadSignature(SOCK *s);
291 bool ClientDownloadHello(CONNECTION *c, SOCK *s);
292 bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str);
293 bool ServerUploadHello(CONNECTION *c);
294 bool ClientUploadAuth(CONNECTION *c);
295 SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect, bool no_tls);
296 SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool try_start_ssl, bool ssl_no_tls);
297 SOCK *TcpConnectEx3(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd, bool no_nat_t, UINT *nat_t_error_code, bool try_start_ssl, bool ssl_no_tls, IP *ret_ip);
298 
299 void InitProtocol();
300 void FreeProtocol();
301 
302 
303 
304 POLICY *PackGetPolicy(PACK *p);
305 void PackAddPolicy(PACK *p, POLICY *y);
306 PACK *PackWelcome(SESSION *s);
307 PACK *PackHello(void *random, UINT ver, UINT build, char *server_str);
308 bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size);
309 PACK *PackLoginWithAnonymous(char *hubname, char *username);
310 PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
311 PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
312 PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size);
313 PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x);
314 bool GetMethodFromPack(PACK *p, char *method, UINT size);
315 bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
316 								   char *hubname, UINT hubname_size);
317 PACK *PackAdditionalConnect(UCHAR *session_key);
318 UINT GetAuthTypeFromPack(PACK *p);
319 UINT GetProtocolFromPack(PACK *p);
320 bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
321 						  char *connection_name, UINT connection_name_size,
322 						  POLICY **policy);
323 
324 
325 bool ClientAdditionalConnect(CONNECTION *c, THREAD *t);
326 SOCK *ClientAdditionalConnectToServer(CONNECTION *c);
327 bool ClientUploadAuth2(CONNECTION *c, SOCK *s);
328 bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32);
329 void GenerateRC4KeyPair(RC4_KEY_PAIR *k);
330 
331 SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
332 				   char *server_host_name, UINT server_port,
333 				   char *username, char *password, bool additional_connect);
334 SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
335 					 char *server_host_name, UINT server_port,
336 					 char *username, char *password, bool additional_connect,
337 					 bool *cancel_flag, void *hWnd);
338 SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
339 					 char *server_host_name, UINT server_port,
340 					 char *username, char *password, bool additional_connect,
341 					 bool *cancel_flag, void *hWnd, UINT timeout);
342 SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
343 				   char *server_host_name, UINT server_port,
344 				   char *username, bool additional_connect);
345 SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
346 					 char *server_host_name, UINT server_port,
347 					 char *username, bool additional_connect,
348 					 bool *cancel_flag, void *hWnd);
349 SOCK *SocksConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
350 					 char *server_host_name, UINT server_port,
351 					 char *username, bool additional_connect,
352 					 bool *cancel_flag, void *hWnd, UINT timeout, IP *ret_ip);
353 bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid);
354 bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s);
355 void CreateNodeInfo(NODE_INFO *info, CONNECTION *c);
356 UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin);
357 void ClientUploadNoop(CONNECTION *c);
358 bool ClientCheckServerCert(CONNECTION *c, bool *expired);
359 void ClientCheckServerCertThread(THREAD *thread, void *param);
360 bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x);
361 void ClientSecureSignThread(THREAD *thread, void *param);
362 UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin);
363 UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list);
364 UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name);
365 TOKEN_LIST *EnumHub(SESSION *s);
366 UINT ChangePasswordAccept(CONNECTION *c, PACK *p);
367 UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass);
368 void PackAddClientVersion(PACK *p, CONNECTION *c);
369 void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info);
370 void GenerateMachineUniqueHash(void *data);
371 
372 LIST *NewCertList(bool load_root_and_chain);
373 void FreeCertList(LIST *o);
374 bool IsXInCertList(LIST *o, X *x);
375 void AddXToCertList(LIST *o, X *x);
376 void AddAllRootCertsToCertList(LIST *o);
377 void AddAllChainCertsToCertList(LIST *o);
378 X *DownloadCert(char *url);
379 X *FindCertIssuerFromCertList(LIST *o, X *x);
380 bool TryGetRootCertChain(LIST *o, X *x, bool auto_save, X **found_root_x);
381 bool TryGetParentCertFromCertList(LIST *o, X *x, LIST *found_chain);
382 bool DownloadAndSaveIntermediateCertificatesIfNecessary(X *x);
383 char *GetMimeTypeFromFileName(char *filename);
384 
385 void MvpnProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target);
386 bool MvpnSendReply(SOCK *s, UINT status_code, char *status_string, UCHAR *data, UINT data_size, char *content_type,
387 						char *add_header_name, char *add_header_value, HTTP_HEADER *request_headers);
388 void MvpnAccept(CONNECTION *c, SOCK *s);
389 UINT MvpnDoAccept(CONNECTION *c, WS *w);
390 
391 
392 WS *NewWs(SOCK *s);
393 void ReleaseWs(WS *w);
394 void CleanupWs(WS *w);
395 UINT WsRecvSync(WS *w, void *data, UINT size);
396 bool WsRecvSyncAll(WS *w, void *data, UINT size);
397 bool WsSendSync(WS *w, void *data, UINT size);
398 UINT WsRecvAsync(WS *w, void *data, UINT size);
399 UINT WsSendAsync(WS *w, void *data, UINT size);
400 bool WsTrySendAsync(WS *w);
401 PACK *WsRecvPack(WS *w);
402 bool WsSendPack(WS *w, PACK *p);
403 PACK *WsNewErrorPack(UINT err);
404 char *WsErrorCodeToString(UINT err);
405 
406 WSP *NewWsp();
407 void FreeWsp(WSP *p);
408 void WspTry(WSP *p);
409 BLOCK *WspTryRecvNextFrame(WSP *p, UINT *read_buffer_size);
410 void WspTrySendFrame(WSP *p, UCHAR opcode, void *data, UINT size);
411 
412 
413 
414 
415 #endif	// PROTOCOL_H
416