source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/BridgeWin32.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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