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 // BridgeWin32.c
103 // Ethernet Bridge Program (Win32)
104
105 #include <GlobalConst.h>
106
107 #ifdef BRIDGE_C
108
109 #include <winsock2.h>
110 #include <Ws2tcpip.h>
111 #include <windows.h>
112 #include <stdio.h>
113 #include <stdlib.h>
114 #include <string.h>
115 #include <wchar.h>
116 #include <stdarg.h>
117 #include <time.h>
118 #include <errno.h>
119 #include <Packet32.h>
120 #include <Mayaqua/Mayaqua.h>
121 #include <Cedar/Cedar.h>
122
123
124 static WP *wp = NULL;
125 static LIST *eth_list = NULL;
126
127 static LOCK *eth_list_lock = NULL;
128 static bool is_see_mode = false;
129 static bool is_using_selow = false;
130 static bool enable_selow = true;
131
132 static bool g_bridge_win32_show_all_if = false;
133
134 #define LOAD_DLL_ADDR(name) \
135 { \
136 void *addr = GetProcAddress(h, #name); \
137 Copy(&wp->name, &addr, sizeof(void *)); \
138 }
139
140 // Set the flag which indicates whether using SeLow
Win32SetEnableSeLow(bool b)141 void Win32SetEnableSeLow(bool b)
142 {
143 enable_selow = b;
144 }
145
146 // Get the flag which indicates whether using SeLow
Win32GetEnableSeLow()147 bool Win32GetEnableSeLow()
148 {
149 return enable_selow;
150 }
151
152 // Set the flag which indicates whether enumerating all interfaces
Win32EthSetShowAllIf(bool b)153 void Win32EthSetShowAllIf(bool b)
154 {
155 g_bridge_win32_show_all_if = b;
156 }
157
158 // Get the flag which indicates whether enumerating all interfaces
Win32EthGetShowAllIf()159 bool Win32EthGetShowAllIf()
160 {
161 return g_bridge_win32_show_all_if;
162 }
163
164 // Compare Ethernet device list
CmpRpcEnumEthVLan(void * p1,void * p2)165 int CmpRpcEnumEthVLan(void *p1, void *p2)
166 {
167 RPC_ENUM_ETH_VLAN_ITEM *v1, *v2;
168 if (p1 == NULL || p2 == NULL)
169 {
170 return 0;
171 }
172 v1 = *((RPC_ENUM_ETH_VLAN_ITEM **)p1);
173 v2 = *((RPC_ENUM_ETH_VLAN_ITEM **)p2);
174 if (v1 == NULL || v2 == NULL)
175 {
176 return 0;
177 }
178
179 return StrCmpi(v1->DeviceName, v2->DeviceName);
180 }
181
182 // Get the value of MTU (Not supported in Windows)
EthGetMtu(ETH * e)183 UINT EthGetMtu(ETH *e)
184 {
185 return 0;
186 }
187
188 // Set the value of MTU (Not supported in Windows)
EthSetMtu(ETH * e,UINT mtu)189 bool EthSetMtu(ETH *e, UINT mtu)
190 {
191 return false;
192 }
193
194 // Check whether setting MEU value (Not supported in Windows)
EthIsChangeMtuSupported(ETH * e)195 bool EthIsChangeMtuSupported(ETH *e)
196 {
197 return false;
198 }
199
200 // Set the state of VLAN tag pass-through
SetVLanEnableStatus(char * title,bool enable)201 bool SetVLanEnableStatus(char *title, bool enable)
202 {
203 RPC_ENUM_ETH_VLAN t;
204 RPC_ENUM_ETH_VLAN_ITEM *e;
205 bool ret = false;
206 char key[MAX_SIZE];
207 char tcpkey[MAX_SIZE];
208 char short_key[MAX_SIZE];
209 // Validate arguments
210 if (title == NULL)
211 {
212 return false;
213 }
214
215 Zero(&t, sizeof(t));
216 if (EnumEthVLanWin32(&t) == false)
217 {
218 return false;
219 }
220
221 e = FindEthVLanItem(&t, title);
222
223 if (e != NULL)
224 {
225 if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid))
226 {
227 if (StrCmpi(e->DriverType, "Intel") == 0)
228 {
229 if (enable)
230 {
231 MsRegWriteStr(REG_LOCAL_MACHINE, key, "VlanFiltering", "0");
232 MsRegWriteStr(REG_LOCAL_MACHINE, key, "TaggingMode", "0");
233 MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorMode", 1);
234 MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled", 1);
235 }
236 else
237 {
238 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "TaggingMode") == 0)
239 {
240 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "TaggingMode");
241 }
242
243 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode") == 1)
244 {
245 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorMode");
246 }
247
248 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled") == 1)
249 {
250 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
251 }
252 }
253
254 ret = true;
255 }
256 else if (StrCmpi(e->DriverType, "Broadcom") == 0)
257 {
258 if (enable)
259 {
260 MsRegWriteStr(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket", "1");
261 }
262 else
263 {
264 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket");
265 }
266
267 ret = true;
268 }
269 else if (StrCmpi(e->DriverType, "Marvell") == 0)
270 {
271 if (enable)
272 {
273 MsRegWriteInt(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip", 1);
274 }
275 else
276 {
277 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip");
278 }
279
280 ret = true;
281 }
282
283 Format(tcpkey, sizeof(tcpkey),
284 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
285 e->Guid);
286
287 if (enable)
288 {
289 if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
290 {
291 MsRegWriteInt(REG_LOCAL_MACHINE, tcpkey, "MTU", 1500);
292 }
293 }
294 else
295 {
296 UINT mtu = MsRegReadInt(REG_LOCAL_MACHINE, tcpkey, "MTU");
297 if (mtu == 1500)
298 {
299 MsRegDeleteValue(REG_LOCAL_MACHINE, tcpkey, "MTU");
300 }
301 }
302 }
303 }
304
305 FreeRpcEnumEthVLan(&t);
306
307 return ret;
308 }
309
310 // Find Ethernet device
FindEthVLanItem(RPC_ENUM_ETH_VLAN * t,char * name)311 RPC_ENUM_ETH_VLAN_ITEM *FindEthVLanItem(RPC_ENUM_ETH_VLAN *t, char *name)
312 {
313 UINT i;
314 // Validate arguments
315 if (t == NULL || name == NULL)
316 {
317 return NULL;
318 }
319
320 for (i = 0;i < t->NumItem;i++)
321 {
322 if (StrCmpi(t->Items[i].DeviceName, name) == 0)
323 {
324 return &t->Items[i];
325 }
326 }
327
328 return NULL;
329 }
330
331 // Get the state of VLAN tag pass-through
GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM * e)332 void GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
333 {
334 char key[MAX_SIZE];
335 char short_key[MAX_SIZE];
336 char tcpkey[MAX_SIZE];
337 // Validate arguments
338 if (e == NULL)
339 {
340 return;
341 }
342
343 e->Enabled = false;
344
345 if (e->Support == false)
346 {
347 return;
348 }
349
350 if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid) == false)
351 {
352 return;
353 }
354
355 Format(tcpkey, sizeof(tcpkey),
356 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
357 e->Guid);
358
359 if (StrCmpi(e->DriverType, "Intel") == 0)
360 {
361 char *VlanFiltering = MsRegReadStr(REG_LOCAL_MACHINE, key, "VlanFiltering");
362 UINT MonitorMode = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode");
363 UINT MonitorModeEnabled = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
364 char *TaggingMode = MsRegReadStr(REG_LOCAL_MACHINE, key, "TaggingMode");
365
366 if (StrCmpi(VlanFiltering, "0") == 0 &&
367 MonitorMode == 1 &&
368 MonitorModeEnabled == 1 &&
369 StrCmpi(TaggingMode, "0") == 0)
370 {
371 e->Enabled = true;
372 }
373
374 Free(VlanFiltering);
375 Free(TaggingMode);
376 }
377 else if (StrCmpi(e->DriverType, "Broadcom") == 0)
378 {
379 char *PreserveVlanInfoInRxPacket = MsRegReadStr(REG_LOCAL_MACHINE,
380 key, "PreserveVlanInfoInRxPacket");
381
382 if (StrCmpi(PreserveVlanInfoInRxPacket, "1") == 0)
383 {
384 e->Enabled = true;
385 }
386
387 Free(PreserveVlanInfoInRxPacket);
388 }
389 else if (StrCmpi(e->DriverType, "Marvell") == 0)
390 {
391 DWORD SkDisableVlanStrip = MsRegReadInt(REG_LOCAL_MACHINE,
392 key, "SkDisableVlanStrip");
393
394 if (SkDisableVlanStrip == 1)
395 {
396 e->Enabled = true;
397 }
398 }
399
400 if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
401 {
402 e->Enabled = false;
403 }
404 }
405
406 // Get VLAN tag pass-through availability of the device
GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM * e)407 void GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
408 {
409 BUF *b;
410 char filename[MAX_SIZE];
411 void *wow;
412 // Validate arguments
413 if (e == NULL)
414 {
415 return;
416 }
417
418 wow = MsDisableWow64FileSystemRedirection();
419
420 // Read the device driver file
421 CombinePath(filename, sizeof(filename), MsGetSystem32Dir(), "drivers");
422 CombinePath(filename, sizeof(filename), filename, e->DriverName);
423
424 b = ReadDump(filename);
425
426 if (b != NULL)
427 {
428 char intel1[] = "VlanFiltering";
429 char intel2[] = "V\0l\0a\0n\0F\0i\0l\0t\0e\0r\0i\0n\0g";
430 char intel3[] = "MonitorMode";
431 char intel4[] = "M\0o\0n\0i\0t\0o\0r\0M\0o\0d\0e";
432 char intel5[] = "TaggingMode";
433 char intel6[] = "T\0a\0g\0g\0i\0n\0g\0M\0o\0d\0e";
434 char broadcom1[] = "PreserveVlanInfoInRxPacket";
435 char broadcom2[] = "P\0r\0e\0s\0e\0r\0v\0e\0V\0l\0a\0n\0I\0n\0f\0o\0I\0n\0R\0x\0P\0a\0c\0k\0e\0t";
436 char marvell1[] = "SkDisableVlanStrip";
437 char marvell2[] = "S\0k\0D\0i\0s\0a\0b\0l\0e\0V\0l\0a\0n\0S\0t\0r\0i\0p";
438 char *driver_type = "";
439
440 if (SearchBin(b->Buf, 0, b->Size, intel1, sizeof(intel1)) != INFINITE
441 || SearchBin(b->Buf, 0, b->Size, intel2, sizeof(intel2)) != INFINITE
442 || SearchBin(b->Buf, 0, b->Size, intel3, sizeof(intel3)) != INFINITE
443 || SearchBin(b->Buf, 0, b->Size, intel4, sizeof(intel4)) != INFINITE
444 || SearchBin(b->Buf, 0, b->Size, intel5, sizeof(intel5)) != INFINITE
445 || SearchBin(b->Buf, 0, b->Size, intel6, sizeof(intel6)) != INFINITE)
446 {
447 driver_type = "Intel";
448 }
449 else if (SearchBin(b->Buf, 0, b->Size, broadcom1, sizeof(broadcom1)) != INFINITE
450 || SearchBin(b->Buf, 0, b->Size, broadcom2, sizeof(broadcom2)) != INFINITE)
451 {
452 driver_type = "Broadcom";
453 }
454 else if (SearchBin(b->Buf, 0, b->Size, marvell1, sizeof(marvell1)) != INFINITE
455 || SearchBin(b->Buf, 0, b->Size, marvell2, sizeof(marvell2)) != INFINITE)
456 {
457 driver_type = "Marvell";
458 }
459
460 if (IsEmptyStr(driver_type) == false)
461 {
462 StrCpy(e->DriverType, sizeof(e->DriverType), driver_type);
463 e->Support = true;
464 }
465
466 FreeBuf(b);
467 }
468
469 MsRestoreWow64FileSystemRedirection(wow);
470 }
471
472 // Get the device instance id from short_key
SearchDeviceInstanceIdFromShortKey(char * short_key)473 char *SearchDeviceInstanceIdFromShortKey(char *short_key)
474 {
475 char *ret = NULL;
476 TOKEN_LIST *t1;
477 // Validate arguments
478 if (short_key == NULL)
479 {
480 return NULL;
481 }
482
483 t1 = MsRegEnumKey(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum");
484
485 if (t1 != NULL)
486 {
487 TOKEN_LIST *t2;
488 char tmp[MAX_SIZE];
489 UINT i;
490
491 for (i = 0;i < t1->NumTokens;i++)
492 {
493 Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Enum\\%s", t1->Token[i]);
494
495 t2 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp);
496
497 if (t2 != NULL)
498 {
499 TOKEN_LIST *t3;
500 UINT i;
501
502 for (i = 0;i < t2->NumTokens;i++)
503 {
504 char tmp2[MAX_SIZE];
505
506 Format(tmp2, sizeof(tmp2), "%s\\%s", tmp, t2->Token[i]);
507
508 t3 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp2);
509
510 if (t3 != NULL)
511 {
512 UINT i;
513
514 for (i = 0;i < t3->NumTokens;i++)
515 {
516 char tmp3[MAX_SIZE];
517 char *s;
518
519 Format(tmp3, sizeof(tmp3), "%s\\%s", tmp2, t3->Token[i]);
520
521 s = MsRegReadStr(REG_LOCAL_MACHINE, tmp3, "Driver");
522
523 if (s != NULL)
524 {
525 if (StrCmpi(s, short_key) == 0)
526 {
527 if (ret != NULL)
528 {
529 Free(ret);
530 }
531
532 ret = CopyStr(tmp3 + StrLen("SYSTEM\\CurrentControlSet\\Enum\\"));
533 }
534
535 Free(s);
536 }
537 }
538
539 FreeToken(t3);
540 }
541 }
542
543 FreeToken(t2);
544 }
545 }
546
547 FreeToken(t1);
548 }
549
550 return ret;
551 }
552
553 // Get VLAN tag pass-through availability of all devices
EnumEthVLanWin32(RPC_ENUM_ETH_VLAN * t)554 bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t)
555 {
556 UINT i;
557 LIST *o;
558 // Validate arguments
559 if (t == NULL)
560 {
561 return false;
562 }
563
564 Zero(t, sizeof(RPC_ENUM_ETH_VLAN));
565
566 if (MsIsWin2000OrGreater() == false)
567 {
568 return false;
569 }
570
571 if (IsEthSupported() == false)
572 {
573 return false;
574 }
575
576 // Get device list
577 Lock(eth_list_lock);
578
579 InitEthAdaptersList();
580
581 o = NewListFast(CmpRpcEnumEthVLan);
582
583 for (i = 0;i < LIST_NUM(eth_list);i++)
584 {
585 WP_ADAPTER *a = LIST_DATA(eth_list, i);
586
587 if (IsEmptyStr(a->Guid) == false)
588 {
589 char class_key[MAX_SIZE];
590 char short_key[MAX_SIZE];
591
592 if (GetClassRegKeyWin32(class_key, sizeof(class_key),
593 short_key, sizeof(short_key), a->Guid))
594 {
595 char *device_instance_id = MsRegReadStr(REG_LOCAL_MACHINE, class_key, "DeviceInstanceID");
596
597 if (IsEmptyStr(device_instance_id))
598 {
599 Free(device_instance_id);
600 device_instance_id = SearchDeviceInstanceIdFromShortKey(short_key);
601 }
602
603 if (IsEmptyStr(device_instance_id) == false)
604 {
605 char device_key[MAX_SIZE];
606 char *service_name;
607
608 Format(device_key, sizeof(device_key), "SYSTEM\\CurrentControlSet\\Enum\\%s",
609 device_instance_id);
610
611 service_name = MsRegReadStr(REG_LOCAL_MACHINE, device_key, "Service");
612 if (IsEmptyStr(service_name) == false)
613 {
614 char service_key[MAX_SIZE];
615 char *sys;
616
617 Format(service_key, sizeof(service_key),
618 "SYSTEM\\CurrentControlSet\\services\\%s",
619 service_name);
620
621 sys = MsRegReadStr(REG_LOCAL_MACHINE, service_key, "ImagePath");
622
623 if (IsEmptyStr(sys) == false)
624 {
625 char sysname[MAX_PATH];
626
627 GetFileNameFromFilePath(sysname, sizeof(sysname), sys);
628
629 Trim(sysname);
630
631 if (EndWith(sysname, ".sys"))
632 {
633 // device found
634 RPC_ENUM_ETH_VLAN_ITEM *e = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM));
635
636 StrCpy(e->DeviceName, sizeof(e->DeviceName), a->Title);
637 StrCpy(e->Guid, sizeof(e->Guid), a->Guid);
638 StrCpy(e->DeviceInstanceId, sizeof(e->DeviceInstanceId), device_instance_id);
639 StrCpy(e->DriverName, sizeof(e->DriverName), sysname);
640
641 // Get VLAN tag pass-through availability of the device
642 GetVLanSupportStatus(e);
643
644 // Get current pass-through setting of the device
645 GetVLanEnableStatus(e);
646
647 Insert(o, e);
648 }
649 }
650
651 Free(sys);
652 }
653
654 Free(service_name);
655 }
656
657 Free(device_instance_id);
658 }
659 }
660 }
661
662 t->NumItem = LIST_NUM(o);
663 t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * i);
664
665 for (i = 0;i < LIST_NUM(o);i++)
666 {
667 RPC_ENUM_ETH_VLAN_ITEM *e = LIST_DATA(o, i);
668
669 Copy(&t->Items[i], e, sizeof(RPC_ENUM_ETH_VLAN_ITEM));
670
671 Free(e);
672 }
673
674 ReleaseList(o);
675
676 Unlock(eth_list_lock);
677
678 return true;
679 }
680
681 // Get registry key of the network class data by GUID
GetClassRegKeyWin32(char * key,UINT key_size,char * short_key,UINT short_key_size,char * guid)682 bool GetClassRegKeyWin32(char *key, UINT key_size, char *short_key, UINT short_key_size, char *guid)
683 {
684 TOKEN_LIST *t;
685 bool ret = false;
686 UINT i;
687 // Validate arguments
688 if (key == NULL || short_key == NULL || guid == NULL)
689 {
690 return false;
691 }
692
693 t = MsRegEnumKey(REG_LOCAL_MACHINE,
694 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
695 if (t == NULL)
696 {
697 return false;
698 }
699
700 for (i = 0;i < t->NumTokens;i++)
701 {
702 char keyname[MAX_SIZE];
703 char *value;
704
705 Format(keyname, sizeof(keyname),
706 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
707 t->Token[i]);
708
709 value = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "NetCfgInstanceId");
710
711 if (StrCmpi(value, guid) == 0)
712 {
713 ret = true;
714
715 StrCpy(key, key_size, keyname);
716
717 Format(short_key, short_key_size, "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
718 t->Token[i]);
719 }
720
721 Free(value);
722 }
723
724 FreeToken(t);
725
726 return ret;
727 }
728
729 // Send multiple packets
EthPutPackets(ETH * e,UINT num,void ** datas,UINT * sizes)730 void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
731 {
732 UINT i, total_size;
733 UCHAR *buf;
734 UINT write_pointer;
735 UINT err = 0;
736 // Validate arguments
737 if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
738 {
739 return;
740 }
741 if (e->HasFatalError)
742 {
743 return;
744 }
745
746 if (e->SuAdapter != NULL)
747 {
748 bool ok = true;
749
750 // Send packets with SeLow
751 for (i = 0;i < num;i++)
752 {
753 UCHAR *data = datas[i];
754 UINT size = sizes[i];
755
756 if (ok)
757 {
758 // Actually, only enqueuing
759 ok = SuPutPacket(e->SuAdapter, data, size);
760 }
761
762 if (ok == false)
763 {
764 // Free memory on write error
765 Free(data);
766 }
767 }
768
769 if (ok)
770 {
771 // Send all data in queue at once
772 ok = SuPutPacket(e->SuAdapter, NULL, 0);
773 }
774
775 if (ok == false)
776 {
777 // Error occurred
778 e->HasFatalError = true;
779 }
780
781 return;
782 }
783
784 if (IsWin32BridgeWithSee() == false)
785 {
786 if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())
787 {
788 e->LastSetSingleCpu = Tick64();
789 MsSetThreadSingleCpu();
790 }
791 }
792
793 // Calculate buffer size
794 total_size = 0;
795 for (i = 0;i < num;i++)
796 {
797 void *data = datas[i];
798 UINT size = sizes[i];
799 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
800 {
801 total_size += size + sizeof(struct dump_bpf_hdr);
802 }
803 }
804
805 buf = MallocFast(total_size * 100 / 75 + 1600);
806
807 write_pointer = 0;
808 // Enqueue
809 for (i = 0;i < num;i++)
810 {
811 void *data = datas[i];
812 UINT size = sizes[i];
813 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
814 {
815 struct dump_bpf_hdr *h;
816
817 h = (struct dump_bpf_hdr *)(buf + write_pointer);
818 Zero(h, sizeof(struct dump_bpf_hdr));
819 h->caplen = h->len = size;
820 write_pointer += sizeof(struct dump_bpf_hdr);
821 Copy(buf + write_pointer, data, size);
822 write_pointer += size;
823
824 PROBE_DATA2("EthPutPackets", data, size);
825 }
826 // Free original buffer
827 Free(data);
828 }
829
830 // Send
831 if (total_size != 0)
832 {
833 err = wp->PacketSendPackets(e->Adapter, buf, total_size, true);
834 }
835
836 Free(buf);
837
838 if (err == 0x7FFFFFFF)
839 {
840 // Critical error (infinite loop) occurred on sending
841 e->HasFatalError = true;
842 }
843 }
844
845 // Send a packet
EthPutPacket(ETH * e,void * data,UINT size)846 void EthPutPacket(ETH *e, void *data, UINT size)
847 {
848 // Validate arguments
849 if (e == NULL || data == NULL || size == 0)
850 {
851 return;
852 }
853
854 EthPutPackets(e, 1, &data, &size);
855 }
856
857 // Read next packet
EthGetPacket(ETH * e,void ** data)858 UINT EthGetPacket(ETH *e, void **data)
859 {
860 BLOCK *b;
861 bool flag = false;
862 // Validate arguments
863 if (e == NULL || data == NULL)
864 {
865 return INFINITE;
866 }
867 if (e->HasFatalError)
868 {
869 return INFINITE;
870 }
871
872 if (e->SuAdapter != NULL)
873 {
874 // Read packet with SeLow
875 UINT size;
876 if (SuGetNextPacket(e->SuAdapter, data, &size) == false)
877 {
878 // Error occurred
879 e->HasFatalError = true;
880 return INFINITE;
881 }
882
883 return size;
884 }
885
886 RETRY:
887 // Check the presence of the packet in queue
888 b = GetNext(e->PacketQueue);
889 if (b != NULL)
890 {
891 UINT size;
892 size = b->Size;
893 *data = b->Buf;
894 Free(b);
895
896 if (e->PacketQueue->num_item == 0)
897 {
898 e->Empty = true;
899 }
900
901 return size;
902 }
903
904 if (e->Empty)
905 {
906 e->Empty = false;
907 return 0;
908 }
909
910 if (flag == false)
911 {
912 // Try to get next packet
913 PROBE_STR("EthGetPacket: PacketInitPacket");
914 wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize);
915 PROBE_STR("EthGetPacket: PacketReceivePacket");
916 if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false)
917 {
918 // Failed
919 return INFINITE;
920 }
921 else
922 {
923 UCHAR *buf;
924 UINT total;
925 UINT offset;
926
927 buf = (UCHAR *)e->Packet->Buffer;
928 total = e->Packet->ulBytesReceived;
929 offset = 0;
930
931 while (offset < total)
932 {
933 struct bpf_hdr *header;
934 UINT packet_size;
935 UCHAR *packet_data;
936
937 header = (struct bpf_hdr *)(buf + offset);
938 packet_size = header->bh_caplen;
939 offset += header->bh_hdrlen;
940 packet_data = buf + offset;
941 offset = Packet_WORDALIGN(offset + packet_size);
942
943 if (packet_size >= 14)
944 {
945 UCHAR *tmp;
946 BLOCK *b;
947
948 PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size);
949
950 tmp = MallocFast(packet_size);
951
952 Copy(tmp, packet_data, packet_size);
953 b = NewBlock(tmp, packet_size, 0);
954 InsertQueue(e->PacketQueue, b);
955 }
956 }
957
958 flag = true;
959 goto RETRY;
960 }
961 }
962
963 // No more packet
964 return 0;
965 }
966
967 // Get cancel object
EthGetCancel(ETH * e)968 CANCEL *EthGetCancel(ETH *e)
969 {
970 // Validate arguments
971 if (e == NULL)
972 {
973 return NULL;
974 }
975
976 AddRef(e->Cancel->ref);
977
978 return e->Cancel;
979 }
980
981 // Close adapter
CloseEth(ETH * e)982 void CloseEth(ETH *e)
983 {
984 BLOCK *b;
985 // Validate arguments
986 if (e == NULL)
987 {
988 return;
989 }
990
991 ReleaseCancel(e->Cancel);
992
993 if (e->SuAdapter != NULL)
994 {
995 // Close SeLow adapter
996 SuCloseAdapter(e->SuAdapter);
997 SuFree(e->Su);
998 }
999 else
1000 {
1001 // Close SEE adapter
1002 wp->PacketCloseAdapter(e->Adapter);
1003 wp->PacketFreePacket(e->Packet);
1004 wp->PacketFreePacket(e->PutPacket);
1005 }
1006
1007 while (b = GetNext(e->PacketQueue))
1008 {
1009 FreeBlock(b);
1010 }
1011 ReleaseQueue(e->PacketQueue);
1012
1013 Free(e->Name);
1014 Free(e->Title);
1015 Free(e->Buffer);
1016
1017 Free(e);
1018 }
1019
1020 // Search adapter with the name
Win32EthSearch(char * name)1021 struct WP_ADAPTER *Win32EthSearch(char *name)
1022 {
1023 UINT i;
1024 UINT id;
1025 char simple_name[MAX_SIZE];
1026 WP_ADAPTER *ret = NULL;
1027
1028 id = Win32EthGetNameAndIdFromCombinedName(simple_name, sizeof(simple_name), name);
1029
1030 if (id != 0)
1031 {
1032 UINT num_match = 0;
1033 // Search with ID when ID is specified
1034 for (i = 0;i < LIST_NUM(eth_list);i++)
1035 {
1036 WP_ADAPTER *a = LIST_DATA(eth_list, i);
1037
1038 if (a->Id != 0 && a->Id == id)
1039 {
1040 ret = a;
1041 num_match++;
1042 }
1043 }
1044
1045 if (num_match >= 2)
1046 {
1047 // If the ID matches to 2 or more devices, search with the name
1048 for (i = 0;i < LIST_NUM(eth_list);i++)
1049 {
1050 WP_ADAPTER *a = LIST_DATA(eth_list, i);
1051
1052 if (a->Id != 0 && a->Id == id)
1053 {
1054 if (StrCmpi(a->Title, name) == 0)
1055 {
1056 ret = a;
1057 break;
1058 }
1059 }
1060 }
1061 }
1062 }
1063 else
1064 {
1065 // Search with name when ID is not specified
1066 for (i = 0;i < LIST_NUM(eth_list);i++)
1067 {
1068 WP_ADAPTER *a = LIST_DATA(eth_list, i);
1069
1070 if (StrCmpi(a->Title, name) == 0)
1071 {
1072 ret = a;
1073 break;
1074 }
1075 }
1076 }
1077
1078 return ret;
1079 }
1080
1081 // Open adapter
OpenEth(char * name,bool local,bool tapmode,char * tapaddr)1082 ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
1083 {
1084 ETH *ret;
1085 void *p;
1086
1087 p = MsDisableWow64FileSystemRedirection();
1088
1089 ret = OpenEthInternal(name, local, tapmode, tapaddr);
1090
1091 MsRestoreWow64FileSystemRedirection(p);
1092
1093 return ret;
1094 }
OpenEthInternal(char * name,bool local,bool tapmode,char * tapaddr)1095 ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr)
1096 {
1097 WP_ADAPTER *t;
1098 ETH *e;
1099 ADAPTER *a = NULL;
1100 HANDLE h;
1101 CANCEL *c;
1102 MS_ADAPTER *ms;
1103 char name_with_id[MAX_SIZE];
1104 SU *su = NULL;
1105 SU_ADAPTER *su_adapter = NULL;
1106 // Validate arguments
1107 if (name == NULL || IsEthSupported() == false)
1108 {
1109 return NULL;
1110 }
1111
1112 if (tapmode)
1113 {
1114 // Tap is not supported in Windows
1115 return NULL;
1116 }
1117
1118 Lock(eth_list_lock);
1119
1120 InitEthAdaptersList();
1121
1122 t = Win32EthSearch(name);
1123
1124 if (t == NULL)
1125 {
1126 Unlock(eth_list_lock);
1127 return NULL;
1128 }
1129
1130 Debug("OpenEthInternal: %s\n", t->Name);
1131
1132 if (StartWith(t->Name, SL_ADAPTER_ID_PREFIX))
1133 {
1134 // Open with SU
1135 su = SuInit();
1136 if (su == NULL)
1137 {
1138 // Fail to initialize SU
1139 Unlock(eth_list_lock);
1140 return NULL;
1141 }
1142
1143 su_adapter = SuOpenAdapter(su, t->Name);
1144
1145 if (su_adapter == NULL)
1146 {
1147 // Fail to get adapter
1148 SuFree(su);
1149 Unlock(eth_list_lock);
1150 return NULL;
1151 }
1152
1153 is_using_selow = true;
1154 }
1155 else
1156 {
1157 // Open with SEE
1158 a = wp->PacketOpenAdapter(t->Name);
1159 if (a == NULL)
1160 {
1161 Unlock(eth_list_lock);
1162 return NULL;
1163 }
1164
1165 if (IsWin32BridgeWithSee() == false)
1166 {
1167 MsSetThreadSingleCpu();
1168 }
1169
1170 is_using_selow = false;
1171 }
1172
1173 e = ZeroMalloc(sizeof(ETH));
1174 e->Name = CopyStr(t->Name);
1175
1176 Win32EthMakeCombinedName(name_with_id, sizeof(name_with_id), t->Title, t->Guid);
1177 e->Title = CopyStr(name_with_id);
1178
1179 if (su_adapter != NULL)
1180 {
1181 // SU
1182 e->SuAdapter = su_adapter;
1183 e->Su = su;
1184
1185 // Get event object
1186 h = e->SuAdapter->hEvent;
1187
1188 c = NewCancelSpecial(h);
1189 e->Cancel = c;
1190 }
1191 else
1192 {
1193 // SEE
1194 e->Adapter = a;
1195
1196 wp->PacketSetBuff(e->Adapter, BRIDGE_WIN32_ETH_BUFFER);
1197 wp->PacketSetHwFilter(e->Adapter, local ? 0x0080 : 0x0020);
1198 wp->PacketSetMode(e->Adapter, PACKET_MODE_CAPT);
1199 wp->PacketSetReadTimeout(e->Adapter, -1);
1200 wp->PacketSetNumWrites(e->Adapter, 1);
1201
1202 if (wp->PacketSetLoopbackBehavior != NULL)
1203 {
1204 // Filter loopback packet in kernel
1205 if (GET_KETA(GetOsType(), 100) >= 3)
1206 {
1207 if (MsIsWindows8() == false)
1208 {
1209 // Enable for Windows XP, Server 2003 or later
1210 // But disable for Windows 8 or later
1211 bool ret = wp->PacketSetLoopbackBehavior(e->Adapter, 1);
1212 Debug("*** PacketSetLoopbackBehavior: %u\n", ret);
1213
1214 e->LoopbackBlock = ret;
1215 }
1216 }
1217 }
1218
1219 // Get event object
1220 h = wp->PacketGetReadEvent(e->Adapter);
1221
1222 c = NewCancelSpecial(h);
1223 e->Cancel = c;
1224
1225 e->Packet = wp->PacketAllocatePacket();
1226
1227 e->PutPacket = wp->PacketAllocatePacket();
1228 }
1229
1230 e->Buffer = Malloc(BRIDGE_WIN32_ETH_BUFFER);
1231 e->BufferSize = BRIDGE_WIN32_ETH_BUFFER;
1232
1233 e->PacketQueue = NewQueue();
1234
1235 // Get MAC address by GUID
1236 ms = MsGetAdapterByGuid(t->Guid);
1237 if (ms != NULL)
1238 {
1239 if (ms->AddressSize == 6)
1240 {
1241 Copy(e->MacAddress, ms->Address, 6);
1242 }
1243
1244 MsFreeAdapter(ms);
1245 }
1246
1247 Unlock(eth_list_lock);
1248
1249 return e;
1250 }
1251
1252 // Generate a combined name from NIC name and GUID
Win32EthMakeCombinedName(char * dst,UINT dst_size,char * nicname,char * guid)1253 void Win32EthMakeCombinedName(char *dst, UINT dst_size, char *nicname, char *guid)
1254 {
1255 // Validate arguments
1256 if (dst == NULL || nicname == NULL || guid == NULL)
1257 {
1258 return;
1259 }
1260
1261 if (IsEmptyStr(guid) == false)
1262 {
1263 Format(dst, dst_size, "%s (ID=%010u)", nicname, Win32EthGenIdFromGuid(guid));
1264 }
1265 else
1266 {
1267 StrCpy(dst, dst_size, nicname);
1268 }
1269 }
1270
1271 // Decompose combined name
Win32EthGetNameAndIdFromCombinedName(char * name,UINT name_size,char * str)1272 UINT Win32EthGetNameAndIdFromCombinedName(char *name, UINT name_size, char *str)
1273 {
1274 UINT ret = 0;
1275 char id_str[MAX_SIZE];
1276 UINT len;
1277 // Validate arguments
1278 ClearStr(name, name_size);
1279 StrCpy(name, name_size, str);
1280 if (name == NULL || str == NULL)
1281 {
1282 return 0;
1283 }
1284
1285 len = StrLen(str);
1286
1287 if (len >= 16)
1288 {
1289 StrCpy(id_str, sizeof(id_str), str + len - 16);
1290
1291 if (StartWith(id_str, " (ID="))
1292 {
1293 if (EndWith(id_str, ")"))
1294 {
1295 char num[MAX_SIZE];
1296
1297 Zero(num, sizeof(num));
1298 StrCpy(num, sizeof(num), id_str + 5);
1299
1300 num[StrLen(num) - 1] = 0;
1301
1302 ret = ToInt(num);
1303
1304 if (ret != 0)
1305 {
1306 name[len - 16] = 0;
1307 }
1308 }
1309 }
1310 }
1311
1312 return ret;
1313 }
1314
1315 // Generate an ID from GUID
Win32EthGenIdFromGuid(char * guid)1316 UINT Win32EthGenIdFromGuid(char *guid)
1317 {
1318 char tmp[MAX_SIZE];
1319 UCHAR hash[SHA1_SIZE];
1320 UINT i;
1321 // Validate arguments
1322 if (guid == NULL)
1323 {
1324 return 0;
1325 }
1326
1327 StrCpy(tmp, sizeof(tmp), guid);
1328 Trim(tmp);
1329 StrUpper(tmp);
1330
1331 HashSha1(hash, tmp, StrLen(tmp));
1332
1333 Copy(&i, hash, sizeof(UINT));
1334
1335 i = Endian32(i);
1336
1337 if (i == 0)
1338 {
1339 i = 1;
1340 }
1341
1342 return i;
1343 }
1344
1345 // Get Ethernet adapter list
GetEthList()1346 TOKEN_LIST *GetEthList()
1347 {
1348 UINT v;
1349
1350 return GetEthListEx(&v, true, false);
1351 }
GetEthListEx(UINT * total_num_including_hidden,bool enum_normal,bool enum_rawip)1352 TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip)
1353 {
1354 TOKEN_LIST *ret;
1355 UINT i;
1356 UINT j;
1357 UINT dummy_int;
1358 MS_ADAPTER_LIST *adapter_list;
1359
1360 if (IsEthSupported() == false)
1361 {
1362 return NULL;
1363 }
1364
1365 if (enum_normal == false)
1366 {
1367 return NullToken();
1368 }
1369
1370 if (total_num_including_hidden == NULL)
1371 {
1372 total_num_including_hidden = &dummy_int;
1373 }
1374
1375 *total_num_including_hidden = 0;
1376
1377 Lock(eth_list_lock);
1378
1379 InitEthAdaptersList();
1380
1381 adapter_list = MsCreateAdapterList();
1382
1383 ret = ZeroMalloc(sizeof(TOKEN_LIST));
1384 ret->NumTokens = LIST_NUM(eth_list);
1385 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
1386 j = 0;
1387 for (i = 0;i < ret->NumTokens;i++)
1388 {
1389 char tmp[MAX_SIZE];
1390 WP_ADAPTER *a = LIST_DATA(eth_list, i);
1391 MS_ADAPTER *msa = NULL;
1392 bool show = true;
1393
1394 if (Win32EthGetShowAllIf() == false)
1395 {
1396 msa = MsGetAdapterByGuidFromList(adapter_list, a->Guid);
1397
1398 if (InStr(a->Title, "vpn client adapter"))
1399 {
1400 // Hide virtual NIC for VPN client
1401 show = false;
1402 }
1403
1404 if (InStr(a->Title, "tunnel adapter"))
1405 {
1406 // Hide tunnel adapter
1407 show = false;
1408 }
1409
1410 if (InStr(a->Title, "teredo tunnel"))
1411 {
1412 // Hide tunnel adapter
1413 show = false;
1414 }
1415
1416 if (InStr(a->Title, "MS Tunnel Interface"))
1417 {
1418 // Hide tunnel adapter
1419 show = false;
1420 }
1421
1422 if (InStr(a->Title, "pseudo-interface"))
1423 {
1424 // Hide tunnel adapter
1425 show = false;
1426 }
1427 }
1428
1429 if (msa != NULL)
1430 {
1431 // Hide except physical Ethernet NIC
1432 if (msa->IsNotEthernetLan)
1433 {
1434 show = false;
1435 }
1436
1437 MsFreeAdapter(msa);
1438 }
1439
1440 Win32EthMakeCombinedName(tmp, sizeof(tmp), a->Title, a->Guid);
1441
1442 if (show)
1443 {
1444 ret->Token[j++] = CopyStr(tmp);
1445
1446 Debug("%s - %s\n", a->Guid, a->Title);
1447 }
1448 }
1449
1450 *total_num_including_hidden = ret->NumTokens;
1451
1452 ret->NumTokens = j;
1453
1454 Unlock(eth_list_lock);
1455
1456 MsFreeAdapterList(adapter_list);
1457
1458 return ret;
1459 }
1460
1461 // Compare the name of WP_ADAPTER
CompareWpAdapter(void * p1,void * p2)1462 int CompareWpAdapter(void *p1, void *p2)
1463 {
1464 int i;
1465 WP_ADAPTER *a1, *a2;
1466 if (p1 == NULL || p2 == NULL)
1467 {
1468 return 0;
1469 }
1470 a1 = *(WP_ADAPTER **)p1;
1471 a2 = *(WP_ADAPTER **)p2;
1472 if (a1 == NULL || a2 == NULL)
1473 {
1474 return 0;
1475 }
1476 i = StrCmpi(a1->Title, a2->Title);
1477 return i;
1478 }
1479
1480 // Get whether the SeLow is used
Win32IsUsingSeLow()1481 bool Win32IsUsingSeLow()
1482 {
1483 return is_using_selow;
1484 }
1485
1486 // Get Ethernet adapter list
GetEthAdapterList()1487 LIST *GetEthAdapterList()
1488 {
1489 void *p;
1490 LIST *o;
1491
1492 p = MsDisableWow64FileSystemRedirection();
1493
1494 o = GetEthAdapterListInternal();
1495
1496 MsRestoreWow64FileSystemRedirection(p);
1497
1498 return o;
1499 }
GetEthAdapterListInternal()1500 LIST *GetEthAdapterListInternal()
1501 {
1502 LIST *o;
1503 LIST *ret;
1504 UINT size;
1505 char *buf;
1506 UINT i, j;
1507 char *qos_tag = " (Microsoft's Packet Scheduler)";
1508 SU *su = NULL;
1509 LIST *su_adapter_list = NULL;
1510
1511 // Try to use SeLow
1512 if (enable_selow)
1513 {
1514 su = SuInit();
1515 }
1516
1517 o = NewListFast(CompareWpAdapter);
1518
1519 size = 200000;
1520 buf = ZeroMalloc(size);
1521
1522 // Try to enumerate with SeLow
1523 if (su != NULL)
1524 {
1525 su_adapter_list = SuGetAdapterList(su);
1526
1527 if (su_adapter_list == NULL)
1528 {
1529 // Fail to enumerate
1530 SuFree(su);
1531 su = NULL;
1532 //WHERE;
1533 is_using_selow = false;
1534 }
1535 else
1536 {
1537 //WHERE;
1538 is_using_selow = true;
1539 }
1540 }
1541 else
1542 {
1543 is_using_selow = false;
1544 }
1545
1546 if (su_adapter_list != NULL)
1547 {
1548 // If 1 or more adapters are enumerated by SeLow, create adapter list object
1549 UINT i;
1550
1551 for (i = 0;i < LIST_NUM(su_adapter_list);i++)
1552 {
1553 SU_ADAPTER_LIST *t = LIST_DATA(su_adapter_list, i);
1554 WP_ADAPTER *a = ZeroMalloc(sizeof(WP_ADAPTER));
1555
1556 StrCpy(a->Name, sizeof(a->Name), t->Name);
1557 StrCpy(a->Guid, sizeof(a->Guid), t->Guid);
1558 StrCpy(a->Title, sizeof(a->Title), t->Info.FriendlyName);
1559
1560 TrimCrlf(a->Title);
1561 Trim(a->Title);
1562 TrimCrlf(a->Title);
1563 Trim(a->Title);
1564
1565 if (EndWith(a->Title, qos_tag))
1566 {
1567 a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;
1568 TrimCrlf(a->Title);
1569 Trim(a->Title);
1570 TrimCrlf(a->Title);
1571 Trim(a->Title);
1572 }
1573
1574 Add(o, a);
1575 }
1576 }
1577 else
1578 {
1579 // When SeLow is not used, create adapter list with SEE or WinPcap
1580 if (wp->PacketGetAdapterNames(buf, &size) == false)
1581 {
1582 Free(buf);
1583 return o;
1584 }
1585
1586 i = 0;
1587
1588 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
1589 {
1590 // Windows NT
1591 if (size >= 2 && buf[0] != 0 && buf[1] != 0)
1592 {
1593 goto ANSI_STR;
1594 }
1595
1596 while (true)
1597 {
1598 wchar_t tmp[MAX_SIZE];
1599 WP_ADAPTER *a;
1600 UniStrCpy(tmp, sizeof(tmp), L"");
1601
1602 if (*((wchar_t *)(&buf[i])) == 0)
1603 {
1604 i += sizeof(wchar_t);
1605 break;
1606 }
1607
1608 for (;*((wchar_t *)(&buf[i])) != 0;i += sizeof(wchar_t))
1609 {
1610 wchar_t str[2];
1611 str[0] = *((wchar_t *)(&buf[i]));
1612 str[1] = 0;
1613 UniStrCat(tmp, sizeof(tmp), str);
1614 }
1615
1616 i += sizeof(wchar_t);
1617
1618 a = ZeroMalloc(sizeof(WP_ADAPTER));
1619 UniToStr(a->Name, sizeof(a->Name), tmp);
1620
1621 Add(o, a);
1622 }
1623 }
1624 else
1625 {
1626 // Windows 9x
1627 ANSI_STR:
1628 while (true)
1629 {
1630 char tmp[MAX_SIZE];
1631 WP_ADAPTER *a;
1632 StrCpy(tmp, sizeof(tmp), "");
1633
1634 if (*((char *)(&buf[i])) == 0)
1635 {
1636 i += sizeof(char);
1637 break;
1638 }
1639
1640 for (;*((char *)(&buf[i])) != 0;i += sizeof(char))
1641 {
1642 char str[2];
1643 str[0] = *((char *)(&buf[i]));
1644 str[1] = 0;
1645 StrCat(tmp, sizeof(tmp), str);
1646 }
1647
1648 i += sizeof(char);
1649
1650 a = ZeroMalloc(sizeof(WP_ADAPTER));
1651 StrCpy(a->Name, sizeof(a->Name), tmp);
1652
1653 Add(o, a);
1654 }
1655 }
1656
1657 for (j = 0;j < LIST_NUM(o);j++)
1658 {
1659 WP_ADAPTER *a = LIST_DATA(o, j);
1660
1661 StrCpy(a->Title, sizeof(a->Title), &buf[i]);
1662 i += StrSize(a->Title);
1663
1664 // If device description is "Unknown" in Win9x, skip 1 byte
1665 if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
1666 {
1667 if (StrCmp(a->Title, "Unknown") == 0)
1668 {
1669 if (buf[i] == 0)
1670 {
1671 i+=sizeof(char);
1672 }
1673 }
1674 }
1675
1676 TrimCrlf(a->Title);
1677 Trim(a->Title);
1678 TrimCrlf(a->Title);
1679 Trim(a->Title);
1680
1681 if (EndWith(a->Title, qos_tag))
1682 {
1683 a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;
1684 TrimCrlf(a->Title);
1685 Trim(a->Title);
1686 TrimCrlf(a->Title);
1687 Trim(a->Title);
1688 }
1689 }
1690 }
1691
1692 for (j = 0;j < LIST_NUM(o);j++)
1693 {
1694 // Extract GUID
1695 WP_ADAPTER *a = LIST_DATA(o, j);
1696
1697 if (IsEmptyStr(a->Guid))
1698 {
1699 StrCpy(a->Guid, sizeof(a->Guid), a->Name);
1700 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\SEE_", "");
1701 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\NPF_", "");
1702 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\PCD_", "");
1703 }
1704 }
1705
1706 // Sort
1707 if (su_adapter_list != NULL)
1708 {
1709 // Since adapter list made by SeLow is already sorted, don't sort here
1710 Sort(o);
1711 }
1712
1713 ret = NewListFast(CompareWpAdapter);
1714
1715 for (i = 0;i < LIST_NUM(o);i++)
1716 {
1717 WP_ADAPTER *a = LIST_DATA(o, i);
1718 ADAPTER *ad;
1719 bool is_ethernet = false;
1720 bool ok = false;
1721
1722 if (SearchStrEx(a->Title, "ppp", 0, false) != INFINITE ||
1723 SearchStrEx(a->Title, "wan", 0, false) != INFINITE ||
1724 SearchStrEx(a->Title, "dialup", 0, false) != INFINITE ||
1725 SearchStrEx(a->Title, "pptp", 0, false) != INFINITE ||
1726 SearchStrEx(a->Title, "telepho", 0, false) != INFINITE ||
1727 SearchStrEx(a->Title, "modem", 0, false) != INFINITE ||
1728 SearchStrEx(a->Title, "ras", 0, false) != INFINITE)
1729 {
1730 Free(a);
1731 continue;
1732 }
1733
1734 // Determine whether the adapter type is Ethernet
1735 if (su == NULL)
1736 {
1737 // Determine with See
1738 ad = wp->PacketOpenAdapter(a->Name);
1739 if (ad != NULL)
1740 {
1741 NetType type;
1742 if (wp->PacketGetNetType(ad, &type))
1743 {
1744 if (type.LinkType == 0)
1745 {
1746 is_ethernet = true;
1747 }
1748 }
1749
1750 wp->PacketCloseAdapter(ad);
1751 }
1752 }
1753 else
1754 {
1755 // In using SeLow, all devices should be Ethernet device
1756 is_ethernet = true;
1757 }
1758
1759 if (is_ethernet)
1760 {
1761 // Add only Ethernet device
1762 char tmp[MAX_SIZE];
1763 UINT k;
1764
1765 StrCpy(tmp, sizeof(tmp), a->Title);
1766
1767 for (k = 0;;k++)
1768 {
1769 if (k == 0)
1770 {
1771 StrCpy(tmp, sizeof(tmp), a->Title);
1772 }
1773 else
1774 {
1775 Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1);
1776 }
1777
1778 ok = true;
1779 for (j = 0;j < LIST_NUM(ret);j++)
1780 {
1781 WP_ADAPTER *aa = LIST_DATA(ret, j);
1782 if (StrCmpi(aa->Title, tmp) == 0)
1783 {
1784 ok = false;
1785 }
1786 }
1787
1788 if (ok)
1789 {
1790 break;
1791 }
1792 }
1793
1794 StrCpy(a->Title, sizeof(a->Title), tmp);
1795 a->Id = Win32EthGenIdFromGuid(a->Guid);
1796 Add(ret, a);
1797 }
1798
1799 if (ok == false)
1800 {
1801 Free(a);
1802 }
1803 }
1804
1805 Free(buf);
1806
1807 Sort(ret);
1808
1809 ReleaseList(o);
1810
1811 if (su != NULL)
1812 {
1813 SuFreeAdapterList(su_adapter_list);
1814
1815 SuFree(su);
1816 }
1817
1818 return ret;
1819 }
1820
1821 // Initialize Ethernet adapter list
InitEthAdaptersList()1822 void InitEthAdaptersList()
1823 {
1824 if (eth_list != NULL)
1825 {
1826 FreeEthAdaptersList();
1827 eth_list = NULL;
1828 }
1829 eth_list = GetEthAdapterList();
1830 }
1831
1832 // Free Ethernet adapter list
FreeEthAdaptersList()1833 void FreeEthAdaptersList()
1834 {
1835 UINT i;
1836 if (eth_list == NULL)
1837 {
1838 return;
1839 }
1840 for (i = 0;i < LIST_NUM(eth_list);i++)
1841 {
1842 WP_ADAPTER *a = LIST_DATA(eth_list, i);
1843 Free(a);
1844 }
1845 ReleaseList(eth_list);
1846 eth_list = NULL;
1847 }
1848
1849 // Is the SU supported
Win32EthIsSuSupported()1850 bool Win32EthIsSuSupported()
1851 {
1852 bool ret = false;
1853 SU *su = SuInit();
1854
1855 if (su != NULL)
1856 {
1857 ret = true;
1858 }
1859
1860 SuFree(su);
1861
1862 return ret;
1863 }
1864
1865 // Is the Ethernet supported
IsEthSupported()1866 bool IsEthSupported()
1867 {
1868 bool ret = IsEthSupportedInner();
1869
1870 if (ret == false)
1871 {
1872 ret = Win32EthIsSuSupported();
1873 }
1874
1875 return ret;
1876 }
IsEthSupportedInner()1877 bool IsEthSupportedInner()
1878 {
1879 if (wp == NULL)
1880 {
1881 return false;
1882 }
1883
1884 return wp->Inited;
1885 }
1886
1887 // Is the PCD driver supported in current OS
IsPcdSupported()1888 bool IsPcdSupported()
1889 {
1890 UINT type;
1891 OS_INFO *info = GetOsInfo();
1892
1893 if (MsIsWindows10())
1894 {
1895 // Windows 10 or later never supports PCD driver.
1896 return false;
1897 }
1898
1899 type = info->OsType;
1900
1901 if (OS_IS_WINDOWS_NT(type) == false)
1902 {
1903 // Only on Windows NT series
1904 return false;
1905 }
1906
1907 if (GET_KETA(type, 100) >= 2)
1908 {
1909 // Good for Windows 2000 or later
1910 return true;
1911 }
1912
1913 // Not good for Windows NT 4.0 or Longhorn
1914 return false;
1915 }
1916
1917 // Save build number of PCD driver
SavePcdDriverBuild(UINT build)1918 void SavePcdDriverBuild(UINT build)
1919 {
1920 MsRegWriteInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE,
1921 build);
1922 }
1923
1924 // Load build number of PCD driver
LoadPcdDriverBuild()1925 UINT LoadPcdDriverBuild()
1926 {
1927 return MsRegReadInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE);
1928 }
1929
1930 // Try to install PCD driver
InstallPcdDriver()1931 HINSTANCE InstallPcdDriver()
1932 {
1933 HINSTANCE ret;
1934 void *p = MsDisableWow64FileSystemRedirection();
1935
1936 ret = InstallPcdDriverInternal();
1937
1938 MsRestoreWow64FileSystemRedirection(p);
1939
1940 return ret;
1941 }
InstallPcdDriverInternal()1942 HINSTANCE InstallPcdDriverInternal()
1943 {
1944 char tmp[MAX_PATH];
1945 bool install_driver = true;
1946 HINSTANCE h;
1947 char *dll_filename;
1948
1949 // Confirm whether the see.sys is installed in system32\drivers folder
1950 Format(tmp, sizeof(tmp), "%s\\drivers\\see.sys", MsGetSystem32Dir());
1951
1952 if (IsFileExists(tmp))
1953 {
1954 // If driver file is exist, try to get build number from registry
1955 if (LoadPcdDriverBuild() >= CEDAR_BUILD)
1956 {
1957 // Already latest driver is installed
1958 install_driver = false;
1959 }
1960 }
1961
1962 if (install_driver)
1963 {
1964 char *src_filename = BRIDGE_WIN32_PCD_SYS;
1965 // If need to install the driver, confirm user is administrator
1966 if (MsIsAdmin() == false)
1967 {
1968 // Non administrator can't install driver
1969 return NULL;
1970 }
1971
1972 if (MsIsX64())
1973 {
1974 src_filename = BRIDGE_WIN32_PCD_SYS_X64;
1975 }
1976
1977 // Copy see.sys
1978 if (FileCopy(src_filename, tmp) == false)
1979 {
1980 return NULL;
1981 }
1982
1983 // Save build number
1984 SavePcdDriverBuild(CEDAR_BUILD);
1985 }
1986
1987 dll_filename = BRIDGE_WIN32_PCD_DLL;
1988
1989 if (Is64())
1990 {
1991 if (MsIsX64())
1992 {
1993 dll_filename = BRIDGE_WIN32_PCD_DLL_X64;
1994 }
1995 }
1996
1997 // Try to load see.dll and initialize
1998 h = MsLoadLibrary(dll_filename);
1999 if (h == NULL)
2000 {
2001 return NULL;
2002 }
2003
2004 return h;
2005 }
2006
2007 // Initialize Ethernet
InitEth()2008 void InitEth()
2009 {
2010 HINSTANCE h;
2011 if (wp != NULL)
2012 {
2013 // Already initialized
2014 return;
2015 }
2016
2017 eth_list_lock = NewLock();
2018
2019 wp = ZeroMalloc(sizeof(WP));
2020
2021 is_see_mode = false;
2022
2023 if (IsPcdSupported())
2024 {
2025 // PCD is supported in this OS
2026 h = InstallPcdDriver();
2027 if (h != NULL)
2028 {
2029 // Try to initialize with PCD
2030 if (InitWpWithLoadLibrary(wp, h) == false)
2031 {
2032 Debug("InitEth: SEE Failed.\n");
2033 FreeLibrary(h);
2034 }
2035 else
2036 {
2037 Debug("InitEth: SEE Loaded.\n");
2038 is_see_mode = true;
2039 }
2040 }
2041 }
2042
2043 if (wp->Inited == false)
2044 {
2045 // Try to initialize with Packet.dll of WinPcap
2046 h = LoadLibrary(BRIDGE_WIN32_PACKET_DLL);
2047 if (h != NULL)
2048 {
2049 if (InitWpWithLoadLibrary(wp, h) == false)
2050 {
2051 Debug("InitEth: Packet.dll Failed.\n");
2052 FreeLibrary(h);
2053 }
2054 else
2055 {
2056 Debug("InitEth: Packet.dll Loaded.\n");
2057 }
2058 }
2059 }
2060 }
2061
2062 // Get whether local-bridge uses see.sys
IsWin32BridgeWithSee()2063 bool IsWin32BridgeWithSee()
2064 {
2065 return is_see_mode;
2066 }
2067
2068 // Initialize WP structure with DLL
InitWpWithLoadLibrary(WP * wp,HINSTANCE h)2069 bool InitWpWithLoadLibrary(WP *wp, HINSTANCE h)
2070 {
2071 TOKEN_LIST *o;
2072 UINT total_num = 0;
2073 // Validate arguments
2074 if (wp == NULL || h == NULL)
2075 {
2076 return false;
2077 }
2078 wp->Inited = true;
2079 wp->hPacketDll = h;
2080
2081 LOAD_DLL_ADDR(PacketGetVersion);
2082 LOAD_DLL_ADDR(PacketGetDriverVersion);
2083 LOAD_DLL_ADDR(PacketSetMinToCopy);
2084 LOAD_DLL_ADDR(PacketSetNumWrites);
2085 LOAD_DLL_ADDR(PacketSetMode);
2086 LOAD_DLL_ADDR(PacketSetReadTimeout);
2087 LOAD_DLL_ADDR(PacketSetBpf);
2088 LOAD_DLL_ADDR(PacketSetSnapLen);
2089 LOAD_DLL_ADDR(PacketGetStats);
2090 LOAD_DLL_ADDR(PacketGetStatsEx);
2091 LOAD_DLL_ADDR(PacketSetBuff);
2092 LOAD_DLL_ADDR(PacketGetNetType);
2093 LOAD_DLL_ADDR(PacketOpenAdapter);
2094 LOAD_DLL_ADDR(PacketSendPacket);
2095 LOAD_DLL_ADDR(PacketSendPackets);
2096 LOAD_DLL_ADDR(PacketAllocatePacket);
2097 LOAD_DLL_ADDR(PacketInitPacket);
2098 LOAD_DLL_ADDR(PacketFreePacket);
2099 LOAD_DLL_ADDR(PacketReceivePacket);
2100 LOAD_DLL_ADDR(PacketSetHwFilter);
2101 LOAD_DLL_ADDR(PacketGetAdapterNames);
2102 LOAD_DLL_ADDR(PacketGetNetInfoEx);
2103 LOAD_DLL_ADDR(PacketRequest);
2104 LOAD_DLL_ADDR(PacketGetReadEvent);
2105 LOAD_DLL_ADDR(PacketSetDumpName);
2106 LOAD_DLL_ADDR(PacketSetDumpLimits);
2107 LOAD_DLL_ADDR(PacketSetDumpLimits);
2108 LOAD_DLL_ADDR(PacketIsDumpEnded);
2109 LOAD_DLL_ADDR(PacketStopDriver);
2110 LOAD_DLL_ADDR(PacketCloseAdapter);
2111 LOAD_DLL_ADDR(PacketSetLoopbackBehavior);
2112
2113 if (wp->PacketSetMinToCopy == NULL ||
2114 wp->PacketSetNumWrites == NULL ||
2115 wp->PacketSetMode == NULL ||
2116 wp->PacketSetReadTimeout == NULL ||
2117 wp->PacketSetBuff == NULL ||
2118 wp->PacketGetNetType == NULL ||
2119 wp->PacketOpenAdapter == NULL ||
2120 wp->PacketSendPacket == NULL ||
2121 wp->PacketSendPackets == NULL ||
2122 wp->PacketAllocatePacket == NULL ||
2123 wp->PacketInitPacket == NULL ||
2124 wp->PacketFreePacket == NULL ||
2125 wp->PacketReceivePacket == NULL ||
2126 wp->PacketSetHwFilter == NULL ||
2127 wp->PacketGetAdapterNames == NULL ||
2128 wp->PacketGetNetInfoEx == NULL ||
2129 wp->PacketCloseAdapter == NULL)
2130 {
2131 RELEASE:
2132 wp->Inited = false;
2133 wp->hPacketDll = NULL;
2134
2135 return false;
2136 }
2137
2138 o = GetEthListEx(&total_num, true, false);
2139 if (o == NULL || total_num == 0)
2140 {
2141 FreeToken(o);
2142 goto RELEASE;
2143 }
2144
2145 FreeToken(o);
2146
2147 return true;
2148 }
2149
2150 // Free Ethernet
FreeEth()2151 void FreeEth()
2152 {
2153 if (wp == NULL)
2154 {
2155 // Not initialized
2156 return;
2157 }
2158
2159 // Free adapter list
2160 FreeEthAdaptersList();
2161
2162 if (wp->Inited)
2163 {
2164 // Free DLL
2165 FreeLibrary(wp->hPacketDll);
2166 }
2167
2168 Free(wp);
2169 wp = NULL;
2170
2171 DeleteLock(eth_list_lock);
2172 eth_list_lock = NULL;
2173 }
2174
2175 // Get network connection name from Ethernet device name
GetEthNetworkConnectionName(wchar_t * dst,UINT size,char * device_name)2176 void GetEthNetworkConnectionName(wchar_t *dst, UINT size, char *device_name)
2177 {
2178 WP_ADAPTER *t;
2179 char *tmp = NULL, guid[MAX_SIZE];
2180 wchar_t *ncname = NULL;
2181
2182 UniStrCpy(dst, size, L"");
2183
2184 // Validate arguments
2185 if (device_name == NULL || IsEthSupported() == false ||
2186 IsNt() == false || MsIsWin2000OrGreater() == false)
2187 {
2188 return;
2189 }
2190
2191 Lock(eth_list_lock);
2192
2193 InitEthAdaptersList();
2194
2195 t = Win32EthSearch(device_name);
2196
2197 if (t == NULL)
2198 {
2199 Unlock(eth_list_lock);
2200 return;
2201 }
2202
2203 tmp = CopyStr(t->Name);
2204 Unlock(eth_list_lock);
2205
2206 if (IsEmptyStr(t->Guid) == false)
2207 {
2208 StrCpy(guid, sizeof(guid), t->Guid);
2209
2210 Free(tmp);
2211 }
2212 else
2213 {
2214 ReplaceStr(guid, sizeof(guid), tmp, "\\Device\\SEE_", "");
2215 Free(tmp);
2216
2217 ReplaceStr(guid, sizeof(guid), guid, "\\Device\\NPF_", "");
2218 ReplaceStr(guid, sizeof(guid), guid, "\\Device\\PCD_", "");
2219 }
2220
2221 if(guid == NULL)
2222 {
2223 return;
2224 }
2225
2226 ncname = MsGetNetworkConnectionName(guid);
2227 if(ncname != NULL)
2228 {
2229 UniStrCpy(dst, size, ncname);
2230 }
2231 Free(ncname);
2232 }
2233
2234 #endif // BRIDGE_C
2235
2236
2237