source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/VLanWin32.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: 34.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// VLanWin32.c
79// Win32 用仮想デバイスドライバライブラリ
80
81#ifdef  VLAN_C
82
83#include <windows.h>
84#include <stdio.h>
85#include <stdlib.h>
86#include <string.h>
87#include <wchar.h>
88#include <stdarg.h>
89#include <time.h>
90#include <errno.h>
91#include <Mayaqua/Mayaqua.h>
92#include <Cedar/Cedar.h>
93
94#ifdef  OS_WIN32
95
96typedef DWORD(CALLBACK* OPENVXDHANDLE)(HANDLE);
97
98// Windows のバージョン情報の取得
99void Win32GetWinVer(RPC_WINVER *v)
100{
101    // 引数チェック
102    if (v == NULL)
103    {
104        return;
105    }
106
107    Zero(v, sizeof(RPC_WINVER));
108
109    v->IsWindows = true;
110
111    if (OS_IS_WINDOWS_NT(GetOsType()) == false)
112    {
113        // Windows 9x
114        OSVERSIONINFO os;
115        Zero(&os, sizeof(os));
116        os.dwOSVersionInfoSize = sizeof(os);
117        GetVersionEx(&os);
118
119        v->Build = LOWORD(os.dwBuildNumber);
120        v->VerMajor = os.dwMajorVersion;
121        v->VerMinor = os.dwMinorVersion;
122
123        Format(v->Title, sizeof(v->Title), "%s %s",
124            GetOsInfo()->OsProductName,
125            GetOsInfo()->OsVersion);
126        Trim(v->Title);
127    }
128    else
129    {
130        // Windows NT 4.0 SP6 以降
131        OSVERSIONINFOEX os;
132        Zero(&os, sizeof(os));
133        os.dwOSVersionInfoSize = sizeof(os);
134        GetVersionEx((LPOSVERSIONINFOA)&os);
135
136        v->IsNT = true;
137        v->Build = os.dwBuildNumber;
138        v->ServicePack = os.wServicePackMajor;
139
140        if (os.wProductType != VER_NT_WORKSTATION)
141        {
142            v->IsServer = true;
143        }
144        v->VerMajor = os.dwMajorVersion;
145        v->VerMinor = os.dwMinorVersion;
146
147        if (GetOsInfo()->OsServicePack == 0)
148        {
149            StrCpy(v->Title, sizeof(v->Title), GetOsInfo()->OsProductName);
150        }
151        else
152        {
153            Format(v->Title, sizeof(v->Title), "%s Service Pack %u",
154                GetOsInfo()->OsProductName,
155                GetOsInfo()->OsServicePack);
156        }
157        Trim(v->Title);
158
159        if (InStr(GetOsInfo()->OsVersion, "rc") ||
160            InStr(GetOsInfo()->OsVersion, "beta"))
161        {
162            v->IsBeta = true;
163        }
164    }
165}
166
167// すべての仮想 LAN カードの DHCP アドレスを解放する
168void Win32ReleaseAllDhcp9x(bool wait)
169{
170    TOKEN_LIST *t;
171    UINT i;
172
173    t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");
174    if (t == NULL)
175    {
176        return;
177    }
178
179    for (i = 0;i < t->NumTokens;i++)
180    {
181        char *name = t->Token[i];
182        UINT id = GetInstanceId(name);
183        if (id != 0)
184        {
185            Win32ReleaseDhcp9x(id, wait);
186        }
187    }
188
189    FreeToken(t);
190}
191
192// ルーティングテーブル追跡メイン
193void RouteTrackingMain(SESSION *s)
194{
195    ROUTE_TRACKING *t;
196    UINT64 now;
197    ROUTE_TABLE *table;
198    ROUTE_ENTRY *rs;
199    bool changed = false;
200    bool check = false;
201    // 引数チェック
202    if (s == NULL)
203    {
204        return;
205    }
206    if (s->ClientModeAndUseVLan == false)
207    {
208        return;
209    }
210
211    // 状態の取得
212    t = ((VLAN *)s->PacketAdapter->Param)->RouteState;
213    if (t == NULL)
214    {
215        return;
216    }
217
218    // 現在時刻
219    PROBE_STR("RouteTrackingMain 1");
220    now = Tick64();
221
222    if (t->RouteChange != NULL)
223    {
224        if (t->NextRouteChangeCheckTime == 0 ||
225            t->NextRouteChangeCheckTime <= now)
226        {
227            t->NextRouteChangeCheckTime = now + 1000ULL;
228
229            check = IsRouteChanged(t->RouteChange);
230
231            if (check)
232            {
233                Debug("*** Routing Table Changed ***\n");
234                t->NextTrackingTime = 0;
235            }
236        }
237    }
238    if (t->NextTrackingTime != 0 && t->NextTrackingTime > now)
239    {
240        PROBE_STR("RouteTrackingMain 2");
241        return;
242    }
243    PROBE_STR("RouteTrackingMain 3");
244
245    // 現在のルーティングテーブルを取得
246    table = GetRouteTable();
247    rs = t->RouteToServer;
248    if (table != NULL)
249    {
250        UINT i;
251        bool route_to_server_erased = true;
252        bool is_vlan_want_to_be_default_gateway = false;
253        UINT vlan_default_gatewat_metric = 0;
254        UINT other_if_default_gateway_metric_min = INFINITE;
255
256        // ルーティングテーブルが変更されたかどうか取得
257        if (t->LastRoutingTableHash != table->HashedValue)
258        {
259            t->LastRoutingTableHash = table->HashedValue;
260            changed = true;
261        }
262
263        //DebugPrintRouteTable(table);
264
265        // ルーティングテーブルを走査
266        for (i = 0;i < table->NumEntry;i++)
267        {
268            ROUTE_ENTRY *e = table->Entry[i];
269
270            if (rs != NULL)
271            {
272                if (CmpIpAddr(&e->DestIP, &rs->DestIP) == 0 &&
273                    CmpIpAddr(&e->DestMask, &rs->DestMask) == 0
274//                  && CmpIpAddr(&e->GatewayIP, &rs->GatewayIP) == 0
275//                  && e->InterfaceID == rs->InterfaceID &&
276//                  e->LocalRouting == rs->LocalRouting &&
277//                  e->Metric == rs->Metric
278                    )
279                {
280                    // 接続時に追加したサーバーへのルーティングテーブルが見つかった
281                    route_to_server_erased = false;
282                }
283            }
284
285            // デフォルトゲートウェイの検索
286            if (IPToUINT(&e->DestIP) == 0 &&
287                IPToUINT(&e->DestMask) == 0)
288            {
289                //Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
290                //  e->InterfaceID, t->VLanInterfaceId);
291
292                if (e->InterfaceID == t->VLanInterfaceId)
293                {
294                    // 仮想 LAN カードがデフォルトゲートウェイになりたいと思っている
295                    is_vlan_want_to_be_default_gateway = true;
296                    vlan_default_gatewat_metric = e->Metric;
297
298                    if (vlan_default_gatewat_metric >= 2 &&
299                        t->OldDefaultGatewayMetric == (vlan_default_gatewat_metric - 1))
300                    {
301                        // PPP サーバーが勝手に
302                        // ルーティングテーブルを書き換えたので戻す
303                        DeleteRouteEntry(e);
304                        e->Metric--;
305                        AddRouteEntry(e);
306                        Debug("** Restore metric destroyed by PPP.\n");
307                    }
308
309                    // このエントリを保存しておく
310                    if (t->DefaultGatewayByVLan != NULL)
311                    {
312                        // 前回追加したものがあれば削除する
313                        FreeRouteEntry(t->DefaultGatewayByVLan);
314                    }
315
316                    t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY));
317                    Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY));
318
319                    t->OldDefaultGatewayMetric = vlan_default_gatewat_metric;
320                }
321                else
322                {
323                    // 仮想 LAN カード以外にデフォルトゲートウェイが存在している
324                    // このデフォルトゲートウェイのメトリック値を記録しておく
325                    if (other_if_default_gateway_metric_min > e->Metric)
326                    {
327                        // Windows Vista の場合はすべての PPP 接続のメトリック値は無視する
328                        if (MsIsVista() == false || e->PPPConnection == false)
329                        {
330                            other_if_default_gateway_metric_min = e->Metric;
331                        }
332                        else
333                        {
334                            // Windows Vista を使用しており PPP を使ってネットワーク
335                            // に接続している
336                            t->VistaAndUsingPPP = true;
337                        }
338                    }
339                }
340            }
341        }
342
343        if (t->VistaAndUsingPPP)
344        {
345            if (t->DefaultGatewayByVLan != NULL)
346            {
347                if (is_vlan_want_to_be_default_gateway)
348                {
349                    if (t->VistaOldDefaultGatewayByVLan == NULL || Cmp(t->VistaOldDefaultGatewayByVLan, t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY)) != 0)
350                    {
351                        ROUTE_ENTRY *e;
352                        // Windows Vista で PPP を使用して接続しており、かつ
353                        // 仮想 LAN カードがデフォルトゲートウェイになるべき場合は
354                        // 0.0.0.0/128.0.0.0 および 128.0.0.0/128.0.0.0 のルートを
355                        // システムに追加する
356
357                        if (t->VistaOldDefaultGatewayByVLan != NULL)
358                        {
359                            FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
360                        }
361
362                        if (t->VistaDefaultGateway1 != NULL)
363                        {
364                            DeleteRouteEntry(t->VistaDefaultGateway1);
365                            FreeRouteEntry(t->VistaDefaultGateway1);
366
367                            DeleteRouteEntry(t->VistaDefaultGateway2);
368                            FreeRouteEntry(t->VistaDefaultGateway2);
369                        }
370
371                        t->VistaOldDefaultGatewayByVLan = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
372
373                        e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
374                        SetIP(&e->DestIP, 0, 0, 0, 0);
375                        SetIP(&e->DestMask, 128, 0, 0, 0);
376                        t->VistaDefaultGateway1 = e;
377
378                        e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
379                        SetIP(&e->DestIP, 128, 0, 0, 0);
380                        SetIP(&e->DestMask, 128, 0, 0, 0);
381                        t->VistaDefaultGateway2 = e;
382
383                        AddRouteEntry(t->VistaDefaultGateway1);
384                        AddRouteEntry(t->VistaDefaultGateway2);
385
386                        Debug("Vista PPP Fix Route Table Added.\n");
387                    }
388                }
389                else
390                {
391                    if (t->VistaOldDefaultGatewayByVLan != NULL)
392                    {
393                        FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
394                        t->VistaOldDefaultGatewayByVLan = NULL;
395                    }
396
397                    if (t->VistaDefaultGateway1 != NULL)
398                    {
399                        Debug("Vista PPP Fix Route Table Deleted.\n");
400                        DeleteRouteEntry(t->VistaDefaultGateway1);
401                        FreeRouteEntry(t->VistaDefaultGateway1);
402
403                        DeleteRouteEntry(t->VistaDefaultGateway2);
404                        FreeRouteEntry(t->VistaDefaultGateway2);
405
406                        t->VistaDefaultGateway1 = t->VistaDefaultGateway2 = NULL;
407                    }
408                }
409            }
410        }
411
412        // 仮想 LAN カードがデフォルトゲートウェイになることを希望しており
413        // かつ仮想 LAN カードの 0.0.0.0/0.0.0.0 のメトリック値よりも小さなメトリック値の
414        // LAN カードが他に 1 枚も無い場合は、他のデフォルトゲートウェイエントリを削除して
415        // 仮想 LAN カードをデフォルトゲートウェイに強制的に選出する
416        if (is_vlan_want_to_be_default_gateway && (rs != NULL && route_to_server_erased == false) &&
417            other_if_default_gateway_metric_min >= vlan_default_gatewat_metric)
418        {
419            // 再度ルーティングテーブルを走査
420            for (i = 0;i < table->NumEntry;i++)
421            {
422                ROUTE_ENTRY *e = table->Entry[i];
423
424                if (e->InterfaceID != t->VLanInterfaceId)
425                {
426                    if (IPToUINT(&e->DestIP) == 0 &&
427                    IPToUINT(&e->DestMask) == 0)
428                    {
429                        char str[64];
430                        // デフォルトゲートウェイを発見
431                        ROUTE_ENTRY *r = ZeroMalloc(sizeof(ROUTE_ENTRY));
432
433                        Copy(r, e, sizeof(ROUTE_ENTRY));
434
435                        // キューに入れておく
436                        InsertQueue(t->DeletedDefaultGateway, r);
437
438                        // このゲートウェイエントリを一旦削除する
439                        DeleteRouteEntry(e);
440
441                        IPToStr(str, sizeof(str), &e->GatewayIP);
442                        Debug("Default Gateway %s Deleted.\n", str);
443                    }
444                }
445            }
446        }
447
448        if (rs != NULL && route_to_server_erased)
449        {
450            // サーバーへの物理的なエントリが消滅している
451            Debug("Route to Server entry ERASED !!!\n");
452
453            // 強制切断 (再接続有効)
454            s->RetryFlag = true;
455            s->Halt = true;
456        }
457
458        // ルーティングテーブルを解放
459        FreeRouteTable(table);
460    }
461
462    // 次回トラッキングを行う時刻を設定
463    if (t->NextTrackingTimeAdd == 0 || changed)
464    {
465        t->NextTrackingTimeAdd = TRACKING_INTERVAL_INITIAL;
466    }
467    else
468    {
469        UINT64 max_value = TRACKING_INTERVAL_MAX;
470        if (t->RouteChange != NULL)
471        {
472            max_value = TRACKING_INTERVAL_MAX_RC;
473        }
474
475        t->NextTrackingTimeAdd += TRACKING_INTERVAL_ADD;
476
477        if (t->NextTrackingTimeAdd >= max_value)
478        {
479            t->NextTrackingTimeAdd = max_value;
480        }
481    }
482    //Debug("t->NextTrackingTimeAdd = %I64u\n", t->NextTrackingTimeAdd);
483    t->NextTrackingTime = now + t->NextTrackingTimeAdd;
484}
485
486// ルーティングテーブルの追跡を開始する
487void RouteTrackingStart(SESSION *s)
488{
489    VLAN *v;
490    ROUTE_TRACKING *t;
491    UINT if_id = 0;
492    ROUTE_ENTRY *e;
493    ROUTE_ENTRY *dns = NULL;
494    char tmp[64];
495    UINT exclude_if_id = 0;
496    bool already_exists = false;
497    bool already_exists_by_other_account = false;
498    // 引数チェック
499    if (s == NULL)
500    {
501        return;
502    }
503
504    v = (VLAN *)s->PacketAdapter->Param;
505    if (v->RouteState != NULL)
506    {
507        return;
508    }
509
510    // 仮想 LAN カードのインターフェース ID を取得する
511    if_id = GetInstanceId(v->InstanceName);
512    Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id);
513
514    if (MsIsVista())
515    {
516        // Windows Vista では明示的に仮想 LAN カード本体によるルーティングテーブル
517        // を除外しなければならない
518        exclude_if_id = if_id;
519    }
520
521    // サーバーまでのルートを取得する
522    e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id);
523    if (e == NULL)
524    {
525        // 取得失敗
526        Debug("Failed to get GetBestRouteEntry().\n");
527        return;
528    }
529    IPToStr(tmp, sizeof(tmp), &e->GatewayIP);
530    Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp);
531
532    // ルートを追加する
533    if (MsIsVista())
534    {
535        e->Metric = e->OldIfMetric;
536    }
537    if (AddRouteEntryEx(e, &already_exists) == false)
538    {
539        FreeRouteEntry(e);
540        e = NULL;
541    }
542    Debug("already_exists: %u\n", already_exists);
543
544    if (already_exists)
545    {
546        if (s->Cedar->Client != NULL && s->Account != NULL)
547        {
548            UINT i;
549            ACCOUNT *a;
550            for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
551            {
552                a = LIST_DATA(s->Cedar->Client->AccountList, i);
553                Lock(a->lock);
554                {
555                    SESSION *sess = a->ClientSession;
556                    if (sess != NULL && sess != s)
557                    {
558                        VLAN *v = sess->PacketAdapter->Param;
559                        if (v != NULL)
560                        {
561                            ROUTE_TRACKING *tr = v->RouteState;
562                            if (tr != NULL && e != NULL)
563                            {
564                                if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0)
565                                {
566                                    already_exists_by_other_account = true;
567                                }
568                            }
569                        }
570                    }
571                }
572                Unlock(a->lock);
573            }
574        }
575
576        if (already_exists_by_other_account)
577        {
578            Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account);
579            already_exists = false;
580        }
581    }
582
583    // DNS サーバーまでのルーティングテーブルを取得する
584    dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id);
585    if (dns == NULL)
586    {
587        // 取得失敗
588        Debug("Failed to get GetBestRouteEntry DNS.\n");
589    }
590    else
591    {
592        // ルートを追加する
593        if (MsIsVista())
594        {
595            dns->Metric = dns->OldIfMetric;
596
597            if (AddRouteEntry(dns) == false)
598            {
599                FreeRouteEntry(dns);
600                dns = NULL;
601            }
602        }
603    }
604
605    // 初期化
606    if (s->Cedar->Client != NULL && s->Account != NULL)
607    {
608        Lock(s->Account->lock);
609    }
610
611    t = ZeroMalloc(sizeof(ROUTE_TRACKING));
612    v->RouteState = t;
613
614    t->RouteToServerAlreadyExists = already_exists;
615    t->RouteToServer = e;
616    t->RouteToDefaultDns = dns;
617    t->VLanInterfaceId = if_id;
618    t->NextTrackingTime = 0;
619    t->DeletedDefaultGateway = NewQueue();
620    t->OldDefaultGatewayMetric = 0x7fffffff;
621
622    if (s->Cedar->Client != NULL && s->Account != NULL)
623    {
624        Unlock(s->Account->lock);
625    }
626
627    // ネットワーク変更を検出するために
628    // 現在のデフォルト DNS サーバーを取得しておく
629    GetDefaultDns(&t->OldDnsServer);
630
631    // DHCP を使用する場合は IP アドレスを解放してすぐに取得する
632    if (IsNt())
633    {
634        char tmp[MAX_SIZE];
635        MS_ADAPTER *a;
636
637        Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
638        a = MsGetAdapter(tmp);
639
640        if (a != NULL)
641        {
642            if (a->UseDhcp)
643            {
644                bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100);
645                Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret);
646
647                ret = Win32RenewAddressByGuidEx(a->Guid, 100);
648                Debug("*** Win32RenewAddressByGuidEx = %u\n", ret);
649            }
650
651            MsFreeAdapter(a);
652        }
653    }
654    else
655    {
656        // Win9x の場合
657        Win32RenewDhcp9x(if_id);
658    }
659
660    // ルーティングテーブルの変更を検出 (対応 OS のみ)
661    t->RouteChange = NewRouteChange();
662    Debug("t->RouteChange = 0x%p\n", t->RouteChange);
663}
664
665// ルーティングテーブルの追跡を終了する
666void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t)
667{
668    ROUTE_ENTRY *e;
669    ROUTE_TABLE *table;
670    IP dns_ip;
671    bool network_has_changed = false;
672    bool do_not_delete_routing_entry = false;
673    // 引数チェック
674    if (s == NULL || t == NULL)
675    {
676        return;
677    }
678
679    Zero(&dns_ip, sizeof(dns_ip));
680
681    // 仮想 LAN カードが追加したデフォルトゲートウェイを削除する
682    if (t->DefaultGatewayByVLan != NULL)
683    {
684        Debug("Default Gateway by VLAN was deleted.\n");
685        DeleteRouteEntry(t->DefaultGatewayByVLan);
686        FreeRouteEntry(t->DefaultGatewayByVLan);
687        t->DefaultGatewayByVLan = NULL;
688    }
689
690    if (t->VistaOldDefaultGatewayByVLan != NULL)
691    {
692        FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
693    }
694
695    if (t->VistaDefaultGateway1 != NULL)
696    {
697        Debug("Vista PPP Fix Route Table Deleted.\n");
698        DeleteRouteEntry(t->VistaDefaultGateway1);
699        FreeRouteEntry(t->VistaDefaultGateway1);
700
701        DeleteRouteEntry(t->VistaDefaultGateway2);
702        FreeRouteEntry(t->VistaDefaultGateway2);
703    }
704
705    if (MsIsNt() == false)
706    {
707        // Windows 9x の場合のみ、仮想 LAN カードの DHCP アドレスを解放する
708        Win32ReleaseDhcp9x(t->VLanInterfaceId, false);
709    }
710
711    if (s->Cedar->Client != NULL && s->Account != NULL)
712    {
713        UINT i;
714        ACCOUNT *a;
715        for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
716        {
717            a = LIST_DATA(s->Cedar->Client->AccountList, i);
718            Lock(a->lock);
719            {
720                SESSION *sess = a->ClientSession;
721                if (sess != NULL && sess != s)
722                {
723                    VLAN *v = sess->PacketAdapter->Param;
724                    if (v != NULL)
725                    {
726                        ROUTE_TRACKING *tr = v->RouteState;
727                        if (tr != NULL)
728                        {
729                            if (Cmp(tr->RouteToServer, t->RouteToServer, sizeof(ROUTE_ENTRY)) == 0)
730                            {
731                                do_not_delete_routing_entry = true;
732                            }
733                        }
734                    }
735                }
736            }
737            Unlock(a->lock);
738        }
739
740        Lock(s->Account->lock);
741    }
742
743    if (do_not_delete_routing_entry == false)
744    {
745        // 最初に追加したルートを削除する
746        if (t->RouteToServerAlreadyExists == false)
747        {
748            DeleteRouteEntry(t->RouteToServer);
749        }
750
751        DeleteRouteEntry(t->RouteToDefaultDns);
752    }
753
754    FreeRouteEntry(t->RouteToDefaultDns);
755    FreeRouteEntry(t->RouteToServer);
756    t->RouteToDefaultDns = t->RouteToServer = NULL;
757
758    if (s->Cedar->Client != NULL && s->Account != NULL)
759    {
760        Unlock(s->Account->lock);
761    }
762
763#if 0
764    // 現在の DNS サーバーを取得する
765    if (GetDefaultDns(&dns_ip))
766    {
767        if (IPToUINT(&t->OldDnsServer) != 0)
768        {
769            if (IPToUINT(&t->OldDnsServer) != IPToUINT(&dns_ip))
770            {
771                char s1[MAX_SIZE], s2[MAX_SIZE];
772                network_has_changed = true;
773                IPToStr(s1, sizeof(s1), &t->OldDnsServer);
774                IPToStr(s2, sizeof(s2), &dns_ip);
775                Debug("Old Dns: %s, New Dns: %s\n",
776                    s1, s2);
777            }
778        }
779    }
780
781    if (network_has_changed == false)
782    {
783        Debug("Network: not changed.\n");
784    }
785    else
786    {
787        Debug("Network: Changed.\n");
788    }
789
790#endif
791
792    // 現在のルーティングテーブルを取得する
793    table = GetRouteTable();
794
795    // これまで削除してきたルーティングテーブルを復元する
796    while (e = GetNext(t->DeletedDefaultGateway))
797    {
798        bool restore = true;
799        UINT i;
800        // 復元しようとしているルーティングテーブルがデフォルトゲートウェイの場合
801        // かつ既存のルーティングテーブルでそのインターフェースによるデフォルト
802        // ルートが 1 つでも登録されている場合は復元しない
803        if (IPToUINT(&e->DestIP) == 0 && IPToUINT(&e->DestMask) == 0)
804        {
805            for (i = 0;i < table->NumEntry;i++)
806            {
807                ROUTE_ENTRY *r = table->Entry[i];
808                if (IPToUINT(&r->DestIP) == 0 && IPToUINT(&r->DestMask) == 0)
809                {
810                    if (r->InterfaceID == e->InterfaceID)
811                    {
812                        restore = false;
813                    }
814                }
815            }
816            if (network_has_changed)
817            {
818                restore = false;
819            }
820        }
821
822        if (restore)
823        {
824            // ルーティングテーブル復元
825            AddRouteEntry(e);
826        }
827
828        // メモリ解放
829        FreeRouteEntry(e);
830    }
831
832    // 解放
833    FreeRouteTable(table);
834    ReleaseQueue(t->DeletedDefaultGateway);
835
836    FreeRouteChange(t->RouteChange);
837
838    Free(t);
839}
840
841// 仮想 LAN カードのインスタンス ID を取得する
842UINT GetInstanceId(char *name)
843{
844    char tmp[MAX_SIZE];
845    UINT id = 0;
846    // 引数チェック
847    if (name == NULL)
848    {
849        return 0;
850    }
851
852    Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, name);
853
854    id = GetVLanInterfaceID(tmp);
855    if (id != 0)
856    {
857        return id;
858    }
859
860    return 0;
861}
862
863// 仮想 LAN カードのインスタンスリストを取得する
864INSTANCE_LIST *GetInstanceList()
865{
866    INSTANCE_LIST *n = ZeroMalloc(sizeof(INSTANCE_LIST));
867
868    // 列挙
869    char **ss = EnumVLan(VLAN_ADAPTER_NAME);
870
871    if (ss == NULL)
872    {
873        // 失敗
874        n->NumInstance = 0;
875        n->InstanceName = Malloc(0);
876        return n;
877    }
878    else
879    {
880        UINT i, num;
881        i = num = 0;
882        while (true)
883        {
884            if (ss[i++] == NULL)
885            {
886                break;
887            }
888            num++;
889        }
890        i = 0;
891        n->NumInstance = num;
892        n->InstanceName = (char **)ZeroMalloc(sizeof(char *) * n->NumInstance);
893        for (i = 0;i < num;i++)
894        {
895            char *s = ss[i] + StrLen(VLAN_ADAPTER_NAME) + StrLen(" - ");
896            if (StrLen(ss[i]) > StrLen(VLAN_ADAPTER_NAME) + StrLen(" - "))
897            {
898                n->InstanceName[i] = CopyStr(s);
899            }
900        }
901        FreeEnumVLan(ss);
902    }
903
904    return n;
905}
906
907// インスタンスリストを解放する
908void FreeInstanceList(INSTANCE_LIST *n)
909{
910    UINT i;
911    // 引数チェック
912    if (n == NULL)
913    {
914        return;
915    }
916
917    for (i = 0;i < n->NumInstance;i++)
918    {
919        Free(n->InstanceName[i]);
920    }
921    Free(n->InstanceName);
922    Free(n);
923}
924
925// パケットアダプタの解放
926void VLanPaFree(SESSION *s)
927{
928    VLAN *v;
929    ROUTE_TRACKING *t;
930    // 引数チェック
931    if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
932    {
933        return;
934    }
935
936    // DHCP を使用している場合は IP アドレスを解放する
937    if (IsNt())
938    {
939        char tmp[MAX_SIZE];
940        MS_ADAPTER *a;
941
942        Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
943        a = MsGetAdapter(tmp);
944
945        if (a != NULL)
946        {
947            if (a->UseDhcp)
948            {
949                bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 50);
950                Debug("*** Win32ReleaseAddressByGuid = %u\n", ret);
951            }
952
953            MsFreeAdapter(a);
954        }
955    }
956
957    t = v->RouteState;
958    // 仮想 LAN カードの終了
959    FreeVLan(v);
960
961    // ルーティングテーブル追跡終了
962    if (s->ClientModeAndUseVLan)
963    {
964        RouteTrackingStop(s, t);
965    }
966    s->PacketAdapter->Param = NULL;
967}
968
969
970// パケットの書き込み
971bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
972{
973    VLAN *v;
974    // 引数チェック
975    if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
976    {
977        return false;
978    }
979
980    return VLanPutPacket(v, data, size);
981}
982
983// 次のパケットを取得
984UINT VLanPaGetNextPacket(SESSION *s, void **data)
985{
986    VLAN *v;
987    UINT size;
988    // 引数チェック
989    if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
990    {
991        return 0;
992    }
993
994    RouteTrackingMain(s);
995
996    if (VLanGetNextPacket(v, data, &size) == false)
997    {
998        return INFINITE;
999    }
1000
1001    return size;
1002}
1003
1004// キャンセルオブジェクトの取得
1005CANCEL *VLanPaGetCancel(SESSION *s)
1006{
1007    VLAN *v;
1008    // 引数チェック
1009    if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
1010    {
1011        return NULL;
1012    }
1013
1014    return VLanGetCancel(v);
1015}
1016
1017// パケットアダプタ初期化
1018bool VLanPaInit(SESSION *s)
1019{
1020    VLAN *v;
1021    // 引数チェック
1022    if ((s == NULL)/* || (s->ServerMode != false) || (s->ClientOption == NULL)*/)
1023    {
1024        return false;
1025    }
1026
1027    // 接続直前の DNS サーバーの IP アドレスの取得
1028    if (s->ClientModeAndUseVLan)
1029    {
1030        Zero(&s->DefaultDns, sizeof(IP));
1031        GetDefaultDns(&s->DefaultDns);
1032    }
1033
1034    // ドライバに接続
1035    v = NewVLan(s->ClientOption->DeviceName, NULL);
1036    if (v == NULL)
1037    {
1038        // 失敗
1039        return false;
1040    }
1041
1042    s->PacketAdapter->Param = v;
1043
1044    // ルーティングテーブル追跡開始
1045    if (s->ClientModeAndUseVLan)
1046    {
1047        RouteTrackingStart(s);
1048    }
1049
1050    return true;
1051}
1052
1053// VLAN のパケットアダプタを取得
1054PACKET_ADAPTER *VLanGetPacketAdapter()
1055{
1056    PACKET_ADAPTER *pa;
1057
1058    pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
1059        VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
1060    if (pa == NULL)
1061    {
1062        return NULL;
1063    }
1064
1065    return pa;
1066}
1067
1068
1069// 次の受信パケットをドライバに書き込む
1070bool VLanPutPacket(VLAN *v, void *buf, UINT size)
1071{
1072    // 引数チェック
1073    if (v == NULL)
1074    {
1075        return false;
1076    }
1077    if (v->Halt)
1078    {
1079        return false;
1080    }
1081    if (size > MAX_PACKET_SIZE)
1082    {
1083        return false;
1084    }
1085
1086    // まず、現在のバッファが一杯になっているかどうか調べる
1087    if ((SEN_NUM_PACKET(v->PutBuffer) >= SEN_MAX_PACKET_EXCHANGE) ||
1088        (buf == NULL && SEN_NUM_PACKET(v->PutBuffer) != 0))
1089    {
1090#ifdef  USE_PROBE
1091        {
1092            char tmp[MAX_SIZE];
1093            snprintf(tmp, sizeof(tmp), "VLanPutPacket: SEN_NUM_PACKET(v->PutBuffer) = %u", SEN_NUM_PACKET(v->PutBuffer));
1094            PROBE_DATA2(tmp, NULL, 0);
1095        }
1096#endif  // USE_PROBE
1097        // パケットをドライバに書き出す
1098        if (VLanPutPacketsToDriver(v) == false)
1099        {
1100            return false;
1101        }
1102        SEN_NUM_PACKET(v->PutBuffer) = 0;
1103    }
1104
1105    // 次のパケットをバッファに追加する
1106    if (buf != NULL)
1107    {
1108        UINT i = SEN_NUM_PACKET(v->PutBuffer);
1109        SEN_NUM_PACKET(v->PutBuffer)++;
1110
1111        SEN_SIZE_OF_PACKET(v->PutBuffer, i) = size;
1112        Copy(SEN_ADDR_OF_PACKET(v->PutBuffer, i), buf, size);
1113        Free(buf);
1114    }
1115
1116    return true;
1117}
1118
1119// 次の送信パケットをドライバから読み出す
1120bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
1121{
1122    // 引数チェック
1123    if (v == NULL || buf == NULL || size == NULL)
1124    {
1125        return false;
1126    }
1127    if (v->Halt)
1128    {
1129        return false;
1130    }
1131
1132    PROBE_STR("VLanGetNextPacket");
1133
1134    while (true)
1135    {
1136        if (v->CurrentPacketCount < SEN_NUM_PACKET(v->GetBuffer))
1137        {
1138            // すでに読み込まれたパケットがまだ残っている
1139            *size = SEN_SIZE_OF_PACKET(v->GetBuffer, v->CurrentPacketCount);
1140            *buf = MallocFast(*size);
1141            Copy(*buf, SEN_ADDR_OF_PACKET(v->GetBuffer, v->CurrentPacketCount), *size);
1142
1143            // パケット番号をインクリメントする
1144            v->CurrentPacketCount++;
1145
1146            return true;
1147        }
1148        else
1149        {
1150            // 次のパケットをドライバから読み込む
1151            if (VLanGetPacketsFromDriver(v) == false)
1152            {
1153                return false;
1154            }
1155
1156            if (SEN_NUM_PACKET(v->GetBuffer) == 0)
1157            {
1158                // 現在パケットは届いていない
1159                *buf = NULL;
1160                *size = 0;
1161                return true;
1162            }
1163
1164            v->CurrentPacketCount = 0;
1165        }
1166    }
1167}
1168
1169// ドライバに現在のすべてのパケットを書き込む
1170bool VLanPutPacketsToDriver(VLAN *v)
1171{
1172    DWORD write_size;
1173    // 引数チェック
1174    if (v == NULL)
1175    {
1176        return false;
1177    }
1178    if (v->Halt)
1179    {
1180        return false;
1181    }
1182
1183    if (v->Win9xMode == false)
1184    {
1185        // Windows NT
1186        PROBE_STR("VLanPutPacketsToDriver: WriteFile");
1187        if (WriteFile(v->Handle, v->PutBuffer, SEN_EXCHANGE_BUFFER_SIZE, &write_size,
1188            NULL) == false)
1189        {
1190            v->Halt = true;
1191            return false;
1192        }
1193        PROBE_STR("VLanPutPacketsToDriver: WriteFile Completed.");
1194
1195        if (write_size != SEN_EXCHANGE_BUFFER_SIZE)
1196        {
1197            v->Halt = true;
1198            return false;
1199        }
1200    }
1201    else
1202    {
1203        // Windows 9x
1204        if (DeviceIoControl(v->Handle, SEN_IOCTL_PUT_PACKET, v->PutBuffer,
1205            SEN_EXCHANGE_BUFFER_SIZE, NULL, 0, &write_size, NULL) == false)
1206        {
1207            v->Halt = true;
1208            return false;
1209        }
1210    }
1211
1212    return true;
1213}
1214
1215// ドライバから次のパケットを読み込む
1216bool VLanGetPacketsFromDriver(VLAN *v)
1217{
1218    DWORD read_size;
1219    // 引数チェック
1220    if (v == NULL)
1221    {
1222        return false;
1223    }
1224    if (v->Halt)
1225    {
1226        return false;
1227    }
1228
1229    if (v->Win9xMode == false)
1230    {
1231        // Windows NT
1232        PROBE_STR("VLanGetPacketsFromDriver: ReadFile");
1233        if (ReadFile(v->Handle, v->GetBuffer, SEN_EXCHANGE_BUFFER_SIZE,
1234            &read_size, NULL) == false)
1235        {
1236            v->Halt = true;
1237            return false;
1238        }
1239    }
1240    else
1241    {
1242        // Windows 9x
1243        if (DeviceIoControl(v->Handle, SEN_IOCTL_GET_PACKET, NULL, 0,
1244            v->GetBuffer, SEN_EXCHANGE_BUFFER_SIZE, &read_size, NULL) == false)
1245        {
1246            v->Halt = true;
1247            return false;
1248        }
1249    }
1250
1251    if (read_size != SEN_EXCHANGE_BUFFER_SIZE)
1252    {
1253        v->Halt = true;
1254        return false;
1255    }
1256
1257    return true;
1258}
1259
1260// キャンセルオブジェクトの取得
1261CANCEL *VLanGetCancel(VLAN *v)
1262{
1263    CANCEL *c;
1264    // 引数チェック
1265    if (v == NULL)
1266    {
1267        return NULL;
1268    }
1269
1270    // キャンセルオブジェクトの作成
1271    c = NewCancel();
1272    c->SpecialFlag = true;
1273    CloseHandle(c->hEvent);
1274
1275    c->hEvent = v->Event;
1276
1277    return c;
1278}
1279
1280// VLAN オブジェクトの解放
1281void FreeVLan(VLAN *v)
1282{
1283    // 引数チェック
1284    if (v == NULL)
1285    {
1286        return;
1287    }
1288
1289    // ハンドルを閉じる
1290    CloseHandle(v->Event);
1291    CloseHandle(v->Handle);
1292
1293    // メモリ解放
1294    Free(v->InstanceName);
1295    Free(v->EventNameWin32);
1296    Free(v->DeviceNameWin32);
1297    Free(v->PutBuffer);
1298    Free(v->GetBuffer);
1299    Free(v);
1300}
1301
1302// VLAN オブジェクトの作成
1303VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
1304{
1305    VLAN *v;
1306    HANDLE h = INVALID_HANDLE_VALUE;
1307    HANDLE e = INVALID_HANDLE_VALUE;
1308    char tmp[MAX_SIZE];
1309    char name_upper[MAX_SIZE];
1310    // 引数チェック
1311    if (instance_name == NULL)
1312    {
1313        return NULL;
1314    }
1315
1316    v = ZeroMalloc(sizeof(VLAN));
1317
1318    if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
1319    {
1320        v->Win9xMode = true;
1321    }
1322
1323    // 名前の初期化
1324    Format(name_upper, sizeof(name_upper), "%s", instance_name);
1325    StrUpper(name_upper);
1326    v->InstanceName = CopyStr(name_upper);
1327    Format(tmp, sizeof(tmp), NDIS_SEN_DEVICE_FILE_NAME, v->InstanceName);
1328    v->DeviceNameWin32 = CopyStr(tmp);
1329
1330    if (v->Win9xMode == false)
1331    {
1332        Format(tmp, sizeof(tmp), NDIS_SEN_EVENT_NAME_WIN32, v->InstanceName);
1333        v->EventNameWin32 = CopyStr(tmp);
1334    }
1335
1336    // デバイスに接続
1337    h = CreateFile(v->DeviceNameWin32,
1338        GENERIC_READ | GENERIC_WRITE,
1339        0,
1340        NULL,
1341        OPEN_EXISTING,
1342        0,
1343        NULL);
1344    if (h == INVALID_HANDLE_VALUE)
1345    {
1346        // 接続失敗
1347        goto CLEANUP;
1348    }
1349
1350    if (v->Win9xMode == false)
1351    {
1352        // イベントに接続
1353        e = OpenEvent(SYNCHRONIZE, FALSE, v->EventNameWin32);
1354        if (e == INVALID_HANDLE_VALUE)
1355        {
1356            // 接続失敗
1357            goto CLEANUP;
1358        }
1359    }
1360    else
1361    {
1362        OPENVXDHANDLE OpenVxDHandle;
1363        DWORD vxd_handle;
1364        UINT bytes_returned;
1365
1366        OpenVxDHandle = (OPENVXDHANDLE)GetProcAddress(GetModuleHandleA("KERNEL32"),
1367            "OpenVxDHandle");
1368
1369        // イベントを作成してドライバに渡す
1370        e = CreateEvent(NULL, FALSE, FALSE, NULL);
1371        vxd_handle = (DWORD)OpenVxDHandle(e);
1372
1373        DeviceIoControl(h, SEN_IOCTL_SET_EVENT, &vxd_handle, sizeof(DWORD),
1374            NULL, 0, &bytes_returned, NULL);
1375    }
1376
1377    v->Event = e;
1378    v->Handle = h;
1379
1380    v->GetBuffer = ZeroMalloc(SEN_EXCHANGE_BUFFER_SIZE);
1381    v->PutBuffer = ZeroMalloc(SEN_EXCHANGE_BUFFER_SIZE);
1382
1383    return v;
1384
1385CLEANUP:
1386    if (h != INVALID_HANDLE_VALUE)
1387    {
1388        CloseHandle(h);
1389    }
1390    if (e != INVALID_HANDLE_VALUE)
1391    {
1392        CloseHandle(e);
1393    }
1394
1395    Free(v->InstanceName);
1396    Free(v->EventNameWin32);
1397    Free(v->DeviceNameWin32);
1398    Free(v);
1399
1400    return NULL;
1401}
1402
1403#endif  // OS_WIN32
1404
1405#endif  //VLAN_C
1406
Note: See TracBrowser for help on using the repository browser.