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