1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
79 // Win32 用仮想デバイスドライバライブラリ
\r
83 #include <windows.h>
\r
91 #include <Mayaqua/Mayaqua.h>
\r
92 #include <Cedar/Cedar.h>
\r
96 typedef DWORD(CALLBACK* OPENVXDHANDLE)(HANDLE);
\r
98 // Windows のバージョン情報の取得
\r
99 void Win32GetWinVer(RPC_WINVER *v)
\r
107 Zero(v, sizeof(RPC_WINVER));
\r
109 v->IsWindows = true;
\r
111 if (OS_IS_WINDOWS_NT(GetOsType()) == false)
\r
115 Zero(&os, sizeof(os));
\r
116 os.dwOSVersionInfoSize = sizeof(os);
\r
119 v->Build = LOWORD(os.dwBuildNumber);
\r
120 v->VerMajor = os.dwMajorVersion;
\r
121 v->VerMinor = os.dwMinorVersion;
\r
123 Format(v->Title, sizeof(v->Title), "%s %s",
\r
124 GetOsInfo()->OsProductName,
\r
125 GetOsInfo()->OsVersion);
\r
130 // Windows NT 4.0 SP6 以降
\r
131 OSVERSIONINFOEX os;
\r
132 Zero(&os, sizeof(os));
\r
133 os.dwOSVersionInfoSize = sizeof(os);
\r
134 GetVersionEx((LPOSVERSIONINFOA)&os);
\r
137 v->Build = os.dwBuildNumber;
\r
138 v->ServicePack = os.wServicePackMajor;
\r
140 if (os.wProductType != VER_NT_WORKSTATION)
\r
142 v->IsServer = true;
\r
144 v->VerMajor = os.dwMajorVersion;
\r
145 v->VerMinor = os.dwMinorVersion;
\r
147 if (GetOsInfo()->OsServicePack == 0)
\r
149 StrCpy(v->Title, sizeof(v->Title), GetOsInfo()->OsProductName);
\r
153 Format(v->Title, sizeof(v->Title), "%s Service Pack %u",
\r
154 GetOsInfo()->OsProductName,
\r
155 GetOsInfo()->OsServicePack);
\r
159 if (InStr(GetOsInfo()->OsVersion, "rc") ||
\r
160 InStr(GetOsInfo()->OsVersion, "beta"))
\r
167 // すべての仮想 LAN カードの DHCP アドレスを解放する
\r
168 void Win32ReleaseAllDhcp9x(bool wait)
\r
173 t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, "---dummy-string-ut--");
\r
179 for (i = 0;i < t->NumTokens;i++)
\r
181 char *name = t->Token[i];
\r
182 UINT id = GetInstanceId(name);
\r
185 Win32ReleaseDhcp9x(id, wait);
\r
193 void RouteTrackingMain(SESSION *s)
\r
197 ROUTE_TABLE *table;
\r
199 bool changed = false;
\r
200 bool check = false;
\r
206 if (s->ClientModeAndUseVLan == false)
\r
212 t = ((VLAN *)s->PacketAdapter->Param)->RouteState;
\r
219 PROBE_STR("RouteTrackingMain 1");
\r
222 if (t->RouteChange != NULL)
\r
224 if (t->NextRouteChangeCheckTime == 0 ||
\r
225 t->NextRouteChangeCheckTime <= now)
\r
227 t->NextRouteChangeCheckTime = now + 1000ULL;
\r
229 check = IsRouteChanged(t->RouteChange);
\r
233 Debug("*** Routing Table Changed ***\n");
\r
234 t->NextTrackingTime = 0;
\r
238 if (t->NextTrackingTime != 0 && t->NextTrackingTime > now)
\r
240 PROBE_STR("RouteTrackingMain 2");
\r
243 PROBE_STR("RouteTrackingMain 3");
\r
245 // 現在のルーティングテーブルを取得
\r
246 table = GetRouteTable();
\r
247 rs = t->RouteToServer;
\r
251 bool route_to_server_erased = true;
\r
252 bool is_vlan_want_to_be_default_gateway = false;
\r
253 UINT vlan_default_gatewat_metric = 0;
\r
254 UINT other_if_default_gateway_metric_min = INFINITE;
\r
256 // ルーティングテーブルが変更されたかどうか取得
\r
257 if (t->LastRoutingTableHash != table->HashedValue)
\r
259 t->LastRoutingTableHash = table->HashedValue;
\r
263 //DebugPrintRouteTable(table);
\r
266 for (i = 0;i < table->NumEntry;i++)
\r
268 ROUTE_ENTRY *e = table->Entry[i];
\r
272 if (CmpIpAddr(&e->DestIP, &rs->DestIP) == 0 &&
\r
273 CmpIpAddr(&e->DestMask, &rs->DestMask) == 0
\r
274 // && CmpIpAddr(&e->GatewayIP, &rs->GatewayIP) == 0
\r
275 // && e->InterfaceID == rs->InterfaceID &&
\r
276 // e->LocalRouting == rs->LocalRouting &&
\r
277 // e->Metric == rs->Metric
\r
280 // 接続時に追加したサーバーへのルーティングテーブルが見つかった
\r
281 route_to_server_erased = false;
\r
286 if (IPToUINT(&e->DestIP) == 0 &&
\r
287 IPToUINT(&e->DestMask) == 0)
\r
289 //Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
\r
290 // e->InterfaceID, t->VLanInterfaceId);
\r
292 if (e->InterfaceID == t->VLanInterfaceId)
\r
294 // 仮想 LAN カードがデフォルトゲートウェイになりたいと思っている
\r
295 is_vlan_want_to_be_default_gateway = true;
\r
296 vlan_default_gatewat_metric = e->Metric;
\r
298 if (vlan_default_gatewat_metric >= 2 &&
\r
299 t->OldDefaultGatewayMetric == (vlan_default_gatewat_metric - 1))
\r
302 // ルーティングテーブルを書き換えたので戻す
\r
303 DeleteRouteEntry(e);
\r
306 Debug("** Restore metric destroyed by PPP.\n");
\r
310 if (t->DefaultGatewayByVLan != NULL)
\r
312 // 前回追加したものがあれば削除する
\r
313 FreeRouteEntry(t->DefaultGatewayByVLan);
\r
316 t->DefaultGatewayByVLan = ZeroMalloc(sizeof(ROUTE_ENTRY));
\r
317 Copy(t->DefaultGatewayByVLan, e, sizeof(ROUTE_ENTRY));
\r
319 t->OldDefaultGatewayMetric = vlan_default_gatewat_metric;
\r
323 // 仮想 LAN カード以外にデフォルトゲートウェイが存在している
\r
324 // このデフォルトゲートウェイのメトリック値を記録しておく
\r
325 if (other_if_default_gateway_metric_min > e->Metric)
\r
327 // Windows Vista の場合はすべての PPP 接続のメトリック値は無視する
\r
328 if (MsIsVista() == false || e->PPPConnection == false)
\r
330 other_if_default_gateway_metric_min = e->Metric;
\r
334 // Windows Vista を使用しており PPP を使ってネットワーク
\r
336 t->VistaAndUsingPPP = true;
\r
343 if (t->VistaAndUsingPPP)
\r
345 if (t->DefaultGatewayByVLan != NULL)
\r
347 if (is_vlan_want_to_be_default_gateway)
\r
349 if (t->VistaOldDefaultGatewayByVLan == NULL || Cmp(t->VistaOldDefaultGatewayByVLan, t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY)) != 0)
\r
352 // Windows Vista で PPP を使用して接続しており、かつ
\r
353 // 仮想 LAN カードがデフォルトゲートウェイになるべき場合は
\r
354 // 0.0.0.0/128.0.0.0 および 128.0.0.0/128.0.0.0 のルートを
\r
357 if (t->VistaOldDefaultGatewayByVLan != NULL)
\r
359 FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
\r
362 if (t->VistaDefaultGateway1 != NULL)
\r
364 DeleteRouteEntry(t->VistaDefaultGateway1);
\r
365 FreeRouteEntry(t->VistaDefaultGateway1);
\r
367 DeleteRouteEntry(t->VistaDefaultGateway2);
\r
368 FreeRouteEntry(t->VistaDefaultGateway2);
\r
371 t->VistaOldDefaultGatewayByVLan = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
\r
373 e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
\r
374 SetIP(&e->DestIP, 0, 0, 0, 0);
\r
375 SetIP(&e->DestMask, 128, 0, 0, 0);
\r
376 t->VistaDefaultGateway1 = e;
\r
378 e = Clone(t->DefaultGatewayByVLan, sizeof(ROUTE_ENTRY));
\r
379 SetIP(&e->DestIP, 128, 0, 0, 0);
\r
380 SetIP(&e->DestMask, 128, 0, 0, 0);
\r
381 t->VistaDefaultGateway2 = e;
\r
383 AddRouteEntry(t->VistaDefaultGateway1);
\r
384 AddRouteEntry(t->VistaDefaultGateway2);
\r
386 Debug("Vista PPP Fix Route Table Added.\n");
\r
391 if (t->VistaOldDefaultGatewayByVLan != NULL)
\r
393 FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
\r
394 t->VistaOldDefaultGatewayByVLan = NULL;
\r
397 if (t->VistaDefaultGateway1 != NULL)
\r
399 Debug("Vista PPP Fix Route Table Deleted.\n");
\r
400 DeleteRouteEntry(t->VistaDefaultGateway1);
\r
401 FreeRouteEntry(t->VistaDefaultGateway1);
\r
403 DeleteRouteEntry(t->VistaDefaultGateway2);
\r
404 FreeRouteEntry(t->VistaDefaultGateway2);
\r
406 t->VistaDefaultGateway1 = t->VistaDefaultGateway2 = NULL;
\r
412 // 仮想 LAN カードがデフォルトゲートウェイになることを希望しており
\r
413 // かつ仮想 LAN カードの 0.0.0.0/0.0.0.0 のメトリック値よりも小さなメトリック値の
\r
414 // LAN カードが他に 1 枚も無い場合は、他のデフォルトゲートウェイエントリを削除して
\r
415 // 仮想 LAN カードをデフォルトゲートウェイに強制的に選出する
\r
416 if (is_vlan_want_to_be_default_gateway && (rs != NULL && route_to_server_erased == false) &&
\r
417 other_if_default_gateway_metric_min >= vlan_default_gatewat_metric)
\r
420 for (i = 0;i < table->NumEntry;i++)
\r
422 ROUTE_ENTRY *e = table->Entry[i];
\r
424 if (e->InterfaceID != t->VLanInterfaceId)
\r
426 if (IPToUINT(&e->DestIP) == 0 &&
\r
427 IPToUINT(&e->DestMask) == 0)
\r
431 ROUTE_ENTRY *r = ZeroMalloc(sizeof(ROUTE_ENTRY));
\r
433 Copy(r, e, sizeof(ROUTE_ENTRY));
\r
436 InsertQueue(t->DeletedDefaultGateway, r);
\r
438 // このゲートウェイエントリを一旦削除する
\r
439 DeleteRouteEntry(e);
\r
441 IPToStr(str, sizeof(str), &e->GatewayIP);
\r
442 Debug("Default Gateway %s Deleted.\n", str);
\r
448 if (rs != NULL && route_to_server_erased)
\r
450 // サーバーへの物理的なエントリが消滅している
\r
451 Debug("Route to Server entry ERASED !!!\n");
\r
454 s->RetryFlag = true;
\r
459 FreeRouteTable(table);
\r
462 // 次回トラッキングを行う時刻を設定
\r
463 if (t->NextTrackingTimeAdd == 0 || changed)
\r
465 t->NextTrackingTimeAdd = TRACKING_INTERVAL_INITIAL;
\r
469 UINT64 max_value = TRACKING_INTERVAL_MAX;
\r
470 if (t->RouteChange != NULL)
\r
472 max_value = TRACKING_INTERVAL_MAX_RC;
\r
475 t->NextTrackingTimeAdd += TRACKING_INTERVAL_ADD;
\r
477 if (t->NextTrackingTimeAdd >= max_value)
\r
479 t->NextTrackingTimeAdd = max_value;
\r
482 //Debug("t->NextTrackingTimeAdd = %I64u\n", t->NextTrackingTimeAdd);
\r
483 t->NextTrackingTime = now + t->NextTrackingTimeAdd;
\r
486 // ルーティングテーブルの追跡を開始する
\r
487 void RouteTrackingStart(SESSION *s)
\r
493 ROUTE_ENTRY *dns = NULL;
\r
495 UINT exclude_if_id = 0;
\r
496 bool already_exists = false;
\r
497 bool already_exists_by_other_account = false;
\r
504 v = (VLAN *)s->PacketAdapter->Param;
\r
505 if (v->RouteState != NULL)
\r
510 // 仮想 LAN カードのインターフェース ID を取得する
\r
511 if_id = GetInstanceId(v->InstanceName);
\r
512 Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id);
\r
516 // Windows Vista では明示的に仮想 LAN カード本体によるルーティングテーブル
\r
518 exclude_if_id = if_id;
\r
522 e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id);
\r
526 Debug("Failed to get GetBestRouteEntry().\n");
\r
529 IPToStr(tmp, sizeof(tmp), &e->GatewayIP);
\r
530 Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp);
\r
535 e->Metric = e->OldIfMetric;
\r
537 if (AddRouteEntryEx(e, &already_exists) == false)
\r
542 Debug("already_exists: %u\n", already_exists);
\r
544 if (already_exists)
\r
546 if (s->Cedar->Client != NULL && s->Account != NULL)
\r
550 for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
\r
552 a = LIST_DATA(s->Cedar->Client->AccountList, i);
\r
555 SESSION *sess = a->ClientSession;
\r
556 if (sess != NULL && sess != s)
\r
558 VLAN *v = sess->PacketAdapter->Param;
\r
561 ROUTE_TRACKING *tr = v->RouteState;
\r
562 if (tr != NULL && e != NULL)
\r
564 if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0)
\r
566 already_exists_by_other_account = true;
\r
576 if (already_exists_by_other_account)
\r
578 Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account);
\r
579 already_exists = false;
\r
583 // DNS サーバーまでのルーティングテーブルを取得する
\r
584 dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id);
\r
588 Debug("Failed to get GetBestRouteEntry DNS.\n");
\r
595 dns->Metric = dns->OldIfMetric;
\r
597 if (AddRouteEntry(dns) == false)
\r
599 FreeRouteEntry(dns);
\r
606 if (s->Cedar->Client != NULL && s->Account != NULL)
\r
608 Lock(s->Account->lock);
\r
611 t = ZeroMalloc(sizeof(ROUTE_TRACKING));
\r
614 t->RouteToServerAlreadyExists = already_exists;
\r
615 t->RouteToServer = e;
\r
616 t->RouteToDefaultDns = dns;
\r
617 t->VLanInterfaceId = if_id;
\r
618 t->NextTrackingTime = 0;
\r
619 t->DeletedDefaultGateway = NewQueue();
\r
620 t->OldDefaultGatewayMetric = 0x7fffffff;
\r
622 if (s->Cedar->Client != NULL && s->Account != NULL)
\r
624 Unlock(s->Account->lock);
\r
627 // ネットワーク変更を検出するために
\r
628 // 現在のデフォルト DNS サーバーを取得しておく
\r
629 GetDefaultDns(&t->OldDnsServer);
\r
631 // DHCP を使用する場合は IP アドレスを解放してすぐに取得する
\r
634 char tmp[MAX_SIZE];
\r
637 Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
\r
638 a = MsGetAdapter(tmp);
\r
644 bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100);
\r
645 Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret);
\r
647 ret = Win32RenewAddressByGuidEx(a->Guid, 100);
\r
648 Debug("*** Win32RenewAddressByGuidEx = %u\n", ret);
\r
657 Win32RenewDhcp9x(if_id);
\r
660 // ルーティングテーブルの変更を検出 (対応 OS のみ)
\r
661 t->RouteChange = NewRouteChange();
\r
662 Debug("t->RouteChange = 0x%p\n", t->RouteChange);
\r
665 // ルーティングテーブルの追跡を終了する
\r
666 void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t)
\r
669 ROUTE_TABLE *table;
\r
671 bool network_has_changed = false;
\r
672 bool do_not_delete_routing_entry = false;
\r
674 if (s == NULL || t == NULL)
\r
679 Zero(&dns_ip, sizeof(dns_ip));
\r
681 // 仮想 LAN カードが追加したデフォルトゲートウェイを削除する
\r
682 if (t->DefaultGatewayByVLan != NULL)
\r
684 Debug("Default Gateway by VLAN was deleted.\n");
\r
685 DeleteRouteEntry(t->DefaultGatewayByVLan);
\r
686 FreeRouteEntry(t->DefaultGatewayByVLan);
\r
687 t->DefaultGatewayByVLan = NULL;
\r
690 if (t->VistaOldDefaultGatewayByVLan != NULL)
\r
692 FreeRouteEntry(t->VistaOldDefaultGatewayByVLan);
\r
695 if (t->VistaDefaultGateway1 != NULL)
\r
697 Debug("Vista PPP Fix Route Table Deleted.\n");
\r
698 DeleteRouteEntry(t->VistaDefaultGateway1);
\r
699 FreeRouteEntry(t->VistaDefaultGateway1);
\r
701 DeleteRouteEntry(t->VistaDefaultGateway2);
\r
702 FreeRouteEntry(t->VistaDefaultGateway2);
\r
705 if (MsIsNt() == false)
\r
707 // Windows 9x の場合のみ、仮想 LAN カードの DHCP アドレスを解放する
\r
708 Win32ReleaseDhcp9x(t->VLanInterfaceId, false);
\r
711 if (s->Cedar->Client != NULL && s->Account != NULL)
\r
715 for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
\r
717 a = LIST_DATA(s->Cedar->Client->AccountList, i);
\r
720 SESSION *sess = a->ClientSession;
\r
721 if (sess != NULL && sess != s)
\r
723 VLAN *v = sess->PacketAdapter->Param;
\r
726 ROUTE_TRACKING *tr = v->RouteState;
\r
729 if (Cmp(tr->RouteToServer, t->RouteToServer, sizeof(ROUTE_ENTRY)) == 0)
\r
731 do_not_delete_routing_entry = true;
\r
740 Lock(s->Account->lock);
\r
743 if (do_not_delete_routing_entry == false)
\r
746 if (t->RouteToServerAlreadyExists == false)
\r
748 DeleteRouteEntry(t->RouteToServer);
\r
751 DeleteRouteEntry(t->RouteToDefaultDns);
\r
754 FreeRouteEntry(t->RouteToDefaultDns);
\r
755 FreeRouteEntry(t->RouteToServer);
\r
756 t->RouteToDefaultDns = t->RouteToServer = NULL;
\r
758 if (s->Cedar->Client != NULL && s->Account != NULL)
\r
760 Unlock(s->Account->lock);
\r
764 // 現在の DNS サーバーを取得する
\r
765 if (GetDefaultDns(&dns_ip))
\r
767 if (IPToUINT(&t->OldDnsServer) != 0)
\r
769 if (IPToUINT(&t->OldDnsServer) != IPToUINT(&dns_ip))
\r
771 char s1[MAX_SIZE], s2[MAX_SIZE];
\r
772 network_has_changed = true;
\r
773 IPToStr(s1, sizeof(s1), &t->OldDnsServer);
\r
774 IPToStr(s2, sizeof(s2), &dns_ip);
\r
775 Debug("Old Dns: %s, New Dns: %s\n",
\r
781 if (network_has_changed == false)
\r
783 Debug("Network: not changed.\n");
\r
787 Debug("Network: Changed.\n");
\r
792 // 現在のルーティングテーブルを取得する
\r
793 table = GetRouteTable();
\r
795 // これまで削除してきたルーティングテーブルを復元する
\r
796 while (e = GetNext(t->DeletedDefaultGateway))
\r
798 bool restore = true;
\r
800 // 復元しようとしているルーティングテーブルがデフォルトゲートウェイの場合
\r
801 // かつ既存のルーティングテーブルでそのインターフェースによるデフォルト
\r
802 // ルートが 1 つでも登録されている場合は復元しない
\r
803 if (IPToUINT(&e->DestIP) == 0 && IPToUINT(&e->DestMask) == 0)
\r
805 for (i = 0;i < table->NumEntry;i++)
\r
807 ROUTE_ENTRY *r = table->Entry[i];
\r
808 if (IPToUINT(&r->DestIP) == 0 && IPToUINT(&r->DestMask) == 0)
\r
810 if (r->InterfaceID == e->InterfaceID)
\r
816 if (network_has_changed)
\r
833 FreeRouteTable(table);
\r
834 ReleaseQueue(t->DeletedDefaultGateway);
\r
836 FreeRouteChange(t->RouteChange);
\r
841 // 仮想 LAN カードのインスタンス ID を取得する
\r
842 UINT GetInstanceId(char *name)
\r
844 char tmp[MAX_SIZE];
\r
852 Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, name);
\r
854 id = GetVLanInterfaceID(tmp);
\r
863 // 仮想 LAN カードのインスタンスリストを取得する
\r
864 INSTANCE_LIST *GetInstanceList()
\r
866 INSTANCE_LIST *n = ZeroMalloc(sizeof(INSTANCE_LIST));
\r
869 char **ss = EnumVLan(VLAN_ADAPTER_NAME);
\r
874 n->NumInstance = 0;
\r
875 n->InstanceName = Malloc(0);
\r
884 if (ss[i++] == NULL)
\r
891 n->NumInstance = num;
\r
892 n->InstanceName = (char **)ZeroMalloc(sizeof(char *) * n->NumInstance);
\r
893 for (i = 0;i < num;i++)
\r
895 char *s = ss[i] + StrLen(VLAN_ADAPTER_NAME) + StrLen(" - ");
\r
896 if (StrLen(ss[i]) > StrLen(VLAN_ADAPTER_NAME) + StrLen(" - "))
\r
898 n->InstanceName[i] = CopyStr(s);
\r
908 void FreeInstanceList(INSTANCE_LIST *n)
\r
917 for (i = 0;i < n->NumInstance;i++)
\r
919 Free(n->InstanceName[i]);
\r
921 Free(n->InstanceName);
\r
926 void VLanPaFree(SESSION *s)
\r
931 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
936 // DHCP を使用している場合は IP アドレスを解放する
\r
939 char tmp[MAX_SIZE];
\r
942 Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
\r
943 a = MsGetAdapter(tmp);
\r
949 bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 50);
\r
950 Debug("*** Win32ReleaseAddressByGuid = %u\n", ret);
\r
962 if (s->ClientModeAndUseVLan)
\r
964 RouteTrackingStop(s, t);
\r
966 s->PacketAdapter->Param = NULL;
\r
971 bool VLanPaPutPacket(SESSION *s, void *data, UINT size)
\r
975 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
980 return VLanPutPacket(v, data, size);
\r
984 UINT VLanPaGetNextPacket(SESSION *s, void **data)
\r
989 if (data == NULL || (s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
994 RouteTrackingMain(s);
\r
996 if (VLanGetNextPacket(v, data, &size) == false)
\r
1005 CANCEL *VLanPaGetCancel(SESSION *s)
\r
1009 if ((s == NULL) || ((v = s->PacketAdapter->Param) == NULL))
\r
1014 return VLanGetCancel(v);
\r
1018 bool VLanPaInit(SESSION *s)
\r
1022 if ((s == NULL)/* || (s->ServerMode != false) || (s->ClientOption == NULL)*/)
\r
1027 // 接続直前の DNS サーバーの IP アドレスの取得
\r
1028 if (s->ClientModeAndUseVLan)
\r
1030 Zero(&s->DefaultDns, sizeof(IP));
\r
1031 GetDefaultDns(&s->DefaultDns);
\r
1035 v = NewVLan(s->ClientOption->DeviceName, NULL);
\r
1042 s->PacketAdapter->Param = v;
\r
1045 if (s->ClientModeAndUseVLan)
\r
1047 RouteTrackingStart(s);
\r
1053 // VLAN のパケットアダプタを取得
\r
1054 PACKET_ADAPTER *VLanGetPacketAdapter()
\r
1056 PACKET_ADAPTER *pa;
\r
1058 pa = NewPacketAdapter(VLanPaInit, VLanPaGetCancel,
\r
1059 VLanPaGetNextPacket, VLanPaPutPacket, VLanPaFree);
\r
1069 // 次の受信パケットをドライバに書き込む
\r
1070 bool VLanPutPacket(VLAN *v, void *buf, UINT size)
\r
1081 if (size > MAX_PACKET_SIZE)
\r
1086 // まず、現在のバッファが一杯になっているかどうか調べる
\r
1087 if ((SEN_NUM_PACKET(v->PutBuffer) >= SEN_MAX_PACKET_EXCHANGE) ||
\r
1088 (buf == NULL && SEN_NUM_PACKET(v->PutBuffer) != 0))
\r
1092 char tmp[MAX_SIZE];
\r
1093 snprintf(tmp, sizeof(tmp), "VLanPutPacket: SEN_NUM_PACKET(v->PutBuffer) = %u", SEN_NUM_PACKET(v->PutBuffer));
\r
1094 PROBE_DATA2(tmp, NULL, 0);
\r
1096 #endif // USE_PROBE
\r
1098 if (VLanPutPacketsToDriver(v) == false)
\r
1102 SEN_NUM_PACKET(v->PutBuffer) = 0;
\r
1105 // 次のパケットをバッファに追加する
\r
1108 UINT i = SEN_NUM_PACKET(v->PutBuffer);
\r
1109 SEN_NUM_PACKET(v->PutBuffer)++;
\r
1111 SEN_SIZE_OF_PACKET(v->PutBuffer, i) = size;
\r
1112 Copy(SEN_ADDR_OF_PACKET(v->PutBuffer, i), buf, size);
\r
1119 // 次の送信パケットをドライバから読み出す
\r
1120 bool VLanGetNextPacket(VLAN *v, void **buf, UINT *size)
\r
1123 if (v == NULL || buf == NULL || size == NULL)
\r
1132 PROBE_STR("VLanGetNextPacket");
\r
1136 if (v->CurrentPacketCount < SEN_NUM_PACKET(v->GetBuffer))
\r
1138 // すでに読み込まれたパケットがまだ残っている
\r
1139 *size = SEN_SIZE_OF_PACKET(v->GetBuffer, v->CurrentPacketCount);
\r
1140 *buf = MallocFast(*size);
\r
1141 Copy(*buf, SEN_ADDR_OF_PACKET(v->GetBuffer, v->CurrentPacketCount), *size);
\r
1143 // パケット番号をインクリメントする
\r
1144 v->CurrentPacketCount++;
\r
1150 // 次のパケットをドライバから読み込む
\r
1151 if (VLanGetPacketsFromDriver(v) == false)
\r
1156 if (SEN_NUM_PACKET(v->GetBuffer) == 0)
\r
1164 v->CurrentPacketCount = 0;
\r
1169 // ドライバに現在のすべてのパケットを書き込む
\r
1170 bool VLanPutPacketsToDriver(VLAN *v)
\r
1183 if (v->Win9xMode == false)
\r
1186 PROBE_STR("VLanPutPacketsToDriver: WriteFile");
\r
1187 if (WriteFile(v->Handle, v->PutBuffer, SEN_EXCHANGE_BUFFER_SIZE, &write_size,
\r
1193 PROBE_STR("VLanPutPacketsToDriver: WriteFile Completed.");
\r
1195 if (write_size != SEN_EXCHANGE_BUFFER_SIZE)
\r
1204 if (DeviceIoControl(v->Handle, SEN_IOCTL_PUT_PACKET, v->PutBuffer,
\r
1205 SEN_EXCHANGE_BUFFER_SIZE, NULL, 0, &write_size, NULL) == false)
\r
1215 // ドライバから次のパケットを読み込む
\r
1216 bool VLanGetPacketsFromDriver(VLAN *v)
\r
1229 if (v->Win9xMode == false)
\r
1232 PROBE_STR("VLanGetPacketsFromDriver: ReadFile");
\r
1233 if (ReadFile(v->Handle, v->GetBuffer, SEN_EXCHANGE_BUFFER_SIZE,
\r
1234 &read_size, NULL) == false)
\r
1243 if (DeviceIoControl(v->Handle, SEN_IOCTL_GET_PACKET, NULL, 0,
\r
1244 v->GetBuffer, SEN_EXCHANGE_BUFFER_SIZE, &read_size, NULL) == false)
\r
1251 if (read_size != SEN_EXCHANGE_BUFFER_SIZE)
\r
1261 CANCEL *VLanGetCancel(VLAN *v)
\r
1272 c->SpecialFlag = true;
\r
1273 CloseHandle(c->hEvent);
\r
1275 c->hEvent = v->Event;
\r
1281 void FreeVLan(VLAN *v)
\r
1290 CloseHandle(v->Event);
\r
1291 CloseHandle(v->Handle);
\r
1294 Free(v->InstanceName);
\r
1295 Free(v->EventNameWin32);
\r
1296 Free(v->DeviceNameWin32);
\r
1297 Free(v->PutBuffer);
\r
1298 Free(v->GetBuffer);
\r
1303 VLAN *NewVLan(char *instance_name, VLAN_PARAM *param)
\r
1306 HANDLE h = INVALID_HANDLE_VALUE;
\r
1307 HANDLE e = INVALID_HANDLE_VALUE;
\r
1308 char tmp[MAX_SIZE];
\r
1309 char name_upper[MAX_SIZE];
\r
1311 if (instance_name == NULL)
\r
1316 v = ZeroMalloc(sizeof(VLAN));
\r
1318 if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
\r
1320 v->Win9xMode = true;
\r
1324 Format(name_upper, sizeof(name_upper), "%s", instance_name);
\r
1325 StrUpper(name_upper);
\r
1326 v->InstanceName = CopyStr(name_upper);
\r
1327 Format(tmp, sizeof(tmp), NDIS_SEN_DEVICE_FILE_NAME, v->InstanceName);
\r
1328 v->DeviceNameWin32 = CopyStr(tmp);
\r
1330 if (v->Win9xMode == false)
\r
1332 Format(tmp, sizeof(tmp), NDIS_SEN_EVENT_NAME_WIN32, v->InstanceName);
\r
1333 v->EventNameWin32 = CopyStr(tmp);
\r
1337 h = CreateFile(v->DeviceNameWin32,
\r
1338 GENERIC_READ | GENERIC_WRITE,
\r
1344 if (h == INVALID_HANDLE_VALUE)
\r
1350 if (v->Win9xMode == false)
\r
1353 e = OpenEvent(SYNCHRONIZE, FALSE, v->EventNameWin32);
\r
1354 if (e == INVALID_HANDLE_VALUE)
\r
1362 OPENVXDHANDLE OpenVxDHandle;
\r
1364 UINT bytes_returned;
\r
1366 OpenVxDHandle = (OPENVXDHANDLE)GetProcAddress(GetModuleHandleA("KERNEL32"),
\r
1369 // イベントを作成してドライバに渡す
\r
1370 e = CreateEvent(NULL, FALSE, FALSE, NULL);
\r
1371 vxd_handle = (DWORD)OpenVxDHandle(e);
\r
1373 DeviceIoControl(h, SEN_IOCTL_SET_EVENT, &vxd_handle, sizeof(DWORD),
\r
1374 NULL, 0, &bytes_returned, NULL);
\r
1380 v->GetBuffer = ZeroMalloc(SEN_EXCHANGE_BUFFER_SIZE);
\r
1381 v->PutBuffer = ZeroMalloc(SEN_EXCHANGE_BUFFER_SIZE);
\r
1386 if (h != INVALID_HANDLE_VALUE)
\r
1390 if (e != INVALID_HANDLE_VALUE)
\r
1395 Free(v->InstanceName);
\r
1396 Free(v->EventNameWin32);
\r
1397 Free(v->DeviceNameWin32);
\r
1403 #endif // OS_WIN32
\r