1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Mayaqua Kernel
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 // Object.c
103 // Object management code
104 
105 #include <GlobalConst.h>
106 
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <wchar.h>
111 #include <stdarg.h>
112 #include <time.h>
113 #include <errno.h>
114 #include <Mayaqua/Mayaqua.h>
115 
116 // Thread to try to lock
CheckDeadLockThread(THREAD * t,void * param)117 void CheckDeadLockThread(THREAD *t, void *param)
118 {
119 	DEADCHECK *c = (DEADCHECK *)param;
120 
121 	if (t == NULL || c == NULL)
122 	{
123 		return;
124 	}
125 
126 	NoticeThreadInit(t);
127 
128 	Lock(c->Lock);
129 	Unlock(c->Lock);
130 	c->Unlocked = true;
131 }
132 
133 // Deadlock Detection
CheckDeadLock(LOCK * lock,UINT timeout,char * name)134 void CheckDeadLock(LOCK *lock, UINT timeout, char *name)
135 {
136 	DEADCHECK c;
137 	THREAD *t;
138 	char msg[MAX_PATH];
139 
140 	if (lock == NULL)
141 	{
142 		return;
143 	}
144 	if (name == NULL)
145 	{
146 		name = "Unknown";
147 	}
148 
149 	Format(msg, sizeof(msg), "error: CheckDeadLock() Failed: %s\n", name);
150 
151 	Zero(&c, sizeof(c));
152 	c.Lock = lock;
153 	c.Timeout = timeout;
154 	c.Unlocked = false;
155 
156 	t = NewThread(CheckDeadLockThread, &c);
157 	WaitThreadInit(t);
158 	if (WaitThread(t, timeout) == false)
159 	{
160 		if (c.Unlocked == false)
161 		{
162 			// Deadlock occured
163 			AbortExitEx(msg);
164 		}
165 		else
166 		{
167 			WaitThread(t, INFINITE);
168 		}
169 	}
170 
171 	ReleaseThread(t);
172 }
173 
174 // Create a lock object
NewLockMain()175 LOCK *NewLockMain()
176 {
177 	LOCK *lock;
178 	UINT retry = 0;
179 
180 	while (true)
181 	{
182 		if ((retry++) > OBJECT_ALLOC__MAX_RETRY)
183 		{
184 			AbortExitEx("error: OSNewLock() failed.\n\n");
185 		}
186 		lock = OSNewLock();
187 		if (lock != NULL)
188 		{
189 			break;
190 		}
191 		SleepThread(OBJECT_ALLOC_FAIL_SLEEP_TIME);
192 	}
193 
194 	return lock;
195 }
NewLock()196 LOCK *NewLock()
197 {
198 	LOCK *lock = NewLockMain();
199 
200 	// KS
201 	KS_INC(KS_NEWLOCK_COUNT);
202 	KS_INC(KS_CURRENT_LOCK_COUNT);
203 
204 	return lock;
205 }
206 
207 // Delete the lock object
DeleteLock(LOCK * lock)208 void DeleteLock(LOCK *lock)
209 {
210 	// Validate arguments
211 	if (lock == NULL)
212 	{
213 		return;
214 	}
215 
216 	// KS
217 	KS_INC(KS_DELETELOCK_COUNT);
218 	KS_DEC(KS_CURRENT_LOCK_COUNT);
219 
220 	OSDeleteLock(lock);
221 }
222 
223 // Lock
LockInner(LOCK * lock)224 bool LockInner(LOCK *lock)
225 {
226 	// Validate arguments
227 	if (lock == NULL)
228 	{
229 		return false;
230 	}
231 
232 	// KS
233 	KS_INC(KS_LOCK_COUNT);
234 	KS_INC(KS_CURRENT_LOCKED_COUNT);
235 
236 	return OSLock(lock);
237 }
238 
239 // Unlock
UnlockInner(LOCK * lock)240 void UnlockInner(LOCK *lock)
241 {
242 	// Validate arguments
243 	if (lock == NULL)
244 	{
245 		return;
246 	}
247 
248 	// KS
249 	KS_INC(KS_UNLOCK_COUNT);
250 	KS_DEC(KS_CURRENT_LOCKED_COUNT);
251 
252 	OSUnlock(lock);
253 }
254 
255 // Creating a counter
NewCounter()256 COUNTER *NewCounter()
257 {
258 	COUNTER *c;
259 
260 	// Memory allocation
261 	c = Malloc(sizeof(COUNTER));
262 
263 	// Initialization
264 	c->Ready = true;
265 	c->c = 0;
266 
267 	// Lock created
268 	c->lock = NewLock();
269 
270 	// KS
271 	KS_INC(KS_NEW_COUNTER_COUNT);
272 
273 	return c;
274 }
275 
276 // Delete the counter
DeleteCounter(COUNTER * c)277 void DeleteCounter(COUNTER *c)
278 {
279 	// Validate arguments
280 	if (c == NULL)
281 	{
282 		return;
283 	}
284 
285 	// KS
286 	KS_INC(KS_DELETE_COUNTER_COUNT);
287 	KS_SUB(KS_CURRENT_COUNT, c->c);
288 
289 	DeleteLock(c->lock);
290 	Free(c);
291 }
292 
293 // Get the count value
Count(COUNTER * c)294 UINT Count(COUNTER *c)
295 {
296 	UINT ret;
297 	// Validate arguments
298 	if (c == NULL)
299 	{
300 		return 0;
301 	}
302 	if (c->Ready == false)
303 	{
304 		return 0;
305 	}
306 
307 	Lock(c->lock);
308 	{
309 		if (c->Ready == false)
310 		{
311 			ret = 0;
312 		}
313 		else
314 		{
315 			ret = c->c;
316 		}
317 	}
318 	Unlock(c->lock);
319 
320 	return ret;
321 }
322 
323 // Increment
Inc(COUNTER * c)324 UINT Inc(COUNTER *c)
325 {
326 	UINT ret;
327 	// Validate arguments
328 	if (c == NULL)
329 	{
330 		return 0;
331 	}
332 	if (c->Ready == false)
333 	{
334 		return 0;
335 	}
336 
337 	Lock(c->lock);
338 	{
339 		if (c->Ready == false)
340 		{
341 			ret = 0;
342 		}
343 		else
344 		{
345 			c->c++;
346 			ret = c->c;
347 		}
348 	}
349 	Unlock(c->lock);
350 
351 	// KS
352 	KS_INC(KS_INC_COUNT);
353 	KS_INC(KS_CURRENT_COUNT);
354 
355 	return ret;
356 }
357 
358 // Decrement
Dec(COUNTER * c)359 UINT Dec(COUNTER *c)
360 {
361 	UINT ret;
362 	// Validate arguments
363 	if (c == NULL)
364 	{
365 		return 0;
366 	}
367 	if (c->Ready == false)
368 	{
369 		return 0;
370 	}
371 
372 	Lock(c->lock);
373 	{
374 		if (c->Ready == false)
375 		{
376 			ret = 0;
377 		}
378 		else
379 		{
380 			if (c->c != 0)
381 			{
382 				c->c--;
383 				ret = c->c;
384 			}
385 			else
386 			{
387 				ret = 0;
388 			}
389 		}
390 	}
391 	Unlock(c->lock);
392 
393 	// KS
394 	KS_INC(KS_DEC_COUNT);
395 	KS_DEC(KS_CURRENT_COUNT);
396 
397 	return ret;
398 }
399 
400 
401 // Release of the reference counter
Release(REF * ref)402 UINT Release(REF *ref)
403 {
404 	UINT c;
405 	// Validate arguments
406 	if (ref == NULL)
407 	{
408 		return 0;
409 	}
410 
411 	// KS
412 	KS_INC(KS_RELEASE_COUNT);
413 	KS_DEC(KS_CURRENT_REFED_COUNT);
414 
415 	c = Dec(ref->c);
416 	if (c == 0)
417 	{
418 		// KS
419 		KS_DEC(KS_CURRENT_REF_COUNT);
420 		KS_INC(KS_FREEREF_COUNT);
421 
422 		DeleteCounter(ref->c);
423 		ref->c = 0;
424 		Free(ref);
425 	}
426 	return c;
427 }
428 
429 // Increase of the reference counter
AddRef(REF * ref)430 UINT AddRef(REF *ref)
431 {
432 	UINT c;
433 	// Validate arguments
434 	if (ref == NULL)
435 	{
436 		return 0;
437 	}
438 
439 	c = Inc(ref->c);
440 
441 	// KS
442 	KS_INC(KS_ADDREF_COUNT);
443 	KS_INC(KS_CURRENT_REFED_COUNT);
444 
445 	return c;
446 }
447 
448 // Create a reference counter
NewRef()449 REF *NewRef()
450 {
451 	REF *ref;
452 
453 	// Memory allocation
454 	ref = Malloc(sizeof(REF));
455 
456 	// Create a Counter
457 	ref->c = NewCounter();
458 
459 	// Increment only once
460 	Inc(ref->c);
461 
462 	// KS
463 	KS_INC(KS_NEWREF_COUNT);
464 	KS_INC(KS_CURRENT_REF_COUNT);
465 	KS_INC(KS_ADDREF_COUNT);
466 	KS_INC(KS_CURRENT_REFED_COUNT);
467 
468 	return ref;
469 }
470 
471 // Creating an event object
NewEvent()472 EVENT *NewEvent()
473 {
474 	// Memory allocation
475 	EVENT *e = Malloc(sizeof(EVENT));
476 
477 	// Reference counter
478 	e->ref = NewRef();
479 
480 	// Event initialization
481 	OSInitEvent(e);
482 
483 	// KS
484 	KS_INC(KS_NEWEVENT_COUNT);
485 
486 	return e;
487 }
488 
489 // Release of the event
ReleaseEvent(EVENT * e)490 void ReleaseEvent(EVENT *e)
491 {
492 	// Validate arguments
493 	if (e == NULL)
494 	{
495 		return;
496 	}
497 
498 	if (Release(e->ref) == 0)
499 	{
500 		CleanupEvent(e);
501 	}
502 }
503 
504 // Delete the event
CleanupEvent(EVENT * e)505 void CleanupEvent(EVENT *e)
506 {
507 	// Validate arguments
508 	if (e == NULL)
509 	{
510 		return;
511 	}
512 
513 	// Release event
514 	OSFreeEvent(e);
515 
516 	// Memory release
517 	Free(e);
518 
519 	// KS
520 	KS_INC(KS_FREEEVENT_COUNT);
521 }
522 
523 // Set event
Set(EVENT * e)524 void Set(EVENT *e)
525 {
526 	// Validate arguments
527 	if (e == NULL)
528 	{
529 		return;
530 	}
531 
532 	OSSetEvent(e);
533 }
534 
535 // Wait for event
Wait(EVENT * e,UINT timeout)536 bool Wait(EVENT *e, UINT timeout)
537 {
538 	// Validate arguments
539 	if (e == NULL)
540 	{
541 		return false;
542 	}
543 
544 	// KS
545 	KS_INC(KS_WAIT_COUNT);
546 
547 	return OSWaitEvent(e, timeout);
548 }
549 
550 // Wait for a event until the cancel flag becomes true
WaitEx(EVENT * e,UINT timeout,volatile bool * cancel)551 bool WaitEx(EVENT *e, UINT timeout, volatile bool *cancel)
552 {
553 	bool dummy_bool = false;
554 	UINT64 start, giveup;
555 	// Validate arguments
556 	if (cancel == NULL)
557 	{
558 		cancel = &dummy_bool;
559 	}
560 
561 	start = Tick64();
562 
563 	if (timeout == INFINITE || timeout == 0x7FFFFFFF)
564 	{
565 		giveup = 0;
566 	}
567 	else
568 	{
569 		giveup = start + (UINT64)timeout;
570 	}
571 
572 	while (true)
573 	{
574 		UINT64 now = Tick64();
575 		UINT interval_to_giveup = (UINT)(giveup - now);
576 		if (giveup == 0)
577 		{
578 			interval_to_giveup = INFINITE;
579 		}
580 		else
581 		{
582 			if (now >= giveup)
583 			{
584 				// Time-out occurs
585 				return false;
586 			}
587 		}
588 
589 		interval_to_giveup = MIN(interval_to_giveup, 25);
590 
591 		if (*cancel)
592 		{
593 			// Cancel flag is set to true. Time-out occurs
594 			return false;
595 		}
596 
597 		if (e != NULL)
598 		{
599 			if (Wait(e, interval_to_giveup))
600 			{
601 				// Event is set
602 				return true;
603 			}
604 		}
605 		else
606 		{
607 			SleepThread(interval_to_giveup);
608 		}
609 	}
610 }
611 
612 
613 
614