* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / BridgeWin32.c
1 // SoftEther UT-VPN SourceCode\r
2 // \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
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \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
13 // \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
18 // \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
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \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
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // BridgeWin32.c\r
79 // Ethernet ブリッジプログラム (Win32 版)\r
80 \r
81 #ifdef  BRIDGE_C\r
82 \r
83 #include <winsock2.h>\r
84 #include <Ws2tcpip.h>\r
85 #include <windows.h>\r
86 #include <stdio.h>\r
87 #include <stdlib.h>\r
88 #include <string.h>\r
89 #include <wchar.h>\r
90 #include <stdarg.h>\r
91 #include <time.h>\r
92 #include <errno.h>\r
93 #include <Packet32.h>\r
94 #include <Mayaqua/Mayaqua.h>\r
95 #include <Cedar/Cedar.h>\r
96 \r
97 \r
98 static WP *wp = NULL;\r
99 static LIST *eth_list = NULL;\r
100 \r
101 static LOCK *eth_list_lock = NULL;\r
102 static bool is_sep_mode = false;\r
103 \r
104 #define LOAD_DLL_ADDR(name)                             \\r
105         {                                                                       \\r
106                 void *addr = GetProcAddress(h, #name);  \\r
107                 Copy(&wp->name, &addr, sizeof(void *)); \\r
108         }\r
109 \r
110 // リスト比較\r
111 int CmpRpcEnumEthVLan(void *p1, void *p2)\r
112 {\r
113         RPC_ENUM_ETH_VLAN_ITEM *v1, *v2;\r
114         if (p1 == NULL || p2 == NULL)\r
115         {\r
116                 return 0;\r
117         }\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
121         {\r
122                 return 0;\r
123         }\r
124 \r
125         return StrCmpi(v1->DeviceName, v2->DeviceName);\r
126 }\r
127 \r
128 // MTU の取得 (Windows では非サポート)\r
129 UINT EthGetMtu(ETH *e)\r
130 {\r
131         return 0;\r
132 }\r
133 \r
134 // MTU の設定 (Windows では非サポート)\r
135 bool EthSetMtu(ETH *e, UINT mtu)\r
136 {\r
137         return false;\r
138 }\r
139 \r
140 // MTU の設定がサポートされているかどうか取得 (Windows では非サポート)\r
141 bool EthIsChangeMtuSupported(ETH *e)\r
142 {\r
143         return false;\r
144 }\r
145 \r
146 // デバイスの VLAN 有効化状態を設定\r
147 bool SetVLanEnableStatus(char *title, bool enable)\r
148 {\r
149         RPC_ENUM_ETH_VLAN t;\r
150         RPC_ENUM_ETH_VLAN_ITEM *e;\r
151         bool ret = false;\r
152         char key[MAX_SIZE];\r
153         char tcpkey[MAX_SIZE];\r
154         char short_key[MAX_SIZE];\r
155         // 引数チェック\r
156         if (title == NULL)\r
157         {\r
158                 return false;\r
159         }\r
160 \r
161         Zero(&t, sizeof(t));\r
162         if (EnumEthVLanWin32(&t) == false)\r
163         {\r
164                 return false;\r
165         }\r
166 \r
167         e = FindEthVLanItem(&t, title);\r
168 \r
169         if (e != NULL)\r
170         {\r
171                 if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid))\r
172                 {\r
173                         if (StrCmpi(e->DriverType, "Intel") == 0)\r
174                         {\r
175                                 if (enable)\r
176                                 {\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
181                                 }\r
182                                 else\r
183                                 {\r
184                                         if (MsRegReadInt(REG_LOCAL_MACHINE, key, "TaggingMode") == 0)\r
185                                         {\r
186                                                 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "TaggingMode");\r
187                                         }\r
188 \r
189                                         if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorMode") == 1)\r
190                                         {\r
191                                                 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorMode");\r
192                                         }\r
193 \r
194                                         if (MsRegReadInt(REG_LOCAL_MACHINE, key, "MonitorModeEnabled") == 1)\r
195                                         {\r
196                                                 MsRegDeleteValue(REG_LOCAL_MACHINE, key, "MonitorModeEnabled");\r
197                                         }\r
198                                 }\r
199 \r
200                                 ret = true;\r
201                         }\r
202                         else if (StrCmpi(e->DriverType, "Broadcom") == 0)\r
203                         {\r
204                                 if (enable)\r
205                                 {\r
206                                         MsRegWriteStr(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket", "1");\r
207                                 }\r
208                                 else\r
209                                 {\r
210                                         MsRegDeleteValue(REG_LOCAL_MACHINE, key, "PreserveVlanInfoInRxPacket");\r
211                                 }\r
212 \r
213                                 ret = true;\r
214                         }\r
215                         else if (StrCmpi(e->DriverType, "Marvell") == 0)\r
216                         {\r
217                                 if (enable)\r
218                                 {\r
219                                         MsRegWriteInt(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip", 1);\r
220                                 }\r
221                                 else\r
222                                 {\r
223                                         MsRegDeleteValue(REG_LOCAL_MACHINE, key, "SkDisableVlanStrip");\r
224                                 }\r
225 \r
226                                 ret = true;\r
227                         }\r
228 \r
229                         Format(tcpkey, sizeof(tcpkey),\r
230                                 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",\r
231                                 e->Guid);\r
232 \r
233                         if (enable)\r
234                         {\r
235                                 if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)\r
236                                 {\r
237                                         MsRegWriteInt(REG_LOCAL_MACHINE, tcpkey, "MTU", 1500);\r
238                                 }\r
239                         }\r
240                         else\r
241                         {\r
242                                 UINT mtu = MsRegReadInt(REG_LOCAL_MACHINE, tcpkey, "MTU");\r
243                                 if (mtu == 1500)\r
244                                 {\r
245                                         MsRegDeleteValue(REG_LOCAL_MACHINE, tcpkey, "MTU");\r
246                                 }\r
247                         }\r
248                 }\r
249         }\r
250 \r
251         FreeRpcEnumEthVLan(&t);\r
252 \r
253         return ret;\r
254 }\r
255 \r
256 // デバイスを検索\r
257 RPC_ENUM_ETH_VLAN_ITEM *FindEthVLanItem(RPC_ENUM_ETH_VLAN *t, char *name)\r
258 {\r
259         UINT i;\r
260         // 引数チェック\r
261         if (t == NULL || name == NULL)\r
262         {\r
263                 return NULL;\r
264         }\r
265 \r
266         for (i = 0;i < t->NumItem;i++)\r
267         {\r
268                 if (StrCmpi(t->Items[i].DeviceName, name) == 0)\r
269                 {\r
270                         return &t->Items[i];\r
271                 }\r
272         }\r
273 \r
274         return NULL;\r
275 }\r
276 \r
277 // デバイスの VLAN 有効化状態を取得\r
278 void GetVLanEnableStatus(RPC_ENUM_ETH_VLAN_ITEM *e)\r
279 {\r
280         char key[MAX_SIZE];\r
281         char short_key[MAX_SIZE];\r
282         char tcpkey[MAX_SIZE];\r
283         // 引数チェック\r
284         if (e == NULL)\r
285         {\r
286                 return;\r
287         }\r
288 \r
289         e->Enabled = false;\r
290 \r
291         if (e->Support == false)\r
292         {\r
293                 return;\r
294         }\r
295 \r
296         if (GetClassRegKeyWin32(key, sizeof(key), short_key, sizeof(short_key), e->Guid) == false)\r
297         {\r
298                 return;\r
299         }\r
300 \r
301         Format(tcpkey, sizeof(tcpkey),\r
302                 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",\r
303                 e->Guid);\r
304 \r
305         if (StrCmpi(e->DriverType, "Intel") == 0)\r
306         {\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
311 \r
312                 if (StrCmpi(VlanFiltering, "0") == 0 &&\r
313                         MonitorMode == 1 &&\r
314                         MonitorModeEnabled == 1 &&\r
315                         StrCmpi(TaggingMode, "0") == 0)\r
316                 {\r
317                         e->Enabled = true;\r
318                 }\r
319 \r
320                 Free(VlanFiltering);\r
321                 Free(TaggingMode);\r
322         }\r
323         else if (StrCmpi(e->DriverType, "Broadcom") == 0)\r
324         {\r
325                 char *PreserveVlanInfoInRxPacket = MsRegReadStr(REG_LOCAL_MACHINE,\r
326                         key, "PreserveVlanInfoInRxPacket");\r
327 \r
328                 if (StrCmpi(PreserveVlanInfoInRxPacket, "1") == 0)\r
329                 {\r
330                         e->Enabled = true;\r
331                 }\r
332 \r
333                 Free(PreserveVlanInfoInRxPacket);\r
334         }\r
335         else if (StrCmpi(e->DriverType, "Marvell") == 0)\r
336         {\r
337                 DWORD SkDisableVlanStrip = MsRegReadInt(REG_LOCAL_MACHINE,\r
338                         key, "SkDisableVlanStrip");\r
339 \r
340                 if (SkDisableVlanStrip == 1)\r
341                 {\r
342                         e->Enabled = true;\r
343                 }\r
344         }\r
345 \r
346         if (MsRegIsValue(REG_LOCAL_MACHINE, tcpkey, "MTU") == false)\r
347         {\r
348                 e->Enabled = false;\r
349         }\r
350 }\r
351 \r
352 // デバイスの VLAN サポート状態を取得\r
353 void GetVLanSupportStatus(RPC_ENUM_ETH_VLAN_ITEM *e)\r
354 {\r
355         BUF *b;\r
356         char filename[MAX_SIZE];\r
357         void *wow;\r
358         // 引数チェック\r
359         if (e == NULL)\r
360         {\r
361                 return;\r
362         }\r
363 \r
364         wow = MsDisableWow64FileSystemRedirection();\r
365 \r
366         // ドライバファイルを読み込む\r
367         CombinePath(filename, sizeof(filename), MsGetSystem32Dir(), "drivers");\r
368         CombinePath(filename, sizeof(filename), filename, e->DriverName);\r
369 \r
370         b = ReadDump(filename);\r
371 \r
372         if (b != NULL)\r
373         {\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
385 \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
392                 {\r
393                         driver_type = "Intel";\r
394                 }\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
397                 {\r
398                         driver_type = "Broadcom";\r
399                 }\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
402                 {\r
403                         driver_type = "Marvell";\r
404                 }\r
405 \r
406                 if (IsEmptyStr(driver_type) == false)\r
407                 {\r
408                         StrCpy(e->DriverType, sizeof(e->DriverType), driver_type);\r
409                         e->Support = true;\r
410                 }\r
411 \r
412                 FreeBuf(b);\r
413         }\r
414 \r
415         MsRestoreWow64FileSystemRedirection(wow);\r
416 }\r
417 \r
418 // short_key からデバイスのインスタンス ID を取得する\r
419 char *SearchDeviceInstanceIdFromShortKey(char *short_key)\r
420 {\r
421         char *ret = NULL;\r
422         TOKEN_LIST *t1;\r
423         // 引数チェック\r
424         if (short_key == NULL)\r
425         {\r
426                 return NULL;\r
427         }\r
428 \r
429         t1 = MsRegEnumKey(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum");\r
430 \r
431         if (t1 != NULL)\r
432         {\r
433                 TOKEN_LIST *t2;\r
434                 char tmp[MAX_SIZE];\r
435                 UINT i;\r
436 \r
437                 for (i = 0;i < t1->NumTokens;i++)\r
438                 {\r
439                         Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Enum\\%s", t1->Token[i]);\r
440 \r
441                         t2 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp);\r
442 \r
443                         if (t2 != NULL)\r
444                         {\r
445                                 TOKEN_LIST *t3;\r
446                                 UINT i;\r
447 \r
448                                 for (i = 0;i < t2->NumTokens;i++)\r
449                                 {\r
450                                         char tmp2[MAX_SIZE];\r
451 \r
452                                         Format(tmp2, sizeof(tmp2), "%s\\%s", tmp, t2->Token[i]);\r
453 \r
454                                         t3 = MsRegEnumKey(REG_LOCAL_MACHINE, tmp2);\r
455 \r
456                                         if (t3 != NULL)\r
457                                         {\r
458                                                 UINT i;\r
459 \r
460                                                 for (i = 0;i < t3->NumTokens;i++)\r
461                                                 {\r
462                                                         char tmp3[MAX_SIZE];\r
463                                                         char *s;\r
464 \r
465                                                         Format(tmp3, sizeof(tmp3), "%s\\%s", tmp2, t3->Token[i]);\r
466 \r
467                                                         s = MsRegReadStr(REG_LOCAL_MACHINE, tmp3, "Driver");\r
468 \r
469                                                         if (s != NULL)\r
470                                                         {\r
471                                                                 if (StrCmpi(s, short_key) == 0)\r
472                                                                 {\r
473                                                                         if (ret != NULL)\r
474                                                                         {\r
475                                                                                 Free(ret);\r
476                                                                         }\r
477 \r
478                                                                         ret = CopyStr(tmp3 + StrLen("SYSTEM\\CurrentControlSet\\Enum\\"));\r
479                                                                 }\r
480 \r
481                                                                 Free(s);\r
482                                                         }\r
483                                                 }\r
484 \r
485                                                 FreeToken(t3);\r
486                                         }\r
487                                 }\r
488 \r
489                                 FreeToken(t2);\r
490                         }\r
491                 }\r
492 \r
493                 FreeToken(t1);\r
494         }\r
495 \r
496         return ret;\r
497 }\r
498 \r
499 // 物理 LAN カードの VLAN 対応状況の列挙\r
500 bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t)\r
501 {\r
502         UINT i;\r
503         LIST *o;\r
504         // 引数チェック\r
505         if (t == NULL)\r
506         {\r
507                 return false;\r
508         }\r
509 \r
510         Zero(t, sizeof(RPC_ENUM_ETH_VLAN));\r
511 \r
512         if (MsIsWin2000OrGreater() == false)\r
513         {\r
514                 return false;\r
515         }\r
516 \r
517         if (IsEthSupported() == false)\r
518         {\r
519                 return false;\r
520         }\r
521 \r
522         // アダプタ一覧の取得\r
523         Lock(eth_list_lock);\r
524 \r
525         InitEthAdaptersList();\r
526 \r
527         o = NewListFast(CmpRpcEnumEthVLan);\r
528 \r
529         for (i = 0;i < LIST_NUM(eth_list);i++)\r
530         {\r
531                 WP_ADAPTER *a = LIST_DATA(eth_list, i);\r
532 \r
533                 if (IsEmptyStr(a->Guid) == false)\r
534                 {\r
535                         char class_key[MAX_SIZE];\r
536                         char short_key[MAX_SIZE];\r
537 \r
538                         if (GetClassRegKeyWin32(class_key, sizeof(class_key),\r
539                                 short_key, sizeof(short_key), a->Guid))\r
540                         {\r
541                                 char *device_instance_id = MsRegReadStr(REG_LOCAL_MACHINE, class_key, "DeviceInstanceID");\r
542 \r
543                                 if (IsEmptyStr(device_instance_id))\r
544                                 {\r
545                                         Free(device_instance_id);\r
546                                         device_instance_id = SearchDeviceInstanceIdFromShortKey(short_key);\r
547                                 }\r
548 \r
549                                 if (IsEmptyStr(device_instance_id) == false)\r
550                                 {\r
551                                         char device_key[MAX_SIZE];\r
552                                         char *service_name;\r
553 \r
554                                         Format(device_key, sizeof(device_key), "SYSTEM\\CurrentControlSet\\Enum\\%s",\r
555                                                 device_instance_id);\r
556 \r
557                                         service_name = MsRegReadStr(REG_LOCAL_MACHINE, device_key, "Service");\r
558                                         if (IsEmptyStr(service_name) == false)\r
559                                         {\r
560                                                 char service_key[MAX_SIZE];\r
561                                                 char *sys;\r
562 \r
563                                                 Format(service_key, sizeof(service_key),\r
564                                                         "SYSTEM\\CurrentControlSet\\services\\%s",\r
565                                                         service_name);\r
566 \r
567                                                 sys = MsRegReadStr(REG_LOCAL_MACHINE, service_key, "ImagePath");\r
568 \r
569                                                 if (IsEmptyStr(sys) == false)\r
570                                                 {\r
571                                                         char sysname[MAX_PATH];\r
572 \r
573                                                         GetFileNameFromFilePath(sysname, sizeof(sysname), sys);\r
574 \r
575                                                         Trim(sysname);\r
576 \r
577                                                         if (EndWith(sysname, ".sys"))\r
578                                                         {\r
579                                                                 // デバイス発見\r
580                                                                 RPC_ENUM_ETH_VLAN_ITEM *e = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM));\r
581 \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
586 \r
587                                                                 // デバイスの VLAN サポート状態を取得\r
588                                                                 GetVLanSupportStatus(e);\r
589 \r
590                                                                 // 有効化状態を取得\r
591                                                                 GetVLanEnableStatus(e);\r
592 \r
593                                                                 Insert(o, e);\r
594                                                         }\r
595                                                 }\r
596 \r
597                                                 Free(sys);\r
598                                         }\r
599 \r
600                                         Free(service_name);\r
601                                 }\r
602 \r
603                                 Free(device_instance_id);\r
604                         }\r
605                 }\r
606         }\r
607 \r
608         t->NumItem = LIST_NUM(o);\r
609         t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * i);\r
610 \r
611         for (i = 0;i < LIST_NUM(o);i++)\r
612         {\r
613                 RPC_ENUM_ETH_VLAN_ITEM *e = LIST_DATA(o, i);\r
614 \r
615                 Copy(&t->Items[i], e, sizeof(RPC_ENUM_ETH_VLAN_ITEM));\r
616 \r
617                 Free(e);\r
618         }\r
619 \r
620         ReleaseList(o);\r
621 \r
622         Unlock(eth_list_lock);\r
623 \r
624         return true;\r
625 }\r
626 \r
627 // GUID からネットワーククラスデータのレジストリキーを取得\r
628 bool GetClassRegKeyWin32(char *key, UINT key_size, char *short_key, UINT short_key_size, char *guid)\r
629 {\r
630         TOKEN_LIST *t;\r
631         bool ret = false;\r
632         UINT i;\r
633         // 引数チェック\r
634         if (key == NULL || short_key == NULL || guid == NULL)\r
635         {\r
636                 return false;\r
637         }\r
638 \r
639         t = MsRegEnumKey(REG_LOCAL_MACHINE,\r
640                 "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");\r
641         if (t == NULL)\r
642         {\r
643                 return false;\r
644         }\r
645 \r
646         for (i = 0;i < t->NumTokens;i++)\r
647         {\r
648                 char keyname[MAX_SIZE];\r
649                 char *value;\r
650 \r
651                 Format(keyname, sizeof(keyname),\r
652                         "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",\r
653                         t->Token[i]);\r
654 \r
655                 value = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "NetCfgInstanceId");\r
656 \r
657                 if (StrCmpi(value, guid) == 0)\r
658                 {\r
659                         ret = true;\r
660 \r
661                         StrCpy(key, key_size, keyname);\r
662 \r
663                         Format(short_key, short_key_size, "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s",\r
664                                 t->Token[i]);\r
665                 }\r
666 \r
667                 Free(value);\r
668         }\r
669 \r
670         FreeToken(t);\r
671 \r
672         return ret;\r
673 }\r
674 \r
675 // 複数のパケットを書き込む\r
676 void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)\r
677 {\r
678         UINT i, total_size;\r
679         UCHAR *buf;\r
680         UINT write_pointer;\r
681         // 引数チェック\r
682         if (e == NULL || num == 0 || datas == NULL || sizes == NULL)\r
683         {\r
684                 return;\r
685         }\r
686 \r
687         if (IsWin32BridgeWithSep() == false)\r
688         {\r
689                 // 古い WinPcap にはバグがあり、2 個以上の CPU が搭載されている場合に\r
690                 // ロックが不十分なところがあってカーネル内でクラッシュすることが\r
691                 // 頻繁にあった。そこで 1 個目の CPU でしか動作しないように工夫していた\r
692                 if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())\r
693                 {\r
694                         e->LastSetSingleCpu = Tick64();\r
695                         MsSetThreadSingleCpu();\r
696                 }\r
697         }\r
698 \r
699         // 必要なデータサイズの計算\r
700         total_size = 0;\r
701         for (i = 0;i < num;i++)\r
702         {\r
703                 void *data = datas[i];\r
704                 UINT size = sizes[i];\r
705                 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)\r
706                 {\r
707                         total_size += size + sizeof(struct dump_bpf_hdr);\r
708                 }\r
709         }\r
710 \r
711         // 適当やな\r
712         buf = MallocFast(total_size * 100 / 75 + 1600);\r
713 \r
714         write_pointer = 0;\r
715         // キューに入れる\r
716         for (i = 0;i < num;i++)\r
717         {\r
718                 void *data = datas[i];\r
719                 UINT size = sizes[i];\r
720                 if (data != NULL && size >= 14 && size <= MAX_PACKET_SIZE)\r
721                 {\r
722                         struct dump_bpf_hdr *h;\r
723 \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
730 \r
731                         PROBE_DATA2("EthPutPackets", data, size);\r
732                 }\r
733                 // 元のメモリは解放する\r
734                 Free(data);\r
735         }\r
736 \r
737         // 送信\r
738         if (total_size != 0)\r
739         {\r
740                 wp->PacketSendPackets(e->Adapter, buf, total_size, true);\r
741         }\r
742 \r
743         Free(buf);\r
744 }\r
745 \r
746 // パケットを書き込む\r
747 void EthPutPacket(ETH *e, void *data, UINT size)\r
748 {\r
749         // 引数チェック\r
750         if (e == NULL || data == NULL || size == 0)\r
751         {\r
752                 return;\r
753         }\r
754         if (size < 14 || size > MAX_PACKET_SIZE)\r
755         {\r
756                 Free(data);\r
757                 return;\r
758         }\r
759 \r
760         if (IsWin32BridgeWithSep() == false)\r
761         {\r
762                 if (e->LastSetSingleCpu == 0 || (e->LastSetSingleCpu + 10000) <= Tick64())\r
763                 {\r
764                         e->LastSetSingleCpu = Tick64();\r
765                         MsSetThreadSingleCpu();\r
766                 }\r
767         }\r
768 \r
769         wp->PacketInitPacket(e->PutPacket, data, size);\r
770         wp->PacketSendPacket(e->Adapter, e->PutPacket, false);\r
771 \r
772         Free(data);\r
773 }\r
774 \r
775 // 次のパケットを読み込む\r
776 UINT EthGetPacket(ETH *e, void **data)\r
777 {\r
778         BLOCK *b;\r
779         bool flag = false;\r
780         // 引数チェック\r
781         if (e == NULL || data == NULL)\r
782         {\r
783                 return INFINITE;\r
784         }\r
785 \r
786 RETRY:\r
787         // まずキューにパケットがたまっているかどうか見てみる\r
788         b = GetNext(e->PacketQueue);\r
789         if (b != NULL)\r
790         {\r
791                 UINT size;\r
792                 size = b->Size;\r
793                 *data = b->Buf;\r
794                 Free(b);\r
795 \r
796                 if (e->PacketQueue->num_item == 0)\r
797                 {\r
798                         e->Empty = true;\r
799                 }\r
800 \r
801                 return size;\r
802         }\r
803 \r
804         if (e->Empty)\r
805         {\r
806                 e->Empty = false;\r
807                 return 0;\r
808         }\r
809 \r
810         if (flag == false)\r
811         {\r
812                 // 次のパケットの取得を試みる\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
817                 {\r
818                         // 失敗\r
819                         return INFINITE;\r
820                 }\r
821                 else\r
822                 {\r
823                         UCHAR *buf;\r
824                         UINT total;\r
825                         UINT offset;\r
826 \r
827                         buf = (UCHAR *)e->Packet->Buffer;\r
828                         total = e->Packet->ulBytesReceived;\r
829                         offset = 0;\r
830 \r
831                         while (offset < total)\r
832                         {\r
833                                 struct bpf_hdr *header;\r
834                                 UINT packet_size;\r
835                                 UCHAR *packet_data;\r
836 \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
842 \r
843                                 if (packet_size >= 14)\r
844                                 {\r
845                                         UCHAR *tmp;\r
846                                         BLOCK *b;\r
847 \r
848                                         PROBE_DATA2("EthGetPacket: NewBlock", packet_data, packet_size);\r
849                                         \r
850                                         tmp = MallocFast(packet_size);\r
851 \r
852                                         Copy(tmp, packet_data, packet_size);\r
853                                         b = NewBlock(tmp, packet_size, 0);\r
854                                         InsertQueue(e->PacketQueue, b);\r
855                                 }\r
856                         }\r
857 \r
858                         flag = true;\r
859                         goto RETRY;\r
860                 }\r
861         }\r
862 \r
863         // これ以上パケットを取得できない\r
864         return 0;\r
865 }\r
866 \r
867 // キャンセルオブジェクトの取得\r
868 CANCEL *EthGetCancel(ETH *e)\r
869 {\r
870         // 引数チェック\r
871         if (e == NULL)\r
872         {\r
873                 return NULL;\r
874         }\r
875 \r
876         AddRef(e->Cancel->ref);\r
877 \r
878         return e->Cancel;\r
879 }\r
880 \r
881 // アダプタを閉じる\r
882 void CloseEth(ETH *e)\r
883 {\r
884         BLOCK *b;\r
885         // 引数チェック\r
886         if (e == NULL)\r
887         {\r
888                 return;\r
889         }\r
890 \r
891         ReleaseCancel(e->Cancel);\r
892 \r
893         wp->PacketCloseAdapter(e->Adapter);\r
894         wp->PacketFreePacket(e->Packet);\r
895         wp->PacketFreePacket(e->PutPacket);\r
896 \r
897         while (b = GetNext(e->PacketQueue))\r
898         {\r
899                 FreeBlock(b);\r
900         }\r
901         ReleaseQueue(e->PacketQueue);\r
902 \r
903         Free(e->Name);\r
904         Free(e->Title);\r
905         Free(e->Buffer);\r
906 \r
907         Free(e);\r
908 }\r
909 \r
910 // アダプタを開く\r
911 ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)\r
912 {\r
913         ETH *ret;\r
914         void *p;\r
915 \r
916         p = MsDisableWow64FileSystemRedirection();\r
917 \r
918         ret = OpenEthInternal(name, local, tapmode, tapaddr);\r
919 \r
920         MsRestoreWow64FileSystemRedirection(p);\r
921 \r
922         return ret;\r
923 }\r
924 ETH *OpenEthInternal(char *name, bool local, bool tapmode, char *tapaddr)\r
925 {\r
926         WP_ADAPTER *t, tt;\r
927         ETH *e;\r
928         ADAPTER *a;\r
929         HANDLE h;\r
930         CANCEL *c;\r
931         // 引数チェック\r
932         if (name == NULL || IsEthSupported() == false)\r
933         {\r
934                 return NULL;\r
935         }\r
936 \r
937         if (tapmode)\r
938         {\r
939                 // Win32 では tap はサポートしていない\r
940                 return NULL;\r
941         }\r
942 \r
943         Lock(eth_list_lock);\r
944 \r
945         InitEthAdaptersList();\r
946 \r
947         Zero(&tt, sizeof(tt));\r
948         StrCpy(tt.Title, sizeof(tt.Title), name);\r
949 \r
950         t = Search(eth_list, &tt);\r
951         if (t == NULL)\r
952         {\r
953                 Unlock(eth_list_lock);\r
954                 return NULL;\r
955         }\r
956 \r
957         a = wp->PacketOpenAdapter(t->Name);\r
958         if (a == NULL)\r
959         {\r
960                 Unlock(eth_list_lock);\r
961                 return NULL;\r
962         }\r
963 \r
964         if (IsWin32BridgeWithSep() == false)\r
965         {\r
966                 MsSetThreadSingleCpu();\r
967         }\r
968 \r
969         e = ZeroMalloc(sizeof(ETH));\r
970         e->Name = CopyStr(t->Name);\r
971         e->Title = CopyStr(t->Title);\r
972 \r
973         e->Adapter = a;\r
974 \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
980 \r
981         if (wp->PacketSetLoopbackBehavior != NULL)\r
982         {\r
983                 if (GET_KETA(GetOsType(), 100) >= 3)\r
984                 {\r
985                         // Windows XP, Server 2003 以降\r
986                         bool ret = wp->PacketSetLoopbackBehavior(e->Adapter, 1);\r
987                         Debug("*** PacketSetLoopbackBehavior: %u\n", ret);\r
988 \r
989                         e->LoopbackBlock = ret;\r
990                 }\r
991         }\r
992 \r
993         h = wp->PacketGetReadEvent(e->Adapter);\r
994 \r
995         c = NewCancelSpecial(h);\r
996         e->Cancel = c;\r
997 \r
998         e->Buffer = Malloc(BRIDGE_WIN32_ETH_BUFFER);\r
999         e->BufferSize = BRIDGE_WIN32_ETH_BUFFER;\r
1000         e->Packet = wp->PacketAllocatePacket();\r
1001 \r
1002         e->PutPacket = wp->PacketAllocatePacket();\r
1003 \r
1004         e->PacketQueue = NewQueue();\r
1005 \r
1006         Unlock(eth_list_lock);\r
1007 \r
1008         return e;\r
1009 }\r
1010 \r
1011 // Ethernet アダプタリストの取得\r
1012 TOKEN_LIST *GetEthList()\r
1013 {\r
1014         TOKEN_LIST *ret;\r
1015         UINT i;\r
1016 \r
1017         if (IsEthSupported() == false)\r
1018         {\r
1019                 return NULL;\r
1020         }\r
1021 \r
1022         Lock(eth_list_lock);\r
1023 \r
1024         InitEthAdaptersList();\r
1025 \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
1030         {\r
1031                 WP_ADAPTER *a = LIST_DATA(eth_list, i);\r
1032                 ret->Token[i] = CopyStr(a->Title);\r
1033         }\r
1034 \r
1035         Unlock(eth_list_lock);\r
1036 \r
1037         return ret;\r
1038 }\r
1039 \r
1040 // WP_ADAPTER の名前比較\r
1041 int CompareWpAdapter(void *p1, void *p2)\r
1042 {\r
1043         int i;\r
1044         WP_ADAPTER *a1, *a2;\r
1045         if (p1 == NULL || p2 == NULL)\r
1046         {\r
1047                 return 0;\r
1048         }\r
1049         a1 = *(WP_ADAPTER **)p1;\r
1050         a2 = *(WP_ADAPTER **)p2;\r
1051         if (a1 == NULL || a2 == NULL)\r
1052         {\r
1053                 return 0;\r
1054         }\r
1055         i = StrCmpi(a1->Title, a2->Title);\r
1056         return i;\r
1057 }\r
1058 \r
1059 // Ethernet アダプタリストの取得\r
1060 LIST *GetEthAdapterList()\r
1061 {\r
1062         void *p;\r
1063         LIST *o;\r
1064 \r
1065         p = MsDisableWow64FileSystemRedirection();\r
1066 \r
1067         o = GetEthAdapterListInternal();\r
1068 \r
1069         MsRestoreWow64FileSystemRedirection(p);\r
1070 \r
1071         return o;\r
1072 }\r
1073 LIST *GetEthAdapterListInternal()\r
1074 {\r
1075         LIST *o;\r
1076         LIST *ret;\r
1077         UINT size;\r
1078         char *buf;\r
1079         UINT i, j;\r
1080         char *qos_tag = " (Microsoft's Packet Scheduler)";\r
1081 \r
1082         o = NewListFast(CompareWpAdapter);\r
1083 \r
1084         size = 200000;\r
1085         buf = ZeroMalloc(size);\r
1086 \r
1087         if (wp->PacketGetAdapterNames(buf, &size) == false)\r
1088         {\r
1089                 Free(buf);\r
1090                 return o;\r
1091         }\r
1092 \r
1093         i = 0;\r
1094 \r
1095         if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))\r
1096         {\r
1097                 // Windows NT\r
1098                 if (size >= 2 && buf[0] != 0 && buf[1] != 0)\r
1099                 {\r
1100                         goto ANSI_STR;\r
1101                 }\r
1102 \r
1103                 while (true)\r
1104                 {\r
1105                         wchar_t tmp[MAX_SIZE];\r
1106                         WP_ADAPTER *a;\r
1107                         UniStrCpy(tmp, sizeof(tmp), L"");\r
1108 \r
1109                         if (*((wchar_t *)(&buf[i])) == 0)\r
1110                         {\r
1111                                 i += sizeof(wchar_t);\r
1112                                 break;\r
1113                         }\r
1114 \r
1115                         for (;*((wchar_t *)(&buf[i])) != 0;i += sizeof(wchar_t))\r
1116                         {\r
1117                                 wchar_t str[2];\r
1118                                 str[0] = *((wchar_t *)(&buf[i]));\r
1119                                 str[1] = 0;\r
1120                                 UniStrCat(tmp, sizeof(tmp), str);\r
1121                         }\r
1122 \r
1123                         i += sizeof(wchar_t);\r
1124 \r
1125                         a = ZeroMalloc(sizeof(WP_ADAPTER));\r
1126                         UniToStr(a->Name, sizeof(a->Name), tmp);\r
1127 \r
1128                         Add(o, a);\r
1129                 }\r
1130         }\r
1131         else\r
1132         {\r
1133                 // Windows 9x\r
1134 ANSI_STR:\r
1135                 while (true)\r
1136                 {\r
1137                         char tmp[MAX_SIZE];\r
1138                         WP_ADAPTER *a;\r
1139                         StrCpy(tmp, sizeof(tmp), "");\r
1140 \r
1141                         if (*((char *)(&buf[i])) == 0)\r
1142                         {\r
1143                                 i += sizeof(char);\r
1144                                 break;\r
1145                         }\r
1146 \r
1147                         for (;*((char *)(&buf[i])) != 0;i += sizeof(char))\r
1148                         {\r
1149                                 char str[2];\r
1150                                 str[0] = *((char *)(&buf[i]));\r
1151                                 str[1] = 0;\r
1152                                 StrCat(tmp, sizeof(tmp), str);\r
1153                         }\r
1154 \r
1155                         i += sizeof(char);\r
1156 \r
1157                         a = ZeroMalloc(sizeof(WP_ADAPTER));\r
1158                         StrCpy(a->Name, sizeof(a->Name), tmp);\r
1159 \r
1160                         Add(o, a);\r
1161                 }\r
1162         }\r
1163 \r
1164         for (j = 0;j < LIST_NUM(o);j++)\r
1165         {\r
1166                 WP_ADAPTER *a = LIST_DATA(o, j);\r
1167 \r
1168                 StrCpy(a->Title, sizeof(a->Title), &buf[i]);\r
1169                 i += StrSize(a->Title);\r
1170 \r
1171                 // Win9x で デバイスの説明が"Unknown"ならば1文字読み飛ばす。\r
1172                 if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))\r
1173                 {\r
1174                         if (StrCmp(a->Title, "Unknown") == 0)\r
1175                         {\r
1176                                 if (buf[i] == 0)\r
1177                                 {\r
1178                                         i+=sizeof(char);\r
1179                                 }\r
1180                         }\r
1181                 }\r
1182 \r
1183                 TrimCrlf(a->Title);\r
1184                 Trim(a->Title);\r
1185                 TrimCrlf(a->Title);\r
1186                 Trim(a->Title);\r
1187 \r
1188                 if (EndWith(a->Title, qos_tag))\r
1189                 {\r
1190                         a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0;\r
1191                         TrimCrlf(a->Title);\r
1192                         Trim(a->Title);\r
1193                         TrimCrlf(a->Title);\r
1194                         Trim(a->Title);\r
1195                 }\r
1196         }\r
1197 \r
1198         for (j = 0;j < LIST_NUM(o);j++)\r
1199         {\r
1200                 // GUID の抽出\r
1201                 WP_ADAPTER *a = LIST_DATA(o, j);\r
1202 \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
1208         }\r
1209 \r
1210         // ソート\r
1211         Sort(o);\r
1212 \r
1213         ret = NewListFast(CompareWpAdapter);\r
1214 \r
1215         for (i = 0;i < LIST_NUM(o);i++)\r
1216         {\r
1217                 WP_ADAPTER *a = LIST_DATA(o, i);\r
1218                 ADAPTER *ad;\r
1219                 bool ok = false;\r
1220 \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
1228                 {\r
1229                         Free(a);\r
1230                         continue;\r
1231                 }\r
1232 \r
1233                 ad = wp->PacketOpenAdapter(a->Name);\r
1234                 if (ad != NULL)\r
1235                 {\r
1236                         NetType type;\r
1237                         if (wp->PacketGetNetType(ad, &type))\r
1238                         {\r
1239                                 if (type.LinkType == 0)\r
1240                                 {\r
1241                                         char tmp[MAX_SIZE];\r
1242                                         UINT k;\r
1243                                         // Ethernet のみ\r
1244                                         StrCpy(tmp, sizeof(tmp), a->Title);\r
1245 \r
1246                                         for (k = 0;;k++)\r
1247                                         {\r
1248                                                 if (k == 0)\r
1249                                                 {\r
1250                                                         StrCpy(tmp, sizeof(tmp), a->Title);\r
1251                                                 }\r
1252                                                 else\r
1253                                                 {\r
1254                                                         Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1);\r
1255                                                 }\r
1256 \r
1257                                                 ok = true;\r
1258                                                 for (j = 0;j < LIST_NUM(ret);j++)\r
1259                                                 {\r
1260                                                         WP_ADAPTER *aa = LIST_DATA(ret, j);\r
1261                                                         if (StrCmpi(aa->Title, tmp) == 0)\r
1262                                                         {\r
1263                                                                 ok = false;\r
1264                                                         }\r
1265                                                 }\r
1266 \r
1267                                                 if (ok)\r
1268                                                 {\r
1269                                                         break;\r
1270                                                 }\r
1271                                         }\r
1272 \r
1273                                         StrCpy(a->Title, sizeof(a->Title), tmp);\r
1274                                         Add(ret, a);\r
1275                                 }\r
1276                                 else\r
1277                                 {\r
1278                                         Debug("%s: type = %u\n", a->Name, type.LinkType);\r
1279                                 }\r
1280                         }\r
1281                         else\r
1282                         {\r
1283                                 Debug("%s: PacketGetNetType() Failed.\n", a->Name);\r
1284                         }\r
1285                         wp->PacketCloseAdapter(ad);\r
1286                 }\r
1287                 else\r
1288                 {\r
1289                         Debug("%s: PacketOpenAdapter() Failed.\n", a->Name);\r
1290                 }\r
1291 \r
1292                 if (ok == false)\r
1293                 {\r
1294                         Free(a);\r
1295                 }\r
1296         }\r
1297 \r
1298         Free(buf);\r
1299 \r
1300         Sort(ret);\r
1301 \r
1302         ReleaseList(o);\r
1303 \r
1304         return ret;\r
1305 }\r
1306 \r
1307 // Ethernet アダプタのリストの初期化\r
1308 void InitEthAdaptersList()\r
1309 {\r
1310         if (eth_list != NULL)\r
1311         {\r
1312                 FreeEthAdaptersList();\r
1313                 eth_list = NULL;\r
1314         }\r
1315         eth_list = GetEthAdapterList();\r
1316 }\r
1317 \r
1318 // Ethernet アダプタのリストの解放\r
1319 void FreeEthAdaptersList()\r
1320 {\r
1321         UINT i;\r
1322         if (eth_list == NULL)\r
1323         {\r
1324                 return;\r
1325         }\r
1326         for (i = 0;i < LIST_NUM(eth_list);i++)\r
1327         {\r
1328                 WP_ADAPTER *a = LIST_DATA(eth_list, i);\r
1329                 Free(a);\r
1330         }\r
1331         ReleaseList(eth_list);\r
1332         eth_list = NULL;\r
1333 }\r
1334 \r
1335 // Ethernet がサポートされているかどうか\r
1336 bool IsEthSupported()\r
1337 {\r
1338         if (wp == NULL)\r
1339         {\r
1340                 return false;\r
1341         }\r
1342 \r
1343         return wp->Inited;\r
1344 }\r
1345 \r
1346 // 現在の OS で PCD ドライバがサポートされているか\r
1347 bool IsPcdSupported()\r
1348 {\r
1349         UINT type;\r
1350         OS_INFO *info = GetOsInfo();\r
1351 \r
1352         type = info->OsType;\r
1353 \r
1354         if (OS_IS_WINDOWS_NT(type) == false)\r
1355         {\r
1356                 // Windows NT 以外はダメ\r
1357                 return false;\r
1358         }\r
1359 \r
1360         if (GET_KETA(type, 100) >= 2)\r
1361         {\r
1362                 // Windows 2000 以降は良い\r
1363                 return true;\r
1364         }\r
1365 \r
1366         // Windows NT 4.0, Longhorn はダメ\r
1367 \r
1368         return false;\r
1369 }\r
1370 \r
1371 // PCD ドライバのビルド番号を書き込む\r
1372 void SavePcdDriverBuild(UINT build)\r
1373 {\r
1374         MsRegWriteInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE,\r
1375                 build);\r
1376 }\r
1377 \r
1378 // PCD ドライバのビルド番号を読み込む\r
1379 UINT LoadPcdDriverBuild()\r
1380 {\r
1381         return MsRegReadInt(REG_LOCAL_MACHINE, BRIDGE_WIN32_PCD_REGKEY, BRIDGE_WIN32_PCD_BUILDVALUE);\r
1382 }\r
1383 \r
1384 // PCD ドライバのインストールを試みる\r
1385 HINSTANCE InstallPcdDriver()\r
1386 {\r
1387         HINSTANCE ret;\r
1388         void *p = MsDisableWow64FileSystemRedirection();\r
1389 \r
1390         ret = InstallPcdDriverInternal();\r
1391 \r
1392         MsRestoreWow64FileSystemRedirection(p);\r
1393 \r
1394         return ret;\r
1395 }\r
1396 HINSTANCE InstallPcdDriverInternal()\r
1397 {\r
1398         char tmp[MAX_PATH];\r
1399         bool install_driver = true;\r
1400         HINSTANCE h;\r
1401         char *dll_filename;\r
1402 \r
1403         // まず sep.sys が system32\drivers ディレクトリにインストールされているかどうか確認する\r
1404         Format(tmp, sizeof(tmp), "%s\\drivers\\sep.sys", MsGetSystem32Dir());\r
1405 \r
1406         if (IsFileExists(tmp))\r
1407         {\r
1408                 // ドライバが存在している場合は、次にレジストリからビルド番号を取得する\r
1409                 if (LoadPcdDriverBuild() >= CEDAR_BUILD)\r
1410                 {\r
1411                         // すでに最新版のドライバがインストールされている\r
1412                         install_driver = false;\r
1413                 }\r
1414         }\r
1415 \r
1416         if (install_driver)\r
1417         {\r
1418                 char *src_filename = BRIDGE_WIN32_PCD_SYS;\r
1419                 // ドライバのインストールをする必要がある場合\r
1420                 // まず Admin かどうかチェックする\r
1421                 if (MsIsAdmin() == false)\r
1422                 {\r
1423                         // Admin で無い場合はドライバのインストールは不能である\r
1424                         return NULL;\r
1425                 }\r
1426 \r
1427                 if (MsIsX64())\r
1428                 {\r
1429                         src_filename = BRIDGE_WIN32_PCD_SYS_X64;\r
1430                 }\r
1431 \r
1432                 if (MsIsIA64())\r
1433                 {\r
1434                         src_filename = BRIDGE_WIN32_PCD_SYS_IA64;\r
1435                 }\r
1436 \r
1437                 // sep.sys をコピーする\r
1438                 if (FileCopy(src_filename, tmp) == false)\r
1439                 {\r
1440                         return NULL;\r
1441                 }\r
1442 \r
1443                 // ビルド番号を書き込む\r
1444                 SavePcdDriverBuild(CEDAR_BUILD);\r
1445         }\r
1446 \r
1447         dll_filename = BRIDGE_WIN32_PCD_DLL;\r
1448 \r
1449         if (Is64())\r
1450         {\r
1451                 if (MsIsX64())\r
1452                 {\r
1453                         dll_filename = BRIDGE_WIN32_PCD_DLL_X64;\r
1454                 }\r
1455                 else if (MsIsIA64())\r
1456                 {\r
1457                         dll_filename = BRIDGE_WIN32_PCD_DLL_IA64;\r
1458                 }\r
1459         }\r
1460 \r
1461         // sep.dll を読み込んで初期化してみる\r
1462         h = MsLoadLibrary(dll_filename);\r
1463         if (h == NULL)\r
1464         {\r
1465                 return NULL;\r
1466         }\r
1467 \r
1468         return h;\r
1469 }\r
1470 \r
1471 // Ethernet の初期化\r
1472 void InitEth()\r
1473 {\r
1474         HINSTANCE h;\r
1475         if (wp != NULL)\r
1476         {\r
1477                 // 初期化済み\r
1478                 return;\r
1479         }\r
1480 \r
1481         eth_list_lock = NewLock();\r
1482 \r
1483         wp = ZeroMalloc(sizeof(WP));\r
1484 \r
1485         is_sep_mode = false;\r
1486 \r
1487         if (IsPcdSupported())\r
1488         {\r
1489                 // PCD がサポートされている OS である\r
1490                 h = InstallPcdDriver();\r
1491                 if (h != NULL)\r
1492                 {\r
1493                         // PCD を使って初期化を試みる\r
1494                         if (InitWpWithLoadLibrary(wp, h) == false)\r
1495                         {\r
1496                                 Debug("InitEth: SEP Failed.\n");\r
1497                                 FreeLibrary(h);\r
1498                         }\r
1499                         else\r
1500                         {\r
1501                                 Debug("InitEth: SEP Loaded.\n");\r
1502                                 is_sep_mode = true;\r
1503                         }\r
1504                 }\r
1505         }\r
1506 \r
1507         if (wp->Inited == false)\r
1508         {\r
1509                 // WinPcap の Packet.dll を使って初期化を試みる\r
1510                 h = LoadLibrary(BRIDGE_WIN32_PACKET_DLL);\r
1511                 if (h != NULL)\r
1512                 {\r
1513                         if (InitWpWithLoadLibrary(wp, h) == false)\r
1514                         {\r
1515                                 Debug("InitEth: Packet.dll Failed.\n");\r
1516                                 FreeLibrary(h);\r
1517                         }\r
1518                         else\r
1519                         {\r
1520                                 Debug("InitEth: Packet.dll Loaded.\n");\r
1521                         }\r
1522                 }\r
1523         }\r
1524 }\r
1525 \r
1526 // sep.sys を用いてブリッジを行っているかどうかを取得\r
1527 bool IsWin32BridgeWithSep()\r
1528 {\r
1529         return is_sep_mode;\r
1530 }\r
1531 \r
1532 // WP 構造体を DLL で初期化する\r
1533 bool InitWpWithLoadLibrary(WP *wp, HINSTANCE h)\r
1534 {\r
1535         TOKEN_LIST *o;\r
1536         // 引数チェック\r
1537         if (wp == NULL || h == NULL)\r
1538         {\r
1539                 return false;\r
1540         }\r
1541         wp->Inited = true;\r
1542         wp->hPacketDll = h;\r
1543 \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
1575 \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
1593         {\r
1594 RELEASE:\r
1595                 wp->Inited = false;\r
1596                 wp->hPacketDll = NULL;\r
1597 \r
1598                 return false;\r
1599         }\r
1600 \r
1601         o = GetEthList();\r
1602         if (o == NULL || o->NumTokens == 0)\r
1603         {\r
1604                 FreeToken(o);\r
1605                 goto RELEASE;\r
1606         }\r
1607 \r
1608         FreeToken(o);\r
1609 \r
1610         return true;\r
1611 }\r
1612 \r
1613 // Ethernet の解放\r
1614 void FreeEth()\r
1615 {\r
1616         if (wp == NULL)\r
1617         {\r
1618                 // 初期化されていない\r
1619                 return;\r
1620         }\r
1621 \r
1622         // アダプタリストの解放\r
1623         FreeEthAdaptersList();\r
1624 \r
1625         if (wp->Inited)\r
1626         {\r
1627                 // DLL 解放\r
1628                 FreeLibrary(wp->hPacketDll);\r
1629         }\r
1630 \r
1631         Free(wp);\r
1632         wp = NULL;\r
1633 \r
1634         DeleteLock(eth_list_lock);\r
1635         eth_list_lock = NULL;\r
1636 }\r
1637 \r
1638 // Ethernet デバイスに対応するネットワーク接続名を取得する\r
1639 void GetEthNetworkConnectionName(wchar_t *dst, UINT size, char *device_name)\r
1640 {\r
1641         WP_ADAPTER *t, tt;\r
1642         char *tmp = NULL, guid[MAX_SIZE];\r
1643         wchar_t *ncname = NULL;\r
1644 \r
1645         UniStrCpy(dst, size, L"");\r
1646 \r
1647         // 引数チェック\r
1648         if (device_name == NULL || IsEthSupported() == false || \r
1649                 IsNt() == false || MsIsWin2000OrGreater() == false)\r
1650         {\r
1651                 return;\r
1652         }\r
1653 \r
1654         Lock(eth_list_lock);\r
1655 \r
1656         InitEthAdaptersList();\r
1657 \r
1658         Zero(&tt, sizeof(tt));\r
1659         StrCpy(tt.Title, sizeof(tt.Title), device_name);\r
1660 \r
1661         t = Search(eth_list, &tt);\r
1662         if (t == NULL)\r
1663         {\r
1664                 Unlock(eth_list_lock);\r
1665                 return;\r
1666         }\r
1667 \r
1668         tmp = Malloc(sizeof(t->Name));\r
1669         StrCpy(tmp, sizeof(t->Name), t->Name);\r
1670         Unlock(eth_list_lock);\r
1671 \r
1672         ReplaceStr(guid, sizeof(guid), tmp, "\\Device\\SEP_", "");\r
1673         Free(tmp);\r
1674 \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
1678 \r
1679         if(guid == NULL)\r
1680         {\r
1681                 return;\r
1682         }\r
1683 \r
1684         ncname = MsGetNetworkConnectionName(guid);\r
1685         if(ncname != NULL)\r
1686         {\r
1687                 UniStrCpy(dst, size, ncname);\r
1688         }\r
1689         Free(ncname);\r
1690 }\r
1691 \r
1692 #endif  // BRIDGE_C\r
1693 \r
1694 \r