1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
79 // Ethernet ブリッジプログラム (Win32 版)
\r
83 #include <winsock2.h>
\r
84 #include <Ws2tcpip.h>
\r
85 #include <windows.h>
\r
93 #include <Packet32.h>
\r
94 #include <Mayaqua/Mayaqua.h>
\r
95 #include <Cedar/Cedar.h>
\r
98 static WP *wp = NULL;
\r
99 static LIST *eth_list = NULL;
\r
101 static LOCK *eth_list_lock = NULL;
\r
102 static bool is_sep_mode = false;
\r
104 #define LOAD_DLL_ADDR(name) \
\r
106 void *addr = GetProcAddress(h, #name); \
\r
107 Copy(&wp->name, &addr, sizeof(void *)); \
\r
111 int CmpRpcEnumEthVLan(void *p1, void *p2)
\r
113 RPC_ENUM_ETH_VLAN_ITEM *v1, *v2;
\r
114 if (p1 == NULL || p2 == NULL)
\r
118 v1 = *((RPC_ENUM_ETH_VLAN_ITEM **)p1);
\r
119 v2 = *((RPC_ENUM_ETH_VLAN_ITEM **)p2);
\r
120 if (v1 == NULL || v2 == NULL)
\r
125 return StrCmpi(v1->DeviceName, v2->DeviceName);
\r
128 // MTU の取得 (Windows では非サポート)
\r
129 UINT EthGetMtu(ETH *e)
\r
134 // MTU の設定 (Windows では非サポート)
\r
135 bool EthSetMtu(ETH *e, UINT mtu)
\r
140 // MTU の設定がサポートされているかどうか取得 (Windows では非サポート)
\r
141 bool EthIsChangeMtuSupported(ETH *e)
\r
146 // デバイスの VLAN 有効化状態を設定
\r
147 bool SetVLanEnableStatus(char *title, bool enable)
\r
149 RPC_ENUM_ETH_VLAN t;
\r
150 RPC_ENUM_ETH_VLAN_ITEM *e;
\r
152 char key[MAX_SIZE];
\r
153 char tcpkey[MAX_SIZE];
\r
154 char short_key[MAX_SIZE];
\r
161 Zero(&t, sizeof(t));
\r
162 if (EnumEthVLanWin32(&t) == false)
\r
167 e = FindEthVLanItem(&t, title);
\r
171 if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid))
\r
173 if (StrCmpi(e->DriverType, "Intel") == 0)
\r
177 MsRegWriteStr(REG_LOCAL_MACHINE, key, "VlanFiltering", "0");
\r
178 MsRegWriteStr(REG_LOCAL_MACHINE, key, "TaggingMode", "0");
\r
179 MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorMode", 1);
\r
180 MsRegWriteInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled", 1);
\r
184 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "TaggingMode") == 0)
\r
186 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "TaggingMode");
\r
189 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode") == 1)
\r
191 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorMode");
\r
194 if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled") == 1)
\r
196 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
\r
202 else if (StrCmpi(e->DriverType, "Broadcom") == 0)
\r
206 MsRegWriteStr(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket", "1");
\r
210 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket");
\r
215 else if (StrCmpi(e->DriverType, "Marvell") == 0)
\r
219 MsRegWriteInt(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip", 1);
\r
223 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip");
\r
229 Format(tcpkey, sizeof(tcpkey),
\r
230 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
\r
235 if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
\r
237 MsRegWriteInt(REG_LOCAL_MACHINE, tcpkey, "MTU", 1500);
\r
242 UINT mtu = MsRegReadInt(REG_LOCAL_MACHINE, tcpkey, "MTU");
\r
245 MsRegDeleteValue(REG_LOCAL_MACHINE, tcpkey, "MTU");
\r
251 FreeRpcEnumEthVLan(&t);
\r
257 RPC_ENUM_ETH_VLAN_ITEM *FindEthVLanItem(RPC_ENUM_ETH_VLAN *t, char *name)
\r
261 if (t == NULL || name == NULL)
\r
266 for (i = 0;i < t->NumItem;i++)
\r
268 if (StrCmpi(t->Items[i].DeviceName, name) == 0)
\r
270 return &t->Items[i];
\r
277 // デバイスの VLAN 有効化状態を取得
\r
278 void GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
\r
280 char key[MAX_SIZE];
\r
281 char short_key[MAX_SIZE];
\r
282 char tcpkey[MAX_SIZE];
\r
289 e->Enabled = false;
\r
291 if (e->Support == false)
\r
296 if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid) == false)
\r
301 Format(tcpkey, sizeof(tcpkey),
\r
302 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
\r
305 if (StrCmpi(e->DriverType, "Intel") == 0)
\r
307 char *VlanFiltering = MsRegReadStr(REG_LOCAL_MACHINE, key, "VlanFiltering");
\r
308 UINT MonitorMode = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode");
\r
309 UINT MonitorModeEnabled = MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");
\r
310 char *TaggingMode = MsRegReadStr(REG_LOCAL_MACHINE, key, "TaggingMode");
\r
312 if (StrCmpi(VlanFiltering, "0") == 0 &&
\r
313 MonitorMode == 1 &&
\r
314 MonitorModeEnabled == 1 &&
\r
315 StrCmpi(TaggingMode, "0") == 0)
\r
320 Free(VlanFiltering);
\r
323 else if (StrCmpi(e->DriverType, "Broadcom") == 0)
\r
325 char *PreserveVlanInfoInRxPacket = MsRegReadStr(REG_LOCAL_MACHINE,
\r
326 key, "PreserveVlanInfoInRxPacket");
\r
328 if (StrCmpi(PreserveVlanInfoInRxPacket, "1") == 0)
\r
333 Free(PreserveVlanInfoInRxPacket);
\r
335 else if (StrCmpi(e->DriverType, "Marvell") == 0)
\r
337 DWORD SkDisableVlanStrip = MsRegReadInt(REG_LOCAL_MACHINE,
\r
338 key, "SkDisableVlanStrip");
\r
340 if (SkDisableVlanStrip == 1)
\r
346 if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)
\r
348 e->Enabled = false;
\r
352 // デバイスの VLAN サポート状態を取得
\r
353 void GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM *e)
\r
356 char filename[MAX_SIZE];
\r
364 wow = MsDisableWow64FileSystemRedirection();
\r
367 CombinePath(filename, sizeof(filename), MsGetSystem32Dir(), "drivers");
\r
368 CombinePath(filename, sizeof(filename), filename, e->DriverName);
\r
370 b = ReadDump(filename);
\r
374 char intel1[] = "VlanFiltering";
\r
375 char intel2[] = "V\0l\0a\0n\0F\0i\0l\0t\0e\0r\0i\0n\0g";
\r
376 char intel3[] = "MonitorMode";
\r
377 char intel4[] = "M\0o\0n\0i\0t\0o\0r\0M\0o\0d\0e";
\r
378 char intel5[] = "TaggingMode";
\r
379 char intel6[] = "T\0a\0g\0g\0i\0n\0g\0M\0o\0d\0e";
\r
380 char broadcom1[] = "PreserveVlanInfoInRxPacket";
\r
381 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";
\r
382 char marvell1[] = "SkDisableVlanStrip";
\r
383 char marvell2[] = "S\0k\0D\0i\0s\0a\0b\0l\0e\0V\0l\0a\0n\0S\0t\0r\0i\0p";
\r
384 char *driver_type = "";
\r
386 if (SearchBin(b->Buf, 0, b->Size, intel1, sizeof(intel1)) != INFINITE
\r
387 || SearchBin(b->Buf, 0, b->Size, intel2, sizeof(intel2)) != INFINITE
\r
388 || SearchBin(b->Buf, 0, b->Size, intel3, sizeof(intel3)) != INFINITE
\r
389 || SearchBin(b->Buf, 0, b->Size, intel4, sizeof(intel4)) != INFINITE
\r
390 || SearchBin(b->Buf, 0, b->Size, intel5, sizeof(intel5)) != INFINITE
\r
391 || SearchBin(b->Buf, 0, b->Size, intel6, sizeof(intel6)) != INFINITE)
\r
393 driver_type = "Intel";
\r
395 else if (SearchBin(b->Buf, 0, b->Size, broadcom1, sizeof(broadcom1)) != INFINITE
\r
396 || SearchBin(b->Buf, 0, b->Size, broadcom2, sizeof(broadcom2)) != INFINITE)
\r
398 driver_type = "Broadcom";
\r
400 else if (SearchBin(b->Buf, 0, b->Size, marvell1, sizeof(marvell1)) != INFINITE
\r
401 || SearchBin(b->Buf, 0, b->Size, marvell2, sizeof(marvell2)) != INFINITE)
\r
403 driver_type = "Marvell";
\r
406 if (IsEmptyStr(driver_type) == false)
\r
408 StrCpy(e->DriverType, sizeof(e->DriverType), driver_type);
\r
415 MsRestoreWow64FileSystemRedirection(wow);
\r
418 // short_key からデバイスのインスタンス ID を取得する
\r
419 char *SearchDeviceInstanceIdFromShortKey(char *short_key)
\r
424 if (short_key == NULL)
\r
429 t1 = MsRegEnumKey(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum");
\r
434 char tmp[MAX_SIZE];
\r
437 for (i = 0;i < t1->NumTokens;i++)
\r
439 Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Enum\\%s", t1->Token[i]);
\r
441 t2 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp);
\r
448 for (i = 0;i < t2->NumTokens;i++)
\r
450 char tmp2[MAX_SIZE];
\r
452 Format(tmp2, sizeof(tmp2), "%s\\%s", tmp, t2->Token[i]);
\r
454 t3 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp2);
\r
460 for (i = 0;i < t3->NumTokens;i++)
\r
462 char tmp3[MAX_SIZE];
\r
465 Format(tmp3, sizeof(tmp3), "%s\\%s", tmp2, t3->Token[i]);
\r
467 s = MsRegReadStr(REG_LOCAL_MACHINE, tmp3, "Driver");
\r
471 if (StrCmpi(s, short_key) == 0)
\r
478 ret = CopyStr(tmp3 + StrLen("SYSTEM\\CurrentControlSet\\Enum\\"));
\r
499 // 物理 LAN カードの VLAN 対応状況の列挙
\r
500 bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t)
\r
510 Zero(t, sizeof(RPC_ENUM_ETH_VLAN));
\r
512 if (MsIsWin2000OrGreater() == false)
\r
517 if (IsEthSupported() == false)
\r
523 Lock(eth_list_lock);
\r
525 InitEthAdaptersList();
\r
527 o = NewListFast(CmpRpcEnumEthVLan);
\r
529 for (i = 0;i < LIST_NUM(eth_list);i++)
\r
531 WP_ADAPTER *a = LIST_DATA(eth_list, i);
\r
533 if (IsEmptyStr(a->Guid) == false)
\r
535 char class_key[MAX_SIZE];
\r
536 char short_key[MAX_SIZE];
\r
538 if (GetClassRegKeyWin32(class_key, sizeof(class_key),
\r
539 short_key, sizeof(short_key), a->Guid))
\r
541 char *device_instance_id = MsRegReadStr(REG_LOCAL_MACHINE, class_key, "DeviceInstanceID");
\r
543 if (IsEmptyStr(device_instance_id))
\r
545 Free(device_instance_id);
\r
546 device_instance_id = SearchDeviceInstanceIdFromShortKey(short_key);
\r
549 if (IsEmptyStr(device_instance_id) == false)
\r
551 char device_key[MAX_SIZE];
\r
552 char *service_name;
\r
554 Format(device_key, sizeof(device_key), "SYSTEM\\CurrentControlSet\\Enum\\%s",
\r
555 device_instance_id);
\r
557 service_name = MsRegReadStr(REG_LOCAL_MACHINE, device_key, "Service");
\r
558 if (IsEmptyStr(service_name) == false)
\r
560 char service_key[MAX_SIZE];
\r
563 Format(service_key, sizeof(service_key),
\r
564 "SYSTEM\\CurrentControlSet\\services\\%s",
\r
567 sys = MsRegReadStr(REG_LOCAL_MACHINE, service_key, "ImagePath");
\r
569 if (IsEmptyStr(sys) == false)
\r
571 char sysname[MAX_PATH];
\r
573 GetFileNameFromFilePath(sysname, sizeof(sysname), sys);
\r
577 if (EndWith(sysname, ".sys"))
\r
580 RPC_ENUM_ETH_VLAN_ITEM *e = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM));
\r
582 StrCpy(e->DeviceName, sizeof(e->DeviceName), a->Title);
\r
583 StrCpy(e->Guid, sizeof(e->Guid), a->Guid);
\r
584 StrCpy(e->DeviceInstanceId, sizeof(e->DeviceInstanceId), device_instance_id);
\r
585 StrCpy(e->DriverName, sizeof(e->DriverName), sysname);
\r
587 // デバイスの VLAN サポート状態を取得
\r
588 GetVLanSupportStatus(e);
\r
591 GetVLanEnableStatus(e);
\r
600 Free(service_name);
\r
603 Free(device_instance_id);
\r
608 t->NumItem = LIST_NUM(o);
\r
609 t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * i);
\r
611 for (i = 0;i < LIST_NUM(o);i++)
\r
613 RPC_ENUM_ETH_VLAN_ITEM *e = LIST_DATA(o, i);
\r
615 Copy(&t->Items[i], e, sizeof(RPC_ENUM_ETH_VLAN_ITEM));
\r
622 Unlock(eth_list_lock);
\r
627 // GUID からネットワーククラスデータのレジストリキーを取得
\r
628 bool GetClassRegKeyWin32(char *key, UINT key_size, char *short_key, UINT short_key_size, char *guid)
\r
634 if (key == NULL || short_key == NULL || guid == NULL)
\r
639 t = MsRegEnumKey(REG_LOCAL_MACHINE,
\r
640 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
\r
646 for (i = 0;i < t->NumTokens;i++)
\r
648 char keyname[MAX_SIZE];
\r
651 Format(keyname, sizeof(keyname),
\r
652 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
\r
655 value = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "NetCfgInstanceId");
\r
657 if (StrCmpi(value, guid) == 0)
\r
661 StrCpy(key, key_size, keyname);
\r
663 Format(short_key, short_key_size, "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",
\r
676 void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
\r
678 UINT i, total_size;
\r
680 UINT write_pointer;
\r
682 if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
\r
687 if (IsWin32BridgeWithSep() == false)
\r
689 // 古い WinPcap にはバグがあり、2 個以上の CPU が搭載されている場合に
\r
690 // ロックが不十分なところがあってカーネル内でクラッシュすることが
\r
691 // 頻繁にあった。そこで 1 個目の CPU でしか動作しないように工夫していた
\r
692 if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())
\r
694 e->LastSetSingleCpu = Tick64();
\r
695 MsSetThreadSingleCpu();
\r
701 for (i = 0;i < num;i++)
\r
703 void *data = datas[i];
\r
704 UINT size = sizes[i];
\r
705 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
\r
707 total_size += size + sizeof(struct dump_bpf_hdr);
\r
712 buf = MallocFast(total_size * 100 / 75 + 1600);
\r
716 for (i = 0;i < num;i++)
\r
718 void *data = datas[i];
\r
719 UINT size = sizes[i];
\r
720 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)
\r
722 struct dump_bpf_hdr *h;
\r
724 h = (struct dump_bpf_hdr *)(buf + write_pointer);
\r
725 Zero(h, sizeof(struct dump_bpf_hdr));
\r
726 h->caplen = h->len = size;
\r
727 write_pointer += sizeof(struct dump_bpf_hdr);
\r
728 Copy(buf + write_pointer, data, size);
\r
729 write_pointer += size;
\r
731 PROBE_DATA2("EthPutPackets", data, size);
\r
738 if (total_size != 0)
\r
740 wp->PacketSendPackets(e->Adapter, buf, total_size, true);
\r
747 void EthPutPacket(ETH *e, void *data, UINT size)
\r
750 if (e == NULL || data == NULL || size == 0)
\r
754 if (size < 14 || size > MAX_PACKET_SIZE)
\r
760 if (IsWin32BridgeWithSep() == false)
\r
762 if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())
\r
764 e->LastSetSingleCpu = Tick64();
\r
765 MsSetThreadSingleCpu();
\r
769 wp->PacketInitPacket(e->PutPacket, data, size);
\r
770 wp->PacketSendPacket(e->Adapter, e->PutPacket, false);
\r
776 UINT EthGetPacket(ETH *e, void **data)
\r
781 if (e == NULL || data == NULL)
\r
787 // まずキューにパケットがたまっているかどうか見てみる
\r
788 b = GetNext(e->PacketQueue);
\r
796 if (e->PacketQueue->num_item == 0)
\r
813 PROBE_STR("EthGetPacket: PacketInitPacket");
\r
814 wp->PacketInitPacket(e->Packet, e->Buffer, e->BufferSize);
\r
815 PROBE_STR("EthGetPacket: PacketReceivePacket");
\r
816 if (wp->PacketReceivePacket(e->Adapter, e->Packet, false) == false)
\r
827 buf = (UCHAR *)e->Packet->Buffer;
\r
828 total = e->Packet->ulBytesReceived;
\r
831 while (offset < total)
\r
833 struct bpf_hdr *header;
\r
835 UCHAR *packet_data;
\r
837 header = (struct bpf_hdr *)(buf + offset);
\r
838 packet_size = header->bh_caplen;
\r
839 offset += header->bh_hdrlen;
\r
840 packet_data = buf + offset;
\r
841 offset = Packet_WORDALIGN(offset + packet_size);
\r
843 if (packet_size >= 14)
\r
848 PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size);
\r
850 tmp = MallocFast(packet_size);
\r
852 Copy(tmp, packet_data, packet_size);
\r
853 b = NewBlock(tmp, packet_size, 0);
\r
854 InsertQueue(e->PacketQueue, b);
\r
868 CANCEL *EthGetCancel(ETH *e)
\r
876 AddRef(e->Cancel->ref);
\r
882 void CloseEth(ETH *e)
\r
891 ReleaseCancel(e->Cancel);
\r
893 wp->PacketCloseAdapter(e->Adapter);
\r
894 wp->PacketFreePacket(e->Packet);
\r
895 wp->PacketFreePacket(e->PutPacket);
\r
897 while (b = GetNext(e->PacketQueue))
\r
901 ReleaseQueue(e->PacketQueue);
\r
911 ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
\r
916 p = MsDisableWow64FileSystemRedirection();
\r
918 ret = OpenEthInternal(name, local, tapmode, tapaddr);
\r
920 MsRestoreWow64FileSystemRedirection(p);
\r
924 ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr)
\r
932 if (name == NULL || IsEthSupported() == false)
\r
939 // Win32 では tap はサポートしていない
\r
943 Lock(eth_list_lock);
\r
945 InitEthAdaptersList();
\r
947 Zero(&tt, sizeof(tt));
\r
948 StrCpy(tt.Title, sizeof(tt.Title), name);
\r
950 t = Search(eth_list, &tt);
\r
953 Unlock(eth_list_lock);
\r
957 a = wp->PacketOpenAdapter(t->Name);
\r
960 Unlock(eth_list_lock);
\r
964 if (IsWin32BridgeWithSep() == false)
\r
966 MsSetThreadSingleCpu();
\r
969 e = ZeroMalloc(sizeof(ETH));
\r
970 e->Name = CopyStr(t->Name);
\r
971 e->Title = CopyStr(t->Title);
\r
975 wp->PacketSetBuff(e->Adapter, BRIDGE_WIN32_ETH_BUFFER);
\r
976 wp->PacketSetHwFilter(e->Adapter, local ? 0x0080 : 0x0020);
\r
977 wp->PacketSetMode(e->Adapter, PACKET_MODE_CAPT);
\r
978 wp->PacketSetReadTimeout(e->Adapter, -1);
\r
979 wp->PacketSetNumWrites(e->Adapter, 1);
\r
981 if (wp->PacketSetLoopbackBehavior != NULL)
\r
983 if (GET_KETA(GetOsType(), 100) >= 3)
\r
985 // Windows XP, Server 2003 以降
\r
986 bool ret = wp->PacketSetLoopbackBehavior(e->Adapter, 1);
\r
987 Debug("*** PacketSetLoopbackBehavior: %u\n", ret);
\r
989 e->LoopbackBlock = ret;
\r
993 h = wp->PacketGetReadEvent(e->Adapter);
\r
995 c = NewCancelSpecial(h);
\r
998 e->Buffer = Malloc(BRIDGE_WIN32_ETH_BUFFER);
\r
999 e->BufferSize = BRIDGE_WIN32_ETH_BUFFER;
\r
1000 e->Packet = wp->PacketAllocatePacket();
\r
1002 e->PutPacket = wp->PacketAllocatePacket();
\r
1004 e->PacketQueue = NewQueue();
\r
1006 Unlock(eth_list_lock);
\r
1011 // Ethernet アダプタリストの取得
\r
1012 TOKEN_LIST *GetEthList()
\r
1017 if (IsEthSupported() == false)
\r
1022 Lock(eth_list_lock);
\r
1024 InitEthAdaptersList();
\r
1026 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
1027 ret->NumTokens = LIST_NUM(eth_list);
\r
1028 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
\r
1029 for (i = 0;i < ret->NumTokens;i++)
\r
1031 WP_ADAPTER *a = LIST_DATA(eth_list, i);
\r
1032 ret->Token[i] = CopyStr(a->Title);
\r
1035 Unlock(eth_list_lock);
\r
1040 // WP_ADAPTER の名前比較
\r
1041 int CompareWpAdapter(void *p1, void *p2)
\r
1044 WP_ADAPTER *a1, *a2;
\r
1045 if (p1 == NULL || p2 == NULL)
\r
1049 a1 = *(WP_ADAPTER **)p1;
\r
1050 a2 = *(WP_ADAPTER **)p2;
\r
1051 if (a1 == NULL || a2 == NULL)
\r
1055 i = StrCmpi(a1->Title, a2->Title);
\r
1059 // Ethernet アダプタリストの取得
\r
1060 LIST *GetEthAdapterList()
\r
1065 p = MsDisableWow64FileSystemRedirection();
\r
1067 o = GetEthAdapterListInternal();
\r
1069 MsRestoreWow64FileSystemRedirection(p);
\r
1073 LIST *GetEthAdapterListInternal()
\r
1080 char *qos_tag = " (Microsoft's Packet Scheduler)";
\r
1082 o = NewListFast(CompareWpAdapter);
\r
1085 buf = ZeroMalloc(size);
\r
1087 if (wp->PacketGetAdapterNames(buf, &size) == false)
\r
1095 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
\r
1098 if (size >= 2 && buf[0] != 0 && buf[1] != 0)
\r
1105 wchar_t tmp[MAX_SIZE];
\r
1107 UniStrCpy(tmp, sizeof(tmp), L"");
\r
1109 if (*((wchar_t *)(&buf[i])) == 0)
\r
1111 i += sizeof(wchar_t);
\r
1115 for (;*((wchar_t *)(&buf[i])) != 0;i += sizeof(wchar_t))
\r
1118 str[0] = *((wchar_t *)(&buf[i]));
\r
1120 UniStrCat(tmp, sizeof(tmp), str);
\r
1123 i += sizeof(wchar_t);
\r
1125 a = ZeroMalloc(sizeof(WP_ADAPTER));
\r
1126 UniToStr(a->Name, sizeof(a->Name), tmp);
\r
1137 char tmp[MAX_SIZE];
\r
1139 StrCpy(tmp, sizeof(tmp), "");
\r
1141 if (*((char *)(&buf[i])) == 0)
\r
1143 i += sizeof(char);
\r
1147 for (;*((char *)(&buf[i])) != 0;i += sizeof(char))
\r
1150 str[0] = *((char *)(&buf[i]));
\r
1152 StrCat(tmp, sizeof(tmp), str);
\r
1155 i += sizeof(char);
\r
1157 a = ZeroMalloc(sizeof(WP_ADAPTER));
\r
1158 StrCpy(a->Name, sizeof(a->Name), tmp);
\r
1164 for (j = 0;j < LIST_NUM(o);j++)
\r
1166 WP_ADAPTER *a = LIST_DATA(o, j);
\r
1168 StrCpy(a->Title, sizeof(a->Title), &buf[i]);
\r
1169 i += StrSize(a->Title);
\r
1171 // Win9x で デバイスの説明が"Unknown"ならば1文字読み飛ばす。
\r
1172 if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
\r
1174 if (StrCmp(a->Title, "Unknown") == 0)
\r
1183 TrimCrlf(a->Title);
\r
1185 TrimCrlf(a->Title);
\r
1188 if (EndWith(a->Title, qos_tag))
\r
1190 a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;
\r
1191 TrimCrlf(a->Title);
\r
1193 TrimCrlf(a->Title);
\r
1198 for (j = 0;j < LIST_NUM(o);j++)
\r
1201 WP_ADAPTER *a = LIST_DATA(o, j);
\r
1203 StrCpy(a->Guid, sizeof(a->Guid), a->Name);
\r
1204 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\SEP_", "");
\r
1205 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\SEE_", "");
\r
1206 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\NPF_", "");
\r
1207 ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\PCD_", "");
\r
1213 ret = NewListFast(CompareWpAdapter);
\r
1215 for (i = 0;i < LIST_NUM(o);i++)
\r
1217 WP_ADAPTER *a = LIST_DATA(o, i);
\r
1221 if (SearchStrEx(a->Title, "ppp", 0, false) != INFINITE ||
\r
1222 SearchStrEx(a->Title, "wan", 0, false) != INFINITE ||
\r
1223 SearchStrEx(a->Title, "dialup", 0, false) != INFINITE ||
\r
1224 SearchStrEx(a->Title, "pptp", 0, false) != INFINITE ||
\r
1225 SearchStrEx(a->Title, "telepho", 0, false) != INFINITE ||
\r
1226 SearchStrEx(a->Title, "modem", 0, false) != INFINITE ||
\r
1227 SearchStrEx(a->Title, "ras", 0, false) != INFINITE)
\r
1233 ad = wp->PacketOpenAdapter(a->Name);
\r
1237 if (wp->PacketGetNetType(ad, &type))
\r
1239 if (type.LinkType == 0)
\r
1241 char tmp[MAX_SIZE];
\r
1244 StrCpy(tmp, sizeof(tmp), a->Title);
\r
1250 StrCpy(tmp, sizeof(tmp), a->Title);
\r
1254 Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1);
\r
1258 for (j = 0;j < LIST_NUM(ret);j++)
\r
1260 WP_ADAPTER *aa = LIST_DATA(ret, j);
\r
1261 if (StrCmpi(aa->Title, tmp) == 0)
\r
1273 StrCpy(a->Title, sizeof(a->Title), tmp);
\r
1278 Debug("%s: type = %u\n", a->Name, type.LinkType);
\r
1283 Debug("%s: PacketGetNetType() Failed.\n", a->Name);
\r
1285 wp->PacketCloseAdapter(ad);
\r
1289 Debug("%s: PacketOpenAdapter() Failed.\n", a->Name);
\r
1307 // Ethernet アダプタのリストの初期化
\r
1308 void InitEthAdaptersList()
\r
1310 if (eth_list != NULL)
\r
1312 FreeEthAdaptersList();
\r
1315 eth_list = GetEthAdapterList();
\r
1318 // Ethernet アダプタのリストの解放
\r
1319 void FreeEthAdaptersList()
\r
1322 if (eth_list == NULL)
\r
1326 for (i = 0;i < LIST_NUM(eth_list);i++)
\r
1328 WP_ADAPTER *a = LIST_DATA(eth_list, i);
\r
1331 ReleaseList(eth_list);
\r
1335 // Ethernet がサポートされているかどうか
\r
1336 bool IsEthSupported()
\r
1343 return wp->Inited;
\r
1346 // 現在の OS で PCD ドライバがサポートされているか
\r
1347 bool IsPcdSupported()
\r
1350 OS_INFO *info = GetOsInfo();
\r
1352 type = info->OsType;
\r
1354 if (OS_IS_WINDOWS_NT(type) == false)
\r
1356 // Windows NT 以外はダメ
\r
1360 if (GET_KETA(type, 100) >= 2)
\r
1362 // Windows 2000 以降は良い
\r
1366 // Windows NT 4.0, Longhorn はダメ
\r
1371 // PCD ドライバのビルド番号を書き込む
\r
1372 void SavePcdDriverBuild(UINT build)
\r
1374 MsRegWriteInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE,
\r
1378 // PCD ドライバのビルド番号を読み込む
\r
1379 UINT LoadPcdDriverBuild()
\r
1381 return MsRegReadInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE);
\r
1384 // PCD ドライバのインストールを試みる
\r
1385 HINSTANCE InstallPcdDriver()
\r
1388 void *p = MsDisableWow64FileSystemRedirection();
\r
1390 ret = InstallPcdDriverInternal();
\r
1392 MsRestoreWow64FileSystemRedirection(p);
\r
1396 HINSTANCE InstallPcdDriverInternal()
\r
1398 char tmp[MAX_PATH];
\r
1399 bool install_driver = true;
\r
1401 char *dll_filename;
\r
1403 // まず sep.sys が system32\drivers ディレクトリにインストールされているかどうか確認する
\r
1404 Format(tmp, sizeof(tmp), "%s\\drivers\\sep.sys", MsGetSystem32Dir());
\r
1406 if (IsFileExists(tmp))
\r
1408 // ドライバが存在している場合は、次にレジストリからビルド番号を取得する
\r
1409 if (LoadPcdDriverBuild() >= CEDAR_BUILD)
\r
1411 // すでに最新版のドライバがインストールされている
\r
1412 install_driver = false;
\r
1416 if (install_driver)
\r
1418 char *src_filename = BRIDGE_WIN32_PCD_SYS;
\r
1419 // ドライバのインストールをする必要がある場合
\r
1420 // まず Admin かどうかチェックする
\r
1421 if (MsIsAdmin() == false)
\r
1423 // Admin で無い場合はドライバのインストールは不能である
\r
1429 src_filename = BRIDGE_WIN32_PCD_SYS_X64;
\r
1434 src_filename = BRIDGE_WIN32_PCD_SYS_IA64;
\r
1438 if (FileCopy(src_filename, tmp) == false)
\r
1444 SavePcdDriverBuild(CEDAR_BUILD);
\r
1447 dll_filename = BRIDGE_WIN32_PCD_DLL;
\r
1453 dll_filename = BRIDGE_WIN32_PCD_DLL_X64;
\r
1455 else if (MsIsIA64())
\r
1457 dll_filename = BRIDGE_WIN32_PCD_DLL_IA64;
\r
1461 // sep.dll を読み込んで初期化してみる
\r
1462 h = MsLoadLibrary(dll_filename);
\r
1481 eth_list_lock = NewLock();
\r
1483 wp = ZeroMalloc(sizeof(WP));
\r
1485 is_sep_mode = false;
\r
1487 if (IsPcdSupported())
\r
1489 // PCD がサポートされている OS である
\r
1490 h = InstallPcdDriver();
\r
1493 // PCD を使って初期化を試みる
\r
1494 if (InitWpWithLoadLibrary(wp, h) == false)
\r
1496 Debug("InitEth: SEP Failed.\n");
\r
1501 Debug("InitEth: SEP Loaded.\n");
\r
1502 is_sep_mode = true;
\r
1507 if (wp->Inited == false)
\r
1509 // WinPcap の Packet.dll を使って初期化を試みる
\r
1510 h = LoadLibrary(BRIDGE_WIN32_PACKET_DLL);
\r
1513 if (InitWpWithLoadLibrary(wp, h) == false)
\r
1515 Debug("InitEth: Packet.dll Failed.\n");
\r
1520 Debug("InitEth: Packet.dll Loaded.\n");
\r
1526 // sep.sys を用いてブリッジを行っているかどうかを取得
\r
1527 bool IsWin32BridgeWithSep()
\r
1529 return is_sep_mode;
\r
1532 // WP 構造体を DLL で初期化する
\r
1533 bool InitWpWithLoadLibrary(WP *wp, HINSTANCE h)
\r
1537 if (wp == NULL || h == NULL)
\r
1541 wp->Inited = true;
\r
1542 wp->hPacketDll = h;
\r
1544 LOAD_DLL_ADDR(PacketGetVersion);
\r
1545 LOAD_DLL_ADDR(PacketGetDriverVersion);
\r
1546 LOAD_DLL_ADDR(PacketSetMinToCopy);
\r
1547 LOAD_DLL_ADDR(PacketSetNumWrites);
\r
1548 LOAD_DLL_ADDR(PacketSetMode);
\r
1549 LOAD_DLL_ADDR(PacketSetReadTimeout);
\r
1550 LOAD_DLL_ADDR(PacketSetBpf);
\r
1551 LOAD_DLL_ADDR(PacketSetSnapLen);
\r
1552 LOAD_DLL_ADDR(PacketGetStats);
\r
1553 LOAD_DLL_ADDR(PacketGetStatsEx);
\r
1554 LOAD_DLL_ADDR(PacketSetBuff);
\r
1555 LOAD_DLL_ADDR(PacketGetNetType);
\r
1556 LOAD_DLL_ADDR(PacketOpenAdapter);
\r
1557 LOAD_DLL_ADDR(PacketSendPacket);
\r
1558 LOAD_DLL_ADDR(PacketSendPackets);
\r
1559 LOAD_DLL_ADDR(PacketAllocatePacket);
\r
1560 LOAD_DLL_ADDR(PacketInitPacket);
\r
1561 LOAD_DLL_ADDR(PacketFreePacket);
\r
1562 LOAD_DLL_ADDR(PacketReceivePacket);
\r
1563 LOAD_DLL_ADDR(PacketSetHwFilter);
\r
1564 LOAD_DLL_ADDR(PacketGetAdapterNames);
\r
1565 LOAD_DLL_ADDR(PacketGetNetInfoEx);
\r
1566 LOAD_DLL_ADDR(PacketRequest);
\r
1567 LOAD_DLL_ADDR(PacketGetReadEvent);
\r
1568 LOAD_DLL_ADDR(PacketSetDumpName);
\r
1569 LOAD_DLL_ADDR(PacketSetDumpLimits);
\r
1570 LOAD_DLL_ADDR(PacketSetDumpLimits);
\r
1571 LOAD_DLL_ADDR(PacketIsDumpEnded);
\r
1572 LOAD_DLL_ADDR(PacketStopDriver);
\r
1573 LOAD_DLL_ADDR(PacketCloseAdapter);
\r
1574 LOAD_DLL_ADDR(PacketSetLoopbackBehavior);
\r
1576 if (wp->PacketSetMinToCopy == NULL ||
\r
1577 wp->PacketSetNumWrites == NULL ||
\r
1578 wp->PacketSetMode == NULL ||
\r
1579 wp->PacketSetReadTimeout == NULL ||
\r
1580 wp->PacketSetBuff == NULL ||
\r
1581 wp->PacketGetNetType == NULL ||
\r
1582 wp->PacketOpenAdapter == NULL ||
\r
1583 wp->PacketSendPacket == NULL ||
\r
1584 wp->PacketSendPackets == NULL ||
\r
1585 wp->PacketAllocatePacket == NULL ||
\r
1586 wp->PacketInitPacket == NULL ||
\r
1587 wp->PacketFreePacket == NULL ||
\r
1588 wp->PacketReceivePacket == NULL ||
\r
1589 wp->PacketSetHwFilter == NULL ||
\r
1590 wp->PacketGetAdapterNames == NULL ||
\r
1591 wp->PacketGetNetInfoEx == NULL ||
\r
1592 wp->PacketCloseAdapter == NULL)
\r
1595 wp->Inited = false;
\r
1596 wp->hPacketDll = NULL;
\r
1602 if (o == NULL || o->NumTokens == 0)
\r
1623 FreeEthAdaptersList();
\r
1628 FreeLibrary(wp->hPacketDll);
\r
1634 DeleteLock(eth_list_lock);
\r
1635 eth_list_lock = NULL;
\r
1638 // Ethernet デバイスに対応するネットワーク接続名を取得する
\r
1639 void GetEthNetworkConnectionName(wchar_t *dst, UINT size, char *device_name)
\r
1641 WP_ADAPTER *t, tt;
\r
1642 char *tmp = NULL, guid[MAX_SIZE];
\r
1643 wchar_t *ncname = NULL;
\r
1645 UniStrCpy(dst, size, L"");
\r
1648 if (device_name == NULL || IsEthSupported() == false ||
\r
1649 IsNt() == false || MsIsWin2000OrGreater() == false)
\r
1654 Lock(eth_list_lock);
\r
1656 InitEthAdaptersList();
\r
1658 Zero(&tt, sizeof(tt));
\r
1659 StrCpy(tt.Title, sizeof(tt.Title), device_name);
\r
1661 t = Search(eth_list, &tt);
\r
1664 Unlock(eth_list_lock);
\r
1668 tmp = Malloc(sizeof(t->Name));
\r
1669 StrCpy(tmp, sizeof(t->Name), t->Name);
\r
1670 Unlock(eth_list_lock);
\r
1672 ReplaceStr(guid, sizeof(guid), tmp, "\\Device\\SEP_", "");
\r
1675 ReplaceStr(guid, sizeof(guid), guid, "\\Device\\SEE_", "");
\r
1676 ReplaceStr(guid, sizeof(guid), guid, "\\Device\\NPF_", "");
\r
1677 ReplaceStr(guid, sizeof(guid), guid, "\\Device\\PCD_", "");
\r
1684 ncname = MsGetNetworkConnectionName(guid);
\r
1685 if(ncname != NULL)
\r
1687 UniStrCpy(dst, size, ncname);
\r
1692 #endif // BRIDGE_C
\r