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 // Bridge.c
103 // Ethernet Bridge Program (Local Bridge)
104
105 #include <GlobalConst.h>
106
107 #define BRIDGE_C
108
109 #ifdef WIN32
110 #define OS_WIN32
111 #endif
112
113 #ifdef OS_WIN32
114
115 // Win32
116 #include "BridgeWin32.c"
117
118 #else
119
120 // Unix
121 #include "BridgeUnix.c"
122
123 #endif // OS_WIN32
124
125 // Hash the list of current Ethernet devices
GetEthDeviceHash()126 UINT GetEthDeviceHash()
127 {
128 #ifdef OS_UNIX
129 // UNIX
130 UINT num;
131 UINT i;
132 char tmp[4096];
133 UCHAR hash[SHA1_SIZE];
134 TOKEN_LIST *t = GetEthList();
135
136 num = t->NumTokens;
137 tmp[0] = 0;
138 for (i = 0;i < t->NumTokens;i++)
139 {
140 StrCat(tmp, sizeof(tmp), t->Token[i]);
141 }
142 FreeToken(t);
143
144 Hash(hash, tmp, StrLen(tmp), true);
145
146 Copy(&num, hash, sizeof(UINT));
147
148 return num;
149 #else // OS_UNIX
150 // Win32
151 UINT ret = 0;
152 MS_ADAPTER_LIST *a = MsCreateAdapterListEx(true);
153 UINT num;
154 UINT i;
155 char tmp[4096];
156 UCHAR hash[SHA1_SIZE];
157
158 tmp[0] = 0;
159 if (a != NULL)
160 {
161 for (i = 0;i < a->Num;i++)
162 {
163 StrCat(tmp, sizeof(tmp), a->Adapters[i]->Title);
164 }
165 }
166 MsFreeAdapterList(a);
167
168 Hash(hash, tmp, StrLen(tmp), true);
169
170 Copy(&num, hash, sizeof(UINT));
171
172 return num;
173 #endif // OS_UNIX
174 }
175
176 // Get whether WinPcap is needed
IsNeedWinPcap()177 bool IsNeedWinPcap()
178 {
179 if (IsBridgeSupported() == false)
180 {
181 // Not in Windows
182 return false;
183 }
184 else
185 {
186 // Windows
187 if (IsEthSupported())
188 {
189 // Already success to access the Ethernet device
190 return false;
191 }
192 else
193 {
194 // Failed to access the Ethernet device
195 return true;
196 }
197 }
198 }
199
200 // Get whether the local-bridging is supported by current OS
IsBridgeSupported()201 bool IsBridgeSupported()
202 {
203 UINT type = GetOsInfo()->OsType;
204
205 if (OS_IS_WINDOWS(type))
206 {
207 if (IsEthSupported())
208 {
209 return true;
210 }
211 else
212 {
213 bool ret = false;
214
215 #ifdef OS_WIN32
216 ret = MsIsAdmin();
217 #endif // OS_WIN32
218
219 return ret;
220 }
221 }
222 else
223 {
224 return IsEthSupported();
225 }
226 }
227
228 // Delete a local-bridge
DeleteLocalBridge(CEDAR * c,char * hubname,char * devicename)229 bool DeleteLocalBridge(CEDAR *c, char *hubname, char *devicename)
230 {
231 bool ret = false;
232 // Validate arguments
233 if (c == NULL || hubname == NULL || devicename == NULL)
234 {
235 return false;
236 }
237
238 LockList(c->HubList);
239 {
240 LockList(c->LocalBridgeList);
241 {
242 UINT i;
243
244 for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
245 {
246 LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
247
248 if (StrCmpi(br->HubName, hubname) == 0)
249 {
250 if (StrCmpi(br->DeviceName, devicename) == 0)
251 {
252 if (br->Bridge != NULL)
253 {
254 BrFreeBridge(br->Bridge);
255 br->Bridge = NULL;
256 }
257
258 Delete(c->LocalBridgeList, br);
259 Free(br);
260
261 ret = true;
262 break;
263 }
264 }
265 }
266 }
267 UnlockList(c->LocalBridgeList);
268 }
269 UnlockList(c->HubList);
270
271 return ret;
272 }
273
274 // Add a local-bridge
AddLocalBridge(CEDAR * c,char * hubname,char * devicename,bool local,bool monitor,bool tapmode,char * tapaddr,bool limit_broadcast)275 void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast)
276 {
277 UINT i;
278 HUB *h = NULL;
279 LOCALBRIDGE *br = NULL;
280 // Validate arguments
281 if (c == NULL || hubname == NULL || devicename == NULL)
282 {
283 return;
284 }
285
286 if (OS_IS_UNIX(GetOsInfo()->OsType) == false)
287 {
288 tapmode = false;
289 }
290
291 LockList(c->HubList);
292 {
293 LockList(c->LocalBridgeList);
294 {
295 bool exists = false;
296
297 // Ensure that the same configuration local-bridge doesn't exist already
298 for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
299 {
300 LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
301 if (StrCmpi(br->DeviceName, devicename) == 0)
302 {
303 if (StrCmpi(br->HubName, hubname) == 0)
304 {
305 if (br->TapMode == tapmode)
306 {
307 exists = true;
308 }
309 }
310 }
311 }
312
313 if (exists == false)
314 {
315 // Add configuration
316 br = ZeroMalloc(sizeof(LOCALBRIDGE));
317 StrCpy(br->HubName, sizeof(br->HubName), hubname);
318 StrCpy(br->DeviceName, sizeof(br->DeviceName), devicename);
319 br->Bridge = NULL;
320 br->Local = local;
321 br->TapMode = tapmode;
322 br->LimitBroadcast = limit_broadcast;
323 br->Monitor = monitor;
324 if (br->TapMode)
325 {
326 if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
327 {
328 Copy(br->TapMacAddress, tapaddr, 6);
329 }
330 else
331 {
332 GenMacAddress(br->TapMacAddress);
333 }
334 }
335
336 Add(c->LocalBridgeList, br);
337
338 // Find the hub
339 for (i = 0;i < LIST_NUM(c->HubList);i++)
340 {
341 HUB *hub = LIST_DATA(c->HubList, i);
342 if (StrCmpi(hub->Name, br->HubName) == 0)
343 {
344 h = hub;
345 AddRef(h->ref);
346 break;
347 }
348 }
349 }
350 }
351 UnlockList(c->LocalBridgeList);
352 }
353 UnlockList(c->HubList);
354
355 // Start the local-bridge immediately
356 if (h != NULL && br != NULL && h->Type != HUB_TYPE_FARM_DYNAMIC)
357 {
358 Lock(h->lock_online);
359 {
360 if (h->Offline == false)
361 {
362 LockList(c->LocalBridgeList);
363 {
364 if (IsInList(c->LocalBridgeList, br))
365 {
366 if (br->Bridge == NULL)
367 {
368 br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor, br->TapMode, br->TapMacAddress, br->LimitBroadcast, br);
369 }
370 }
371 }
372 UnlockList(c->LocalBridgeList);
373 }
374 }
375 Unlock(h->lock_online);
376 }
377
378 ReleaseHub(h);
379 }
380
381 // Initialize the local-bridge list
InitLocalBridgeList(CEDAR * c)382 void InitLocalBridgeList(CEDAR *c)
383 {
384 // Validate arguments
385 if (c == NULL)
386 {
387 return;
388 }
389
390 c->LocalBridgeList = NewList(NULL);
391 }
392
393 // Free the local-bridge list
FreeLocalBridgeList(CEDAR * c)394 void FreeLocalBridgeList(CEDAR *c)
395 {
396 UINT i;
397 // Validate arguments
398 if (c == NULL)
399 {
400 return;
401 }
402
403 for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
404 {
405 LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
406 Free(br);
407 }
408
409 ReleaseList(c->LocalBridgeList);
410 c->LocalBridgeList = NULL;
411 }
412
413 // Bridging thread
BrBridgeThread(THREAD * thread,void * param)414 void BrBridgeThread(THREAD *thread, void *param)
415 {
416 BRIDGE *b;
417 CONNECTION *c;
418 SESSION *s;
419 HUB *h;
420 char name[MAX_SIZE];
421 // Validate arguments
422 if (thread == NULL || param == NULL)
423 {
424 return;
425 }
426
427 b = (BRIDGE *)param;
428
429 // Create a connection object
430 c = NewServerConnection(b->Cedar, NULL, thread);
431 c->Protocol = CONNECTION_HUB_BRIDGE;
432
433 // Create a session object
434 s = NewServerSession(b->Cedar, c, b->Hub, BRIDGE_USER_NAME, b->Policy);
435 HLog(b->Hub, "LH_START_BRIDGE", b->Name, s->Name);
436 StrCpy(name, sizeof(name), b->Name);
437 h = b->Hub;
438 AddRef(h->ref);
439 s->BridgeMode = true;
440 s->Bridge = b;
441 c->Session = s;
442 ReleaseConnection(c);
443
444 // Dummy user name for local-bridge
445 s->Username = CopyStr(BRIDGE_USER_NAME_PRINT);
446
447 b->Session = s;
448 AddRef(s->ref);
449
450 // Notify completion
451 NoticeThreadInit(thread);
452
453 // Main procedure of the session
454 Debug("Bridge %s Start.\n", b->Name);
455 SessionMain(s);
456 Debug("Bridge %s Stop.\n", b->Name);
457
458 HLog(h, "LH_STOP_BRIDGE", name);
459
460 ReleaseHub(h);
461
462 ReleaseSession(s);
463 }
464
465 // Free the local-bridge object
BrFreeBridge(BRIDGE * b)466 void BrFreeBridge(BRIDGE *b)
467 {
468 // Validate arguments
469 if (b == NULL)
470 {
471 return;
472 }
473
474 if (b->ParentLocalBridge != NULL)
475 {
476 b->ParentLocalBridge = NULL;
477 }
478
479 // Stop session thread
480 StopSession(b->Session);
481 ReleaseSession(b->Session);
482
483 Free(b);
484 }
485
486 // Create new local-bridge
BrNewBridge(HUB * h,char * name,POLICY * p,bool local,bool monitor,bool tapmode,char * tapaddr,bool limit_broadcast,LOCALBRIDGE * parent_local_bridge)487 BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge)
488 {
489 BRIDGE *b;
490 POLICY *policy;
491 THREAD *t;
492 // Validate arguments
493 if (h == NULL || name == NULL || parent_local_bridge == NULL)
494 {
495 return NULL;
496 }
497
498 if (p == NULL)
499 {
500 policy = ClonePolicy(GetDefaultPolicy());
501 }
502 else
503 {
504 policy = ClonePolicy(p);
505 }
506
507 b = ZeroMalloc(sizeof(BRIDGE));
508 b->Cedar = h->Cedar;
509 b->Hub = h;
510 StrCpy(b->Name, sizeof(b->Name), name);
511 b->Policy = policy;
512 b->Local = local;
513 b->Monitor = monitor;
514 b->TapMode = tapmode;
515 b->LimitBroadcast = limit_broadcast;
516 b->ParentLocalBridge = parent_local_bridge;
517
518 if (b->TapMode)
519 {
520 if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
521 {
522 Copy(b->TapMacAddress, tapaddr, 6);
523 }
524 else
525 {
526 GenMacAddress(b->TapMacAddress);
527 }
528 }
529
530 if (monitor)
531 {
532 // Enabling monitoring mode
533 policy->MonitorPort = true;
534 }
535
536 if (b->LimitBroadcast == false)
537 {
538 // Disable broadcast limiter
539 policy->NoBroadcastLimiter = true;
540 }
541
542 // Start thread
543 t = NewThread(BrBridgeThread, b);
544 WaitThreadInit(t);
545 ReleaseThread(t);
546
547 return b;
548 }
549
550 // Raw IP bridge is supported only on Linux
IsRawIpBridgeSupported()551 bool IsRawIpBridgeSupported()
552 {
553 #ifdef UNIX_LINUX
554 return true;
555 #else // UNIX_LINUX
556 return false;
557 #endif // UNIX_LINUX
558 }
559
560