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